summaryrefslogtreecommitdiff
path: root/sys-kernel
diff options
context:
space:
mode:
authorLiguros - Gitlab CI/CD [master] <gitlab@liguros.net>2021-03-01 00:37:58 +0000
committerLiguros - Gitlab CI/CD [master] <gitlab@liguros.net>2021-03-01 00:37:58 +0000
commit8ddb1a3d1229412a438971f82d37d518a0223726 (patch)
tree83438b5ddb9d23a390f1a3fc505303d3d2223bf2 /sys-kernel
parent9acab46e1a820daece7b2e631485c157ce2210ad (diff)
downloadbaldeagleos-repo-21.1.5.tar.gz
baldeagleos-repo-21.1.5.tar.xz
baldeagleos-repo-21.1.5.zip
Adding metadatav21.1.5
Diffstat (limited to 'sys-kernel')
-rw-r--r--sys-kernel/bliss-initramfs/metadata.xml14
-rw-r--r--sys-kernel/bliss-kernel-bin/metadata.xml13
-rw-r--r--sys-kernel/cairn-sources/Manifest298
-rw-r--r--sys-kernel/cairn-sources/cairn-sources-5.10.13.ebuild700
-rw-r--r--sys-kernel/cairn-sources/cairn-sources-5.10.14.ebuild703
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0001-ctf-generate-CTF-information-for-the-kernel.patch7297
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch1050
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch809
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0004-dtrace-core-and-x86.patch8052
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0005-dtrace-modular-components-and-x86-support.patch18392
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0006-dtrace-systrace-provider-core-components.patch326
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0007-dtrace-systrace-provider.patch374
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0008-dtrace-sdt-provider-core-components.patch3112
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0009-dtrace-sdt-provider-for-x86.patch1076
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0010-dtrace-profile-provider-and-test-probe-core-componen.patch50
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch641
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch412
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0013-dtrace-USDT-and-pid-providers.patch2691
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch1799
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0015-dtrace-fbt-provider-modular-components.patch683
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0016-dtrace-arm-arm64-port.patch2667
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0017-dtrace-add-SDT-probes.patch3306
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch241
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch86
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/0000_README120
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/1500_XATTR_USER_PREFIX.patch67
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch20
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch37
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch30
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2920_sign-file-patch-for-libressl.patch16
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/4567_distro-Gentoo-Kconfig.patch169
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/5000_shiftfs-ubuntu-20.04.patch2203
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch27
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0002-enable-HARDENED_USERCOPY-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0005-set-kptr_restrict-2-by-default.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0006-enable-DEBUG_LIST-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0009-arm64-enable-RANDOMIZE_BASE-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0010-enable-SLAB_FREELIST_RANDOM-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0011-enable-SLAB_FREELIST_HARDENED-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0012-disable-SLAB_MERGE_DEFAULT-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0013-enable-FORTIFY_SOURCE-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0014-enable-PANIC_ON_OOPS-by-default.patch34
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0016-stop-hiding-X86_16BIT-behind-EXPERT.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0017-disable-X86_16BIT-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0019-disable-MODIFY_LDT_SYSCALL-by-default.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0020-set-LEGACY_VSYSCALL_NONE-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0021-stop-hiding-AIO-behind-EXPERT.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0022-disable-AIO-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch32
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0024-disable-DEVPORT-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0025-disable-PROC_VMCORE-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0026-disable-NFS_DEBUG-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0027-enable-DEBUG_WX-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0028-disable-LEGACY_PTYS-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0029-disable-DEVMEM-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0030-enable-IO_STRICT_DEVMEM-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0031-disable-COMPAT_BRK-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch35
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0033-enable-protected_-symlinks-hardlinks-by-default.patch27
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0034-enable-SECURITY-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0035-enable-SECURITY_YAMA-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0036-enable-SECURITY_NETWORK-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0037-enable-AUDIT-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0038-enable-SECURITY_SELINUX-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0039-enable-SYN_COOKIES-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch27
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0044-disable-SYSFS_SYSCALL-by-default.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0045-stop-hiding-UID16-behind-EXPERT.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0046-disable-UID16-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0047-add-__read_only-for-non-init-related-usage.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0048-make-sysctl-constants-read-only.patch108
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch67
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch70
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0051-mark-slub-runtime-configuration-as-__ro_after_init.patch57
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch38
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0053-mark-kmem_cache-as-__ro_after_init.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0054-mark-__supported_pte_mask-as-__ro_after_init.patch49
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0055-mark-kobj_ns_type_register-as-only-used-for-init.patch45
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0056-mark-open_softirq-as-only-used-for-init.patch39
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0057-remove-unused-softirq_action-callback-parameter.patch208
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0058-mark-softirq_vec-as-__ro_after_init.patch28
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch34
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch40
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0061-bug-on-PageSlab-PageCompound-in-ksize.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0062-mm-add-support-for-verifying-page-sanitization.patch70
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch75
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0064-slub-Add-support-for-verifying-slab-sanitization.patch116
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0065-slub-add-multi-purpose-random-canaries.patch264
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0066-security-perf-Allow-further-restriction-of-perf_even.patch122
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch124
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0069-add-CONFIG-for-unprivileged_userns_clone.patch66
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0070-add-kmalloc-krealloc-alloc_size-attributes.patch65
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0071-add-vmalloc-alloc_size-attributes.patch47
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0072-add-kvmalloc-alloc_size-attribute.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0073-add-percpu-alloc_size-attributes.patch37
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0074-add-alloc_pages_exact-alloc_size-attributes.patch30
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0075-Add-the-extra_latent_entropy-kernel-parameter.patch104
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0076-ata-avoid-null-pointer-dereference-on-bug.patch37
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0077-sanity-check-for-negative-length-in-nla_memcpy.patch28
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0078-add-page-destructor-sanity-check.patch71
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch52
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0080-add-writable-function-pointer-detection.patch98
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0081-support-overriding-early-audit-kernel-cmdline.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch135
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch54
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch118
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch60
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch51
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0087-randomize-lower-bits-of-the-argument-block.patch47
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0088-x86_64-match-arm64-brk-randomization-entropy.patch38
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0089-support-randomizing-the-lower-bits-of-brk.patch42
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0090-mm-randomize-lower-bits-of-brk.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0091-x86-randomize-lower-bits-of-brk.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0092-mm-guarantee-brk-gap-is-at-least-one-page.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0093-x86-guarantee-brk-gap-is-at-least-one-page.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0094-x86_64-bound-mmap-between-legacy-modern-bases.patch37
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0095-restrict-device-timing-side-channels.patch174
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch95
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch92
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0098-usb-implement-dedicated-subsystem-sysctl-tables.patch195
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0099-hard-wire-legacy-checkreqprot-option-to-0.patch133
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch70
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch197
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0103-disable-unprivileged-eBPF-access-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0104-enable-BPF-JIT-hardening-by-default-if-available.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0105-enable-protected_-fifos-regular-by-default.patch27
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch129
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0107-mm-Fix-extra_latent_entropy.patch103
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0108-add-CONFIG-for-unprivileged_userfaultfd.patch68
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch81
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch151
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch238
-rw-r--r--sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch40
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0001-ctf-generate-CTF-information-for-the-kernel.patch7297
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch1050
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch809
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0004-dtrace-core-and-x86.patch8053
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0005-dtrace-modular-components-and-x86-support.patch18392
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0006-dtrace-systrace-provider-core-components.patch326
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0007-dtrace-systrace-provider.patch374
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0008-dtrace-sdt-provider-core-components.patch3112
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0009-dtrace-sdt-provider-for-x86.patch1076
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0010-dtrace-profile-provider-and-test-probe-core-componen.patch50
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch641
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch412
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0013-dtrace-USDT-and-pid-providers.patch2691
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch1799
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0015-dtrace-fbt-provider-modular-components.patch683
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0016-dtrace-arm-arm64-port.patch2667
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0017-dtrace-add-SDT-probes.patch3307
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch241
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch86
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/0000_README132
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/1500_XATTR_USER_PREFIX.patch67
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch20
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch37
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch30
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2920_sign-file-patch-for-libressl.patch16
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/5000_shiftfs-ubuntu-20.04.patch2203
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch27
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0002-enable-HARDENED_USERCOPY-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0005-set-kptr_restrict-2-by-default.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0006-enable-DEBUG_LIST-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0009-arm64-enable-RANDOMIZE_BASE-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0010-enable-SLAB_FREELIST_RANDOM-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0011-enable-SLAB_FREELIST_HARDENED-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0012-disable-SLAB_MERGE_DEFAULT-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0013-enable-FORTIFY_SOURCE-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0014-enable-PANIC_ON_OOPS-by-default.patch34
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0016-stop-hiding-X86_16BIT-behind-EXPERT.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0017-disable-X86_16BIT-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0019-disable-MODIFY_LDT_SYSCALL-by-default.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0020-set-LEGACY_VSYSCALL_NONE-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0021-stop-hiding-AIO-behind-EXPERT.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0022-disable-AIO-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch32
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0024-disable-DEVPORT-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0025-disable-PROC_VMCORE-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0026-disable-NFS_DEBUG-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0027-enable-DEBUG_WX-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0028-disable-LEGACY_PTYS-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0029-disable-DEVMEM-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0030-enable-IO_STRICT_DEVMEM-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0031-disable-COMPAT_BRK-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch35
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0033-enable-protected_-symlinks-hardlinks-by-default.patch27
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0034-enable-SECURITY-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0035-enable-SECURITY_YAMA-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0036-enable-SECURITY_NETWORK-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0037-enable-AUDIT-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0038-enable-SECURITY_SELINUX-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0039-enable-SYN_COOKIES-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch27
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0044-disable-SYSFS_SYSCALL-by-default.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0045-stop-hiding-UID16-behind-EXPERT.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0046-disable-UID16-by-default.patch24
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0047-add-__read_only-for-non-init-related-usage.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0048-make-sysctl-constants-read-only.patch108
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch67
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch70
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0051-mark-slub-runtime-configuration-as-__ro_after_init.patch57
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch38
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0053-mark-kmem_cache-as-__ro_after_init.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0054-mark-__supported_pte_mask-as-__ro_after_init.patch49
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0055-mark-kobj_ns_type_register-as-only-used-for-init.patch45
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0056-mark-open_softirq-as-only-used-for-init.patch39
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0057-remove-unused-softirq_action-callback-parameter.patch208
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0058-mark-softirq_vec-as-__ro_after_init.patch28
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch34
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch40
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0061-bug-on-PageSlab-PageCompound-in-ksize.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0062-mm-add-support-for-verifying-page-sanitization.patch70
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch75
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0064-slub-Add-support-for-verifying-slab-sanitization.patch116
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0065-slub-add-multi-purpose-random-canaries.patch264
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0066-security-perf-Allow-further-restriction-of-perf_even.patch122
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch124
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0069-add-CONFIG-for-unprivileged_userns_clone.patch66
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0070-add-kmalloc-krealloc-alloc_size-attributes.patch65
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0071-add-vmalloc-alloc_size-attributes.patch47
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0072-add-kvmalloc-alloc_size-attribute.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0073-add-percpu-alloc_size-attributes.patch37
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0074-add-alloc_pages_exact-alloc_size-attributes.patch30
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0075-Add-the-extra_latent_entropy-kernel-parameter.patch104
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0076-ata-avoid-null-pointer-dereference-on-bug.patch37
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0077-sanity-check-for-negative-length-in-nla_memcpy.patch28
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0078-add-page-destructor-sanity-check.patch71
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch52
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0080-add-writable-function-pointer-detection.patch98
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0081-support-overriding-early-audit-kernel-cmdline.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch135
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch54
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch118
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch60
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch51
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0087-randomize-lower-bits-of-the-argument-block.patch47
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0088-x86_64-match-arm64-brk-randomization-entropy.patch38
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0089-support-randomizing-the-lower-bits-of-brk.patch42
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0090-mm-randomize-lower-bits-of-brk.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0091-x86-randomize-lower-bits-of-brk.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0092-mm-guarantee-brk-gap-is-at-least-one-page.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0093-x86-guarantee-brk-gap-is-at-least-one-page.patch31
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0094-x86_64-bound-mmap-between-legacy-modern-bases.patch37
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0095-restrict-device-timing-side-channels.patch174
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch95
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch92
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0098-usb-implement-dedicated-subsystem-sysctl-tables.patch195
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0099-hard-wire-legacy-checkreqprot-option-to-0.patch133
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch70
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch197
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch26
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0103-disable-unprivileged-eBPF-access-by-default.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0104-enable-BPF-JIT-hardening-by-default-if-available.patch25
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0105-enable-protected_-fifos-regular-by-default.patch27
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch129
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0107-mm-Fix-extra_latent_entropy.patch103
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0108-add-CONFIG-for-unprivileged_userfaultfd.patch68
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch81
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch151
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch238
-rw-r--r--sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch40
-rw-r--r--sys-kernel/cryptodev/metadata.xml14
-rw-r--r--sys-kernel/debian-sources/Manifest4
-rw-r--r--sys-kernel/debian-sources/debian-sources-5.10.13_p1.ebuild (renamed from sys-kernel/debian-sources/debian-sources-5.10.12_p1.ebuild)0
-rw-r--r--sys-kernel/debian-sources/metadata.xml23
-rw-r--r--sys-kernel/dracut-crypt-ssh/metadata.xml24
-rw-r--r--sys-kernel/dracut/metadata.xml30
-rw-r--r--sys-kernel/dummy-sources/metadata.xml10
-rw-r--r--sys-kernel/genkernel/Manifest4
-rw-r--r--sys-kernel/genkernel/genkernel-9999.ebuild4
-rw-r--r--sys-kernel/genkernel/metadata.xml32
-rw-r--r--sys-kernel/gentoo-kernel-bin/Manifest61
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.14.ebuild48
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.15.ebuild48
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.17-r1.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.10-r1.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.17.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.10.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.18-r1.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.11-r1.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.18.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.11.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.19-r1.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.12-r1.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.19.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.12.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.9.ebuild48
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.11.2-r1.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.9-r1.ebuild)2
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.11.2.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.13.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.100-r1.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.91-r1.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.100.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.91.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.101-r1.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.92-r1.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.101.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.92.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.80-r2.ebuild53
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.83-r1.ebuild57
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.83.ebuild53
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.88.ebuild55
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.94-r1.ebuild2
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.94.ebuild2
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.95.ebuild55
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.96.ebuild55
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.97-r1.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.93-r1.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.97.ebuild2
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.99-r1.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.88-r1.ebuild)2
-rw-r--r--sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.99.ebuild (renamed from sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.93.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel-bin/metadata.xml20
-rw-r--r--sys-kernel/gentoo-kernel/Manifest57
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.10.11.ebuild89
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.10.14.ebuild89
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.10.15.ebuild89
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.10.17.ebuild (renamed from sys-kernel/gentoo-kernel/gentoo-kernel-5.10.13.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.10.18.ebuild (renamed from sys-kernel/gentoo-kernel/gentoo-kernel-5.10.9.ebuild)6
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.10.19.ebuild (renamed from sys-kernel/gentoo-kernel/gentoo-kernel-5.10.10.ebuild)8
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.11.2.ebuild (renamed from sys-kernel/gentoo-kernel/gentoo-kernel-5.10.12.ebuild)8
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.100.ebuild (renamed from sys-kernel/gentoo-kernel/gentoo-kernel-5.4.91.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.101.ebuild (renamed from sys-kernel/gentoo-kernel/gentoo-kernel-5.4.92.ebuild)6
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.80-r1.ebuild94
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.80.ebuild94
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.83.ebuild94
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.88.ebuild96
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.93.ebuild96
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.94.ebuild2
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.95.ebuild96
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.97.ebuild2
-rw-r--r--sys-kernel/gentoo-kernel/gentoo-kernel-5.4.99.ebuild (renamed from sys-kernel/gentoo-kernel/gentoo-kernel-5.4.96.ebuild)0
-rw-r--r--sys-kernel/gentoo-kernel/metadata.xml20
-rw-r--r--sys-kernel/gentoo-sources/Manifest139
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.14.217.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.14.222.ebuild (renamed from sys-kernel/gentoo-sources/gentoo-sources-4.14.218.ebuild)2
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.19.169.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.19.170.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.19.171.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.19.172.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.19.176.ebuild (renamed from sys-kernel/gentoo-sources/gentoo-sources-4.14.215.ebuild)2
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.19.177.ebuild (renamed from sys-kernel/gentoo-sources/gentoo-sources-4.14.216.ebuild)2
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.4.251.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.4.252.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.4.253.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.4.254.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.4.258.ebuild (renamed from sys-kernel/gentoo-sources/gentoo-sources-4.19.168.ebuild)2
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.9.251.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.9.252.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.9.253.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.9.254.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-4.9.258.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.10.10.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.10.16.ebuild (renamed from sys-kernel/gentoo-sources/gentoo-sources-5.10.11.ebuild)2
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.10.17.ebuild (renamed from sys-kernel/gentoo-sources/gentoo-sources-5.10.12.ebuild)2
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.10.18.ebuild (renamed from sys-kernel/gentoo-sources/gentoo-sources-5.10.13.ebuild)2
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.10.19.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.10.8.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.10.9.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.11.0.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.11.1.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.11.2.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.100.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.101.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.90.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.91.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.92.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.93.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.94.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.95.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.96.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.98.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/gentoo-sources-5.4.99.ebuild28
-rw-r--r--sys-kernel/gentoo-sources/metadata.xml19
-rw-r--r--sys-kernel/git-sources/metadata.xml27
-rw-r--r--sys-kernel/installkernel-gentoo/metadata.xml14
-rw-r--r--sys-kernel/installkernel-systemd-boot/metadata.xml14
-rw-r--r--sys-kernel/kergen/metadata.xml27
-rw-r--r--sys-kernel/kpatch/metadata.xml24
-rw-r--r--sys-kernel/linux-docs/Manifest2
-rw-r--r--sys-kernel/linux-docs/linux-docs-4.19.114.ebuild31
-rw-r--r--sys-kernel/linux-docs/linux-docs-5.10.17.ebuild (renamed from sys-kernel/linux-docs/linux-docs-5.10.0.ebuild)21
-rw-r--r--sys-kernel/linux-docs/linux-docs-5.4.39.ebuild32
-rw-r--r--sys-kernel/linux-docs/metadata.xml12
-rw-r--r--sys-kernel/linux-firmware/metadata.xml42
-rw-r--r--sys-kernel/linux-headers/Manifest3
-rw-r--r--sys-kernel/linux-headers/linux-headers-5.10.ebuild2
-rw-r--r--sys-kernel/linux-headers/linux-headers-5.11.ebuild (renamed from sys-kernel/linux-headers/linux-headers-5.4.ebuild)6
-rw-r--r--sys-kernel/linux-headers/metadata.xml13
-rw-r--r--sys-kernel/liquorix-sources/Manifest8
-rw-r--r--sys-kernel/liquorix-sources/files/4567_distro-Gentoo-Kconfig.patch (renamed from sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/4567_distro-Gentoo-Kconfig.patch)19
-rw-r--r--sys-kernel/liquorix-sources/liquorix-sources-5.10.17_p1.ebuild67
-rw-r--r--sys-kernel/liquorix-sources/liquorix-sources-5.11.2_p2.ebuild67
-rw-r--r--sys-kernel/liquorix-sources/metadata.xml7
-rw-r--r--sys-kernel/mips-sources/Manifest6
-rw-r--r--sys-kernel/mips-sources/metadata.xml31
-rw-r--r--sys-kernel/mips-sources/mips-sources-4.14.221.ebuild (renamed from sys-kernel/mips-sources/mips-sources-4.14.213.ebuild)2
-rw-r--r--sys-kernel/mips-sources/mips-sources-4.19.176.ebuild (renamed from sys-kernel/mips-sources/mips-sources-4.19.163.ebuild)2
-rw-r--r--sys-kernel/mips-sources/mips-sources-5.4.99.ebuild (renamed from sys-kernel/mips-sources/mips-sources-5.4.85.ebuild)2
-rw-r--r--sys-kernel/opensuse-sources/metadata.xml23
-rw-r--r--sys-kernel/opensuse-sources/opensuse-sources-5.6.2.ebuild1
-rw-r--r--sys-kernel/pf-sources/Manifest17
-rw-r--r--sys-kernel/pf-sources/metadata.xml19
-rw-r--r--sys-kernel/pf-sources/pf-sources-5.10_p2.ebuild69
-rw-r--r--sys-kernel/pf-sources/pf-sources-5.10_p3.ebuild66
-rw-r--r--sys-kernel/pf-sources/pf-sources-5.10_p4.ebuild66
-rw-r--r--sys-kernel/pf-sources/pf-sources-5.10_p5.ebuild66
-rw-r--r--sys-kernel/pf-sources/pf-sources-5.10_p6.ebuild66
-rw-r--r--sys-kernel/pf-sources/pf-sources-5.10_p7.ebuild66
-rw-r--r--sys-kernel/pf-sources/pf-sources-5.10_p8.ebuild66
-rw-r--r--sys-kernel/pf-sources/pf-sources-5.10_p9.ebuild66
-rw-r--r--sys-kernel/pf-sources/pf-sources-5.11_p1.ebuild (renamed from sys-kernel/pf-sources/pf-sources-5.10_p10.ebuild)0
-rw-r--r--sys-kernel/pf-sources/pf-sources-5.11_p2.ebuild (renamed from sys-kernel/pf-sources/pf-sources-5.10_p11.ebuild)0
-rw-r--r--sys-kernel/raspberrypi-image/Manifest1
-rw-r--r--sys-kernel/raspberrypi-image/metadata.xml19
-rw-r--r--sys-kernel/raspberrypi-image/raspberrypi-image-5.10.11_p20210201.ebuild43
-rw-r--r--sys-kernel/raspberrypi-sources/metadata.xml19
-rw-r--r--sys-kernel/rt-sources/metadata.xml23
-rw-r--r--sys-kernel/vanilla-kernel/Manifest54
-rw-r--r--sys-kernel/vanilla-kernel/metadata.xml20
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.10.11.ebuild100
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.10.12.ebuild100
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.10.17.ebuild (renamed from sys-kernel/vanilla-kernel/vanilla-kernel-5.10.13.ebuild)0
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.10.18.ebuild (renamed from sys-kernel/vanilla-kernel/vanilla-kernel-5.10.15.ebuild)2
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.10.19.ebuild (renamed from sys-kernel/vanilla-kernel/vanilla-kernel-5.10.14.ebuild)2
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.10.9.ebuild100
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.11.2.ebuild (renamed from sys-kernel/vanilla-kernel/vanilla-kernel-5.10.10.ebuild)6
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.4.100.ebuild (renamed from sys-kernel/vanilla-kernel/vanilla-kernel-5.4.91.ebuild)0
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.4.101.ebuild (renamed from sys-kernel/vanilla-kernel/vanilla-kernel-5.4.92.ebuild)0
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.4.80.ebuild104
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.4.83.ebuild104
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.4.88.ebuild107
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.4.95.ebuild106
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.4.96.ebuild106
-rw-r--r--sys-kernel/vanilla-kernel/vanilla-kernel-5.4.99.ebuild (renamed from sys-kernel/vanilla-kernel/vanilla-kernel-5.4.93.ebuild)0
-rw-r--r--sys-kernel/vanilla-sources/Manifest14
-rw-r--r--sys-kernel/vanilla-sources/metadata.xml29
-rw-r--r--sys-kernel/vanilla-sources/vanilla-sources-4.14.222.ebuild (renamed from sys-kernel/vanilla-sources/vanilla-sources-4.14.221.ebuild)0
-rw-r--r--sys-kernel/vanilla-sources/vanilla-sources-4.19.177.ebuild (renamed from sys-kernel/vanilla-sources/vanilla-sources-4.19.175.ebuild)0
-rw-r--r--sys-kernel/vanilla-sources/vanilla-sources-4.4.258.ebuild (renamed from sys-kernel/vanilla-sources/vanilla-sources-4.4.257.ebuild)0
-rw-r--r--sys-kernel/vanilla-sources/vanilla-sources-4.9.258.ebuild (renamed from sys-kernel/vanilla-sources/vanilla-sources-4.9.257.ebuild)0
-rw-r--r--sys-kernel/vanilla-sources/vanilla-sources-5.10.19.ebuild (renamed from sys-kernel/vanilla-sources/vanilla-sources-5.10.15.ebuild)0
-rw-r--r--sys-kernel/vanilla-sources/vanilla-sources-5.11.2.ebuild (renamed from sys-kernel/vanilla-sources/vanilla-sources-5.4.97.ebuild)0
-rw-r--r--sys-kernel/vanilla-sources/vanilla-sources-5.4.101.ebuild16
-rw-r--r--sys-kernel/zen-sources/Manifest7
-rw-r--r--sys-kernel/zen-sources/metadata.xml21
-rw-r--r--sys-kernel/zen-sources/zen-sources-5.10.16.ebuild (renamed from sys-kernel/zen-sources/zen-sources-5.10.10.ebuild)0
-rw-r--r--sys-kernel/zen-sources/zen-sources-5.11.ebuild (renamed from sys-kernel/zen-sources/zen-sources-5.10.6.ebuild)4
456 files changed, 984 insertions, 129130 deletions
diff --git a/sys-kernel/bliss-initramfs/metadata.xml b/sys-kernel/bliss-initramfs/metadata.xml
index 7cb74c4691c2..f06501a4c5a8 100644
--- a/sys-kernel/bliss-initramfs/metadata.xml
+++ b/sys-kernel/bliss-initramfs/metadata.xml
@@ -1,8 +1,8 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <!--maintainer-needed-->
- <upstream>
- <remote-id type="github">fearedbliss/bliss-initramfs</remote-id>
- </upstream>
-</pkgmetadata>
+ <upstream>
+ <remote-id type="github">fearedbliss/bliss-initramfs</remote-id>
+ </upstream>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/bliss-kernel-bin/metadata.xml b/sys-kernel/bliss-kernel-bin/metadata.xml
index 5c3f9d281df0..14b68cc9360b 100644
--- a/sys-kernel/bliss-kernel-bin/metadata.xml
+++ b/sys-kernel/bliss-kernel-bin/metadata.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <!--maintainer-needed-->
- <use>
- <flag name='initramfs'>Build initramfs along with the kernel.</flag>
- </use>
-</pkgmetadata>
+
+ <use>
+ <flag name="initramfs">Build initramfs along with the kernel.</flag>
+ </use>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/cairn-sources/Manifest b/sys-kernel/cairn-sources/Manifest
deleted file mode 100644
index c38c17082248..000000000000
--- a/sys-kernel/cairn-sources/Manifest
+++ /dev/null
@@ -1,298 +0,0 @@
-AUX 5.10.13/dtrace-patches/0001-ctf-generate-CTF-information-for-the-kernel.patch 245882 BLAKE2B a62e7987ad2e2102448920bb1d75fa489c2d960d3de458604acc6a1c35158f108dea038bceea63392931446ad5dbc8e0146b37a6973691adf746f693d6bdeb33 SHA512 f0289de6e00cadb2c4c38d5e7ae4ec5e8036f41bd0aa7313589ce3af6c7d9cff6cc916030a0bd61a6e2ddf4ebdc863a8550ed384b96c7847797ce57e2550c8c8
-AUX 5.10.13/dtrace-patches/0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch 32718 BLAKE2B bdf611b26c724c3a55e95a39df8eb2911f2fab4a95ea5a2163979a5ecab478d25b2b39b668b9e3b7d10ea7ca7269e12f58fb0ca2a7a3619db472b4f2f49370ce SHA512 1773efe326b6d70568eb17ee35f677ee1352a003c11faaf0a1e2ca30e23d4c73c644cb785074e0b6869c57d0a348c4ff65c5f179b2eed8597cf0840c19feb088
-AUX 5.10.13/dtrace-patches/0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch 26905 BLAKE2B e40145dd7361ba37b5f9e63a0f70a5fb80df0a12471b61e6b2fbef0aa15fa90122bc248894ed936812b3fa8c7257182a142aa20dd8ce239bc081580a936156bc SHA512 f6af8f29855879373415cac02011074eb141a3c3f2e79732af127cf243d755e9ae0e1188cbcfac6d6bea9e648dbf74d9285b40154278eb9de8edabb49b05ddb3
-AUX 5.10.13/dtrace-patches/0004-dtrace-core-and-x86.patch 275923 BLAKE2B d45d18422ee9e7381fac40fcfb65cb16d799832df640f1297af004148afd7a36d2cce9ead51cf9db844085ab5e15e9767d27bf45a6df22f2eaa0d341f7da69bf SHA512 4438bcae2617d69eb8239d5614d811269d5b1dbaf7077e8ec1df4dd8b7c4e28b4bb9a11b17630243f8715db6229b371c9a1a201b97cc6047d33244332ffa64a0
-AUX 5.10.13/dtrace-patches/0005-dtrace-modular-components-and-x86-support.patch 484600 BLAKE2B 2dabade3a2e1c5b49c946c30768ed0d637a55b60a228ff025809ec7669761e0452168ebdc25717494a5d96deec21c7e2a28a04338ca63345df59724bb49e6776 SHA512 447e674de2a65f9b83ec250510d65d53bbeb5855068b597f4d6fb3e69105f578a1d74272574f945d3f8c86bddc364df66aea619251b367185eaffa2878e219ee
-AUX 5.10.13/dtrace-patches/0006-dtrace-systrace-provider-core-components.patch 9861 BLAKE2B b0a5a80467126108bb5b61a8d70bd094dcce965a5e4a117b38c36650de9deb1241986f22ade6016e725b5907f1f7a828b9768529cac43b28daac2bca21844fca SHA512 70dfdbade9819c0fa8b2e2c1db496526835333113d38d8ae257588eef3bd6cbe94e306effdfa747013948784b56258a03a42bd2c8ffda9b3bd32a5bd184a0f0f
-AUX 5.10.13/dtrace-patches/0007-dtrace-systrace-provider.patch 11199 BLAKE2B 3787cb9da781e4008a9754858e925a8626f858ae66528fec8a38366a3e4167a6037fb6760e91a3792e3cb49fe2c49c13af9ac8054a1f4ff9f44a32a5e32c45fd SHA512 f668e6c84d3ec901daaff993124e2a3da6ef101fa86eadc30214b02218c2e18742607c2f39a7eca0de674c4eb54c77e73ddd920637d6591e92c0d2c185570570
-AUX 5.10.13/dtrace-patches/0008-dtrace-sdt-provider-core-components.patch 101126 BLAKE2B 938a4c5bb38da112d84bce2e8a835b05dc34f6781e2a09f4c189c8a0b5e4a7ce73dccfb13505f1ce6bb17ae539e33663f041a5fcc1786d8c94e4b831f6abc5a1 SHA512 ba3bd0a073ec80c97c8f7789434191023b00722cc0fb2a57567efa8e101b2dc9829b70f991bf919ee395a6160bd144dfdabb60c2652ceebe0947b0ba73871d0b
-AUX 5.10.13/dtrace-patches/0009-dtrace-sdt-provider-for-x86.patch 33276 BLAKE2B ab8e00705288255b68e8b23175d2e9dcb0180a12ac8a8a380372d38ce6a63c4cc1117e7d52a4833691258ff6cf8022160fd7910c5f59bd6cff30ba029172cbc0 SHA512 0aba8eae7e8a8087b9f6fee4f77647c7ad3824d568c0a4e4a69895d4480c79fd3170d603da42d5aee2fdb44c19fc5d3ca4d2a1d948cf75ce7878b2c357f1ad23
-AUX 5.10.13/dtrace-patches/0010-dtrace-profile-provider-and-test-probe-core-componen.patch 1426 BLAKE2B 852b0943e452a83860c5bfeb88db5dc6d52d3e700b81933646f6f4966f11b92907449c4621176f2d6d1c749d272bb208d64ddad381aab0abc03079c92224dfbf SHA512 b059a3645b4d754932ee79aabd2a2c86452fd809e9ac4e1f51b1be874d1beee2870ec276bc5bc6c857e1eb31e2a909abbfe47f77aaeb8c79c86857d5277228bb
-AUX 5.10.13/dtrace-patches/0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch 17675 BLAKE2B 6ea9ec19cd71da3016ddf99e0598f04f077b8ec41e189aa0a87d328765b903e6c194b5991d4ae407fa98efc372f693a914c71c817d27a7f75a81487c687f43f8 SHA512 6ad985c1b53f4fd01c1db2e07c4d861b81aedfbe4729e1367b00f56b80166caa28cce037a7be311bebc2bf3e39f540ee091c2a0a9277bf35b3e5ae3e73dd3600
-AUX 5.10.13/dtrace-patches/0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch 10977 BLAKE2B 5d50e4ff56a86c1be202b4563b77e140db0b2ce56b61d84c1c85ae8955d6ea5bab6aa30e5f1375e5c7258d259ae9436c033cb944c5dae56159f905969c9ef81b SHA512 139ecb4b2fe3f5f51a3af333dd7dded854df3c549ff265f946e2f191f93c23ae48394007dee32958f98ebb2135d3d72cffb01edf5cb2a43b466a7c4329aea290
-AUX 5.10.13/dtrace-patches/0013-dtrace-USDT-and-pid-providers.patch 73642 BLAKE2B 506b98a4c1e9958f8d8cf42b20cae4b6665f5443e0cf09bea542db09012713545203480331dd8fa23a537b568b82532cc0028c32c9633c0b20dc639f63ca6dde SHA512 199a2ddd12c72950cb6646f7ff1b43a91065536a5501cfe76179a786e2dab4b7bff5c4ed0df29e73e51d633949157d5bb12801544298ce13dbaed85d14e632af
-AUX 5.10.13/dtrace-patches/0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch 54502 BLAKE2B 683ced4e432b1515a714d342e65bd155a02c79b5001ee627b3302a9b2b9c4654c0772ab08092f2c7f4b2628a6dcb2b1c23ada9aed2f7493a9776c351ad5fa6d7 SHA512 e51601fd80e9f59e987164cdae387b290c34b7a51b1fd98adc02bc9b821fc9f73e1ca9d7b2b5a6bb2127bce52e04455d9951b90823696efc3175abff57d6b57f
-AUX 5.10.13/dtrace-patches/0015-dtrace-fbt-provider-modular-components.patch 19711 BLAKE2B ecdb0fd324de883585e4abe564204e8b67ba0934f4a39dfd3d32ccd3069de1875275414d69aa461199115000318fbf631c1585f147c6c07746df3c215e60e397 SHA512 ed1a0bcaa2e2514765fd66df99a7ab19df066d121e215fb0e0f16712823f1aaa47d3b60771160f206329c4bff6acbec568cc3921d142e286d965db6704d4d2b8
-AUX 5.10.13/dtrace-patches/0016-dtrace-arm-arm64-port.patch 75498 BLAKE2B b6cdd7a1e363746492250bf38b9bfb7e3f46c6a295db1b0d298bc6c4e9aedb73b62945a91d070643f9424b1adf447f271a05d3a0594202ead243fa66662402e3 SHA512 cbe9bcb6f1abaed9e7e0aa96bc8f4a7386cf27070868b0a4d75cb92e9c2adef96d7d5282cc8fb2cf5fbce81c7f472f072211ab59c0cf312188c54b0e5442b1bf
-AUX 5.10.13/dtrace-patches/0017-dtrace-add-SDT-probes.patch 105896 BLAKE2B 2f18953f34af9d11ce240aec6f86a2a35b2efad0f68bc9940c5980788931099c66c9f00fc5f1901de7cbe31d932f34fd5a9dad73af41e593a44763f443eed832 SHA512 51345a53594beeeb3047685a8d50843610b3c9969660e2fc73b8d8ad8fbcb6aefec4cf50b1d72da2659ae36b2ae1669a8e6a0d96c77d2b625d1c35073c53dfd1
-AUX 5.10.13/dtrace-patches/0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch 8549 BLAKE2B 2b0ed98f3a95c5589b7cc143d6a95a302568da0c63019728071cb448f2e7963ec1797e8d6965b6730023b0171973f3d4ba6b7280b72424297944257542c82eef SHA512 3c04b5f9d1170cfdd13632693564a9c0205e662b2ad2d748f274e1572b32557ca7832e15e292a6cba135412b38aa6f0cb95c239f9149de6470ad5561653850cd
-AUX 5.10.13/dtrace-patches/0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch 2431 BLAKE2B 8ffcbf3b70c46fa21e9f1a03c4d2139b980df2bcb9704489d76666b5d2e72722415f04ff759fb2418ae502434050a7cafbdb6a7a36d1adca71a754af783a2ee5 SHA512 70307162146460093f9d9a1d39c0fa1275e38ef76f29f24675c505ac64f84d98f5308a826cd4cb9533fd023b63b0776ff55f6e714d350f4c96e7b0b1701fe4b7
-AUX 5.10.13/gentoo-patches/0000_README 3702 BLAKE2B cf545e5849b9beea0d24c8dac628bb1bcc651ac863a7f514b2c036aa3cdfd28285b2a0362941803fcc1dab00d97196bc64ced1ee15426336597d55e717e363ed SHA512 d9b9b54f6d9063697768c32301197da3fd1efcc7f71f24e2f688402b9539eb276651af157701a608b9f2346a044b12e6bfb3a3e3fe6b6ebea9ba608f5b6a7beb
-AUX 5.10.13/gentoo-patches/1500_XATTR_USER_PREFIX.patch 2293 BLAKE2B c2bde13ef40e7066340afefe55454dc933ac3b65dda4dcf81d9958ba84d9531143e58c4d35151d912bfe21a43aaed35fd99571a769ca8e823fc0d99797a96f4b SHA512 3ed100909f9aed72836a3c712e45e0116cd3c4331961a76a27b867a7098d0df9458387b656c9ea01385c3c37585436e48168ac35666b0e46dca7da05e5e38a61
-AUX 5.10.13/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch 810 BLAKE2B bb749b365f37988253206ddff130651e1042af49a6c773ba6f93642d5927af9a9926eab278979e048c13d2ca683e726a5d0cd509de9e6177d59c85197051e230 SHA512 c97a3799a2d5e4da9c9dfe129756da629fba8183479b02ca82f9b6d9993f17a165a96bd35ac50eb25fb293785b9b529a95165b1a2eb79c05134bee8ccf22a5d3
-AUX 5.10.13/gentoo-patches/2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch 1290 BLAKE2B 35f8f2a707da3bdb4df74844f72244dc6cb9fb0d41ac2034af61ce61c96e4bd472fb5bc5c687611356d06f3940e9f6669c80f4261165809592173bf5dac54b61 SHA512 dc47b18749d95a456f8bc47fd6a0618c286b646b38466c3d950dfbeb25adf3fc1a794e95552e4da1abb58e49f0bd841f7222e71c4d04cb0264ca23476ca9caef
-AUX 5.10.13/gentoo-patches/2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch 958 BLAKE2B 095d70ef085c6200b3ac69695339b8937e54b49c45acb7a741d0f471f66c1fe1bedf0b7df0951eff6ccd53ade10abcc66d5d2bca994e28a49d3e4296d7332e55 SHA512 4e637935c2f37cc18f347293e3c94b18f90e2caccca726304a95c4891257a5b2bb3093aee7a97571038b29c0c987cc60a9a80aefd0d4c9a063b33d102f03579e
-AUX 5.10.13/gentoo-patches/2920_sign-file-patch-for-libressl.patch 565 BLAKE2B ea33143cebfccbc5fdeab46161ab28c8ed6dbe265b35454659ba87f09705ed80219e9a9e47f7fc3df51292a3a7656c7a6d633e24a37911c35e47d039da530ad5 SHA512 79eaf814d76402a445efc961666a7c7c74207e552b0cb32d93d5cb828da580f7dbe93509dc9f53321c7844663205a8dce4e518ba047e4c57fc55f5c3498088ec
-AUX 5.10.13/gentoo-patches/4567_distro-Gentoo-Kconfig.patch 4784 BLAKE2B ccbb902ac828a26a69bda7f7eb7c69770bca7685ed5e58459e473b7a8ac0f396ac9f1aa1ee23a9248de22c5aebbfecf76930420b640cf6307a4d1e73bc9add0a SHA512 bf681566831b583537eda1df1db9c9d1b310cf54a974dcdc437c8da11b65cda423ac86a1a8ae56c84cfc947a6ad363adb25983e51933cf7acb494934c1ad3eb5
-AUX 5.10.13/gentoo-patches/5000_shiftfs-ubuntu-20.04.patch 55494 BLAKE2B 5c56cb45b70a340d6eb65140f3772f3c4a26e30811645d471d0db7a389c813edbfe6f46ed2fb5fa8c96596c9486c1040948d3074b4fc5ebdc8080c4b02b0992b SHA512 e832d44d4a450c45eb7a517d6cd849258985aed08349d18ea21cf4d1eb37dcbac9153f50ca8b910955bfe64169298c631a7ec7857e9235bbce0167d97d69e55b
-AUX 5.10.13/hardened-patches/0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch 840 BLAKE2B 9740839753747aac0851874597e83390d9415bbb2b2d2eb5e1d03449849817d25126d37bac0ea64ef796457ded20e4913d57f43c4adbeb06a9019a732b899092 SHA512 7d28c8d57da9ee854a139fd6a83603311e2798e11865017d4a2a0950f21f1d3312b7252e7c2c48b5112529fbc80713098d2fbb4bd0a63b2168f67d127f6eeb57
-AUX 5.10.13/hardened-patches/0002-enable-HARDENED_USERCOPY-by-default.patch 790 BLAKE2B 16134839ab373cae29238fd8fe909bdd4c90d1c49054962e9c281de155a4d8e4464926c96c717ecb4bb0dc35c703fff078e307f0a5acb3aab4992bf4bfd76c09 SHA512 028ed1e01bccc632adb08c2e59322ea3d22dca3d911e8601cdf4a5252b88f3b8243ff91df929a37317bfacd26d26225ad9f463585e5d5f576777717ad4d0055a
-AUX 5.10.13/hardened-patches/0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch 768 BLAKE2B f03d98ce300492e36abd73a4921e0871d455b894f65d62de7f728490d9630d9b3ea7a3d53e386fcbcf373196eaf0a569d9c3dd8592d966b3a39fba38536f152d SHA512 b95aa576e8512cf3e0b9c9196d66e7689f9275b4c3c3e176f37ea1de66da188c29e9196f34fe9e9cfebd97fddb7b49a5804e2df2dad0a65595420461aaf2e658
-AUX 5.10.13/hardened-patches/0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch 763 BLAKE2B d4b42a83da68f06395fafd3740d08bb146245aee34b85a1a9314f49baff61710c75d4e34715981235d2a4e917a4d328d197119c05a1a23ee269e67ed099e3a7a SHA512 b2006a32d4ef359d06568326e6a82c3420bb4d466676ade05a60ae1ece39b3eb128ca953bb61e8e9e95eb76b39a37d9205440f850012068703cfb71d44cf9018
-AUX 5.10.13/hardened-patches/0005-set-kptr_restrict-2-by-default.patch 791 BLAKE2B 8a94466a420466de93a38784520d9e0223223468ff1dc0e1e434d1d42efae8ec6fb38a671cacd399fde6a00079137ed1490dbeb34e1ce1332e2d6c6efffdfe82 SHA512 efe5da03926403eaf35f65a4c9b8b59c6569199a4f3eb95ceac48cfd8c6e701d42d704d53f3993ebb65cfe7cb3bfe37899dfeab81d4dc97ef121c49a47c28dab
-AUX 5.10.13/hardened-patches/0006-enable-DEBUG_LIST-by-default.patch 743 BLAKE2B 6f850632b28bed969f046eb6a8d338afcb028413ff54a1a1da7b13ac9363fa060ddd4ddb3fb65587dd62a7d480b261f7c1f2d0f3bf8cdd3e84ef16aeac9b98b3 SHA512 35811cc68afd7402fde62fbdc6597266a90d1c67f3de6d01eb38ed7136357a9aa26e37d64597763836d9942712e90b0f1be2894601175253f7a0225e3c540dea
-AUX 5.10.13/hardened-patches/0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch 792 BLAKE2B 05183b3b00d234b560f7ed4cc577f0fc27c5bc86664beeb1b12c4dbc4631dfab08e866f2c0eb5f137f1ead38568acbb4a07adefc306efb97c8445106df8bf451 SHA512 6e91f5c113ca729e77e57d6f0629073303947905c3a00df6fed6307f3fc51670007f724f038ef427ec998975ea9857159d21e0c053522f3ee7c453b4b1b2f3a3
-AUX 5.10.13/hardened-patches/0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch 732 BLAKE2B 0a91552dc6675c0359b8bfb5d6cb64d6281531ce687361b3c4101c67caf208f042a5be9f35d73f594b516db8de756d2acfeba71dcc1ee50f5602893918fadfcb SHA512 ed077f3f7d06112508de3d8669af45a1266a3c95e2c0a3557d4b9a1f7b623ef3f5b1627d13851ab2ef8c131f0f69321238f01822cff11877c04b97ade8ade17a
-AUX 5.10.13/hardened-patches/0009-arm64-enable-RANDOMIZE_BASE-by-default.patch 736 BLAKE2B 0e2a0a4972db7f5285ebd6e44d03cac6c393fe5ffcc05c5047d01ee17982981057e9389b13387ed217422e3be4a693bbb2d42c4005f83747b8fcf762d26260a0 SHA512 09f7e9f38664b68d2273859bd04209634964d190eb3061a7d19664470fa6046ec3516eec33b498bcc494369ad565cbca0ef274b0976576c14ea3b01f74c2c4a6
-AUX 5.10.13/hardened-patches/0010-enable-SLAB_FREELIST_RANDOM-by-default.patch 745 BLAKE2B 11bc8611d78e330ec3a6c90a6e1b4bdd60b8898bebbca2125980d666fddcd2678303485595c1a2459abb692ec1552cc36fe16c06e2bfc3f5a0b0eab39de7b51f SHA512 ccd814cae6a113b166b7651aa7d2f5165127656fb44ac85457fde9064648040b0b67d78f352802e3cc58a939096595ceae14012080f13cbd284d838bb753402d
-AUX 5.10.13/hardened-patches/0011-enable-SLAB_FREELIST_HARDENED-by-default.patch 702 BLAKE2B 02844156366aa67c6bcddb01eabc24547bd31d400e3d553e47d8c0006ae19a8a48bd5518194a95a6c5ac7ff5a59da08ac7ef1382c620e8e5d4c8987ba4ee2e38 SHA512 3b1611a3fa6def95fa5670e305027825097ce5a9fd5282e8944b25adf87c6fa5678213c513ca06bbe13d87de65ed7ef3f29ef2c7b6ab0000b583c9bedef2f585
-AUX 5.10.13/hardened-patches/0012-disable-SLAB_MERGE_DEFAULT-by-default.patch 654 BLAKE2B 6d635e574ebcb81c81f4cb26df07c2561fede01136fe9dbf00f1dab6a5c31def57e68c4b3094f75cf45652450b3c4f21cdce201481e27c8dfaeac411f2ccc506 SHA512 4f499329f93b9a8e0955d19f4b37b19024365cd198c09a5de950543630afdd5c68926eca13cd779a60c7b2dc5119434449680d5a75d7ce2a7dbb9418cc733b8d
-AUX 5.10.13/hardened-patches/0013-enable-FORTIFY_SOURCE-by-default.patch 807 BLAKE2B ad40e70bb9f0ff40e10d7f49062c9cb29b3baaddd7568b641e4ecfa9169fc13cc83cbb85ae2d89cfec471a96f7337e2dd31138f987293ff749148801363ec094 SHA512 63e79f3702529c296f5622db2186a22333ae30d3810311d16f791df39cb83eb25a158cd1416927e2ae93333d6388697cbf8b16f08bef2f5a70adbd32eeb9e0af
-AUX 5.10.13/hardened-patches/0014-enable-PANIC_ON_OOPS-by-default.patch 966 BLAKE2B c59fd4cc939c8a8596f97dc580c0788379981be28b8b9bc2f4879223143c2ac1898df21f033c3fc34840ff1bbbb92beab1716225b0820d56c7a72b883f5995d7 SHA512 35b67fcd2061aa804154b3bfade833209425ae42df75dc4a763c43c8c636b5d52cf3d2be0c2c410391c6214e89426af783d1b2f1bdc127d2b6c26a61a69e9442
-AUX 5.10.13/hardened-patches/0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch 761 BLAKE2B e2893f624213216d853d891260971bca90d776871c8bde6ef3da97f48a52a740d217bfe4fc2a2b5d5756238efa1401a18cad063e8d040e892caf7594d95aaa80 SHA512 90778e1d01a4ccb20871d99b4a2c06ddac1e5a20c41a03e92cca4c651025024552c3fa4951994a29f1efee1e4f966245dcc55d63e21934e2dd4c11aca529b4a0
-AUX 5.10.13/hardened-patches/0016-stop-hiding-X86_16BIT-behind-EXPERT.patch 666 BLAKE2B ccd226cbc0262389477a0a74dbd6eda129a10500ca87d12f0d5a6b10ab8f09dffdaafd8c7389ff4033407f3ee101400f9dd12677330619c08c073be475b4bb16 SHA512 17322c22dd373055345c117c5ddcccf8be3de05ac3ff44a8b57c137cb9b0e6c94e81b44efb9fd8889083495da219fdeab2992ca5bffe0fd2957d493abb1aa4c8
-AUX 5.10.13/hardened-patches/0017-disable-X86_16BIT-by-default.patch 678 BLAKE2B 7f955ba8bada00ec5f4733d68a70e66fb363eaa1f416b74bdbcf3bb93bcdf9225c8584a02683d6d6a19f4282b4e6f54473418711b8393f543288f0bfa0bac507 SHA512 cf8c501b8cb576c243b3143f2c9abf24973d684e2f7f99277e1e923d6a01b54ee986d30c1abddc8ec758a7fcfb843436cb092145f506b4c0218775f8fde2ad55
-AUX 5.10.13/hardened-patches/0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch 754 BLAKE2B bc720fa0bb3d620870cc387343adc8584a9e4c70b971637d4d79dafeb3c5c79be143ac6eef5c38a022029090e5294467199e7d6bc6bcc98f16e66d0bfa57f12e SHA512 77b2e26a85dfb72aa7fef8029f0dbdc1ddd514016cea0bc2dd1022ad69c7586505273bc8081a3972f8853b3dd8e93363bc516535c6c19e769ff9f9942c1abb8e
-AUX 5.10.13/hardened-patches/0019-disable-MODIFY_LDT_SYSCALL-by-default.patch 802 BLAKE2B a2811c4ace54206b4e89cefc1d3c8542b575d4742853718da9003b278ef3a8783cc2a5b6e24abdb6466bfb0b8e2264a35be060ed2f5be424145714949987054a SHA512 54f92e5a6ce513f8a6d3181721f064f06389fc3dad50a07e439c7e97a728bc84a4b5b0f60124ed0b66b5c79251438ce35471f0cfb33ab154d208a66a29bed9e8
-AUX 5.10.13/hardened-patches/0020-set-LEGACY_VSYSCALL_NONE-by-default.patch 765 BLAKE2B 39ea1e7339515ce36dba14e0ec7e1982d74a23cb020521fc5aa2598c64525726095631dbf361128f3493e1d6bf853022d832e01f47a70e41e91ab175e8a74b99 SHA512 389900f39aa2f93a72dc43cafff54039d0f85dd65dba009421d69e31fa85e8d2389c9e233d66964989b4de1d6db8926a7c8e4849c06890073d8b4148cba1a34e
-AUX 5.10.13/hardened-patches/0021-stop-hiding-AIO-behind-EXPERT.patch 691 BLAKE2B 86b3c14c8971f30138754f385a8e743ea532aab3ae317ee67b13ee1826058965ae11cfe748ced6ea892dfefad9000e5aac24eb3a4d761cbe890fb928836791aa SHA512 9c02566c735a9efb2d2d0679dbefe580c65c003c685ffb489b19e91ee031152e79a6880fec1afe02c4b7890d0f7fca94ce0175326561e1e2a387a829ce041da0
-AUX 5.10.13/hardened-patches/0022-disable-AIO-by-default.patch 631 BLAKE2B 02f409c9ae1dd53cf82086b7c8789443e59b08503c439ad2c019c55eda2da6926c77d29cd64c95fd58ede64e30d92dbc0f583e0101a579eee8dbaf459fb89f2e SHA512 214bf009dab05cdb4db3f4f2e45e2992d29c363d4f95721d69a87720d894ec5acab19beff0b92950b501f51334daadc61ded0116d84553a147ca0b41664e4252
-AUX 5.10.13/hardened-patches/0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch 962 BLAKE2B e6bb32327a83f9fcefcc1a75485f543d1801b812ac43b9dce3c91a4c4226f254a4feb815bdd3408d3d8a09d52c565e99fb7d14407277de784ec2d5c4f5bf1136 SHA512 b7f7c7e0728f60a1472f1782795b8831f24bb7d3aa8e340d97e09d92f14a2aae524a568fbc46ad84af2c2263ad87e643aa12184621aa064e141aa45ddcbd7852
-AUX 5.10.13/hardened-patches/0024-disable-DEVPORT-by-default.patch 695 BLAKE2B 709dd45f36f1a2032463431de19cefed5aed685aad94da287d156bee75a1ff544946d210aea6de8faee1a24be65c18e51e8b64346a45aab94a44de7e73033a4b SHA512 e494ce4d276d31b97a169624141b4bbb5c30f622e6d864aabc71b16a3c7e1da89438c75ca73750d3788981e4322c667372e8712a04d62e42df9e186f585b289b
-AUX 5.10.13/hardened-patches/0025-disable-PROC_VMCORE-by-default.patch 613 BLAKE2B a7c1fa67265f9cbeed1da5c0a8504fb91fff3962c81af2e8c25eeeb1391e9b729d7ac7beb03a30ab9b05c08d0524c392552092e1d73ee51d298bcd7b16f02557 SHA512 1a64ff3dfe94f97fe468cc6103925d4b2999b660af6e1d72f6b569c3dcf67b4c79a2fa7f1961dbad6d4cfa70ad8d8bf1aa6b781afebee7580487a2420cb8cd93
-AUX 5.10.13/hardened-patches/0026-disable-NFS_DEBUG-by-default.patch 598 BLAKE2B d6555576fb217b84608f2e83ab4ecc6eeb8b0f88267d7cc4d84d993f903087eeacf2aa1dd84eca02c7b55755ee2535697f5dadd3a9529108ff8d0834e3f16029 SHA512 a605e3fbcd2eaff7dd9cbfee7de909891638555dc663715b1e4d20ae4180e12010537037b5f06ebf88378cbf2b50bee4fc5e3ebd6419bc13978f06c22b30d781
-AUX 5.10.13/hardened-patches/0027-enable-DEBUG_WX-by-default.patch 653 BLAKE2B d093280754f3490512d4b3884471f409428af26e70f766ad33312bb80f4b6567b24be20249d5655d670929528d909b774c91f21bcce62a8c992c02a1120d678f SHA512 f4b485adb459700c2c7f3013f73e5975d3d74e82f5e7f205b3689d111fffc1dc3439170a4e0049cd58b5722b5c4ca693d9481ea5981dbab6e8b2083709444850
-AUX 5.10.13/hardened-patches/0028-disable-LEGACY_PTYS-by-default.patch 683 BLAKE2B c23ff7faa6dff5af4c8ba1811aec96541f2236e72860c41afad0c4abce5221b4b919878e2026ab05a2a813fc2ef0589fee70acc8b683611807c481518102347b SHA512 4fc9188343ab0a0e99ec5a9a4d25844fc5ec564a273df4011a29bfb16431ab2ebe5120ab86ced1dd6499abdf4090c63c373b54d3edefdb2bdea4293770cbd6aa
-AUX 5.10.13/hardened-patches/0029-disable-DEVMEM-by-default.patch 662 BLAKE2B fc36e504f1bfa5cfa763e8e446ba45022af596129607566fed6ed7f4e671614801a468d65f3e1a3015f839b0927ad4de6fa2053e0c6f63ac04b2205df8d42a4c SHA512 d4100d1c11e7d1bf9dcab25e62ea5b17374ae1741da15f7dbc74c3af2b98292ac481ba7d1cfaf301dc77b5513124c9cae9d5da4c74695de467f047bd2619b3a3
-AUX 5.10.13/hardened-patches/0030-enable-IO_STRICT_DEVMEM-by-default.patch 719 BLAKE2B c20a5b170e5fd5148ee776b45ea84c7a742f7b71dd234ae03e86461262e552af3ef4ce32f951a862784317bf36dea3fa421a2db1e2ee7adfa942e2f2cd6f6f25 SHA512 395b5508e343bc6a7a92efed2ee417ea644e5f4d279ba948cb0a95c7a19842989df31f3fb83d1bf1700cf0f5d1155729dfcd997174da16afcb680d0fbc59da5d
-AUX 5.10.13/hardened-patches/0031-disable-COMPAT_BRK-by-default.patch 652 BLAKE2B a11063b2f8222b29520dee9bfa4431ba6aef8ff11c81cb9f221a920716bac29125a6dc57032b3490ddc3a34cbe20450f25e11de9ab27b1e4743807b13f638fd3 SHA512 a317448879ec3cafece4c6aa27a6c5631142a8e0d51236e3e9d101cd6bb0961627ef9c9b86c5c6a2acbc7c42277e713ffe6455c171aa4556971cc3d48f4b04a6
-AUX 5.10.13/hardened-patches/0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch 1397 BLAKE2B 0e279151811d14d35230858acaf0fe2be92ca344209b77b1177ad1df6dcdded7d784504216a038c74d9cc035adc2aae1d0594b18a179b96f013c539931dca9dd SHA512 06f2d0a2fd139bb5861304f8125692ac2e81673dc6ce2d15e695c7628dedc2e9a1d29c73864934fdea0cfea61d5ddc3b58762b5bd480c15dfd8d049f2d18b642
-AUX 5.10.13/hardened-patches/0033-enable-protected_-symlinks-hardlinks-by-default.patch 818 BLAKE2B 77018a473bc85f85250f835e416f532191c06591d3d5c6044c5cb0489da831ce40a5f4f7427660b27977058296203189a316f367f943326c498d8432a76f72b4 SHA512 acc95ebd557767d98ec055df29f73097fe3129929133dd8955de9a61f988cc5edd621ef21096adeba7c706ff133b438d6d8e07158a29d656b03550e1a96f79c8
-AUX 5.10.13/hardened-patches/0034-enable-SECURITY-by-default.patch 646 BLAKE2B 2c6feb548818edbecd84b5768f8420b486040bd6197cc52b2d2486ba841b088171195124cdec25583d185eb6e8fb344a5362a350a4ce059ec79623423cfd0f6f SHA512 09100fb65bb6832e1c5f0e3aecca2dd4c34ec44f545d7ccd8a38564138575362e9401a8fe73091e5149b2dc0ba8d34bec0f15a164e6686ad8e6248d96a85ff35
-AUX 5.10.13/hardened-patches/0035-enable-SECURITY_YAMA-by-default.patch 706 BLAKE2B 1639d21f203e71e6726b23f9f4bb7ef41b4cad6a75b1707a8670d4dff8a494ebbc1847a18b62877abed26b5858e2ddffc96369f3ce741129927d4560658f8e97 SHA512 81109e2f2d366f8183ddac40de91060377a50e67d38df83334ddceedd2f389cc75d537ffc7ad26dd9e3bf85543f3bb0d7f931c31a3880dfb0b5ee1201a26ff98
-AUX 5.10.13/hardened-patches/0036-enable-SECURITY_NETWORK-by-default.patch 685 BLAKE2B cbba761799a71262a5e65caa5d791082ed8476ffbb4ae02bb00e8710cb53776fc15ede8c5e3774f020e7264e5764b900c0bc5b9ff2ab6614e52bbc0f310feae0 SHA512 c5e68b6bb0d5d3e78fdbd1d28414d2789568e702a6684c4f8519672e5d50e3175b0a2bed53b2f6e7458c6f40fef8ba95da493715850730131c97ce3f1c128417
-AUX 5.10.13/hardened-patches/0037-enable-AUDIT-by-default.patch 628 BLAKE2B 7bbf1ad22af9b66427c5dc1a86a5109114a5c35fb53e837a37338bd53cca091df2c334b8ec98471ae0d390d4f9bfb2df6111054076bbcd46787f089a00b1e56a SHA512 4133ddaf4d6e6021f3002813619d2a048deb8a41d97a29b1dfec3af7a50e3372a36a8e37b67421c3ab197fb74795bb3af4ccc1dd615180753700380640bf4afd
-AUX 5.10.13/hardened-patches/0038-enable-SECURITY_SELINUX-by-default.patch 784 BLAKE2B e4680319c1751da3beff6bd7fda39bd13ccc12fd27fa41566a5a3eb28a1154dc57b2c9070a82c79899a5f31a4d6ec14cf458b595b0c3791e9589044824b9cf2b SHA512 3ae00e48dd399c02c484150a1689dbb3d79112d4d51bf7de79ef5ee77f5727a45510cc29514db705ce6463bda58237e0c470f817956c9e9a9550805cdc1c781a
-AUX 5.10.13/hardened-patches/0039-enable-SYN_COOKIES-by-default.patch 666 BLAKE2B 2e43652288dee79e8eaa18abfb8065bbf2123dbc604d43b94e7b24e05c865db41347184fb306f2a06459eb06105c4496f167a939678c46f1bfbbee983f9faa09 SHA512 5919f0055d077b651a6f7bf4324d5b55318dd1399036575ea59d0170d8b62a57e79afb8a97d59a809c8b26f821ab8dbc9e41baf409810768cbbe2b813dd92dd0
-AUX 5.10.13/hardened-patches/0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch 785 BLAKE2B e37d5653fba0ceadc4be64cb598d76e91082f612e9d0b2e3bdc2c059aff10f347e98c23aa7d1d0d51a8f888045466e7ee741385542dfff301315f34fb639465f SHA512 14712f6209062aa2211e2903df3e4623d498690b72222eddd8e2901550adee31d707f3c62936a9aef678e866f033f959b5ada29c1b6fc42033413514406f4aa6
-AUX 5.10.13/hardened-patches/0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch 774 BLAKE2B 7ebfed15a2749359241fe846569dfecf25433a5503a0e68cf501a29d2f09f71a6e3c36a3f6636f7dc3b3d540c648c3373de41f1601fbca20ad31c323c769f31a SHA512 e1c7b084ed56e1001fed6723d76d4ac3fe9447a93462f6bbd39e575311fb6ce4aaa94a7ec52663c94b3416f4d42b13ba5c372caf3eed0a96cf00491bf52c07d4
-AUX 5.10.13/hardened-patches/0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch 827 BLAKE2B df605131e42444a5b2c54c2402b0f5b8d5355abc2e38567d40005b7eae53fa7b0949c4d8b2bb4e4cefc4f53c265143013b77dba2a2ae7c0c828377158e39734d SHA512 22aab6f0bcb8dcc356ecd6897b61202ef0b40af4dcda150614d54ee25d33bb3d3eefa19a0d5e15217213c824e00922314aa853a42a513da6756282993fae12de
-AUX 5.10.13/hardened-patches/0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch 705 BLAKE2B fe7c98fb16258c0fc34f74a8d653b5c76ccfbb4be546ab501a70736f4cf09a06644676f209573fd64a065c82948aafa0cea5650bd81d4f3dc13ffd9e2aff2320 SHA512 4b3c143165d96c0a19fe221a15b82bc7f04da6bd1186d5367d484110e93c621df57a2b04da0c59ba39939452aec309cefc16d3fefafce7b5fc9d2b0a67eff5fe
-AUX 5.10.13/hardened-patches/0044-disable-SYSFS_SYSCALL-by-default.patch 835 BLAKE2B 957133513de18e23a7af92c5703e103831c2ba3234087103080458ec5eabab3f013bf93d95df47b3a9dd2c6cf02dc8959fe921e346352606a66275f440616572 SHA512 61179e8238e3a0586a089130c1e690b300039e80132cdbfa5e61a9c74072aa543f2687ff90f3da6fe5ea99f538b228138deb1f09b42aab6545db1985f97e9f52
-AUX 5.10.13/hardened-patches/0045-stop-hiding-UID16-behind-EXPERT.patch 679 BLAKE2B e220f96afc064e3e184984653a3ca2d1b33394d53219f4fd0a1eb8caedab9de961981128d3afd3de1deb1ba061b07ac7ece8f41c7f034230275fd6bba966b4c5 SHA512 8070f011542ea47b680e53e03390db26849a161c24b479a707ef9188823598d61821f3cd6da28db846fe461f3c147fd86fce36d701b77cc21be2e9476a7802af
-AUX 5.10.13/hardened-patches/0046-disable-UID16-by-default.patch 605 BLAKE2B a9d034bbb206fa92eb489a7ad07ce11ff08433f632b25380243abbedebf18c9f22b53e621e19e19f4d00261270022e78585d457faeb1ee3e5af1372273439d55 SHA512 16b51b2c2c8c645cc22f1702d902741893903ed5a5b91ead757f4db9a43aab3cb2799f6f802eff4399125ed25d9593407ed967680e028d94f44da179a223acfd
-AUX 5.10.13/hardened-patches/0047-add-__read_only-for-non-init-related-usage.patch 697 BLAKE2B 58daa57dfc54a5c9effc7848c5cc75e14652a8f32969396a9b9046d115a28b65e204bb425b275d56b073c33a567274c4637f1e43c1ed025884c0084ee587e81f SHA512 eaf3f955e398aff305f94e5fcfa55d86e675d9e7f09d6d32f80b19cb406c068fa5b5941ff5c5f1f27233430850a4554ae03fc1901495546d725a477bab8f2e5c
-AUX 5.10.13/hardened-patches/0048-make-sysctl-constants-read-only.patch 3971 BLAKE2B 8273e7d2ce05d26e5be0e8cd3e56bc469a2746d9fbdcf5f92a659b6b157e8007b37817db9c01fa91c43ebc6656b6cee89eb72924a8eb67c2044e2d153798a9aa SHA512 80b6f51a5b732e9d2f927e483ea27d9f8a8766925e939c5c39fa5a7fe4eeaf1cf7ff8797d29ffbfeb800d0f468e3753411cb6eff83ec3ebb54d3aef1cb3b0186
-AUX 5.10.13/hardened-patches/0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch 2089 BLAKE2B 49dbb022d028007b769bd1de0536ab1ded05c875c9d4102384cffb06c3eb6661a53efe4328a055c711f804ecd56ef4088664a9b22c1800172d395cd685f7c649 SHA512 4589cf5184de1901b21a89950ad2b810f9d9e361ebca7e7285b4a49eaafde1cf972b292b0196f0dfb5ec2c69b3c5e9e0f5be2d35db5101756f6f9a70fb18633f
-AUX 5.10.13/hardened-patches/0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch 2171 BLAKE2B 7f0244b2e73496f5a816762dbf643a9a9dcb7aac1ee9c891b0f8a1c9f543dd829ef92cb285abc444bc1ef14fa6b99f2f31847dec5ae9076d552fc2a79c775f7a SHA512 db18a51626138940f867e4e9309e6d0dfb7a6d461f08143e3c199f8174417f2d5bc0723d2ae9693df5df2e8f67693073311f9a29a8c568cf1dee7052e093182e
-AUX 5.10.13/hardened-patches/0051-mark-slub-runtime-configuration-as-__ro_after_init.patch 2004 BLAKE2B a260a771772e51aaf7236ffbdeb09637937b824153285a539d2b54a0a603142416263f4836ab4b6f7d8fa18c0fa08942f0907d6260d8728663214b012e61123b SHA512 3feb0c2f0763ee85be2ce6ba5748b8a43c2df616f89e6cdfd590a5bdaa961010f15507704335a6147dac0c391adbb7b2f411d848631b1f9f602995d97ca5c0cf
-AUX 5.10.13/hardened-patches/0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch 1165 BLAKE2B 33d7b9ab6e52f2d45e6eb3ba106bd87400f5a13f52063dcaa9dcfa7ae0917c7996f3c16592e89cca1cdc9d675ecd8641894f44edd5e17a569b36c0fe7b65de02 SHA512 81316345449f35512b8085b57e4c82b9efd0068a2f8c9ba7a7515e780ea6147a338bbb813f1281714cc607dc7e218e0b1ef8a93d6cba86ba2748c712ddf3e5c4
-AUX 5.10.13/hardened-patches/0053-mark-kmem_cache-as-__ro_after_init.patch 709 BLAKE2B 1957f637fc75bda1a4f495172c5a7fb115438846b0d3425736e751a3a7905e425d069ac6ede8568d435ea7071fa8795b969191549139f8540a987390b0c5027c SHA512 79eb682165482d3e4e4041e4fa3b8883de633f582482bdf039877fb67cb1c982f68bc485afaa47da6d3dfc4c0ea0fc29e98012326ec1db3a98676135bd326a59
-AUX 5.10.13/hardened-patches/0054-mark-__supported_pte_mask-as-__ro_after_init.patch 1954 BLAKE2B 0d727a9002adce44bddff512e74897e782223ec70073897b23319522bca8c1c7d482203cbd27fdac89e4ce7c1787f274a2c250c137441ab4582068a01850455c SHA512 904895c292d2b08b94215dae9551040ab96f44d126773760eb7a6a9cfad75d1c172b9d4b75153e0c5913fa512cc944bd0ee227b966550faec254a713f2b03e38
-AUX 5.10.13/hardened-patches/0055-mark-kobj_ns_type_register-as-only-used-for-init.patch 1663 BLAKE2B 78e0e5017b2b6f2d581ffcfd0a7c34b416ac9d68812c7f63f5f124e66051c48f081f2f6296b9b3a43d006702eec594f68a7910ca5de751da7cdb63af9c987fa9 SHA512 98be1eafa7c371e6eacbd16c2519e6c501ca728eb36c99afc7b3783fe91f1337d320f5b251f50e6fab4515e7d0fb716fe7dea95a36ccdcbcb06b2fcabf4eeec8
-AUX 5.10.13/hardened-patches/0056-mark-open_softirq-as-only-used-for-init.patch 1272 BLAKE2B 7279e9c96877a43341a81611f1bcd7a3a0ec5d09da4656fcbf97018729c0f67f5cc47c357568d38f609b149895bad6794a498f731f1498f4a61d14f7365a4823 SHA512 525cca315ec2aeba731a0cf4e59e8bc35d361c7fc1b8d8e9f670cd4c7699016d5d25fe39356f11cc7a6a989784c155503f89037f000553ed70a8b3bd6198e388
-AUX 5.10.13/hardened-patches/0057-remove-unused-softirq_action-callback-parameter.patch 7357 BLAKE2B 8c14093958ee78b194b049ad811f6ef79146d9355f28e2cd865248e3edcaddca4084711da1a37fb2a52e75b8bd9c9daa302778190c7a0bc82cda10651d5ce985 SHA512 b56bc3db68517329bb05b785908d037fa1b9e47c24680cb446717fd29479f56963338b56bdfa440bf79af38d22df75edb900b0bf32e16d96bd35a1a75bdf14a9
-AUX 5.10.13/hardened-patches/0058-mark-softirq_vec-as-__ro_after_init.patch 871 BLAKE2B ff8c249b2fbf303654b695867bb1585b106aaecd36aa13439b1d689de58515428379b06593e594d523e5c4b7aa03875d3a243921d76ba150e4fed464b8c3a149 SHA512 78fab67f6fd40d679bd49b903cb23f8c8b41b92d9fc95f9a214bd46cecc6c11be225c71733c4c4aaf75fb0062821d58df17d08e39d2b273cebed01eafa6194e1
-AUX 5.10.13/hardened-patches/0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch 947 BLAKE2B 785073b1a53cee070cbab2e3de4f88199ca7a19b066592836f982a7135c359f25f02fb18e30bf5a9f4ade95bb47803253449a0fd1742ad869bcf39225d174a03 SHA512 9cc3b9ee7d7c204c26b219ff857c53b9035a68761b49ddfc66c0dad8a2a924516cedbb3606c018145fa9140eb18ea12150d9ff66c493189348aa97a83ff263dd
-AUX 5.10.13/hardened-patches/0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch 1180 BLAKE2B 60b981b2221ea72ee33559869c6c902093031d584f714e14f7e2d0df032bdac286c246af66dd746b62e6d744f15cbfc78273bbad122c57329cb9f9774665287e SHA512 0985b57de96b96db9623cd25c1a7a0b93189cfc0b4f3945de30d7daf2be6ff8795d151a6041771c0a659ff49edeb32ff57c3250179d55384482e83670afb4b58
-AUX 5.10.13/hardened-patches/0061-bug-on-PageSlab-PageCompound-in-ksize.patch 788 BLAKE2B 73d61d2006e643a563e0a245e51134e19ab8cb64c987d49ef2550c6f02d2e2f2c34fdea4bbd0f1b3c548c2aa50ec014e3ed9ccbd1c58458345f1ba0a20707d22 SHA512 afe8131acfdf4651557d61c40e6a77331fa5bc9a8495661af498e2956180af8185f477b71996397517607eb7621668de67c8e19e37f0232471801a536866a88e
-AUX 5.10.13/hardened-patches/0062-mm-add-support-for-verifying-page-sanitization.patch 2256 BLAKE2B 076757e10877845dc20c1c9f2835696344481b3eb6b7b0d8296b76cb7d84adc913bab72b46ad0a7e698aca2ce26bd3d9805568bd7bce1d9194eac737adfc95ce SHA512 4e6399df0a4c395c110cb3f0b32c6e2531782ee878c18327a6ff7bfb90e9a3aa7a79c131f035337836b19a1b1168a925aa87f662c6cc8ade0ab95932c8d327d9
-AUX 5.10.13/hardened-patches/0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch 2454 BLAKE2B c575e589c071913a15e14e07f82af6eee6c7fed4adde18ae2597fb60e80a53bce19b62be491da3fbb52adc787c492c605fbb868856e868710e270e97a9510450 SHA512 2300a77b709e34135da4fdee510357b38681b09755e796113f5f208ad317e83d7b019ba3d057fea8447dd9311e0c605d3d38af77d4f04a5e2f85ba1969a3b155
-AUX 5.10.13/hardened-patches/0064-slub-Add-support-for-verifying-slab-sanitization.patch 4020 BLAKE2B 18fb888858012e261900e53b87ecc2d3b946d53f3d26a83b4051624be3a49db23421423ed4c2c9bd6426de40124e52f510c77c02df00d564e014d14c048dead5 SHA512 9ac1585cc4e0a79dd2aac6173766de968662df4025596aa74b968517149bb120fa076aa3d53b19426eb9eaa20321d756c61961cbbf28115695e4d53373adb3b4
-AUX 5.10.13/hardened-patches/0065-slub-add-multi-purpose-random-canaries.patch 8811 BLAKE2B e5b5df14cf1bc43f571795c3526fcf301bb5d416397f2cb9c2c830e269c38b8bb486b9374927c0ec5d8e615ac911cecffd83dac17eea06a5dfb8f6d047fdd8f1 SHA512 7e2bfd646d687c1fcf119189d2c2c059f5730a2877b14f9908cdc33a35d0bfb99e68da38b90363c5685298cd80707ca4fa09cce282f79de1c0aa1fbeff1e81e4
-AUX 5.10.13/hardened-patches/0066-security-perf-Allow-further-restriction-of-perf_even.patch 4744 BLAKE2B 69f7fe4d990d6f159f61ca6ca9ad4eb8a9fc4632274a6825acf831d75e9beb4524a8b8f38e0c44a90104c403b1b45170ad318b0593ef856d13534ac38bf374ab SHA512 3dc336e54fbe812d8e700f25227f1d0ebe89ec20a120659c8773d1982b897837a6b5bfccc951ef88ee25cf59ce5dde01839840a5bd01f65b1add4e30c64b25d6
-AUX 5.10.13/hardened-patches/0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch 798 BLAKE2B 5f4bc3b1709dc5302004a6e17f4f78f2a646b839f82adf5facb07ef0219a239cb505f4eedb95ea417a06d75315abf287e12bc8fdb9ef7775f3a679186dbf9c7e SHA512 2969a47a7c7a929fc3a17bdc4456cf40b408aa8e58e73c47dacd4b5b77eb02f141ba03cfbf40624311396014b1226b606ffa977845da800608b4172db3ba280c
-AUX 5.10.13/hardened-patches/0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch 3791 BLAKE2B c1d0a1949a09647079521b90e58c12da63da14f1954aace9acab05c82037ef89c427abc8b257a5aace35bc5e8c77aa9f89aff495d61f43acad25f0b52411cf20 SHA512 ccf00c57467990d56a62b8a22df409539aee155f95ca28fd5c8c120f031ecbdf32269f0b406ddaeb98868ac284205d8617a05e34f1602469fd8b4f508e0917e9
-AUX 5.10.13/hardened-patches/0069-add-CONFIG-for-unprivileged_userns_clone.patch 2070 BLAKE2B 6ae81d5f14ed7953c961f1d30bf4c87c86b62e9192257636c0ccb3d52966c5dab6946bf4dda52ec9ce02c06dc71bcac5e5a46221c9d53093b4a1f38f21417100 SHA512 7e2520a61eaafb8ff0f50b9c22c50c784f3afe77def13ccdc6ce030af629382afa3a27a045b79276975e125c89684b43afe38148b8c552cfab621c528ba0a0df
-AUX 5.10.13/hardened-patches/0070-add-kmalloc-krealloc-alloc_size-attributes.patch 2735 BLAKE2B 9edcf7104d5bd9f11acc91593219f81176fa8ad3c7dfe9492d3e2682bbf575461187955076611a490eb21972eaa49769ed07b6e538515611f1c462701b9db26e SHA512 33d94ece1c681ac0e105a23953871e69543df05243a71852dc472e037932db3d8006faacdcba1a862aa9997f6ccf7a7c7c6c0d929f37c7d7e65ec0327cf79c1b
-AUX 5.10.13/hardened-patches/0071-add-vmalloc-alloc_size-attributes.patch 2249 BLAKE2B ea003015c0cdcb89dbfaea6368712bab52906e4ff045bcd5ca1e955baedb41b93d417b4d8fe800678822c6d4a0d72c031926717e2d781311cd567126f2f115b4 SHA512 2eb14030deae8480b13399fcdc07ed9691875f88da4eb57db117ca64498651e9be9586b2e4883d2450c48b339ffb893f08b0f78d85273c0014efaa791aab6559
-AUX 5.10.13/hardened-patches/0072-add-kvmalloc-alloc_size-attribute.patch 860 BLAKE2B ca8ad8c53354206a8c914d241d2ba44b6bf12d700c3d092fbf11119dae49f65b4d1098c198068ae881f1a77c875521f71821a7e761f544fd2c7d2345f3667fb7 SHA512 51361d144aaddc622dae0413d3c474ab9ccfe8e03ec837473b6d8c1e736b2d5b1ad2629587822241129fdacaa202e944c182ee9af4105ff8cf46f18748ec2f23
-AUX 5.10.13/hardened-patches/0073-add-percpu-alloc_size-attributes.patch 1588 BLAKE2B 9d07d9d6ed92e81acc82beea9ce82b907098b4e8bfa8bc44d83f0510d0250de6775d2b48b88cdcec57e0812c9a0421e2702996af48b60228b082ccbb1dedd103 SHA512 687430472329cc4b2b93cab8094354ef95e0cde6608993d1b647459b3bbf902fbd1dfb7dff53621a28d9d93806b52ef94330d3609488b70d9c1c86c96eab83d2
-AUX 5.10.13/hardened-patches/0074-add-alloc_pages_exact-alloc_size-attributes.patch 1259 BLAKE2B 8086efd9c041d169b13177032fa4bbed5501cd6ef3647c0d64c54ef81542237c7f93d90af267f897ae7cd0e705e64e1cb54767ebf72892e02b78cafe8cf3de22 SHA512 84526a71aba59ff9a395fc1be37e434049495ec960c657c89f931d3615363263d92d26e31469ae549760548217721945491021cbbc54cad6a3e6a8f263f3c2fe
-AUX 5.10.13/hardened-patches/0075-Add-the-extra_latent_entropy-kernel-parameter.patch 3591 BLAKE2B 223a9d0aa677ebced49bbf8aa0bc4e56b0b9e735d553ba4cf52c04f5acffd94d5e7c55833bba8d36db76ae284ea07d138a957ddbadaed943953d2901e5603e11 SHA512 e666c64e0e81602c7f9df666b5dd237927b3404162acc44258229ee5580ce6b1d291dd1847f5de905d7e7151519072746fa9d4c45e620ca28507138c2ee65497
-AUX 5.10.13/hardened-patches/0076-ata-avoid-null-pointer-dereference-on-bug.patch 1191 BLAKE2B f7315357051ff89bb83f86dc943fe10d7f3132a34021c6fb8ed6ce2c6ae16df4266cc6ae7ea68f3946b8abdd19d84ee00069015194d0f7e323f51c3fa6ec8eff SHA512 74a3cf41ce115840ba2d8a707eae0c706ffc6ab3b83b875e8209180cd01bf3d10cc60013bc65bb40eb1f1efc0298877b75dacc9454e521152fe7c5059e8b4840
-AUX 5.10.13/hardened-patches/0077-sanity-check-for-negative-length-in-nla_memcpy.patch 755 BLAKE2B 43dd93aa7c6f497aa1d098fbc07243f4e00bd7918d886952d29d2c4bf1cb85e3aad1ef5203dadb3b45b1256ed7fff96935d9c8607256921b7f4a60894b814e0b SHA512 984a1c90b6bae2862ada94ed3e1ac48b3badca55ec82e99921e02695e45cbb175124af5e195edd24556af5a0a9f1604a2d4f42c90a993d80fbb587c64f1ca467
-AUX 5.10.13/hardened-patches/0078-add-page-destructor-sanity-check.patch 2205 BLAKE2B d06097eb17d8409167e5c8db231f2dfbb5fc63a835d30f8d373fee4e7dc9367bef10286100a91567fb287cd2cc675e749cd83cf3667e22fee23d3e04bcf5a834 SHA512 88b3558d5b0d10ad4f85461fbc29ec90eec47e3f1be2682b5e7bff09331b981afffef2bf71346de127242420315385dccc59072dc50a73ab034ee4fab9888e9a
-AUX 5.10.13/hardened-patches/0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch 1793 BLAKE2B 120c718eef8c985a321dd08cdf29f000da2d9fb6a33e7001d7e4f2013938026d07beed900ed510920a3607c254f50e3b27303057fdaec7c9562a5bebdab4297a SHA512 27bf699acf2e5ba1a6c7a1c0dee07d0104e5de7e136212e7a5c0d4aadca006be422c546e2e7c37a0d7b4cf278fa41113c5aec3f60afcb94b9f36f7d5a8d7241b
-AUX 5.10.13/hardened-patches/0080-add-writable-function-pointer-detection.patch 2688 BLAKE2B 489df22066fa9f4703ebba205c5b94d6033e63d88f51153c86a5c0941074d5bf0988fe4859186a2616f32ee2e20839ebab22681c936294bf879dc24e4f6e47aa SHA512 d1a60e26b16e224ae2c39a7d7eb0f2f56051e42ff1bc2448bb726f22587288a65a90dc2d20545386258dfd4afe6c0b5c90db61163f1ade59fa3278a087268642
-AUX 5.10.13/hardened-patches/0081-support-overriding-early-audit-kernel-cmdline.patch 760 BLAKE2B 308f3a96ef212baf58e6daa3fc8f86d35802201c91a020f2529f7dc1765fc02bae9461f9e460bc277af56c07d55687f9a7340f755bb76f1c0011cb6a3a5a4483 SHA512 f44b7133895d0c84b767dffb390a002c86711966b09fbb418a55986c144eb91407fa57dda04f5b135808bfe7308bdb62112a4ab2d9be17ac2de9d85534f7fd77
-AUX 5.10.13/hardened-patches/0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch 5669 BLAKE2B 257a4a3b2b239c1e04ac38fdfaf9baf57568f202b061ed64f4193be69159aa837fa105fe10fb1e2be8e57deafe70505ca516f7675a90421a1c665429e50f9399 SHA512 6330eeda635f963b7f7f4c973a607b9e6cf3f0498b16987518f68e242247d71719728787911e02dc0670685aab74a02241f4f99ebc2f2fb851c83180ecccd290
-AUX 5.10.13/hardened-patches/0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch 1986 BLAKE2B 08be0d398821871f64c1481fdfc49e02732cb83fd6da1753959d3813ca6625b2cb32cb58f042d671222e0e19d1b60384e496abbf50aef33268d77ca84819b344 SHA512 a60ad839e05532dbeabbd894edf906201932fce7734691d7f16ed4bb04aaab0e7cdd59fff8a7f05ae963a2258b7fa849ee23b50d715fd00bc28d3b1e00c566e3
-AUX 5.10.13/hardened-patches/0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch 3921 BLAKE2B 906c8fef3136600240ca9fa1896215aa5d14560ef647f770c470e847f3131fc3ad6b763c1925ee9296bb9ca4d486007011291612f4a8a42632004ba1105e0189 SHA512 c1cab75c805fa26f55ff40ddf63159e7833f5a541729b8309e2445b0254f6d82081fe59b93db69d4ee214d77e47b80bf32577780a9c294e468a455cabdf4259e
-AUX 5.10.13/hardened-patches/0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch 2502 BLAKE2B a65998852fa28400031904cde9050d950b71edc7ae685c348c2b3d77fbf45355bef26efb6734ae8a5777ca46e4d602b75a98012a72b5410909d85b27bd9bf055 SHA512 097d20c78267478996b4def275d13814edca04544415b67aa177bd2ac5f1d745400eaaf74c12b71224f6566b5b2a5eae05bc4585761028e3cba3b7e56df6bba3
-AUX 5.10.13/hardened-patches/0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch 2224 BLAKE2B ee89f671fde423cfe5db8744ab5cd84e96acc1134f4280e4615c1abeccdfd303c483f45e51144f634ede0ca4106ca71ab5df4a5df9315b98038001dada5f6e63 SHA512 5978c2bd950f1e3c4f9358e5a4f48a2eadcfa7bb7b2665004e516732c6818fd7785a2fc2422916a777a2bbe53d9b92abe9d2d587c19d9e44246f3ff7dc2424dd
-AUX 5.10.13/hardened-patches/0087-randomize-lower-bits-of-the-argument-block.patch 1466 BLAKE2B 249cabd5182b5c5cff56e6103b6c18e31433221e7793ba168f64032c03032ca1c7f8e7f0901d30bb8a6b7927224cd3698634075bb97317281011474b9d8c15e0 SHA512 04350dfca19c33d0bdee1a692d87bb7a0880e2381a1c4f73e95082d1154abaf514fd92d20daf8d76deb25a3193e3e6e8acd1ddb8e120dd397ce2c26a9fef7174
-AUX 5.10.13/hardened-patches/0088-x86_64-match-arm64-brk-randomization-entropy.patch 1019 BLAKE2B 179bf924841c4ba7caa6314daa1dbc5cc4b5cb88b60ed5439b656a022c57f29c568a793afe4cc083d611bc1d05fc38bd3d589c84e48f220cdf5c8023aaeac513 SHA512 d86d047c4af2dcd72d767c55f4ebd15efc563ccb2099586b3245bdddf58e009538ce5c2a0830b5285682a51fd7d99d02e61548751c4b878888bfcdf68c2eeb5a
-AUX 5.10.13/hardened-patches/0089-support-randomizing-the-lower-bits-of-brk.patch 1368 BLAKE2B a62e6103ed649262826695df318275f0ee9df487b6ee85171ec64888170f8c2dd5fe9f1e1e6f1d5f2bb87a3e49fad4248160dd6fd730655b317700c5d540919e SHA512 6c6b7e08981d04d7aa900d5e034ecc73171414458dbe7abe97f827577632fed3dfb9db6076f4e359d9377e2e90491e288f1a77a6e370226633082bb87fd7fa91
-AUX 5.10.13/hardened-patches/0090-mm-randomize-lower-bits-of-brk.patch 902 BLAKE2B 0c79f27474e68d3d670fbc97715b6a202f6183e1a2b108981dd3d19a7c542559a921e1c6932922b134efb928959899bfe40d99e5c3da4a7310bd4c87a1e50ccc SHA512 b6fdb4e99a7a81347eaf2134acd5bfba1d157b60f41cbbdab7a00c53d8019d6b9b1741b4c36032ab729a1266d44be54ac04f0e755b871b8f2d748496edf01da2
-AUX 5.10.13/hardened-patches/0091-x86-randomize-lower-bits-of-brk.patch 942 BLAKE2B 9258f1d7a2c90f694af7424184052027556516d0ca4160b0711d70b09c1bad5a959aeecd2d29bf7610b79ef65954f5769b0d7a51873d6edb1c6478b551c707d4 SHA512 95ae981a1b0ed4b687a557599d71a4a309a440cfe570e78f6647eeb85274c1a855884e8507865cd9ac56d9b670c56791bc6a3241edf6633767a89269a6812f8b
-AUX 5.10.13/hardened-patches/0092-mm-guarantee-brk-gap-is-at-least-one-page.patch 947 BLAKE2B 4cf37e255e8a349b87214326b153cc3d0e8280f52815a654e37ce6b9d1d0b1e966227d3b3fec6e0b08e4bc597f23e0f643e8aabbbdfb374eeccf2470941024d1 SHA512 e222962feef0cb2a71ec6b57b21545486a765b3cc1dc8f07a34a7510ae1bc2400fff4b0f0d0848d2d13072eb6437df3ce9c571d6e659d6b712a08077a4abe542
-AUX 5.10.13/hardened-patches/0093-x86-guarantee-brk-gap-is-at-least-one-page.patch 987 BLAKE2B 0bfb7789fabd6ed26ae7219522ae1c6edf51faa9218af8ebf90c031d6b568224fd1c3c257e13683cfb393af25f305b15f10a97b7b486447568adb98bc0fe5d00 SHA512 5ca09be711637741be202da3f0825aa950b32f47696aff83db506829f6c9bd076fc541f21bcc4ca5f39ad06002304375a16bc3c7dcf6fb4474fa07c4ee62aed9
-AUX 5.10.13/hardened-patches/0094-x86_64-bound-mmap-between-legacy-modern-bases.patch 1075 BLAKE2B aa035f4978df03d3a632dff3c368e4a12fed232f957fc63628c2970f93f086c78111302366e657238d270d47241a73f209285e26c3f23567caa726a4393670a4 SHA512 e822787332fd792cd87e545d5943d8f14a52c0323c6f3433f7b0e31f506a857d1d2998502eaa1453c9129a36e09de7eacab8abcf26f9de7b93cce94cbc4c2c84
-AUX 5.10.13/hardened-patches/0095-restrict-device-timing-side-channels.patch 5426 BLAKE2B 6a9136a51b4522ce9041cba24d6b19be039026b291109a1d280b2576d7591ad60c9a74efe852659386a4fae8e1ecd60e38f1bb194fede6179f93fa09864a75ef SHA512 20b24aa4da9a48a1fbd64cb08761a626a4e9a47378f2223aa0668540451408c7605a28a0e126694bb63394d7465854c584953bb4a8c307ce6728d8cf4bcf27db
-AUX 5.10.13/hardened-patches/0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch 3572 BLAKE2B cc24cfd9b71e42e51872fc8d45977500619430f44de44a344c0acba80af33eec9f72befb438e25da9ba8660e6b9dc756098e64fcd6a685f701364d548d0da0fc SHA512 c590254c9caeb695139486cf3c8740e1e60cdbec7e20666878ec3c0c2241ab81e5ab56e527f5d4927f69b008276203e2a31dde9a426ee89e6f282bff894dc5ea
-AUX 5.10.13/hardened-patches/0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch 2474 BLAKE2B 4d8b8034e61314d05e8a6410097aabb4fe0f41f4f7d49368d38981079d6ce798b23f9d48cedb0045d0a1fe57374ba043c047de61ee85a6346ec5ded40002f457 SHA512 ea82525c446b72b7719b42d0d02536ca1331c757d7f69efa8e825268a166e311d13232a7aa5a826bd3ca57248138008ea3f1e0049782114add8b5f785c6c82bf
-AUX 5.10.13/hardened-patches/0098-usb-implement-dedicated-subsystem-sysctl-tables.patch 5440 BLAKE2B bf4a6ee5ded69fe028d917775f573cd6985e6f2809acbf242a0edf8e88168ff848f45d844524f06e930129063de902e1e3b3b6ab0309c44f0128e7b0c2320dd2 SHA512 bdd4dd6bb55a6869ad37224a3de5593b7643845ad147934ffc78f43b8d27fa1ef85ead77f2207c95a56ed38bbfde0668478c562933ab1a5490eefb0394057b06
-AUX 5.10.13/hardened-patches/0099-hard-wire-legacy-checkreqprot-option-to-0.patch 5154 BLAKE2B 5404c83036fe17922dd03509152b998af85afae806bd4e29c1d048ba72f43c334e94786340d68e06d556f4b34f41f8b69996ec1233e5df97eeb43989373a4b0d SHA512 559edc0555887fccfa3732502c2d1fa99b5e0d17f82cbc203bf4db83580196042faa6ceb99a0d76d129ebf004538382e95a258911acf0838bec4f7dc2b5ee1d6
-AUX 5.10.13/hardened-patches/0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch 2194 BLAKE2B a31776248feeb6094b72b2ba286976bf23ab92a0d9292934694024c6f368305456513b07fd0725321706aa0934653749f5a14018f489d44d723a57f2b02d4142 SHA512 1164e536ac7709d34dc1598858d7aca163a78efc7cec3c71ec918085aa37129d624ff2d20f30d6753d4223d8e72e8a64d1670fc7ef29692b45d7a0b09d091221
-AUX 5.10.13/hardened-patches/0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch 6822 BLAKE2B 8332ad39f58fc7ea036a7570e56bb0ae0122b8aef898a525a39a52bf81d057b39176f6491640b144248c7fe612a1f86c75e949310a0b33d85afd25956faad97a SHA512 c701018def6ecaa27a80b6b9b071624521fd25238159a9c310ea103ee93f33c540b7cf40a93bda5a1f2cef21a87dde679d407b07cb12277eed97c1748f45cfb5
-AUX 5.10.13/hardened-patches/0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch 824 BLAKE2B bb3d7c00ab15471f50ed39bafceb52cc44e35c3f60c20d5258efac21d8f67bb1a1773d112ce4e135f052984b6490d3f6fc5989a680735773340e9a3ef4746647 SHA512 d81e737e81f89c4f65cf8349a3cbd89e95cd741cbe3970d898045902153c4dccc7db4f117d69d3b4902b22092b5882647753a0620fd3c8b5ff9b89ad5de6c80f
-AUX 5.10.13/hardened-patches/0103-disable-unprivileged-eBPF-access-by-default.patch 837 BLAKE2B b3bdcea4d9217ef61fd96d9d200685f67743b35f1ea03d0e525df2ada7a80d33e0ca5468f35f8cb9523c9891309f92b81b1c628a24fa63ee6a385720ac188a08 SHA512 e5081cc114866460994dfd809ed5dd166476687d15de8383954975ad4524cfb703814591e531576ab1501cb2bf804475f636ed59cbb1c66178ea8bc5fed6a089
-AUX 5.10.13/hardened-patches/0104-enable-BPF-JIT-hardening-by-default-if-available.patch 857 BLAKE2B 49c195d3d91420597f7ee857c6e5453a6e4c8ec190277d4ae845dae072c22704e5fcc8749ed7334bc23756a01c28cac28ee7a05e738461842de3fb60305c07df SHA512 63ea362c0b368c942f395157a89e82c16916ff8891a89868e987447e8156150a3d140336e53be63bd34cb1bcd46f754172bb961b498dabf4f0967def7161e95d
-AUX 5.10.13/hardened-patches/0105-enable-protected_-fifos-regular-by-default.patch 857 BLAKE2B 29872960607c71cc2db9f34c172fe1487be5e529b4d26238837581e822bc9197d1748ecdd2ccb1297f211ac617dbed4ab120d0af3ae293d145b273de4f14f61c SHA512 93753ee4bffcbf11d52aaae50824cf3093962fd252b6b1bcab2d97324934d5d51558b5086c318f0a9b2aeca4ccab7d4b4053cb85931605e79632c11c6e17fd3b
-AUX 5.10.13/hardened-patches/0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch 4376 BLAKE2B c5efe70bd73a7ace8eaeb79a4f9f1347af939cd09d940ade036087a4c58c7b9b01c0f8416489c24057ffad67a5356b9fe98d5a4a977d3d3e581443f83a684410 SHA512 824b0e8cf5cef8824d57b0f61bb631f6b7446cb7714ce15292e24e4098facce153b51f0c7067cc026d3e820d5732d2c921547c1d8f71c1100924c9060fa817a9
-AUX 5.10.13/hardened-patches/0107-mm-Fix-extra_latent_entropy.patch 3878 BLAKE2B b67bac3eb674ff9a9ec0160e7208366859548c8c8f06aa32317b257232beb5e137237633ad3a02edf37c331086acff300284f0aa727662f882017baf763f8929 SHA512 cd2f6f9d44a93f01d8c014fec59b96ccb80658e5f4444e93016ef11a4070d9e800d96e5baebf43a27d79f5cc7da6539498e26d9b1216b66ea36fc8dba78e5dd2
-AUX 5.10.13/hardened-patches/0108-add-CONFIG-for-unprivileged_userfaultfd.patch 2287 BLAKE2B 81a4b8b6347eb7cf4a1f1c3f26aa65eee0b9a0bef613c9dadaf3d83ee860ca064eff4a8d8362e8f286a810871aa09a6ae937afc282b5a757a709e0b5f9ebff6d SHA512 0953686bad27bee326345fff93609dfb3998d6c6031505c6e2a1f7cea0d486e0d75cc6788b5054a3859eba571d7ddf2905ab5e06b30c7b7343ef263d4e2deca2
-AUX 5.10.13/hardened-patches/0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch 2692 BLAKE2B 60ecaf551b537addc225cc0553a0e4e36adbacfdd76bc8b303bda85ca34e2a314468e61f6c0778710790eaf0d4122e8f7d83d0690e0d8268a9f6d4095c31aaca SHA512 74000addd7457353a1dba7a773e7c2eeed348ab5a5fa53e10bc0e384f03552bd0beda427a3dbc1e6dc3380fd701ed808bde525185c38e1a4a78d8e2f4bcf5eb4
-AUX 5.10.13/hardened-patches/0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch 6075 BLAKE2B 56daa5c86020ac6c1b210974bcff6e7cc336b97dfc51e762f8da9c68dfe3409c8d199b1dc466fd26e891aa71244e034cf3e09ee6de300efd481931d36b75cb8a SHA512 d4cafd292cdacc46c022f0484eff5a1b88178fbaffbf1f97e234f1ca5631bf816eefb354b9f2e4f46f1f16dacc8fb232260980cf60b9db5164f07d6982415c3d
-AUX 5.10.13/hardened-patches/0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch 8416 BLAKE2B 6a01bda897586ad9f44c76aac543d3a717b409152980ce09af6176fbab985c9948b26f3d65fff401a00d403dc393b9a723d54ecf605369660b83ef71955cba03 SHA512 dc6ff7cd53fd78ed9c1fdfeef19becfd12efba44f4d8dab4c1b0f8bf4c218b384f5b830c5ab5e4072dda4a26e8587c92c3f1daf940f67eb1a76375a24b30164a
-AUX 5.10.13/hardened-patches/0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch 1427 BLAKE2B 2fd45142b37c5e85bbe1aecee5f7f934d560b1da97bab7cf6a1c94916bd27bd7eaaf76f040a4bbb93d56a26d0c131771de4cbf256d6edccd00ccadde4a6382a5 SHA512 8fc1b9308032598ead61823e852606dc67a5fe52e0f99e165f0e7ef74fe1d59f001fa25b6ee4100b9a822eb40651bcd0fe72f0aad2c99971bebd0cf329dfd0dc
-AUX 5.10.14/dtrace-patches/0001-ctf-generate-CTF-information-for-the-kernel.patch 247058 BLAKE2B 4b73eff4320983d16b2148199d2d92a0ae7c2c04cca49c28239e611b82816efab67c9c01a7b1e9ee1733678665185bf2a40f7163b16b5963a2c4a49df6c76e3f SHA512 c53b0386de0bcca7a44f6f37c76ec93ab1e09eb098459d3c5a83ee902840758469117ac30a9f87ec152cd7710136b14b2e0e5875c59a41f301f5100e03866581
-AUX 5.10.14/dtrace-patches/0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch 33222 BLAKE2B 653922fba5b5ae73e2bc1e6c5e8f841bd4ba2d2c2e5b7b823fa9f3eb1ba495d0a781f58662b25620bc2b3b4c8a4df3b92801e93b3cdd39f3c52d8e62a91029ac SHA512 d370462e393bdcfcedde131f4861411200b99f7d8985465f747485def237767fd400cca612578cffc254af004e9edd28357e6b25189fad8be7a80bb25182596a
-AUX 5.10.14/dtrace-patches/0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch 28081 BLAKE2B 924d5977765939bea5690270aa2ec5a24de7fef611cb9c20f5cf9aa08d3aee1a495e3ff3546b2a80954f00016f5fba2a06d425e9b6671836459b24cd3fb9a77b SHA512 05e42489feef048b626e6b32e118207f0581f58745daf8c613666f62524a9a9c3403f700e7f531ec992bbf5646cef6c2379efd2f578c6da45a2e847804264aef
-AUX 5.10.14/dtrace-patches/0004-dtrace-core-and-x86.patch 280654 BLAKE2B 45ed0c03342e6095a85f8d1ea2a62da84612e09d3b267bd265cce2e373ce3a1887f8550165d4ade57b506939434280718f426cb7e8f36d4910972ba8fcd3e482 SHA512 712f536418a38230f69c4e0a22b7cb97cf8b67348068698974273fc19cbfc999847991b3d780aed759eabb313d17158091cbb78e377b6138ab5682368d6a7493
-AUX 5.10.14/dtrace-patches/0005-dtrace-modular-components-and-x86-support.patch 486448 BLAKE2B 5bd65c56bb739c640acc7ecbf8be1d80b89ed8b66f8137540f6687379f1c8930a279c51e9df2b66a00e4e37b5f1732b65d329235981e40eee5f8fc08290a7b83 SHA512 88ba86436e2e0c16e584c0e443ebf494fc9bc9114aa239e07733175275e11cde6ca5e8b77809c1599c649d8123352f5c92baeb00cfda5cb1ff103cca0bf661f3
-AUX 5.10.14/dtrace-patches/0006-dtrace-systrace-provider-core-components.patch 10421 BLAKE2B 913a09ffec28992a48ee70b9047c2f6f1111c37c1def1bcc34169b9b7dddee58314428087179f9a231f2dd247815089dd526e2739992efd8f78bb0a081cc474e SHA512 bd3b94340931149e92b432b930aca4b4066223313851b8c81067324ca295f3a4c7cbc24ac9517b8c7802ca7c7bc45a418ec0988c1697952c9e9d84f4f87dc750
-AUX 5.10.14/dtrace-patches/0007-dtrace-systrace-provider.patch 11423 BLAKE2B 5caf2b371ae6fa58d372ccb8bbdb49d214b5c63074cec0476852ea32af4dbc625032096b6db4336e0bd8b7286fe5b5d6c2e2457c59eeb9f5c564b89c82924896 SHA512 343b5ac5b2e311696c89fa685371d18127dff5548a56b8e71d18d561a577e5bbf4dc9c8f9b494637be00135d5ec4b33bf7dc84a711df753450589623da5f241f
-AUX 5.10.14/dtrace-patches/0008-dtrace-sdt-provider-core-components.patch 102862 BLAKE2B ee9b3b8683c1d24b37e1b7d7ef5138d0545b699df415a75ffc1928d5df5196170f0a60cd5d38166b9e417c5ecdb99517c1cf1cd72e9479a6c2c72194b6151396 SHA512 a735b5fdf8270a11df0aa3858a59c29355739dd6b633a97b528a97a7779ac909091c1be4fe47382ff66a5e4c960bbaa286fd040721f70bd236fe01e0107b3fcb
-AUX 5.10.14/dtrace-patches/0009-dtrace-sdt-provider-for-x86.patch 33724 BLAKE2B 49029ce6be2d7fff1afb8833720c6ca9f2d4254e151ccdf5a5d1a4b9e6935e5cb24ac916e81c7ab00b66766b53ff1ad6a62b6f7f33fb0e3b1e3dd4c118780875 SHA512 081230067584ab9904f6a245ea976ba9008a6acf1e2fe926c3fcfc5979c654c3c79b4b361e327e910ac295485c1cd4e6ed7226eaa069d35a26027c01d70bdb59
-AUX 5.10.14/dtrace-patches/0010-dtrace-profile-provider-and-test-probe-core-componen.patch 1482 BLAKE2B ea1ee229b6dc1a226335732fa3f8548b6fbbd46f018ece49b6a5acca562132049647b4fefb926d721122b287a5c666b20c974aee9806e1547d1dc3f2b08680bc SHA512 255ff4396e84d59fc1a757c9257e0e11ae9ea83c89564b9f4cbb93a2ca0a349874e5d61c97dd6ba82c7abd6ea91a8dd305190c3bac033a050bb1956735b300bd
-AUX 5.10.14/dtrace-patches/0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch 17899 BLAKE2B d6c25e8a3251c79e06dea96eb9f376476a1a508aff0e4a78562765cad690e4d053862d7b7705989bc807c562d65a4ca41236beed1724aa84d5d12f124caa27c0 SHA512 63568f1ed7bb3ea179cbc2d0a33c69955c0b85bf0b964fc56075ad0ba660c5da1a41c042c63f754c2e9bc991bc8ba59972fbbd2686d314144284491151970b0f
-AUX 5.10.14/dtrace-patches/0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch 11201 BLAKE2B 63a4416d108264d7fb0fbf2fea33f89785258a474d6d18c00e183207a5d8b56fee1c802e3a00c611ae04ad8e76f88ac6d346cf438bc777cc7f9d607e992468b4 SHA512 ebe6f9f15ffba602f1e36039b63a3b502872fc96329ea877d937db103d92b2af48530067936f38229acc43f8df3e0cce56bb62f2ebc5f5fa1738496d54ce0247
-AUX 5.10.14/dtrace-patches/0013-dtrace-USDT-and-pid-providers.patch 74034 BLAKE2B ca9564374935a859e2c1de6509806ab77a50a1dfb3e8fc64638a3f102746b4fc9d792c98209f38d6f81e5c9b2bdc988f74552a48d18d038d15ce70149322e326 SHA512 4859daf54677352dcf41e52f0b1fd4fafa0802aa76c6ffd68896942ca6280f869d9f88091708c915a0bf0e52a64793f6d6332d5b3e4fd58be3d30e8236cb7123
-AUX 5.10.14/dtrace-patches/0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch 56182 BLAKE2B 4d289e910edf48e6631c8aadbeb07bf0886c720d75104f315d8b4c5c4716c646863f817ba207ac1d6e384a5bc4e4fa487ef2867962e28445fc69877e6bece37f SHA512 7531d3a2f548f01106ecd024e8be03ce8b27ae70e178c19686424e9dc982f6fdb73f5fd317e4451c7b8ba8571646b15c4c2a0570e0fdea1c165e83d8880e99bf
-AUX 5.10.14/dtrace-patches/0015-dtrace-fbt-provider-modular-components.patch 20103 BLAKE2B ded20e58edd9df815dc4b04b940d3b9a8819e5838a6fab973b84eed90e316e18798555682f43ea05c4203781ed7dd00d336dce25e2890dbd413f1dcbb9016b21 SHA512 77733a952f8250722eb4a92ed71e20cac16120e72ed8a2b2e2717e1dba8df38e1f430ec9b185d1499f5c1cd9dc550a3d5369f438e6e9fc67348ce7f1b4e097f1
-AUX 5.10.14/dtrace-patches/0016-dtrace-arm-arm64-port.patch 77514 BLAKE2B f84c71a74942d5cdcef6103f35888a3a71323f0bcc6816d5e8c192adb9381ad628598e3f78e12a3753a7ed9f5bda937f08496aefda912f41d2d319cacf89124f SHA512 1f57a2f272457e3db47bebb6c64f8a7fd5c7847b1d87014202e20e6f2bcb5f608a80a38d6ac951e0ffb2e001577ee22a1a6b5fbe75de15cc66d75a71e37ba771
-AUX 5.10.14/dtrace-patches/0017-dtrace-add-SDT-probes.patch 107827 BLAKE2B cc92348d1b5a2442cfc21958e0abf4cc53c5fceeb27ed3c0cde00171ab34779faff252b90588f32c5cfd22a268de36a21f992c87b8cd2fe8d4f94772e6fbee4d SHA512 77b8c0e8e82e68278344d3725ef6c07282ad66b1083b858e220953005b4567bd909e151aa5d54aee802dc41b143328b18a178d98940e0ad18f86901bcb22317e
-AUX 5.10.14/dtrace-patches/0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch 8605 BLAKE2B c569da23290d9028e8cf161dc4ef11154c7e1b98d7fc935a976f58da968950b755797c43c8f22ebda326625775f2c196fe95548829b3ffc9ea1abd2f6fa1fd25 SHA512 2d17e532f5c871c2d85f33785feca7472ca078efad11f955a3734f31dd99999a937c1f416444a2f330f75faffd95e7313a9ad9c5e0a0998464fcc905850d352e
-AUX 5.10.14/dtrace-patches/0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch 2599 BLAKE2B 52e58733dc81f34b844b340ed29ac9a569d7afd784f1d15893a5cb481a92600bae57af992beec46198fdbdd6c17136f0632c58119abe4eb37c38795bc6c1e5f6 SHA512 3c45d39bd727265dea556751830f7848e3f36c33cc3860c4c06d5f6b21df3d09e1248f634e97e4d7581d1d6e60485d0d2d4a0341cd6c4bc161e7ed652debbc58
-AUX 5.10.14/gentoo-patches/0000_README 3960 BLAKE2B 264a1e288facf7c19ec01225f86f3be963b47037fc971acbbe30059f0d30128ff4b50cfd0110414460e2e1d3e6af9c73117787db0bda620907c37cd305a20425 SHA512 08adee7285fb29471ff8c9df17133b5b0f0f1dc66a6daa5c06b444b3654541986da63f82d72373ba4e8cac4b4b2f1b6914c4c90a5b187cceb9ace7fb1d43d1bb
-AUX 5.10.14/gentoo-patches/1500_XATTR_USER_PREFIX.patch 2293 BLAKE2B c2bde13ef40e7066340afefe55454dc933ac3b65dda4dcf81d9958ba84d9531143e58c4d35151d912bfe21a43aaed35fd99571a769ca8e823fc0d99797a96f4b SHA512 3ed100909f9aed72836a3c712e45e0116cd3c4331961a76a27b867a7098d0df9458387b656c9ea01385c3c37585436e48168ac35666b0e46dca7da05e5e38a61
-AUX 5.10.14/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch 810 BLAKE2B bb749b365f37988253206ddff130651e1042af49a6c773ba6f93642d5927af9a9926eab278979e048c13d2ca683e726a5d0cd509de9e6177d59c85197051e230 SHA512 c97a3799a2d5e4da9c9dfe129756da629fba8183479b02ca82f9b6d9993f17a165a96bd35ac50eb25fb293785b9b529a95165b1a2eb79c05134bee8ccf22a5d3
-AUX 5.10.14/gentoo-patches/2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch 1290 BLAKE2B 35f8f2a707da3bdb4df74844f72244dc6cb9fb0d41ac2034af61ce61c96e4bd472fb5bc5c687611356d06f3940e9f6669c80f4261165809592173bf5dac54b61 SHA512 dc47b18749d95a456f8bc47fd6a0618c286b646b38466c3d950dfbeb25adf3fc1a794e95552e4da1abb58e49f0bd841f7222e71c4d04cb0264ca23476ca9caef
-AUX 5.10.14/gentoo-patches/2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch 958 BLAKE2B 095d70ef085c6200b3ac69695339b8937e54b49c45acb7a741d0f471f66c1fe1bedf0b7df0951eff6ccd53ade10abcc66d5d2bca994e28a49d3e4296d7332e55 SHA512 4e637935c2f37cc18f347293e3c94b18f90e2caccca726304a95c4891257a5b2bb3093aee7a97571038b29c0c987cc60a9a80aefd0d4c9a063b33d102f03579e
-AUX 5.10.14/gentoo-patches/2920_sign-file-patch-for-libressl.patch 565 BLAKE2B ea33143cebfccbc5fdeab46161ab28c8ed6dbe265b35454659ba87f09705ed80219e9a9e47f7fc3df51292a3a7656c7a6d633e24a37911c35e47d039da530ad5 SHA512 79eaf814d76402a445efc961666a7c7c74207e552b0cb32d93d5cb828da580f7dbe93509dc9f53321c7844663205a8dce4e518ba047e4c57fc55f5c3498088ec
-AUX 5.10.14/gentoo-patches/4567_distro-Gentoo-Kconfig.patch 4784 BLAKE2B ccbb902ac828a26a69bda7f7eb7c69770bca7685ed5e58459e473b7a8ac0f396ac9f1aa1ee23a9248de22c5aebbfecf76930420b640cf6307a4d1e73bc9add0a SHA512 bf681566831b583537eda1df1db9c9d1b310cf54a974dcdc437c8da11b65cda423ac86a1a8ae56c84cfc947a6ad363adb25983e51933cf7acb494934c1ad3eb5
-AUX 5.10.14/gentoo-patches/5000_shiftfs-ubuntu-20.04.patch 55494 BLAKE2B 5c56cb45b70a340d6eb65140f3772f3c4a26e30811645d471d0db7a389c813edbfe6f46ed2fb5fa8c96596c9486c1040948d3074b4fc5ebdc8080c4b02b0992b SHA512 e832d44d4a450c45eb7a517d6cd849258985aed08349d18ea21cf4d1eb37dcbac9153f50ca8b910955bfe64169298c631a7ec7857e9235bbce0167d97d69e55b
-AUX 5.10.14/hardened-patches/0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch 840 BLAKE2B f872f632768b933e5a5a07d78f7e1160160f07301d29a44332a64c97831dc7184dd3eb8b5321b9662b896cade8a5a14bd1f0956a248033b36f5b28bc9917256b SHA512 eb0aa32286528531096ae00933da8302804f3560396c26414908e18bcbf32face3eccd9ff0ea7fe59144d51d4ab33a889dba410d5849e4134fc1da77ae574734
-AUX 5.10.14/hardened-patches/0002-enable-HARDENED_USERCOPY-by-default.patch 790 BLAKE2B 36e63c612bf5e2ca41f1c2fd47cf026bb11c34b8fd36a67e959ad4c594913385fa989cb4049806d3fcf6bdb1b0e40bcf48fe9c6813060a9dda9056c0a3ae7901 SHA512 b63d623bef827a6482bcbcedee937c8f331ded20687331b9bbddcd14e42e844df2efa0950eb6749e76982efce73c9aaa3c3086ed31e928773f115b6236caac67
-AUX 5.10.14/hardened-patches/0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch 768 BLAKE2B 0b11fbbb769c84644872f6168ded3b5c12a4a2d85ead43a658608020c9c9058a58fb37c2bfe4b0e516e4c498054ca2ec1798b86ec6e365463a56df1a250936e1 SHA512 a7bb768ae526a5fdcd2ed4a83e4530f345e7901db4003d8ab63bb79ec0e4716fa7ea13f7331eba7e85d3610d213e34e77d8c3444004d834c8681702bcd03fa9a
-AUX 5.10.14/hardened-patches/0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch 763 BLAKE2B 505c9e38f72c5a4b7ccb52b5784df0406c151cab2d1d4dfd9e936c180d4b21dc54ba9994fc1aca2b56ab657ba401b6c1046596a61a6f8df118a684506a2054b5 SHA512 e3e6a0ea0d624fe9361f1e49d3a5f5526955f3062d76514dfd330c22c89f2fc2ab532f85b7c1149dd01ad4bac75e4502316bd1c709fe3297b8639c6ef8ee9797
-AUX 5.10.14/hardened-patches/0005-set-kptr_restrict-2-by-default.patch 791 BLAKE2B 5930fd8dd7a5a98e211bfd8b43de5de4589e3fb275d3a7b825b052e220f772c6d2248f8a606cbdc6a28a790a35d4db7f42be02f8615c824f7a7cef72a6511855 SHA512 cd5b6fd8ffb21910ccfadfd019f13444ae059d41d02097f2c897336a909ff74fe84bec968e9d10f21404b4730153c2a3d380641d931b7d210212bdd835aecced
-AUX 5.10.14/hardened-patches/0006-enable-DEBUG_LIST-by-default.patch 743 BLAKE2B 620f63780d82da598e95d8055cfeaef333da80f50a8b10e08430346342bc28a744e7ab3e0d153fc9196f2fc1891e4b7a0925ef469b3cebc1f9847593f53b6af8 SHA512 29f43da5f488ef7055974b504a874034ebc89f3492da2894edc59bc82a6ba2baa36c6674639b6689f5d9f738fd6ea62d0088bdfaa33ab95b9a7efcef284c03a3
-AUX 5.10.14/hardened-patches/0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch 792 BLAKE2B 47f328006b7cb7c9f27e90ac67404d8c208a5ff5f79f0ef55b2cf8ea23dfcb7286b1514927eb343c27c0a8321fa55d932c9a0293c799a0236ef1905337bd6714 SHA512 6d1721342859fecf853875d619c58ef92031b4dbb6aeeda0b745b07095d22a34d4de577b5490598766e2545a7f24c82ff945516bc083badd87a7d40dacb4161f
-AUX 5.10.14/hardened-patches/0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch 732 BLAKE2B 028b7a8d9cd7fd94a2c14c2c3c4a940742aa0ee912cfc551c8c3255e3f521f686986556a332100d496d01138487784ce63faf421f68be1aebbe901d6005d00bc SHA512 74e6272dba59ea008f85c76e322ae1ddf3999d909f737b96eb63652cdd6980fe1c053751899ff30b17a4aacbf14ccc0ffed9da61f2ed6d54858c4f506cb24a4f
-AUX 5.10.14/hardened-patches/0009-arm64-enable-RANDOMIZE_BASE-by-default.patch 736 BLAKE2B eabff1e8717e90fffad491a57743ab8fdb97e6b93679b66d04f4fcf28a5f6c3b7e5073235b65f52c154b55ed2e4bef3cf32aa3d9f3fec0f979886db16ad68d52 SHA512 a633a6c646ef0c4172d7c734cf0c592e11c3fdd981d1a383af9e538a51f43a76986df904d2068352272a31fae633e94090f3c55d81265845e841202570cf8616
-AUX 5.10.14/hardened-patches/0010-enable-SLAB_FREELIST_RANDOM-by-default.patch 745 BLAKE2B 3848e4db317916bd5a83593e7cff4aca04f5afa8b85e7d37e440c49332a37318c47f19627503ac58fb05c6bc5fb56462f7bf14ffbea7eacef66218e712fe51c4 SHA512 82683219d37f70e78f41f62f036f9eef756695c4ce6be26e0ab0c9e4baa4a1b8d852d992cc5d817148663a1e7b81cabb1f4c39a9e788b1f9e0d8a043fef4aeea
-AUX 5.10.14/hardened-patches/0011-enable-SLAB_FREELIST_HARDENED-by-default.patch 702 BLAKE2B f2e7111221aa91476539301bb86d26569e9160f86c124f8edf326dcac3260afe612989d053dd0eb39172e1e09d3add1ab78a7323542eeff81d0f0ec97857430d SHA512 5538d83e24a73e972204637a07c20c13890c1893b4ec5b83d48a9952b16a8034dd2100651d41a57d9ada4456fe799ec7e0f932ad567f21a74e44e4aced4e492b
-AUX 5.10.14/hardened-patches/0012-disable-SLAB_MERGE_DEFAULT-by-default.patch 654 BLAKE2B a1175eff67c3b02d7f2d7ecffe7ed792b80232088f1fdefe07ec2761cc3f00a62284fae76b234b6474681da191c53871497bd49a6b8f0dcb8b03fb887c2a0e80 SHA512 9467e449b793dc2fe1a9e01df21caabf9ac8b7758c955d4a298fe27db4297e341add564e130fbbedfb96a122da695dda9882707fe0b4acc77e5ce3a7558eb4c2
-AUX 5.10.14/hardened-patches/0013-enable-FORTIFY_SOURCE-by-default.patch 807 BLAKE2B 69d125d64984fb720ea87d3e3901b0c6bcaaff32a0121a74e5cea4df3c93657fc7fbb576c403b986d12d96439e4e4cfa92ac2339a95644306b7376af4a401f16 SHA512 e1212581272c534b6e81b88c231b0ef99acbd5c15d756644a3fdd85a8af6a7f46c45bcf1e73e7c06b487446a09f4b047f8cc2ec78810b2bca3d7fbd956bab343
-AUX 5.10.14/hardened-patches/0014-enable-PANIC_ON_OOPS-by-default.patch 966 BLAKE2B 427d372190d1a22fd7701c4c7d2ceb90bfe56764841c26412f023fe6c034a531ce94a39cda6b013e88ba7274a807cac9df96e542585eafeb864827ac130eba92 SHA512 ff79da00ce2a2bce7ab9c8951fa98bad9bc5bb1b7db7b3d47f6bb5c2fefb72654e60f64f9a61841c408d36924ff562bd7c82347022b09e834150715bc100b439
-AUX 5.10.14/hardened-patches/0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch 761 BLAKE2B 7b8e25c6bec06c32077130738c699a2e1b08e4696cfc41b91ca8025c1c1815f6346d0ce9b1d564850e2a8e5d0cc006446190c6c5373595eb270b0eb8e88a0020 SHA512 197ae9a39cb4cef3190fb704771df9ea26390ecddcd6c16d62b2d5574891cb927990119a356c4e4b362132030d62848509be2331477e5ecea772a64dc3ddffde
-AUX 5.10.14/hardened-patches/0016-stop-hiding-X86_16BIT-behind-EXPERT.patch 666 BLAKE2B e6f5a0a422472b4176f19bbae665846462352fded3e3eb8351055f8a729ea453d9d20b676ea9de81b6c84c534aaa257afd93bde7d331b15af5a08079a520c9b7 SHA512 86ea847be054ea0079f11622c701aa85b06f6b12b921ce7c09aaca405636fba5886dc1755b3f5abf35516980bfe92cb5bb3e81dad791ca6bf69b96ad0149cac3
-AUX 5.10.14/hardened-patches/0017-disable-X86_16BIT-by-default.patch 678 BLAKE2B 2df66c9ddebaf6b61c4cbea97448d505cd6f989dd1d0c57a861bc1f424e848cea3bb88b49fca45ac82ccaf6862eb9163088922988362bd9332fb5873ad5315ad SHA512 59c7bf70299effb4feba588380162a0dee73e50b094077301b0d631222c1ebab4b4102d6a9172a8c7954f2360f26b67810b8c779524f7a674763c1c238bf5df3
-AUX 5.10.14/hardened-patches/0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch 754 BLAKE2B ab32f2541a5b1cb6384b37d8bddea661fc309844616b0142b51c74ae92f8e0ac9111bc6dcc7f5abc85b52de9d5fa01ed2cc00d976dcf7de263731c1cfbf91a9a SHA512 110c7ce806e623a99b2e3769b67b2e07cf2c27fe41229e35652489670b82614ccbbab8a3c6a8f73e7884720f3a67b64489f9479364254fe485054af547ae5ca3
-AUX 5.10.14/hardened-patches/0019-disable-MODIFY_LDT_SYSCALL-by-default.patch 802 BLAKE2B 6bd3fb37c973fe67a3b68cbb690f27917661dedfc90b102f46530991919444b9a1346fca396e5bd3dea3dfd453f037d2e584713e26911185292bef3c7e9d81b1 SHA512 6b830af858a20e05eefa1e6e468f8e7c860bb037e995e029784c5943dfe3d89e9fb74038e5f03c44e9d8ef9f431e824f2faa660161854791f5712394fc3533ec
-AUX 5.10.14/hardened-patches/0020-set-LEGACY_VSYSCALL_NONE-by-default.patch 765 BLAKE2B 51df35ebaf0b02fd4f63577e52e6027713e351b0b0e34668f770798b0658da1c68f0898fc671d71f06f4fdd9455216199474a5302ffe1f738d4388eb2c80a9a3 SHA512 f106329f56bc229bcdf674197d380465013aa6ca3144f1c0670917109ab969e59568beb2f33c42bda587dbcdeb3bce46ee2a5f7c10eb2336099ce106febb200e
-AUX 5.10.14/hardened-patches/0021-stop-hiding-AIO-behind-EXPERT.patch 691 BLAKE2B d4dd58609d600c1d956609b4704559bd0552ea11a53033c3a5783d2a15f4af02b4fbfe70579bd7798f5de21c9f428dfb520da2305cfea6992d9638a6a38de6b9 SHA512 670fba56b7ad8fe823036a3dd851142565a60ed45221b122c7488b226a84e7fa87d3b5e4c56f697a4462940ff8913e0119f22f4004ecec9496294937bb387e11
-AUX 5.10.14/hardened-patches/0022-disable-AIO-by-default.patch 631 BLAKE2B 2e36f2a2ea7818e029fee1869b8e81e8e8e7a08d3bab1f4edaeaa2e5ea8a1a1b197f2c7706611c8394b0be5227534a46e5b27f127b0f7692ae4443fa53c92527 SHA512 e6612fefd3a89bf0fd7ab8ca8de8583c1cc818f8bc9f3cfb7ccc17f0aef354c8dd872c342c35b632b3e1f3f7bb81561a0e76839788e3dda0df8c4e7878a833f9
-AUX 5.10.14/hardened-patches/0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch 962 BLAKE2B 683bb0a4d330119eeca89c54ae0b76a1cbaa06f28465eb3d5434656763bb14ee67f523b8d99b7e1385cca886d7ffaf949786307125b25ff4a0fa8e21946a34eb SHA512 e9c9afe723898d547c9937628379ae99aaf688d5df9c06dbf5c9a67295b535b7637ebb43760b438ba4e9a0f456b01de879362e8bc648539fa6a8a128e3296bd4
-AUX 5.10.14/hardened-patches/0024-disable-DEVPORT-by-default.patch 695 BLAKE2B 47431c16dcf22efca336a54ea0ac34be6f07e292de44637692a2cfbe61bb4b79fbc963727373b77b528bb10ac028fede079f689d38a2a8035cdd4c6242f68ba2 SHA512 97f0adbee3b589bf51c8d505ae946f8f4574ad9206815f2b4f0d36765ffc5ea4756b4d4e067d586f7f1722ea7cc02837a79fa457c087096466e905143698c5b9
-AUX 5.10.14/hardened-patches/0025-disable-PROC_VMCORE-by-default.patch 613 BLAKE2B 888ee4beacde4804029afe590da92b1fb0bbc1dffb982df8f4515045299da280045eeae898c59df7c5bd52483ecb9018478025f19aa8e97735db874e61a54a9b SHA512 a65bc64cbad98b8edec2cc13c06d1396b33f5c7faf912710d5242ab7f3d06430d02af1ab8b243d0c51871c5a6911f7f37ee18da7f9e1690f9ddef78f00b88718
-AUX 5.10.14/hardened-patches/0026-disable-NFS_DEBUG-by-default.patch 598 BLAKE2B fc29b7ea3c098b4fa91b1e31e8a1a204e6d87fb5b2a0a56079d4be1bb8186a320c838764fe1873fcd7dd7514ee7b034be296a2ccf548c8005aa4841309de2c6d SHA512 67b2d862716a6f55d08c318d4a1b98572d5d3234fdbca535b3307953ea487fe1aab5b341e19f097adab0fa921e1f0359f5433a7ebe5ab5cec395e21d39d63639
-AUX 5.10.14/hardened-patches/0027-enable-DEBUG_WX-by-default.patch 653 BLAKE2B d387310d653a8139d470978901bb510d0e0082ff4ca9274fe40553aa9d70a0a2b97d6d1e517bec895588b8452c445d48b98adceea9091e5739ed93d4efbdb445 SHA512 c8c5ee77afd4fac5c79271cdcb9c7cd6516f6fe8fa90220f264095f5a53f7db490a72a88ef03ac329381fa1709f9c095294a5a10fa97f6b8dc53281465d1d197
-AUX 5.10.14/hardened-patches/0028-disable-LEGACY_PTYS-by-default.patch 683 BLAKE2B 5e05216047d47da9cfac49e029f8a3999d8515a854a7e370b8e0ca8bd0a75c248d7eec33da3c4789fda1b683ac57b61e9d18ab345ddd0eee58a3d98bd2d784ed SHA512 422579b7b810cda09e988c0a4b1a7bf7489e51eaf85a52a59da9e88fd5ab89797f6818f851aac4e92b212834fde6db64a3b2bb79d6209a468775c859e3cc6299
-AUX 5.10.14/hardened-patches/0029-disable-DEVMEM-by-default.patch 662 BLAKE2B 40a17ee691fe2183b835f372fbb03e6bf0a9d3df016f89c84bf8b5e76c602e97739ced38b1eb4152608514d78539b8b040dc262ffcac5327397ad26937169efd SHA512 aed3ad87151ba18511e797f4ed6e0585c53099cb0f8b4609eb0369fc7060e85625172c79272656bff816cdd39a5f88d3a43955270bbeac7208dcfb5012bbc2f4
-AUX 5.10.14/hardened-patches/0030-enable-IO_STRICT_DEVMEM-by-default.patch 719 BLAKE2B a19d38454a3a370830f3451794fe252ce077710fc3c6ee5a336458ed2de17cdebb803ac23b9cc5dfc634e84ee6c5b0fcb056d46b7b60e1bfdfa638889be37883 SHA512 d4f6a52d7f4d979a58a066e2149bf4e27d95cfcb353a364445950023d5b55d4409175bc6af95d241e6fa6e27af48f4448ed9bc59ebfd92f471f52e16369de035
-AUX 5.10.14/hardened-patches/0031-disable-COMPAT_BRK-by-default.patch 652 BLAKE2B f5eb29ed31bed116758faa42a6138cd8695988f83956a58fc416645bf7d656afb75183a23f4966e29685328429bd2600ab2251ac1eab2e63d95328673538504a SHA512 6954b9c1cc54601e1e9aa2fb817d14a4de0557e82272fc761c240a429abe9d0fcedf95fe6da27cecb6505a6447367afddbfbf97e0d92046b4cde75d79b9393d8
-AUX 5.10.14/hardened-patches/0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch 1397 BLAKE2B 8bac4fc388e50eaa8fa3ec6071823300acedb7c64d85922b2aad4c39592a7509041faf0080d9c9b31685701506715979e5e33e23104588eff109a38169f00c77 SHA512 d11337d35366b78130fc332346fc5d0fe477f670be5a2619fe863c8f0847abba37de400d6f8ceaf0588236fe1917f4cd4add656b512583966ee8c2e61d9a77ab
-AUX 5.10.14/hardened-patches/0033-enable-protected_-symlinks-hardlinks-by-default.patch 818 BLAKE2B 5231045e59ea1cb5607d5cab3cb24ae1a6ab5c79959ab2f82f699cfe02af453e93d617d0c8e276a86b2126b156bd44f665ca756b4e72ebde308f3944c77bad61 SHA512 3b498659f80266e1aebcaa82f4a9b3b8a89e90f83b313c67a6f213bc56333f4801e7ff6d9bd0ea7163410acf404981ea56a01066e23ab9673c70d4a55b1b1bac
-AUX 5.10.14/hardened-patches/0034-enable-SECURITY-by-default.patch 646 BLAKE2B 8c4970fc32ba4d2dd4fb218379c578465a2fd16255572dfbca2889f5cc36acbdb2e7a51638cf7a8f1356f3281d70731f31a0629b1292e3116a74ff377444055a SHA512 963161fc185a9257334d42e1c3f5657c9a9a00e3605f1a7655c5deb1e86c1d0be9ee1efd7ab5eefc65d947b7e67b94b3a461e65a96e7d84fe36fa5d2ca09475c
-AUX 5.10.14/hardened-patches/0035-enable-SECURITY_YAMA-by-default.patch 706 BLAKE2B d36ee2acbeac5f0e0c38ce7da682dc939159a8fdb4b6c292362d3c96c3b74b5dfdff71fb9a01b177a48ec836ac7134d25234ba45dbc32e2a1243834fb04a68c1 SHA512 a21c6b4ea4635e5610733aa76ac908a06b954c44b66657c4fe19b021c65036c3f736085871b3bfc9e4fc044da44c0d7cabf3d1c88fcb76ffdbe7b652169a5116
-AUX 5.10.14/hardened-patches/0036-enable-SECURITY_NETWORK-by-default.patch 685 BLAKE2B b05a33b12fea32d7be6b24ae5a17061462441c94f23df3055fcf929d32536e62e9cac388ba6df9f659260cab413b831cc35648cd94ca5bdbe9548e01dad8515c SHA512 6c720a9ef2c0c07cf7022815ddef6bd36e81ffdee7fcbbdd0f72b3a23dade2ea485b2faf1e874f7df81fe02f2d2cd86046fe997ef5b5f85483472645d0c7c4a7
-AUX 5.10.14/hardened-patches/0037-enable-AUDIT-by-default.patch 628 BLAKE2B 058ed7827b6e07e1e74c215551efc2410cc76309a36e0399d788fd712dc98f8edc82f54d24f943b2e936817abadac990b7b8e4fa2119b5b91aa1271f0c0da3d2 SHA512 1f57ab25cc2ea8daeb4234befc457c048781b6089c3fbc3f9edf81655bcac820c974829316a7faae573f47169c3831f2ec9572b97666fa957239d592864a2dbb
-AUX 5.10.14/hardened-patches/0038-enable-SECURITY_SELINUX-by-default.patch 784 BLAKE2B 6bd382053af37ccd813cbda898138fa1de212a53e622d67cca6fd2d17b0dbb154ec28f408dd9911ecd001301bfa4505cc7dc139b2230596d18964c4e0f1e7ed3 SHA512 f20c7975cf65bdcb416a172493067d2c93dee772704d5bdf6bf532b51a4f36d5364d0e51baded96a7c77a5462950f422e3bc697b86d02895c7077a94d901e93a
-AUX 5.10.14/hardened-patches/0039-enable-SYN_COOKIES-by-default.patch 666 BLAKE2B c706034352e7e67fdfbcbfafd87cf10fa9488d7ba6fab08b8afc4b3c2987035118bf20da16fe61356792d0f773a0e9a6443a6163adadcdb73d2b34648feb3c31 SHA512 c2dc7a87e09bf2298636179bbbf1921b0918ee38c4dd0088c920597261df9de29afdbd278e9fdc11114d25b2cc72d9963f59461b3e791c9759b61b4402b555af
-AUX 5.10.14/hardened-patches/0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch 785 BLAKE2B 2493d4410761a525a561feb06b7b2eb2bb0fc97de4c31bcdf8e1c26cd0551483a1fade15570feeade28de99d7342e7406792b144038c0dd4d9d8df143fc22c17 SHA512 da78c43e340af7e1d542340253d4985ec9aa2e11e96dea41c5db8b2d47dc07220d5b4aaf229e89d71fc43645497c26da2bce51f3f8f34b4865f5f40aba1ca3a2
-AUX 5.10.14/hardened-patches/0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch 774 BLAKE2B 31675210dafc5cd5ae25bab7506358482317eb8978c9f94edb2f3b052b6a2dbf075edd8b81e29925fe55288639b3b05d9f6ddbb1829b05e9a3b7d9e97015f8e0 SHA512 c776bdd490d47e7690e26f77ed9d13b8c473ccee2a6fb01bdb50a96e1d29640943172f4d0d3b657c1ee09f59176fe6ce291ea8fef519730fc61b7f6b11b20d9b
-AUX 5.10.14/hardened-patches/0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch 827 BLAKE2B 63e56a61e1dfb18141dcc288e56e78cc1c9957bf793333437f2a9eb6f7f75fc22abb8a6dc34d0a66f97fb582075507aee0c29eb2e1ead8941c0f7fa4a5a5e5ea SHA512 b3e8291567f66195a47ad85c5d2725f9231dea704c16ea6d9c9f74be4780067ad9c5901fd9543f6b350ee74dfb2c7427a507c3073451710cb69ca54b97335b4c
-AUX 5.10.14/hardened-patches/0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch 705 BLAKE2B 4efca3c39d11b967e96710f0e48aae03a464d0c6b3b8a578cd9fa7cf2b00f8065420149c9c6e41f0a97f03243ce95afe7279c6621b55bb34e5b04cf7faa03ed3 SHA512 df051fa07c3c0003747191d312dfd678ed6123d750baf6d3446f91daa5ca53001c127fb0d9ba480ee62753f9c4fa309f132710b1baeef5236a359139dfcc93e7
-AUX 5.10.14/hardened-patches/0044-disable-SYSFS_SYSCALL-by-default.patch 835 BLAKE2B 85ecdbc3f76e9b63c74f9ca75e455be70864d34ae89b63d2d1ac0e522ac4c3270176513f2386ec9f278ba9f1104346b1d1b36870cf09cdcb213416eb6cfd84ef SHA512 d8af6c401e1bdcaa370af47fbfdb8d615b0d58bf9f7b1a026466ab74bec5c5fd7a27b3ae9acdc9e0c939fafd68c34171e83721e505aafa96867eab12c642ec79
-AUX 5.10.14/hardened-patches/0045-stop-hiding-UID16-behind-EXPERT.patch 679 BLAKE2B da984dab4a2c4e33cdb255a69ff792fabd087b874f2e60131ba2c52c74f5ebbed4342eb54cbe561a8a125e59d33ed437d98dc1c2674359c0f8a731494a0a7bcc SHA512 34754705947fdd7615b3bf99ad9a3b60c9f52eb71f6a56f13da2827bd1dc297093fe7a18e0aa88ca5bc2c6c44d5a01dea38ce6dd2a1d431c19cbd0d2783e0e6c
-AUX 5.10.14/hardened-patches/0046-disable-UID16-by-default.patch 605 BLAKE2B 51b82834c3bc2677066c337b8378d8520810f3587e12aa04763666d2cebe6accba1e05abc2f17c3e734633a47844e7b2b5e246b5f196523d66b508ea16e72e99 SHA512 5c6d2be0255f6bc7c6b169f5ccc090f90fb678e47fc4baea7e8d75eb4626b427e14625eeae62b35b8308a4d5d0c5b4ef56c821f29ec73ffcbf9fff516638b9b7
-AUX 5.10.14/hardened-patches/0047-add-__read_only-for-non-init-related-usage.patch 697 BLAKE2B c573367d3d7f9f26e1275725c00b0d7a0642155bd08352f5786bd64edcf4ba5235a337bf7f728c289f92fc78f84744e5613f5ebeb0aef6870fd0efd5e92af32b SHA512 9c70f722a78dbf885e8f1186846cee8b1e04a400331a124f7934f6b5513702fc6eab5b111144504e3adb1743417ad46e80874bbe9a4b43e926685195a5117666
-AUX 5.10.14/hardened-patches/0048-make-sysctl-constants-read-only.patch 3971 BLAKE2B 92ae02371c633dc0bdf467199375b0c04d2a592ef180f7991eccb3a677e786e447562fff332e8d92d1cce5ed7191f34bcce8e980c5c429f13ef503f2bef4db06 SHA512 9c883678c0a40bdea0f02f5a9181fdfd7301103e533fd41a378075c32266d52a73de30ff1b317e78aff3eadae434a7b24c4a683c712c238518e137381ca2c906
-AUX 5.10.14/hardened-patches/0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch 2089 BLAKE2B e9866f11472fb2893b2826fbbc8f84ea6be2a30d3a5f982d46e129e9584fb9c83634721fe571a8893a45cda1eb8fabf78eb24afe34f81634d6bc32dbd423fc1b SHA512 e71db6c353181d9d65f235a8e392704f1f0c3969c164f3bc7922c185db103e6f9dc3f34f73a792915d83f76b729612ea7a56724e0143c5f97814de66d822878d
-AUX 5.10.14/hardened-patches/0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch 2171 BLAKE2B e96a6eca5b3a2228ff16688658a51f0c796576d02c0d79d728a063530a50051f095f8f2a180ee9521d9aacc91c6bf77dffc4e9995fe8a1fd15f143f66217908e SHA512 21d550ad873dd857db68c143454dea74aae1c3ad0c33e2b4879c6aa5cf66f7df27a630682afd6dbd3d1fb11caea4b3e1bc1ee306414eff6fdfa023712576ee91
-AUX 5.10.14/hardened-patches/0051-mark-slub-runtime-configuration-as-__ro_after_init.patch 2004 BLAKE2B 43c884daf8fc0841d11d9851bff39526888b1fd4a734bbc081b44eb0332c33e4e5130586e042403ba0f66385a2cab2d25e7ff5adfe0549ecbfde82728c7cddca SHA512 38c698265c65a60cc2c725d64689d9571b3f15941c0fefac4d9fa528831db153cb8e792172587d91d0fc84ed14dcec7f9e7e6bcb2b242d074627f4e9f4ec0a04
-AUX 5.10.14/hardened-patches/0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch 1165 BLAKE2B 6e0f48e49da4fce2279afe75aa7c16bac6f0a9240ab37effb657a769def3beed6a73a49e322476c30233208182cdbecf6e5560412154913424b642c8a254e578 SHA512 2e6eba94301f803e434b0e1d930b34ef2c996fe0aa8d3f19fc76b3ccaa264effb4b3bc8e670d7ffef6a43105a83cb83af7bac4b0c29e94dec0f6a91fd9dfc8ef
-AUX 5.10.14/hardened-patches/0053-mark-kmem_cache-as-__ro_after_init.patch 709 BLAKE2B 5fa2a7380601873d3141a7ad632cc566abf66c65ffbdb9c0724c9719d182ab61e8417062fd855db695158c05420e9b26ce9e28d323bb9fc68925ccf088780d04 SHA512 929aa752c00c12b835d8ee566e77ee01e8d74b25f0db4cbbc4954a3e346719ce6cd776aedc868dfa4cb16ed25f72802307aa8e6191d353c42b50fd6dd1a0ffac
-AUX 5.10.14/hardened-patches/0054-mark-__supported_pte_mask-as-__ro_after_init.patch 1954 BLAKE2B 169f477851ca8954cfd29fea13419e287eb18e4ab1869ad8b58144ce9685a1af2685e83faff7c438088586e836de718e96fcc718752e9c105d535c6c0137a002 SHA512 39ea7258eab2dbb64f9a09dee64c7fb8fdf5b8eba84ff00e780ffe1836a01efbdb06ec46aeccbb0fe907b21b79010743d34a1f83c67b61e594afdce549e5df27
-AUX 5.10.14/hardened-patches/0055-mark-kobj_ns_type_register-as-only-used-for-init.patch 1663 BLAKE2B 87db11abc0f6b6d7a31e26b224748fc4d87a0fc32772809d5c0de678b34a8d8aca1404d463237530d03ef3aa677ba51c79131bd66ed6d8d0cd2c825b4ff17222 SHA512 8b61236e656921a911762fb854633f808fdfbf7861b6c8d6eebbf606839f8e46040851535437ff449445a8518b1fb92c9c8279fb80fb79691090410b38794932
-AUX 5.10.14/hardened-patches/0056-mark-open_softirq-as-only-used-for-init.patch 1272 BLAKE2B 417281b39b08ca457757c0ac9b9651a661e4d8b28c9fc7799eec7fb4163405ebd98d8e818cb0a8f3d7cc384e3678e650f189b4699a86b0e2d562df7abafe0bec SHA512 1c5a50efd51c3db850c21b8cb974e125249792ab5cd1c5bb757ee1226a9b00e4fe582cac920ad90bb8278d51155fc28dc73ee28ff6a6b9d2d090d962a73a0233
-AUX 5.10.14/hardened-patches/0057-remove-unused-softirq_action-callback-parameter.patch 7357 BLAKE2B 87c0548d6650433af370e1a7337dc0f0c674795a1030b089f48f41c291d804307a8dd3a42a52d6cecaf96a4fcd49df89078e27f0742747b0042cc24dfc06f957 SHA512 e6b26eaad8755ec04558e6659f8ce094dcc46619db24937207dd4864d53f19856baadf17a5880267c837306c53a9251dc874f5619cd9c90da5b087192521ac52
-AUX 5.10.14/hardened-patches/0058-mark-softirq_vec-as-__ro_after_init.patch 871 BLAKE2B 54ba8ea5ece9ac776c3725a64a0922770ebd20cff1683ae5dfbf405617396fb6425bc29f8182c9e30d0a5bb69e2ba9ba4605be389bcb57824544cf44117fa172 SHA512 b6802edd05d1af365a12a91ef7c7b1b90659fdff5ac82ed031b31ffe520c08a3dff6d379a5165b48158743ad68799055af86316ad7c39fb07fb0fb3dfb62c5ae
-AUX 5.10.14/hardened-patches/0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch 947 BLAKE2B a09cfe40534289a5126b577507f77596f72a029b16af3e6c3af4e6a89126bf7313e8982a5d0bece7c5836dfd52844823dff7b4c7bad79a43d7ae7e6ab152d26a SHA512 12dc9ca1e5544ab8532df0e005fe35f6137eceb5b246d5971cdf148aa5c036dac646a0faf6128948360b225c01eb292ca0fac609cd22f719cbe252f2ffb3eab2
-AUX 5.10.14/hardened-patches/0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch 1180 BLAKE2B 59081fb7f8b23f8824177846427faa20cb3fabe60a896355ab67b69c1807298316bf941f1089e8382864aa25b56692e57cf3c9a3df7a91660b9fe29d94a8dcf0 SHA512 7e64eb05ca141a2a9e06f37c0f4c7364e8ee1a253351a343ed4451f8fe94140b4ecabe552912107f233ddb9250e578dc66d2f5980b499ec6cb84dde6457fb069
-AUX 5.10.14/hardened-patches/0061-bug-on-PageSlab-PageCompound-in-ksize.patch 788 BLAKE2B f1ed4d4ca9321d0a172de8f3b43a51cc6499a9748283492a5cffdeb3b2eff1ef31b065a64510aa70802ffb2d9b6ffe2f0302a4855aed0b09211529c4a30abc25 SHA512 4f77f4de4ac9d18314ce630c23d383064287e6ca8f8d139e8a66354139f6dfd72112754bbc2f234da3f1d97e399e4f42afe2ace6c37d3e05e127328cd1822e3f
-AUX 5.10.14/hardened-patches/0062-mm-add-support-for-verifying-page-sanitization.patch 2256 BLAKE2B af3ee1d212bfe6d680b94e48f18982bcdbae0bc41c582d169a3e0551b7ff047e6e4abdd3895248fd0443be878943c68d16ce930832a7843bcc6d0eab2dbddb11 SHA512 72f956cbaf03e9515bd38d41f0f50d24fa791c2a76a18bbda29f8810455743439109f1d6aca35498ffa4f66e3e52746d7b73e6f00b6d1ef0ed91ba7d21eee885
-AUX 5.10.14/hardened-patches/0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch 2454 BLAKE2B 64a9952217fcbe318ea355263caf8c4c7a65992a23b62ec6ba03587160e020ec18bc50c5afeb948a2d5e639d11c1568869e01183e50873b609c7e8b7f72cbe5e SHA512 33ae0d7c14f97942fd63913ff41d2c3956e272e9a026c45c35a8e7488e48df076dda3aed23193391bcb41d9642ced55d1942809b510bb7aec9bc9ba871cb5c84
-AUX 5.10.14/hardened-patches/0064-slub-Add-support-for-verifying-slab-sanitization.patch 4020 BLAKE2B e10151a5329a5eba85375c2e71a66b86217b51f712adb05137b4d698a0b25cd84693e3d0682f0a169216f2fd8dece55e0ed78fa37735cbe5632ad5cff9c46502 SHA512 e26f64274e347982ef640584fdbf0dc0244749b3d0f8654d38bf613ba0d015aa8be56775788e48909d44f4308b251fd58bb656e9552d2daf6316c563916b4707
-AUX 5.10.14/hardened-patches/0065-slub-add-multi-purpose-random-canaries.patch 8811 BLAKE2B dd33ba1d4fdc1610fc0987ac184bce72385fe7691d6adff8838d057f78c0818c0ff62b696f9ccf780762480248fcfc8a11ff62e9e7644902793621fca1aef2da SHA512 0fbd30cb842c0d3f1e7f65a0d45c1cbaeab4fa9fa01d42764c212cec63b6254c05f50b39b82b6ecb3f11e3144b5663eab0d6b9fe7270c98834b93b26832fac0f
-AUX 5.10.14/hardened-patches/0066-security-perf-Allow-further-restriction-of-perf_even.patch 4744 BLAKE2B 0534b43ab38c6c9308ef935b2b9e9345873f6aff3975ea5148d5fa5398a7e4c786de7918bf0b00e56c8facc4c0d6b75736f3695d6c3c4e75a50fc9444229ef9a SHA512 650f35b2886224abff0fa5fd9fbb8e1d355b45b26007ac847f0f0490884219ec38aed5fefc904aa7ee9614390eff658e55bcb8bed8dfbf2cc85412da2ed5e937
-AUX 5.10.14/hardened-patches/0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch 798 BLAKE2B 5064c2a36b63533a78a185d3c651bc8be4d7be579a9f33f97e57f6c608227619b40cc746367b36e5a06f0e9a6cd99d7eceecfc59b3804f51f1c79ed4e7728622 SHA512 03bb7a37a24894c10170e33d16e4f81be504c2ce4c806973f3328edcac009b2ae29da829212d434b4014a4b81eaab2600d7a0b962a6b30c1a9c7b2214063c1c6
-AUX 5.10.14/hardened-patches/0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch 3791 BLAKE2B 71bd3a8a9627e850a770df799318f52946bf46a7fbbde1991576115b64d5c469cf7a928eb1b4db2a3abe73ac69d56e02c20449ec883151a789b4093d627ea1ae SHA512 9ea2a209c5b003b92b35e0621b7b889dec48c259284070c3a879064b9d4443b92791398a02ff7406d64ae7db367737d91481bc52a655a015e320b61c4d3ed7fc
-AUX 5.10.14/hardened-patches/0069-add-CONFIG-for-unprivileged_userns_clone.patch 2070 BLAKE2B 242767131e5d851ae5b62f6bbae60ff2d53cec3ddbb7eafd3144ac12812391449c51808776af0986f81cb609e5dee142b338c74c265e5c193fcd3d6a6fabd0f3 SHA512 2af0b36d0cdea8748935b33160e86b1526563e4163ff0948f483abd4dcf28cd56c6a96d94c7d8e4795646acfa6a3d5b5958b029d4ba60b27403a4aeb74e3630a
-AUX 5.10.14/hardened-patches/0070-add-kmalloc-krealloc-alloc_size-attributes.patch 2735 BLAKE2B ae8eefa4178092947f9534e485c7c88e6c3a443a4fac97494fb751b5c73cb1d4de9ec598e999cb792abadc0fdacc9ebd84e5947d60a60311434e232249193afd SHA512 3b3611dadd8b8ff963c58d0d702683c1b5e69788b3b99b519f580de62d92b9bce8b67640072b4bbfa22c86dbb4878889ee0da06b740d86c1a4f5236ae43890aa
-AUX 5.10.14/hardened-patches/0071-add-vmalloc-alloc_size-attributes.patch 2249 BLAKE2B eb9ff3856984a1d5bee866290bbea45f4ec1a3c9019a662abae8b749fed5ae4c5fa43d3130ede2d5b6b517ee2f0fa162e947706a2af97ae792d77c3f57d0aba3 SHA512 352ff70e07bc59ea2b4e5f77e7e72460f663730a81c0f3f5a05205f955ff755e1abe9ccf9995de8859ec7714c6239be7f64c2c1564215c12388abc983e1b0616
-AUX 5.10.14/hardened-patches/0072-add-kvmalloc-alloc_size-attribute.patch 860 BLAKE2B d524c0cbdf2aa1691631659ffdcdf8e20464ad4a9d108c9340cd1917e7f17ea9d07e9f803dba384bd460005e44b318864adbc6f9d6b4faf76e816b8015fa141f SHA512 a1bd23efc934e61bafef8795a54c128baa97f3de9f2b8f8a3ad6d1b0d74e0f615750f2bfcd73b872d79c9641444a411a4d535d0148fb7ba6e37dc77833883228
-AUX 5.10.14/hardened-patches/0073-add-percpu-alloc_size-attributes.patch 1588 BLAKE2B e7da3104527c3c818426aae7f35c209b63082907d73ecfb2d1c145b42570ccf15b2031e340701ff37146c2490d97a1147fb20c6826d8cb100a0fc7f1bb4ca13a SHA512 413463e5bd8c7fe04515c93f6c4511241700129338e4b87a001f773ebfe8d194be86ae8885ae479dceea31a10b9a2990d12028a82a65236e2db585e19f53b7bf
-AUX 5.10.14/hardened-patches/0074-add-alloc_pages_exact-alloc_size-attributes.patch 1259 BLAKE2B b1477beed1aa7a823668b43479b18ce7f1defea70974125361a86807b720894f4e294767fbbac367047be29d15430f780da867716a17fb7a28705794444adf82 SHA512 d9ae2c2cd111b20a0c90c5cb12ab95cb9aee387003e15110408d19ce8f70494b42ee658d4f4ed58ed1d0f369b9d2d69faf4c43d202d3f67dbbc4fced36242c43
-AUX 5.10.14/hardened-patches/0075-Add-the-extra_latent_entropy-kernel-parameter.patch 3591 BLAKE2B 6e1ae96b5530c4d9bb58f476689417e3b9a134072be6e325041d79ba253c60341ff82673d85dc184bbb27d7422d7490b1ec0d4294eb682756d0f9e6c4628acb8 SHA512 0fe5b024f03066dcd634d639cfbf4578d62de910a9cbce7323ca302e007a89b81c0972c26fee5bdac1446078f4e89efd8e17df8253f9a14c2fdf95875753a5aa
-AUX 5.10.14/hardened-patches/0076-ata-avoid-null-pointer-dereference-on-bug.patch 1191 BLAKE2B 73bd6d8ec109ff67ba947179a969587af1ade929cb1ea0bcfccbaf66da2625c4f074d67ffcea2ee0e27bc9a8295e131a5db3c0729ed041f7c6b2ff4e48851b11 SHA512 74991d815a6aa27d976e15ab5eeb9e9fe97db86e7d5cc6e54c4c748420d4e975278206b1c094cad509c4f2bd182daf6f22c8a80a7b93b2f6916fc335ae472c3f
-AUX 5.10.14/hardened-patches/0077-sanity-check-for-negative-length-in-nla_memcpy.patch 755 BLAKE2B ba31a34d293a1aba3fffd8a76a6953195deb0c5a0c9e80e003f2a71c7284313b66cc6aba961b18baed21a7c22eb8f7414e3a450fa85d2204f123a69a33c80cfd SHA512 5fdba09d6a5cac9ce104c5d223823665e1764376fb77c51004b00584a9c511699d25c0b109fbe4b11b253303a9103400efcad2af302ecf6a001b09c0c9886c4d
-AUX 5.10.14/hardened-patches/0078-add-page-destructor-sanity-check.patch 2205 BLAKE2B 146ea9ec8dd21e17cd37588c4b1ea76ed8a52ccf37253c29a6052df1d6c436b8516a4a9f55fedb5a444c82845787be911117a259b5412ea7d4bb678d71bff0a6 SHA512 a86ca4a64ce6f24964782fd724368adf91e04a999373f0951d5b8b1f54aee2e6bb1aec41f8554a9baf1d259206265433c215fdebbeb9581a63d90607e3a072d7
-AUX 5.10.14/hardened-patches/0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch 1793 BLAKE2B 148463bdecf3d22ec0e8a4062181dbd69c7447cd3c62c84650d502f4061f148c06044b501f066852c131c0f6d04da6fc503e3e9c22202f6771266bae4f2bb95d SHA512 c2610af8b12dc872037b0383e56d7dd8e6cb2730678d9f727ef31db7bb74c56a3a64875209e14d13a14d1451572e01af66378870ba765d940abd3a99990bdc7b
-AUX 5.10.14/hardened-patches/0080-add-writable-function-pointer-detection.patch 2688 BLAKE2B 99dc1fb03f1a4c6c502aae588b8e16205ec4186d156ddc4d45cc064f4c82613298712c92d48f1cbdf6b651313dae286f2409f83c60573436f8dafb3a23b35e29 SHA512 ebdaec0da553554c44d07375062c648700d56bc2d00e0c5722dc2e707f1b0fdb1d5b0e2ac79919b9f2621a04acfcb8d328420fcd74b99b299f6ade16c791cdd7
-AUX 5.10.14/hardened-patches/0081-support-overriding-early-audit-kernel-cmdline.patch 760 BLAKE2B a2fe0b0f9511111aeafca9373aa6eaf8054c63f7643bd76a98233de47326c01eeca7741f176f59438b513aff828e8890c9e3161d85c2e048d8934ab0dece4044 SHA512 6735d28b89dc6b5114df737e16b73cf4658b661a29ce43e3cc04514b4440ebfb4e3a94a6e2163f6af70c3d9acafba91981ecddbde6c785e222d2742e1b816242
-AUX 5.10.14/hardened-patches/0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch 5669 BLAKE2B ed17ac562215b97f7c48d10b2dfe65137e494eeab2df844c94a916c090739d0ac76ca21f4fca4630794b9f5efa8b43c62dfd98fde89729b7fb8aed9b1318e350 SHA512 8ddd1434a840157610bc7c866ddb8f3f0e251a9d7bdd3b6bdf8336eae27760664322fd163844d07560ed6fb55010c52a2cf8dcbd84181171e56ddc15c0f63933
-AUX 5.10.14/hardened-patches/0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch 1986 BLAKE2B 0fb823061842195e42e6cce628f2e75555285cda8b3bd9ecb0714245e22d67dbfd284604d333ba138dbf405519cbd6593fe2c5126a6d31ca2d33277999fac6f4 SHA512 e4c61f9ae28ce58f35543b43629db570f3a342185b9034e3376a2c7afa37f35a8b0bccebbb9e41a959a8d473dddbe7256895020ebce9e12f2789dc72a746814a
-AUX 5.10.14/hardened-patches/0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch 3921 BLAKE2B f35a58e8d5604201193e6be08ea9f89825579f245683947153d1c532ce2c8762e3b8bf3c0325d07b6ae2cca6783eaf387148e01f1e7d91dd35aeda527bcb85b8 SHA512 15325d27d952bed62851f550e1bd7a08f06c8532c269e1f2201fed0d66626720a2df92e1b7cd913e21a5d7729e99b1801be4974b44cddd007570e8828aa76020
-AUX 5.10.14/hardened-patches/0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch 2502 BLAKE2B 0083a76021192fcd8d3ac3547d7e5148b622524e7ccfd25e45640c6f4db4e425eb13db343681e56b51dfcb0d5aaad4c107d91caeb722f64ac2b09b07640841bc SHA512 462879e4ade7e1daf174a32c8929107d86c1a243031a4f006a514d88e62b8a49a0117654ce1b551c2af18e4d4feb9399aa350cae17f0454d4b5553105147f247
-AUX 5.10.14/hardened-patches/0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch 2224 BLAKE2B 6798e9ab9936ed48182d32ca72993905b95fa74d42c4c44a3859bc6e0f365d26a42355bf58febe2c3bf73d717a7247c83b8317d11237eb10a1ed3ced0b308763 SHA512 9086ea3da59864672159d83025e8836c4a21e5d490424a7d29ef4df9f9bac896e52365e1504e36598d8b1aade12fd3d7b880e3cf81aa5402ed70da3befe7ccc6
-AUX 5.10.14/hardened-patches/0087-randomize-lower-bits-of-the-argument-block.patch 1466 BLAKE2B bb09f0baca64c8bc75c278ca67297a14a19b520b63d07703b0ffe23ae8bf2f378bfae68310ad6d6948523c4b69b2872ee3f9debee0958329c719482beb71d8a7 SHA512 0f6756254115971c7416f009c56a2abb634a131e4dbe8526faac3bdc7d265d6c737673515083cb4b26cb8b53ed6c087838c40501a47724af961bc11448c413b6
-AUX 5.10.14/hardened-patches/0088-x86_64-match-arm64-brk-randomization-entropy.patch 1019 BLAKE2B f0d2cf9c9c2de3f72621424644a47e6e9a62efcf07392cbdeeea6ab60cf7c31a8393e5c4797c48667246ecad4d53c7ba884b295d15eefbfd28a5f4eee21b045e SHA512 34a77b4b3b404f2288885a7df2e3002faf4bf9e692456e92404a2f595e49e9d20434fc6175aec0cad3c1f1a26a179a1c9578796fc7d2149209bda139894113ce
-AUX 5.10.14/hardened-patches/0089-support-randomizing-the-lower-bits-of-brk.patch 1368 BLAKE2B aa53fd7795bddcecb3761da181f19a0812f95482e81648a0f7ab669aae6d648a92c228695d050fada9539090fdd5bb43520d643849bc5e05459cec5f848c26b8 SHA512 05f519ec692130b1cc7bb98bf9a24257ac918a0428cc1081aba2ace5f3d83c693ef8f378d198d7340c0055dee06d89d6048768c27bd412474a2e7504538d7c29
-AUX 5.10.14/hardened-patches/0090-mm-randomize-lower-bits-of-brk.patch 902 BLAKE2B 49a0d28970187fd71e2dfa4aa57511492505cbee0cf3cf91aeb199f38b2bfc5e84143d30e4c58f8eada035c98cab68595335013fd02de1383d257f915fd4dc2c SHA512 8e8a75e59c107ec81b4ad117998cf89c76fbb50d5793b1cee433bf4ad101cffa44f1a8b861607c33c8aad606f8a046300446ae584840f6f65c8f3690be0f4c22
-AUX 5.10.14/hardened-patches/0091-x86-randomize-lower-bits-of-brk.patch 942 BLAKE2B 5bdcf728fbd15710500c810b47f23f39f3edfdcb602e44f6dff19b16f1e2da88eb4f18db90bbf5a936ccf1b4a011e2fd03b7a9fc1b97cbcd8d36d0ab297d9d8c SHA512 cfeac1314491d94cd18c18eb425fc611ea8924b0f77ad5a4825269bd29892be1ce01dbfe3ad0c92fb52b36361692fd33beba2b7b0fd567b5b197bd214e0f31b4
-AUX 5.10.14/hardened-patches/0092-mm-guarantee-brk-gap-is-at-least-one-page.patch 947 BLAKE2B 520d9c42f1994f42782a5424325dbd199a63cb6b4e84c981efdb1ddd7c84e34b1e72ca7bea7a1cebc009625594c547a36551848985ad35eeacfbefec6f515e0d SHA512 071899a50a6d38303bf01c7236a371ce69797e364ec526d421875f49001b3b3d4d977d2faa4f833625d8b8862aceb5c3f63dd08375e7540f7d87438d5466ebc7
-AUX 5.10.14/hardened-patches/0093-x86-guarantee-brk-gap-is-at-least-one-page.patch 987 BLAKE2B 0d00afeed6fab54aee2aeeee2afa1625b9adf5baeb4734a959b29bbc3285d11e6df2b8ec47383aaa5d8348ac4e4dda2e34e0dc40fefa65873d2efae084bef82b SHA512 700db640cd25d3d3f2ce378ef2706e549a2762c71692710a518638621fea23b8c47e8c2dee996ff343d371830af4df81e6c5f582f84ff0e45931a48ca3fd8509
-AUX 5.10.14/hardened-patches/0094-x86_64-bound-mmap-between-legacy-modern-bases.patch 1075 BLAKE2B a322809c9405f2101e05ebf4f4526a12477438c8fbdb5b18606dd44b536274db1d0126f0a44fca9cf4ccab8dcb59c09f367cf4e05e5c9e42c5f00b5cf6ade997 SHA512 10e8cb3ef76699428f702059c8ad99a52d540ad739665480119a0e2c17fee8e2838916b788fcd40940f8de7cc6f9647b9a42775c4c0099171bc34a5ef869e88c
-AUX 5.10.14/hardened-patches/0095-restrict-device-timing-side-channels.patch 5426 BLAKE2B da23d7c184c1cdc51144a029bab59db721a431d5e7a6fe2243e361d4334a61ef87e6b92a7032862ae5ec36ac08a94a51d8fba54e810c94c9f1a51995ffe1a224 SHA512 cc6a021f75b38bd4046f38e599e189efa55d7d11022bd179a5673dede47c0e26613d1870533550fad7e487b973e06d65bb7ee9c379c8eeb85bbdaf7d509621c3
-AUX 5.10.14/hardened-patches/0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch 3572 BLAKE2B ce1f17c5e0875bb3568a1d41800c383096dd35ed49115d15d723a00419d909f07b01a5a40dd12a5f06defc2cf28b4c174c081eea4049988a8b3fa8d076f00197 SHA512 1969399884540e01526a524a4dbae4dd0e1b533c7f003a585ceae70bdc97d86fd07b336cc614f3436a4aac03cd6b824aeb20e45ccd9912cda3327c1984300711
-AUX 5.10.14/hardened-patches/0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch 2474 BLAKE2B 0d80a45becd17ce86c935952719e385efc8a8850644e94d165328d7b5bf3f680cd275914571f785bbbd3de7a25223cfa2c948fca86606c0eb64b7a45c91e1e1b SHA512 733d9460fe331becf6988bdcae27de49541c1dfa7311fdedfc84d8a83c3eb03217e3d211c98a66b255ecffdc86ac80b06527ce254db7e20234210e15d9676e40
-AUX 5.10.14/hardened-patches/0098-usb-implement-dedicated-subsystem-sysctl-tables.patch 5440 BLAKE2B 93a3eef18da347a0da66943701022fa471f75068d6e54aa6b3dd19f4ef9253045e95058cdb6d52fcf0be795470e6ec035e9ff5d2cc55f6f0f445a6828c1edad8 SHA512 6eece0eefee82214552c1e2b94504c4bcd54c5d90e4b838ce0d87d8b579820e605a260db8fca5dfe9bd5654692bd42b731826af889df784df59c5b9785771efb
-AUX 5.10.14/hardened-patches/0099-hard-wire-legacy-checkreqprot-option-to-0.patch 5154 BLAKE2B 739ca15ebe38a4fc2959610224a70bee87d2828f1d36c23d446ee67576c6d4bf6a72057c3955fbfc9eceba22b6a3d833f97d129a6bcd9bb338b9f1482845df29 SHA512 54f3429452318b79c29661f9f77f36e4495fc8dc9ee562d616cc7f1d6574b93e7a8b2912817a2cdb362c0ec3421d9b9559b5a13ad74511e074e1be722feb9210
-AUX 5.10.14/hardened-patches/0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch 2194 BLAKE2B 939c53581aeba0521aa3ddbaa55d4766351e6f82efd3f803710edf405b4d7f410c8ee381fab3f8cae11173165e2285c79c1f7623df1950c72f2d623008d1ef4b SHA512 9dd812a4e7e3a7b614ade873079aa779628cb82d5454a93ec7c9df40b6950a1b77fa1c0c97e2630b3c92bef947736421e8377afe33c06f14b30c7435df176614
-AUX 5.10.14/hardened-patches/0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch 6822 BLAKE2B b7ff538ea957a76cbcb3d679bc0ed2134b4c03f7524d8e7ea30f16b53116ee592372d8c43906ab025f604dc64af640cb23c605cceecc97ceca940c569178b4d1 SHA512 5584284e66d6ac25c95442e15faee51cd5f615d7538e79a431fbbaf462493b480b0976b28360b694d7cc9f659e22237c20b07a81e6b590bc29d08bd2c7c6d647
-AUX 5.10.14/hardened-patches/0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch 824 BLAKE2B f1b9e35dfbe19a6e16b12a8d60e853385b6bdb22d60a7554637abfdd58f0836afe74c51346adae5b07e10bb0b4eb2bcf838e8275654b4001cfa0ae3f1696185a SHA512 27179484d797c841a844e8661d5553fab76bb79c156f59f895dbfaf846421753eaea827c4ffc0d3a9ce700f0490e6f4f1640470fc3b8b43a7027acb7cf75298c
-AUX 5.10.14/hardened-patches/0103-disable-unprivileged-eBPF-access-by-default.patch 837 BLAKE2B 2baae02e7f275fe7855f12aab01aa27e67276efa8e7efc8827d7d321981c0fda0b1bb4bd8a79908a5570738e94d79d380777eb874fbeb9e248e5ceb19f6b54a9 SHA512 a4911a63bdde28c6c0feb90417dd146a9e6f222f103a5342d9df7559b703b390e6851ec958075631c48ca17cd799fe633f05a0646e8e6c42dd48bdade54109de
-AUX 5.10.14/hardened-patches/0104-enable-BPF-JIT-hardening-by-default-if-available.patch 857 BLAKE2B 28d5e4c408634f28ad7779634f6a0cae4ff0bd7395f0ba315127b582446117a30b3fadcdaf6b21837d699cbcb2b070afbcbb223f80a3864028b2a27e2bb18c73 SHA512 9ec667103b6dec895c225f8026c30495765054431abc36d0b215f88b5bf8828971c158cc3f4160982bdbda38d75829ebc18101c7b199ef6c9d1f7d240478e28e
-AUX 5.10.14/hardened-patches/0105-enable-protected_-fifos-regular-by-default.patch 857 BLAKE2B a46a0054e558e5152461d170b1e1b54cbbd24572153bdce5bd86459daa4061deae46ae5d43223e594f585c1ea42064430d78bd1fa4dc0f8105e9265c4ceef84e SHA512 834a3986ce8c7eeb39a1de07c412281a28ab775209bb177b4f82ef11d3a94c7bee4fab0ba812795f7fc6ebbecfb054603457d246d636c3e803d23dc976db9afb
-AUX 5.10.14/hardened-patches/0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch 4376 BLAKE2B b7a8aa31449ba71324f2a0fce914a54495490fd3a3222e26fbf34c21f56f919bedda8351b62ddee07044b46fb33658c8919ccef3b6b135354a52df41491a9b37 SHA512 219e208a65bf23b60b423330ff30b8ea5f30df9b50e0196cb8fb5e7d7ee41ea5ded28fe5e2a80f91105d4713d0dddecbaf3d4f7126e771bee610a886e253417d
-AUX 5.10.14/hardened-patches/0107-mm-Fix-extra_latent_entropy.patch 3878 BLAKE2B 81a60e1d461dc87df58822808e962890e29ae2d3d3ed2e5200315c5492792717e9ffd94d4d1c011e2fc52862dd27b6ee3deeeef4c6d83eb2617d5a156ed8a4ff SHA512 6d31f2a68ee0426718c99b547ac68bb471a88490b3b3f614a2217c713ac4b1954c728d36ff58297952911b1cf9f26cac476fa7ceb56a1d05e990e20b8ce63ceb
-AUX 5.10.14/hardened-patches/0108-add-CONFIG-for-unprivileged_userfaultfd.patch 2287 BLAKE2B 80d6bcfeda7904c7446a2a7e44bad1b76038d7960943e03cbd143dbbd41ed8933a5f920c1cb191055bba9b826775f034ab21485b4508d6fed909b0cb282a0186 SHA512 f0cb27a29172b6b0d08179c2108a28eee830474cf77c59ba45bdd33069156fdbce19e8c939595cfa58a29a67da0fa32ff29489c8707792e40ace05d660f5892c
-AUX 5.10.14/hardened-patches/0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch 2692 BLAKE2B 7f63b34062b872667ccd38d67c1d48aac2fa7ee97f92a005daaa874ac368b13f466b835b23f8f0616265cabc218e029e9f97b51e2c8443931eb571e66d5d2dc9 SHA512 4ae4e1bff7be423c854772dbb59bf4adc4677f2e3185c01ed2969b8f5fb19ddd978f4efae08bd291e9ba4e98e6cb5f84716dcd86224c566c2b64d296ca5eacf3
-AUX 5.10.14/hardened-patches/0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch 6075 BLAKE2B be6e150cc235fb13e4c51818d7b49a10bfb1675998390a16ed91230fa8f01e23f8724975de2954fe34b8b161cec51af7928c53453d881df8e995c71c341abfcd SHA512 c46549df950202cdfde765bb4d7d947c9858413265a44ad39b233a39e509a39e2b5c7dd08c1d449a09917364e3c0e7a744af38a441fed8338d51f222e629074e
-AUX 5.10.14/hardened-patches/0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch 8416 BLAKE2B ebe7841ce32fd3c1d36d993dc9fb46cc7d9ea57ee3d22904244183e1bf6fa1de93d10e3890a9c49c21a544b8651ae7ec2fe8a4151ec1ef5d4173c813052d5448 SHA512 a2ef4ffa7132f93ef77a71687c9f8f6ca31af10c80449a014332e2c5b3bb618dc6003ae4b4edcb1199a7f7382638acd8b9db160ddd68219ab7348f6de983b730
-AUX 5.10.14/hardened-patches/0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch 1427 BLAKE2B 077003157e1328b70ddd1d9c650224194c329db05760776fcbb8c6144a42c66685b6384120e5744d70c34106330fbf810c10d453c66d0b19fa28e55890e7eb20 SHA512 90724e27f99d734c86658b90185bb92fdacc0cd01b978c047bbbd6869afede1bebd3a28e1c8191caf8cc4ab0914db99dc76e0de61cf428efe01eb9776f93164f
-DIST debian-kconfig-5.10.13 172354 BLAKE2B 2f1fb579a89863fe28dce8f6ba7b8fac9322251c067912c270476c23e47edd43b07a05c968a5583fdf620282fc0d091b7912a1fa49b269c2b151373e3d920e62 SHA512 1087c56c1d923545e3309b24776f4aa3badc21befd56e3bffd22f718b9d84ad03b286d45ad24e1ce61c9d4a61f02612d97cd7fc962d652da18c8b3187f919a6f
-DIST debian-kconfig-5.10.14 172354 BLAKE2B 2f1fb579a89863fe28dce8f6ba7b8fac9322251c067912c270476c23e47edd43b07a05c968a5583fdf620282fc0d091b7912a1fa49b269c2b151373e3d920e62 SHA512 1087c56c1d923545e3309b24776f4aa3badc21befd56e3bffd22f718b9d84ad03b286d45ad24e1ce61c9d4a61f02612d97cd7fc962d652da18c8b3187f919a6f
-DIST debian-kconfig-amd64-5.10.13 4367 BLAKE2B dfa1559a2c8c5d2447979eee4bc52b5f7e7b310aee6e326f9b55036c01714d120ebc6ca7c9ffdba6c3241ffd6b3b13e8222f511db30797527145640680a39d26 SHA512 6473dceb7641a9e60eedfaa24be95e4d20401e9508ec907c49da2d73983f54eb293e781245ee84aa41f2728354be9bdb06191867008c111735e6962a1d79e888
-DIST debian-kconfig-amd64-5.10.14 4367 BLAKE2B dfa1559a2c8c5d2447979eee4bc52b5f7e7b310aee6e326f9b55036c01714d120ebc6ca7c9ffdba6c3241ffd6b3b13e8222f511db30797527145640680a39d26 SHA512 6473dceb7641a9e60eedfaa24be95e4d20401e9508ec907c49da2d73983f54eb293e781245ee84aa41f2728354be9bdb06191867008c111735e6962a1d79e888
-DIST debian-kconfig-arm64-5.10.13 25993 BLAKE2B 96c85926edde53779ea02c45a6cddff97c42fd6cd0c9df0b806e0c88f85aa6122826e7588c0646db1ee24ecb09f6e7d1b481b937ed10b5de216db81ae766c217 SHA512 805b5b286a17eb1adb1369ed27f4e3ed750d563edad7598773c447698671a1db72289fb87cb5f14acb51362c1029fea9f0a2e6c58f7e60c8c99d8f3c0f417632
-DIST debian-kconfig-arm64-5.10.14 26025 BLAKE2B 59dcb6f5c2c8c28a936644654dc33f14db235c7fa4ede999bffbc04162f3eb3d5c80fd9df15fe03fbaf085772048d6c0e37a2660090666f4e09d749b0e1e3db8 SHA512 9f1d9e367fb789e7ab998145d1dc2fbf6c129d77fa4c91936031f6505ad00e8365d01ff585dec9f6fce98f899a1bf4f64eefd0e35c3ce7315534c8ed3b3b5eb3
-DIST debian-kconfig-i386-5.10.13 8990 BLAKE2B 72fac181239cbc9eb8fd0dcfc8edac3f68447ca3368ec87a1beffe499c0cd30c4da6a44756dc0de56e2997ac265f238ce07e23f7b1883f9dfcf9a272d07005df SHA512 de116317bccce4476901597bbbf47ec62feba828e4fe74bdecd36f009b6a9d46c168a06eb0448bc688503e3ea8b9d427fb381513763a1d6389cbafdec7f1def5
-DIST debian-kconfig-i386-5.10.14 8990 BLAKE2B 72fac181239cbc9eb8fd0dcfc8edac3f68447ca3368ec87a1beffe499c0cd30c4da6a44756dc0de56e2997ac265f238ce07e23f7b1883f9dfcf9a272d07005df SHA512 de116317bccce4476901597bbbf47ec62feba828e4fe74bdecd36f009b6a9d46c168a06eb0448bc688503e3ea8b9d427fb381513763a1d6389cbafdec7f1def5
-DIST debian-kconfig-i686-5.10.13 1296 BLAKE2B a015d0163d8c484f59b85e18b32d4226bcf42416f94e732f44f9121cda8f99b88e3744bc4ae2fc31f88a48f972b7d6a842a1dab488341fcd4eec125ce649ecd7 SHA512 ab20d397b14d774706c278340d992a57b616b8f8aa084e17f9500d87d83915bdb922679275766ae7aebb42f4cc05d25dfd4e75ac9aae84e8dfa85141d31f0011
-DIST debian-kconfig-i686-5.10.14 1296 BLAKE2B a015d0163d8c484f59b85e18b32d4226bcf42416f94e732f44f9121cda8f99b88e3744bc4ae2fc31f88a48f972b7d6a842a1dab488341fcd4eec125ce649ecd7 SHA512 ab20d397b14d774706c278340d992a57b616b8f8aa084e17f9500d87d83915bdb922679275766ae7aebb42f4cc05d25dfd4e75ac9aae84e8dfa85141d31f0011
-DIST debian-kconfig-i686-pae-5.10.13 856 BLAKE2B 3c5a77d9a0c3dadbe4c1d1beb9b2f08e74d77635b520d27397218b4d63815f270e9d06939e17221a0df46fd6de8f758b9236a6654793eda21a336841e3d19f5d SHA512 920a5807ec1a742c35429b88b7702fed870b89ae365e95c9cd521b54102aa51f9ad1abcb0b1424d315b346af2e8ec57054ada5ddcc0ab1872d400956090fbf4b
-DIST debian-kconfig-i686-pae-5.10.14 856 BLAKE2B 3c5a77d9a0c3dadbe4c1d1beb9b2f08e74d77635b520d27397218b4d63815f270e9d06939e17221a0df46fd6de8f758b9236a6654793eda21a336841e3d19f5d SHA512 920a5807ec1a742c35429b88b7702fed870b89ae365e95c9cd521b54102aa51f9ad1abcb0b1424d315b346af2e8ec57054ada5ddcc0ab1872d400956090fbf4b
-DIST debian-kconfig-kernelarch-arm-5.10.13 2082 BLAKE2B 330b1d06e663ec20de70daf4d513f612366aa2e096c1a8f1cbdd93a86b32632c45060b1a3534fb29835baf1e908f346ef273606d82e5905fd49c26b8ca59941c SHA512 90f5ed4d96aa7a386ddf32c2cb58b0c36f85d99694d9f46ef2564dfe3deb94898585b6a899755afe4f78358d966730487d64730f3300f1b31cbe54246daa0128
-DIST debian-kconfig-kernelarch-arm-5.10.14 2082 BLAKE2B 330b1d06e663ec20de70daf4d513f612366aa2e096c1a8f1cbdd93a86b32632c45060b1a3534fb29835baf1e908f346ef273606d82e5905fd49c26b8ca59941c SHA512 90f5ed4d96aa7a386ddf32c2cb58b0c36f85d99694d9f46ef2564dfe3deb94898585b6a899755afe4f78358d966730487d64730f3300f1b31cbe54246daa0128
-DIST debian-kconfig-kernelarch-x86-5.10.13 40792 BLAKE2B 156921f8c394ad76e49216e83c7fba299cafa1e58655a3c7173ae8bd196fafe3227af872fc590a036d4b4959b06ab6d02e53d5730ad4ecc951d47fb52cb7dace SHA512 327574ed49d79089a505f1e8e3eb38e515fbe1e807120815aef4c858153a6ef77572a6a26b792a964c132f0ad704235005a95d3171246812e9622c4551aa9030
-DIST debian-kconfig-kernelarch-x86-5.10.14 40792 BLAKE2B 156921f8c394ad76e49216e83c7fba299cafa1e58655a3c7173ae8bd196fafe3227af872fc590a036d4b4959b06ab6d02e53d5730ad4ecc951d47fb52cb7dace SHA512 327574ed49d79089a505f1e8e3eb38e515fbe1e807120815aef4c858153a6ef77572a6a26b792a964c132f0ad704235005a95d3171246812e9622c4551aa9030
-DIST linux-5.10.13.tar.xz 116258488 BLAKE2B f2d6f5512c10ced0990d0d0cbc1aa29e5b54b90bff01f16d16093e9c192de9eb0f31e60c9dd51c686ce88c2a1d89a49bedb503af61c91a6a186794fbe71eedde SHA512 e894b9a98d34b0734ad87336530361b712ce60b57e47ea51e0efd66a4446e740b7e2bebc489e41e59523c0cc5f4066f36036eac2c4cfd7d99a63682c24d887be
-DIST linux-5.10.14.tar.xz 116254224 BLAKE2B 34ba86c15532eff73ed3cd5d34bb125a534776425a98c43ceff187a9f950c4a12afbe35c5e63306150cdeff5d4e43c5094182d6533381661fe6e5ce82aeaed16 SHA512 8e5016bfc7f5c090af6247ddac41cb3f811576bd078b2e145d798be6f214f72ee77bbff09d48d54a0154a9b137166650c88a1d178d50d5901dcaa03bb2c5e6f1
-EBUILD cairn-sources-5.10.13.ebuild 28705 BLAKE2B 2eacea3d0d6773cfe9c22c1cd6f34e26c14558f88b227c29fbc139ce50f2871098ee11882777c6459eecf4370aa106e80e26e96e441c7ea1e25789a24c4b741a SHA512 a9c7b2548fb80a0d64ca886e2b0d576b59518f6add35b483bdb2a9cea44cc8e54a8bbd3039cf1c82a53d616483a357f5c9c7c3b8cb39343df031c25ad3a5be35
-EBUILD cairn-sources-5.10.14.ebuild 28803 BLAKE2B 1b3619fe2708a0247822e8f0f27f7c5f2856bbbc367438a21c64be7a94839fc2558640dce01e5bb2b1ef1a42c0e05644cc71b11db9fdf33dd14bbbb82031ff02 SHA512 6b406fab0e0ac34fd2e860cfb6c1a330bbf6110f04f9163da39455f302f67bf05c6e40247c10c9b5a10f51bbfa9f6e0601477490fbc6c8f260687c633f72471f
diff --git a/sys-kernel/cairn-sources/cairn-sources-5.10.13.ebuild b/sys-kernel/cairn-sources/cairn-sources-5.10.13.ebuild
deleted file mode 100644
index 2bcdb056c783..000000000000
--- a/sys-kernel/cairn-sources/cairn-sources-5.10.13.ebuild
+++ /dev/null
@@ -1,700 +0,0 @@
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit check-reqs eutils mount-boot toolchain-funcs
-
-DESCRIPTION="Linux kernel sources with some optional patches."
-HOMEPAGE="https://kernel.org"
-
-LICENSE="GPL-2"
-KEYWORDS="x86 amd64 arm arm64"
-
-SLOT="${PV}"
-
-RESTRICT="binchecks strip mirror"
-
-IUSE="binary btrfs clang custom-cflags debug dmraid dtrace ec2 firmware hardened iscsi luks lvm mcelog mdadm microcode multipath nbd nfs plymouth selinux sign-modules symlink systemd wireguard zfs"
-
-BDEPEND="
- sys-devel/bc
- debug? ( dev-util/dwarves )
- virtual/libelf
-"
-
-DEPEND="
- binary? ( sys-kernel/dracut )
- btrfs? ( sys-fs/btrfs-progs )
- dtrace? (
- dev-util/dtrace-utils
- dev-libs/libdtrace-ctf
- )
- firmware? (
- sys-kernel/linux-firmware
- )
- luks? ( sys-fs/cryptsetup )
- lvm? ( sys-fs/lvm2 )
- mdadm? ( sys-fs/mdadm )
- mcelog? ( app-admin/mcelog )
- plymouth? (
- x11-libs/libdrm[libkms]
- sys-boot/plymouth[libkms,udev]
- )
- sign-modules? (
- || ( dev-libs/openssl
- dev-libs/libressl
- )
- sys-apps/kmod
- )
- systemd? ( sys-apps/systemd )
- wireguard? ( virtual/wireguard )
- zfs? ( sys-fs/zfs )
-"
-
-# linux kernel upstream
-KERNEL_VERSION="5.10.13"
-KERNEL_ARCHIVE="linux-${KERNEL_VERSION}.tar.xz"
-KERNEL_UPSTREAM="https://cdn.kernel.org/pub/linux/kernel/v5.x/${KERNEL_ARCHIVE}"
-KERNEL_EXTRAVERSION="-cairn"
-
-KERNEL_CONFIG_UPSTREAM="https://salsa.debian.org/kernel-team/linux/-/raw/debian/5.10.12-1/debian/config"
-
-SRC_URI="
- ${KERNEL_UPSTREAM}
-
- ${KERNEL_CONFIG_UPSTREAM}/config -> debian-kconfig-${PV}
- x86? (
- ${KERNEL_CONFIG_UPSTREAM}/i386/config -> debian-kconfig-i386-${PV}
- ${KERNEL_CONFIG_UPSTREAM}/i386/config.686 -> debian-kconfig-i686-${PV}
- ${KERNEL_CONFIG_UPSTREAM}/i386/config.686-pae -> debian-kconfig-i686-pae-${PV}
- ${KERNEL_CONFIG_UPSTREAM}/kernelarch-x86/config -> debian-kconfig-kernelarch-x86-${PV}
- )
- amd64? (
- ${KERNEL_CONFIG_UPSTREAM}/amd64/config -> debian-kconfig-amd64-${PV}
- ${KERNEL_CONFIG_UPSTREAM}/kernelarch-x86/config -> debian-kconfig-kernelarch-x86-${PV}
- )
- arm64? (
- ${KERNEL_CONFIG_UPSTREAM}/arm64/config -> debian-kconfig-arm64-${PV}
- ${KERNEL_CONFIG_UPSTREAM}/kernelarch-arm/config -> debian-kconfig-kernelarch-arm-${PV}
- )
-"
-
-S="$WORKDIR/linux-${KERNEL_VERSION}"
-
-# TODO: manage HARDENED_PATCHES and GENTOO_PATCHES
-# can be managed in a git repository and packed into tar balls per version.
-
-HARDENED_PATCHES_DIR="${FILESDIR}/${KERNEL_VERSION}/hardened-patches"
-
-# 'linux-hardened' minimal patch set to compliment existing Kernel-Self-Protection-Project
-# 0033-enable-protected_-symlinks-hardlinks-by-default.patch
-# 0066-security-perf-Allow-further-restriction-of-perf_even.patch
-# 0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch
-HARDENED_PATCHES=(
- 0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch
- 0002-enable-HARDENED_USERCOPY-by-default.patch
- 0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch
- 0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch
- 0005-set-kptr_restrict-2-by-default.patch
- 0006-enable-DEBUG_LIST-by-default.patch
- 0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch
- 0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch
- 0009-arm64-enable-RANDOMIZE_BASE-by-default.patch
- 0010-enable-SLAB_FREELIST_RANDOM-by-default.patch
- 0011-enable-SLAB_FREELIST_HARDENED-by-default.patch
- 0012-disable-SLAB_MERGE_DEFAULT-by-default.patch
- 0013-enable-FORTIFY_SOURCE-by-default.patch
- 0014-enable-PANIC_ON_OOPS-by-default.patch
- 0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch
- 0016-stop-hiding-X86_16BIT-behind-EXPERT.patch
- 0017-disable-X86_16BIT-by-default.patch
- 0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch
- 0019-disable-MODIFY_LDT_SYSCALL-by-default.patch
- 0020-set-LEGACY_VSYSCALL_NONE-by-default.patch
- 0021-stop-hiding-AIO-behind-EXPERT.patch
- 0022-disable-AIO-by-default.patch
- 0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch
- 0024-disable-DEVPORT-by-default.patch
- 0025-disable-PROC_VMCORE-by-default.patch
- 0026-disable-NFS_DEBUG-by-default.patch
- 0027-enable-DEBUG_WX-by-default.patch
- 0028-disable-LEGACY_PTYS-by-default.patch
- 0029-disable-DEVMEM-by-default.patch
- 0030-enable-IO_STRICT_DEVMEM-by-default.patch
- 0031-disable-COMPAT_BRK-by-default.patch
- 0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch
- 0033-enable-protected_-symlinks-hardlinks-by-default.patch
- 0034-enable-SECURITY-by-default.patch
- 0035-enable-SECURITY_YAMA-by-default.patch
- 0036-enable-SECURITY_NETWORK-by-default.patch
- 0037-enable-AUDIT-by-default.patch
- 0038-enable-SECURITY_SELINUX-by-default.patch
- 0039-enable-SYN_COOKIES-by-default.patch
- 0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch
- 0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch
- 0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch
- 0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch
- 0044-disable-SYSFS_SYSCALL-by-default.patch
- 0045-stop-hiding-UID16-behind-EXPERT.patch
- 0046-disable-UID16-by-default.patch
- 0047-add-__read_only-for-non-init-related-usage.patch
- 0048-make-sysctl-constants-read-only.patch
- 0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch
- 0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch
- 0051-mark-slub-runtime-configuration-as-__ro_after_init.patch
- 0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch
- 0053-mark-kmem_cache-as-__ro_after_init.patch
- 0054-mark-__supported_pte_mask-as-__ro_after_init.patch
- 0055-mark-kobj_ns_type_register-as-only-used-for-init.patch
- 0056-mark-open_softirq-as-only-used-for-init.patch
- 0057-remove-unused-softirq_action-callback-parameter.patch
- 0058-mark-softirq_vec-as-__ro_after_init.patch
- 0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch
- 0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch
- 0061-bug-on-PageSlab-PageCompound-in-ksize.patch
- 0062-mm-add-support-for-verifying-page-sanitization.patch
- 0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch
- 0064-slub-Add-support-for-verifying-slab-sanitization.patch
- 0065-slub-add-multi-purpose-random-canaries.patch
- 0066-security-perf-Allow-further-restriction-of-perf_even.patch
- 0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch
- 0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch
- 0069-add-CONFIG-for-unprivileged_userns_clone.patch
- 0070-add-kmalloc-krealloc-alloc_size-attributes.patch
- 0071-add-vmalloc-alloc_size-attributes.patch
- 0072-add-kvmalloc-alloc_size-attribute.patch
- 0073-add-percpu-alloc_size-attributes.patch
- 0074-add-alloc_pages_exact-alloc_size-attributes.patch
- 0075-Add-the-extra_latent_entropy-kernel-parameter.patch
- 0076-ata-avoid-null-pointer-dereference-on-bug.patch
- 0077-sanity-check-for-negative-length-in-nla_memcpy.patch
- 0078-add-page-destructor-sanity-check.patch
- 0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch
- 0080-add-writable-function-pointer-detection.patch
- 0081-support-overriding-early-audit-kernel-cmdline.patch
- 0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch
- 0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch
- 0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch
- 0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch
- 0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch
- 0087-randomize-lower-bits-of-the-argument-block.patch
- 0088-x86_64-match-arm64-brk-randomization-entropy.patch
- 0089-support-randomizing-the-lower-bits-of-brk.patch
- 0090-mm-randomize-lower-bits-of-brk.patch
- 0091-x86-randomize-lower-bits-of-brk.patch
- 0092-mm-guarantee-brk-gap-is-at-least-one-page.patch
- 0093-x86-guarantee-brk-gap-is-at-least-one-page.patch
- 0094-x86_64-bound-mmap-between-legacy-modern-bases.patch
- 0095-restrict-device-timing-side-channels.patch
- 0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch
- 0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch
- 0098-usb-implement-dedicated-subsystem-sysctl-tables.patch
- 0099-hard-wire-legacy-checkreqprot-option-to-0.patch
- 0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch
- 0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch
- 0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch
- 0103-disable-unprivileged-eBPF-access-by-default.patch
- 0104-enable-BPF-JIT-hardening-by-default-if-available.patch
- 0105-enable-protected_-fifos-regular-by-default.patch
- 0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch
- 0107-mm-Fix-extra_latent_entropy.patch
- 0108-add-CONFIG-for-unprivileged_userfaultfd.patch
- 0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch
- 0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch
- 0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch
- 0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch
-)
-
-GENTOO_PATCHES_DIR="${FILESDIR}/${KERNEL_VERSION}/gentoo-patches"
-
-# Gentoo Linux 'genpatches' patch set
-# 1510_fs-enable-link-security-restrctions-by-default.patch is already provided in hardened patches
-# 4567_distro-Gentoo-Kconfiig TODO?
-GENTOO_PATCHES=(
- 1500_XATTR_USER_PREFIX.patch
-# 1510_fs-enable-link-security-restrictions-by-default.patch
- 2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
- 2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch
- 2920_sign-file-patch-for-libressl.patch
-# 4567_distro-Gentoo-Kconfig.patch
- 5000_shiftfs-ubuntu-20.04.patch
-)
-
-DTRACE_PATCHES_DIR="${FILESDIR}/${KERNEL_VERSION}/dtrace-patches"
-
-DTRACE_PATCHES=(
- 0001-ctf-generate-CTF-information-for-the-kernel.patch
- 0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch
- 0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch
- 0004-dtrace-core-and-x86.patch
- 0005-dtrace-modular-components-and-x86-support.patch
- 0006-dtrace-systrace-provider-core-components.patch
- 0007-dtrace-systrace-provider.patch
- 0008-dtrace-sdt-provider-core-components.patch
- 0009-dtrace-sdt-provider-for-x86.patch
- 0010-dtrace-profile-provider-and-test-probe-core-componen.patch
- 0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch
- 0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch
- 0013-dtrace-USDT-and-pid-providers.patch
- 0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch
- 0015-dtrace-fbt-provider-modular-components.patch
- 0016-dtrace-arm-arm64-port.patch
- 0017-dtrace-add-SDT-probes.patch
- 0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch
- 0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch
-)
-
-get_certs_dir() {
- # find a certificate dir in /etc/kernel/certs/ that contains signing cert for modules.
- for subdir in $PF $P linux; do
- certdir=/etc/kernel/certs/$subdir
- if [ -d $certdir ]; then
- if [ ! -e $certdir/signing_key.pem ]; then
- eerror "$certdir exists but missing signing key; exiting."
- exit 1
- fi
- echo $certdir
- return
- fi
- done
-}
-
-pkg_pretend() {
- # Ensure we have enough disk space to compile
- if use binary ; then
- CHECKREQS_DISK_BUILD="5G"
- check-reqs_pkg_setup
- fi
-}
-
-pkg_setup() {
- export REAL_ARCH="$ARCH"
- unset ARCH; unset LDFLAGS #will interfere with Makefile if set
-}
-
-src_unpack() {
-
- # unpack the kernel sources to ${WORKDIR}
- unpack ${KERNEL_ARCHIVE} || die "failed to unpack kernel sources"
-
- # unpack the various kconfig files into a single file
- cat "${DISTDIR}"/debian-kconfig-* >> "${WORKDIR}"/debian-kconfig-${PV} || die "failed to unpack kconfig"
-}
-
-src_prepare() {
-
- ### PATCHES ###
-
- # only apply these if USE=hardened as the patches will break proprietary userspace and some others.
- if use hardened; then
- # apply hardening patches
- einfo "Applying hardening patches ..."
- for my_patch in ${HARDENED_PATCHES[*]} ; do
- eapply "${HARDENED_PATCHES_DIR}/${my_patch}" || die "failed to apply hardened patches"
- done
- fi
-
- # apply gentoo patches
- einfo "Applying Gentoo Linux patches ..."
- for my_patch in ${GENTOO_PATCHES[*]} ; do
- eapply "${GENTOO_PATCHES_DIR}/${my_patch}" || die "failed to apply Gentoo Linux patches"
- done
-
- # apply DTrace patches
- einfo "Applying DTrace patches ..."
- for my_patch in ${DTRACE_PATCHES[*]} ; do
- eapply "${DTRACE_PATCHES_DIR}/${my_patch}" || die "failed to apply DTrace patches"
- done
-
- if ! use hardened; then
- eapply "${FILESDIR}"/${KERNEL_VERSION}/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch
- fi
-
- # append EXTRAVERSION to the kernel sources Makefile
- sed -i -e "s:^\(EXTRAVERSION =\).*:\1 ${KERNEL_EXTRAVERSION}:" Makefile || die "failed to append EXTRAVERSION to kernel Makefile"
-
- # todo: look at this, haven't seen it used in many cases.
- sed -i -e 's:#export\tINSTALL_PATH:export\tINSTALL_PATH:' Makefile || die "failed to fix-up INSTALL_PATH in kernel Makefile"
-
- # copy the kconfig file into the kernel sources tree
- cp "${WORKDIR}"/debian-kconfig-${PV} "${S}"/.config
-
- ### TWEAK CONFIG ###
-
- # Do not configure Debian devs certificates
- echo 'CONFIG_SYSTEM_TRUSTED_KEYS=""' >> .config
-
- # enable IKCONFIG so that /proc/config.gz can be used for various checks
- # TODO: Maybe not a good idea for USE=hardened, look into this...
- echo "CONFIG_IKCONFIG=y" >> .config
- echo "CONFIG_IKCONFIG_PROC=y" >> .config
-
- if use custom-cflags; then
- MARCH="$(python -c "import portage; print(portage.settings[\"CFLAGS\"])" | sed 's/ /\n/g' | grep "march")"
- if [ -n "$MARCH" ]; then
- sed -i -e 's/-mtune=generic/$MARCH/g' arch/x86/Makefile || die "Canna optimize this kernel anymore, captain!"
- fi
- fi
-
- # only enable debugging symbols etc if USE=debug...
- if use debug; then
- echo "CONFIG_DEBUG_INFO=y" >> .config
- else
- echo "CONFIG_DEBUG_INFO=n" >> .config
- fi
-
- if use dtrace; then
- echo "CONFIG_DTRACE=y" >> .config
- echo "CONFIG_DT_CORE=m" >> .config
- echo "CONFIG_DT_FASTTRAP=m" >> .config
- echo "CONFIG_DT_PROFILE=m" >> .config
- echo "CONFIG_DT_SDT=m" >> .config
- echo "CONFIG_DT_SDT_PERF=y" >> .config
- echo "CONFIG_DT_FBT=m" >> .config
- echo "CONFIG_DT_SYSTRACE=m" >> .config
- echo "CONFIG_DT_DT_TEST=m" >> .config
- echo "CONFIG_DT_DT_PERF=m" >> .config
- echo "CONFIG_DT_DEBUG=n" >> .config
- echo "CONFIG_WAITFD=y" >> .config
- fi
-
- # these options should already be set, but are a hard dependency for ec2, so we ensure they are set if USE=ec2
- if use ec2; then
- echo "CONFIG_BLK_DEV_NVME=y" >> .config
- echo "CONFIG_XEN_BLKDEV_FRONTEND=m" >> .config
- echo "CONFIG_XEN_BLKDEV_BACKEND=m" >> .config
- echo "CONFIG_IXGBEVF=m" >> .config
- fi
-
- # hardening opts
- # TODO: document these
- if use hardened; then
- echo "CONFIG_AUDIT=y" >> .config
- echo "CONFIG_EXPERT=y" >> .config
- echo "CONFIG_SLUB_DEBUG=y" >> .config
- echo "CONFIG_SLAB_MERGE_DEFAULT=n" >> .config
- echo "CONFIG_SLAB_FREELIST_RANDOM=y" >> .config
- echo "CONFIG_SLAB_FREELIST_HARDENED=y" >> .config
- echo "CONFIG_SLAB_CANARY=y" >> .config
- echo "CONFIG_SHUFFLE_PAGE_ALLOCATOR=y" >> .config
- echo "CONFIG_RANDOMIZE_BASE=y" >> .config
- echo "CONFIG_RANDOMIZE_MEMORY=y" >> .config
- echo "CONFIG_HIBERNATION=n" >> .config
- echo "CONFIG_HARDENED_USERCOPY=y" >> .config
- echo "CONFIG_HARDENED_USERCOPY_FALLBACK=n" >> .config
- echo "CONFIG_FORTIFY_SOURCE=y" >> .config
- echo "CONFIG_STACKPROTECTOR=y" >> .config
- echo "CONFIG_STACKPROTECTOR_STRONG=y" >> .config
- echo "CONFIG_ARCH_MMAP_RND_BITS=32" >> .config
- echo "CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16" >> .config
- echo "CONFIG_INIT_ON_FREE_DEFAULT_ON=y" >> .config
- echo "CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y" >> .config
- echo "CONFIG_SLAB_SANITIZE_VERIFY=y" >> .config
- echo "CONFIG_PAGE_SANITIZE_VERIFY=y" >> .config
-
- # gcc plugins
- if ! use clang; then
- echo "CONFIG_GCC_PLUGINS=y" >> .config
- echo "CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y" >> .config
- echo "CONFIG_GCC_PLUGIN_STRUCTLEAK=y" >> .config
- echo "CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL=y" >> .config
- echo "CONFIG_GCC_PLUGIN_STACKLEAK=y" >> .config
- echo "CONFIG_STACKLEAK_TRACK_MIN_SIZE=100" >> .config
- echo "CONFIG_STACKLEAK_METRICS=n" >> .config
- echo "CONFIG_STACKLEAK_RUNTIME_DISABLE=n" >> .config
- echo "CONFIG_GCC_PLUGIN_RANDSTRUCT=y" >> .config
- echo "CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE=n" >> .config
- fi
-
- # main hardening options complete... anything after this point is a focus on disabling potential attack vectors
- # i.e legacy drivers, new complex code that isn't yet proven, or code that we really don't want in a hardened kernel.
- echo 'CONFIG_KEXEC=n' >> .config
- echo "CONFIG_KEXEC_FILE=n" >> .config
- echo 'CONFIG_KEXEC_SIG=n' >> .config
- fi
-
- # mcelog is deprecated, but there are still some valid use cases and requirements for it... so stick it behind a USE flag for optional kernel support.
- if use mcelog; then
- echo "CONFIG_X86_MCELOG_LEGACY=y" >> .config
- fi
-
- # sign kernel modules via
- if use sign-modules; then
- certs_dir=$(get_certs_dir)
- echo
- if [ -z "$certs_dir" ]; then
- eerror "No certs dir found in /etc/kernel/certs; aborting."
- die
- else
- einfo "Using certificate directory of $certs_dir for kernel module signing."
- fi
- echo
- # turn on options for signing modules.
- # first, remove existing configs and comments:
- echo 'CONFIG_MODULE_SIG=""' >> .config
-
- # now add our settings:
- echo 'CONFIG_MODULE_SIG=y' >> .config
- echo 'CONFIG_MODULE_SIG_FORCE=n' >> .config
- echo 'CONFIG_MODULE_SIG_ALL=n' >> .config
- echo 'CONFIG_MODULE_SIG_HASH="sha512"' >> .config
- echo 'CONFIG_MODULE_SIG_KEY="${certs_dir}/signing_key.pem"' >> .config
- echo 'CONFIG_SYSTEM_TRUSTED_KEYRING=y' >> .config
- echo 'CONFIG_SYSTEM_EXTRA_CERTIFICATE=y' >> .config
- echo 'CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE="4096"' >> .config
- echo "CONFIG_MODULE_SIG_SHA512=y" >> .config
-
- # print some info to warn user
- ewarn "This kernel will ALLOW non-signed modules to be loaded with a WARNING."
- ewarn "To enable strict enforcement, YOU MUST add module.sig_enforce=1 as a kernel boot"
- ewarn "parameter (to params in /etc/boot.conf, and re-run boot-update.)"
- echo
- fi
-
- # enable wireguard support within kernel
- if use wireguard; then
- echo 'CONFIG_WIREGUARD=m' >> .config
- # there are some other options, but I need to verify them first, so I'll start with this
- fi
-
- # get config into good state:
- yes "" | make oldconfig >/dev/null 2>&1 || die
- cp .config "${T}"/.config || die
- make -s mrproper || die "make mrproper failed"
-
- # Apply any user patches
- eapply_user
-}
-
-src_configure() {
-
- if use binary; then
-
- tc-export_build_env
- MAKEARGS=(
- V=1
-
- HOSTCC="$(tc-getBUILD_CC)"
- HOSTCXX="$(tc-getBUILD_CXX)"
- HOSTCFLAGS="${BUILD_CFLAGS}"
- HOSTLDFLAGS="${BUILD_LDFLAGS}"
-
- CROSS_COMPILE=${CHOST}-
- AS="$(tc-getAS)"
- CC="$(tc-getCC)"
- LD="$(tc-getLD)"
- AR="$(tc-getAR)"
- NM="$(tc-getNM)"
- STRIP=":"
- OBJCOPY="$(tc-getOBJCOPY)"
- OBJDUMP="$(tc-getOBJDUMP)"
-
- # we need to pass it to override colliding Gentoo envvar
- ARCH=$(tc-arch-kernel)
- )
-
- mkdir -p "${WORKDIR}"/modprep || die
- cp "${T}"/.config "${WORKDIR}"/modprep/ || die
- emake O="${WORKDIR}"/modprep "${MAKEARGS[@]}" olddefconfig || die "kernel configure failed"
- emake O="${WORKDIR}"/modprep "${MAKEARGS[@]}" modules_prepare || die "modules_prepare failed"
- cp -pR "${WORKDIR}"/modprep "${WORKDIR}"/build || die
- fi
-}
-
-src_compile() {
-
- if use binary; then
-
- emake O="${WORKDIR}"/build "${MAKEARGS[@]}" all || "kernel build failed"
- fi
-}
-
-src_install() {
-
- # TODO: Change to SANDBOX_WRITE=".." for installkernel writes
- # Disable sandbox
- export SANDBOX_ON=0
-
- # create sources directory if required
- dodir /usr/src
-
- # copy kernel sources into place
- cp -a "${S}" "${D}"/usr/src/linux-${PV}${KERNEL_EXTRAVERSION} || die "failed to install kernel sources"
-
- # change to installed kernel sources directory
- cd "${D}"/usr/src/linux-${PV}${KERNEL_EXTRAVERSION}
-
- # prepare for real-world use and 3rd-party module building:
- make mrproper || die "failed to prepare kernel sources"
-
- # copy kconfig into place
- cp "${T}"/.config .config || die "failed to copy kconfig from ${TEMPDIR}"
-
- # if we didn't USE=binary - we're done.
- # The kernel source tree is left in an unconfigured state - you can't compile 3rd-party modules against it yet.
- if use binary; then
- make prepare || die
- make scripts || die
-
- local targets=( modules_install )
-
- # ARM / ARM64 requires dtb
- if (use arm || use arm64); then
- targets+=( dtbs_install )
- fi
-
- emake O="${WORKDIR}"/build "${MAKEARGS[@]}" INSTALL_MOD_PATH="${ED}" INSTALL_PATH="${ED}/boot" "${targets[@]}"
- installkernel "${PV}${KERNEL_EXTRAVERSION}" "${WORKDIR}/build/arch/x86_64/boot/bzImage" "${WORKDIR}/build/System.map" "${EROOT}/boot"
-
- # module symlink fix-up:
- rm -rf "${D}"/lib/modules/${PV}${KERNEL_EXTRAVERSION}/source || die "failed to remove old kernel source symlink"
- rm -rf "${D}"/lib/modules/${PV}${KERNEL_EXTRAVERSION}/build || die "failed to remove old kernel build symlink"
-
- # Set-up module symlinks:
- ln -s /usr/src/linux-${PV}${KERNEL_EXTRAVERSION} "${ED}"/lib/modules/${PV}${KERNEL_EXTRAVERSION}/source || die "failed to create kernel source symlink"
- ln -s /usr/src/linux-${PV}${KERNEL_EXTRAVERSION} "${ED}"/lib/modules/${PV}${KERNEL_EXTRAVERSION}/build || die "failed to create kernel build symlink"
-
- # Fixes FL-14
- cp "${WORKDIR}/build/System.map" "${D}"/usr/src/linux-${PV}${KERNEL_EXTRAVERSION}/ || die "failed to install System.map"
- cp "${WORKDIR}/build/Module.symvers" "${D}"/usr/src/linux-${PV}${KERNEL_EXTRAVERSION}/ || die "failed to install Module.symvers"
-
- if use sign-modules; then
- for x in $(find "${D}"/lib/modules -iname *.ko); do
- # $certs_dir defined previously in this function.
- ${WORKDIR}/build/scripts/sign-file sha512 $certs_dir/signing_key.pem $certs_dir/signing_key.x509 $x || die
- done
- # install the sign-file executable for future use.
- exeinto /usr/src/linux-${PV}-${KERNEL_EXTRAVERSION}/scripts
- doexe ${WORKDIR}/build/scripts/sign-file
- fi
- fi
-}
-
-pkg_postinst() {
-
- # TODO: Change to SANDBOX_WRITE=".." for Dracut writes
- export SANDBOX_ON=0
-
- # if USE=symlink...
- if use symlink; then
- # delete the existing symlink if one exists
- if [[ -h "${EROOT}"/usr/src/linux ]]; then
- rm "${EROOT}"/usr/src/linux
- fi
- # and now symlink the newly installed sources
- ewarn ""
- ewarn "WARNING... WARNING... WARNING"
- ewarn ""
- ewarn "/usr/src/linux symlink automatically set to linux-${PV}${KERNEL_EXTRAVERSION}"
- ewarn ""
- ln -sf "${EROOT}"/usr/src/linux-${PV}${KERNEL_EXTRAVERSION} "${EROOT}"/usr/src/linux
- fi
-
- # if there's a modules folder for these sources, generate modules.dep and map files
- if [[ -d ${EROOT}/lib/modules/${PV}${KERNEL_EXTRAVERSION} ]]; then
- depmod -a ${PV}${KERNEL_EXTRAVERSION}
- fi
-
- # NOTE: WIP and not well tested yet.
- #
- # Dracut will build an initramfs when USE=binary.
- #
- # The initramfs will be configurable via USE, i.e.
- # USE=zfs will pass '--zfs' to Dracut
- # USE=-systemd will pass '--omit dracut-systemd systemd systemd-networkd systemd-initrd' to exclude these (Dracut) modules from the initramfs.
- #
- # NOTE 2: this will create a fairly.... minimal, and modular initramfs. It has been tested with things with ZFS and LUKS, and 'works'.
- # Things like network support have not been tested (I am currently unsure how well this works with Gentoo Linux based systems),
- # and may end up requiring network-manager for decent support (this really needs further research).
- if use binary; then
- einfo ""
- einfo ">>> Dracut: building initramfs"
- dracut \
- --stdlog=1 \
- --force \
- --no-hostonly \
- --add "base dm fs-lib i18n kernel-modules rootfs-block shutdown terminfo udev-rules usrmount" \
- --omit "biosdevname bootchart busybox caps convertfs dash debug dmsquash-live dmsquash-live-ntfs fcoe fcoe-uefi fstab-sys gensplash ifcfg img-lib livenet mksh network network-manager qemu qemu-net rpmversion securityfs ssh-client stratis syslog url-lib" \
- $(usex btrfs "-a btrfs" "-o btrfs") \
- $(usex dmraid "-a dmraid" "-o dmraid") \
- $(usex hardened "-o resume" "-a resume") \
- $(usex iscsi "-a iscsi" "-o iscsi") \
- $(usex lvm "-a lvm" "-o lvm") \
- $(usex lvm "--lvmconf" "--nolvmconf") \
- $(usex luks "-a crypt" "-o crypt") \
- $(usex mdadm "--mdadmconf" "--nomdadmconf") \
- $(usex mdadm "-a mdraid" "-o mdraid") \
- $(usex microcode "--early-microcode" "--no-early-microcode") \
- $(usex multipath "-a multipath" "-o multipath") \
- $(usex nbd "-a nbd" "-o nbd") \
- $(usex nfs "-a nfs" "-o nfs") \
- $(usex plymouth "-a plymouth" "-o plymouth") \
- $(usex selinux "-a selinux" "-o selinux") \
- $(usex systemd "-a systemd -a systemd-initrd -a systemd-networkd" "-o systemd -o systemd-initrd -o systemd-networkd") \
- $(usex zfs "-a zfs" "-o zfs") \
- --kver ${PV}${KERNEL_EXTRAVERSION} \
- --kmoddir ${EROOT}/lib/modules/${PV}${KERNEL_EXTRAVERSION} \
- --fwdir ${EROOT}/lib/firmware \
- --kernel-image ${EROOT}/boot/vmlinuz-${PV}${KERNEL_EXTRAVERSION}
- einfo ""
- einfo ">>> Dracut: Finished building initramfs"
- ewarn ""
- ewarn "WARNING... WARNING... WARNING..."
- ewarn ""
- ewarn "Dracut initramfs has been generated!"
- ewarn ""
- ewarn "Required kernel arguments:"
- ewarn ""
- ewarn " root=/dev/ROOT"
- ewarn ""
- ewarn " Where ROOT is the device node for your root partition as the"
- ewarn " one specified in /etc/fstab"
- ewarn ""
- ewarn "Additional kernel cmdline arguments that *may* be required to boot properly..."
- ewarn ""
- ewarn "If you use hibernation:"
- ewarn ""
- ewarn " resume=/dev/SWAP"
- ewarn ""
- ewarn " Where $SWAP is the swap device used by hibernate software of your choice."
- ewarn""
- ewarn " Please consult "man 7 dracut.kernel" for additional kernel arguments."
- fi
-
- # warn about the issues with running a hardened kernel
- if use hardened; then
- ewarn ""
- ewarn "WARNING... WARNING... WARNING..."
- ewarn ""
- ewarn "Hardened patches have been applied to the kernel and KCONFIG options have been set."
- ewarn "These KCONFIG options and patches change kernel behavior."
- ewarn "Changes include:"
- ewarn "Increased entropy for Address Space Layout Randomization"
- ewarn "GCC plugins (if using GCC)"
- ewarn "Memory allocation"
- ewarn "... and more"
- ewarn ""
- ewarn "These changes will stop certain programs from functioning"
- ewarn "e.g. VirtualBox, Skype"
- ewarn "Full information available in $DOCUMENTATION"
- ewarn ""
- fi
-
- # if there are out-of-tree kernel modules detected, warn warn warn
- # TODO: tidy up below
- if use binary && [[ -e "${EROOT}"/var/lib/module-rebuild/moduledb ]]; then
- ewarn ""
- ewarn "WARNING... WARNING... WARNING..."
- ewarn ""
- ewarn "External kernel modules are not yet automatically built"
- ewarn "by USE=binary - emerge @modules-rebuild to do this"
- ewarn "and regenerate your initramfs if you are using ZFS root filesystem"
- ewarn ""
- fi
-
- if use binary; then
- if [[ -e /etc/boot.conf ]]; then
- ego boot update
- fi
- fi
-}
diff --git a/sys-kernel/cairn-sources/cairn-sources-5.10.14.ebuild b/sys-kernel/cairn-sources/cairn-sources-5.10.14.ebuild
deleted file mode 100644
index 38da68c76efe..000000000000
--- a/sys-kernel/cairn-sources/cairn-sources-5.10.14.ebuild
+++ /dev/null
@@ -1,703 +0,0 @@
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit check-reqs eutils mount-boot toolchain-funcs
-
-DESCRIPTION="Linux kernel sources with some optional patches."
-HOMEPAGE="https://kernel.org"
-
-LICENSE="GPL-2"
-KEYWORDS="x86 amd64 arm arm64"
-
-SLOT="${PV}"
-
-RESTRICT="binchecks strip mirror"
-
-IUSE="binary btrfs clang custom-cflags debug dmraid dtrace ec2 firmware hardened iscsi luks lvm mcelog mdadm microcode multipath nbd nfs plymouth selinux sign-modules symlink systemd wireguard zfs"
-
-BDEPEND="
- sys-devel/bc
- debug? ( dev-util/dwarves )
- virtual/libelf
-"
-
-DEPEND="
- binary? ( sys-kernel/dracut )
- btrfs? ( sys-fs/btrfs-progs )
- dtrace? (
- dev-util/dtrace-utils
- dev-libs/libdtrace-ctf
- )
- firmware? (
- sys-kernel/linux-firmware
- )
- luks? ( sys-fs/cryptsetup )
- lvm? ( sys-fs/lvm2 )
- mdadm? ( sys-fs/mdadm )
- mcelog? ( app-admin/mcelog )
- plymouth? (
- x11-libs/libdrm[libkms]
- sys-boot/plymouth[libkms,udev]
- )
- sign-modules? (
- || ( dev-libs/openssl
- dev-libs/libressl
- )
- sys-apps/kmod
- )
- systemd? ( sys-apps/systemd )
- wireguard? ( virtual/wireguard )
- zfs? ( sys-fs/zfs )
-"
-
-# linux kernel upstream
-KERNEL_VERSION="5.10.14"
-KERNEL_ARCHIVE="linux-${KERNEL_VERSION}.tar.xz"
-KERNEL_UPSTREAM="https://cdn.kernel.org/pub/linux/kernel/v5.x/${KERNEL_ARCHIVE}"
-KERNEL_EXTRAVERSION="-cairn"
-
-KERNEL_CONFIG_UPSTREAM="https://salsa.debian.org/kernel-team/linux/-/raw/debian/5.10.13-1/debian/config"
-
-SRC_URI="
- ${KERNEL_UPSTREAM}
-
- ${KERNEL_CONFIG_UPSTREAM}/config -> debian-kconfig-${PV}
- x86? (
- ${KERNEL_CONFIG_UPSTREAM}/i386/config -> debian-kconfig-i386-${PV}
- ${KERNEL_CONFIG_UPSTREAM}/i386/config.686 -> debian-kconfig-i686-${PV}
- ${KERNEL_CONFIG_UPSTREAM}/i386/config.686-pae -> debian-kconfig-i686-pae-${PV}
- ${KERNEL_CONFIG_UPSTREAM}/kernelarch-x86/config -> debian-kconfig-kernelarch-x86-${PV}
- )
- amd64? (
- ${KERNEL_CONFIG_UPSTREAM}/amd64/config -> debian-kconfig-amd64-${PV}
- ${KERNEL_CONFIG_UPSTREAM}/kernelarch-x86/config -> debian-kconfig-kernelarch-x86-${PV}
- )
- arm64? (
- ${KERNEL_CONFIG_UPSTREAM}/arm64/config -> debian-kconfig-arm64-${PV}
- ${KERNEL_CONFIG_UPSTREAM}/kernelarch-arm/config -> debian-kconfig-kernelarch-arm-${PV}
- )
-"
-
-S="$WORKDIR/linux-${KERNEL_VERSION}"
-
-# TODO: manage HARDENED_PATCHES and GENTOO_PATCHES
-# can be managed in a git repository and packed into tar balls per version.
-
-HARDENED_PATCHES_DIR="${FILESDIR}/${KERNEL_VERSION}/hardened-patches"
-
-# 'linux-hardened' minimal patch set to compliment existing Kernel-Self-Protection-Project
-# 0033-enable-protected_-symlinks-hardlinks-by-default.patch
-# 0066-security-perf-Allow-further-restriction-of-perf_even.patch
-# 0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch
-HARDENED_PATCHES=(
- 0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch
- 0002-enable-HARDENED_USERCOPY-by-default.patch
- 0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch
- 0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch
- 0005-set-kptr_restrict-2-by-default.patch
- 0006-enable-DEBUG_LIST-by-default.patch
- 0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch
- 0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch
- 0009-arm64-enable-RANDOMIZE_BASE-by-default.patch
- 0010-enable-SLAB_FREELIST_RANDOM-by-default.patch
- 0011-enable-SLAB_FREELIST_HARDENED-by-default.patch
- 0012-disable-SLAB_MERGE_DEFAULT-by-default.patch
- 0013-enable-FORTIFY_SOURCE-by-default.patch
- 0014-enable-PANIC_ON_OOPS-by-default.patch
- 0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch
- 0016-stop-hiding-X86_16BIT-behind-EXPERT.patch
- 0017-disable-X86_16BIT-by-default.patch
- 0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch
- 0019-disable-MODIFY_LDT_SYSCALL-by-default.patch
- 0020-set-LEGACY_VSYSCALL_NONE-by-default.patch
- 0021-stop-hiding-AIO-behind-EXPERT.patch
- 0022-disable-AIO-by-default.patch
- 0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch
- 0024-disable-DEVPORT-by-default.patch
- 0025-disable-PROC_VMCORE-by-default.patch
- 0026-disable-NFS_DEBUG-by-default.patch
- 0027-enable-DEBUG_WX-by-default.patch
- 0028-disable-LEGACY_PTYS-by-default.patch
- 0029-disable-DEVMEM-by-default.patch
- 0030-enable-IO_STRICT_DEVMEM-by-default.patch
- 0031-disable-COMPAT_BRK-by-default.patch
- 0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch
- 0033-enable-protected_-symlinks-hardlinks-by-default.patch
- 0034-enable-SECURITY-by-default.patch
- 0035-enable-SECURITY_YAMA-by-default.patch
- 0036-enable-SECURITY_NETWORK-by-default.patch
- 0037-enable-AUDIT-by-default.patch
- 0038-enable-SECURITY_SELINUX-by-default.patch
- 0039-enable-SYN_COOKIES-by-default.patch
- 0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch
- 0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch
- 0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch
- 0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch
- 0044-disable-SYSFS_SYSCALL-by-default.patch
- 0045-stop-hiding-UID16-behind-EXPERT.patch
- 0046-disable-UID16-by-default.patch
- 0047-add-__read_only-for-non-init-related-usage.patch
- 0048-make-sysctl-constants-read-only.patch
- 0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch
- 0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch
- 0051-mark-slub-runtime-configuration-as-__ro_after_init.patch
- 0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch
- 0053-mark-kmem_cache-as-__ro_after_init.patch
- 0054-mark-__supported_pte_mask-as-__ro_after_init.patch
- 0055-mark-kobj_ns_type_register-as-only-used-for-init.patch
- 0056-mark-open_softirq-as-only-used-for-init.patch
- 0057-remove-unused-softirq_action-callback-parameter.patch
- 0058-mark-softirq_vec-as-__ro_after_init.patch
- 0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch
- 0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch
- 0061-bug-on-PageSlab-PageCompound-in-ksize.patch
- 0062-mm-add-support-for-verifying-page-sanitization.patch
- 0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch
- 0064-slub-Add-support-for-verifying-slab-sanitization.patch
- 0065-slub-add-multi-purpose-random-canaries.patch
- 0066-security-perf-Allow-further-restriction-of-perf_even.patch
- 0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch
- 0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch
- 0069-add-CONFIG-for-unprivileged_userns_clone.patch
- 0070-add-kmalloc-krealloc-alloc_size-attributes.patch
- 0071-add-vmalloc-alloc_size-attributes.patch
- 0072-add-kvmalloc-alloc_size-attribute.patch
- 0073-add-percpu-alloc_size-attributes.patch
- 0074-add-alloc_pages_exact-alloc_size-attributes.patch
- 0075-Add-the-extra_latent_entropy-kernel-parameter.patch
- 0076-ata-avoid-null-pointer-dereference-on-bug.patch
- 0077-sanity-check-for-negative-length-in-nla_memcpy.patch
- 0078-add-page-destructor-sanity-check.patch
- 0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch
- 0080-add-writable-function-pointer-detection.patch
- 0081-support-overriding-early-audit-kernel-cmdline.patch
- 0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch
- 0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch
- 0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch
- 0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch
- 0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch
- 0087-randomize-lower-bits-of-the-argument-block.patch
- 0088-x86_64-match-arm64-brk-randomization-entropy.patch
- 0089-support-randomizing-the-lower-bits-of-brk.patch
- 0090-mm-randomize-lower-bits-of-brk.patch
- 0091-x86-randomize-lower-bits-of-brk.patch
- 0092-mm-guarantee-brk-gap-is-at-least-one-page.patch
- 0093-x86-guarantee-brk-gap-is-at-least-one-page.patch
- 0094-x86_64-bound-mmap-between-legacy-modern-bases.patch
- 0095-restrict-device-timing-side-channels.patch
- 0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch
- 0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch
- 0098-usb-implement-dedicated-subsystem-sysctl-tables.patch
- 0099-hard-wire-legacy-checkreqprot-option-to-0.patch
- 0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch
- 0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch
- 0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch
- 0103-disable-unprivileged-eBPF-access-by-default.patch
- 0104-enable-BPF-JIT-hardening-by-default-if-available.patch
- 0105-enable-protected_-fifos-regular-by-default.patch
- 0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch
- 0107-mm-Fix-extra_latent_entropy.patch
- 0108-add-CONFIG-for-unprivileged_userfaultfd.patch
- 0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch
- 0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch
- 0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch
- 0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch
-)
-
-GENTOO_PATCHES_DIR="${FILESDIR}/${KERNEL_VERSION}/gentoo-patches"
-
-# Gentoo Linux 'genpatches' patch set
-# 1510_fs-enable-link-security-restrctions-by-default.patch is already provided in hardened patches
-# 4567_distro-Gentoo-Kconfiig TODO?
-GENTOO_PATCHES=(
- 1500_XATTR_USER_PREFIX.patch
-# 1510_fs-enable-link-security-restrictions-by-default.patch
- 2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
- 2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch
- 2920_sign-file-patch-for-libressl.patch
-# 4567_distro-Gentoo-Kconfig.patch
- 5000_shiftfs-ubuntu-20.04.patch
-)
-
-DTRACE_PATCHES_DIR="${FILESDIR}/${KERNEL_VERSION}/dtrace-patches"
-
-DTRACE_PATCHES=(
- 0001-ctf-generate-CTF-information-for-the-kernel.patch
- 0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch
- 0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch
- 0004-dtrace-core-and-x86.patch
- 0005-dtrace-modular-components-and-x86-support.patch
- 0006-dtrace-systrace-provider-core-components.patch
- 0007-dtrace-systrace-provider.patch
- 0008-dtrace-sdt-provider-core-components.patch
- 0009-dtrace-sdt-provider-for-x86.patch
- 0010-dtrace-profile-provider-and-test-probe-core-componen.patch
- 0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch
- 0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch
- 0013-dtrace-USDT-and-pid-providers.patch
- 0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch
- 0015-dtrace-fbt-provider-modular-components.patch
- 0016-dtrace-arm-arm64-port.patch
- 0017-dtrace-add-SDT-probes.patch
- 0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch
- 0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch
-)
-
-get_certs_dir() {
- # find a certificate dir in /etc/kernel/certs/ that contains signing cert for modules.
- for subdir in $PF $P linux; do
- certdir=/etc/kernel/certs/$subdir
- if [ -d $certdir ]; then
- if [ ! -e $certdir/signing_key.pem ]; then
- eerror "$certdir exists but missing signing key; exiting."
- exit 1
- fi
- echo $certdir
- return
- fi
- done
-}
-
-pkg_pretend() {
- # Ensure we have enough disk space to compile
- if use binary ; then
- CHECKREQS_DISK_BUILD="5G"
- check-reqs_pkg_setup
- fi
-}
-
-pkg_setup() {
- export REAL_ARCH="$ARCH"
- unset ARCH; unset LDFLAGS #will interfere with Makefile if set
-}
-
-src_unpack() {
-
- # unpack the kernel sources to ${WORKDIR}
- unpack ${KERNEL_ARCHIVE} || die "failed to unpack kernel sources"
-
- # unpack the various kconfig files into a single file
- cat "${DISTDIR}"/debian-kconfig-* >> "${WORKDIR}"/debian-kconfig-${PV} || die "failed to unpack kconfig"
-}
-
-src_prepare() {
-
- ### PATCHES ###
-
- # only apply these if USE=hardened as the patches will break proprietary userspace and some others.
- if use hardened; then
- # apply hardening patches
- einfo "Applying hardening patches ..."
- for my_patch in ${HARDENED_PATCHES[*]} ; do
- eapply "${HARDENED_PATCHES_DIR}/${my_patch}" || die "failed to apply hardened patches"
- done
- fi
-
- # apply gentoo patches
- einfo "Applying Gentoo Linux patches ..."
- for my_patch in ${GENTOO_PATCHES[*]} ; do
- eapply "${GENTOO_PATCHES_DIR}/${my_patch}" || die "failed to apply Gentoo Linux patches"
- done
-
- if use dtrace ; then
- # apply DTrace patches
- einfo "Applying DTrace patches ..."
- for my_patch in ${DTRACE_PATCHES[*]} ; do
- eapply "${DTRACE_PATCHES_DIR}/${my_patch}" || die "failed to apply DTrace patches"
- done
- fi
-
- if ! use hardened; then
- eapply "${FILESDIR}"/${KERNEL_VERSION}/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch
- fi
-
- # append EXTRAVERSION to the kernel sources Makefile
- sed -i -e "s:^\(EXTRAVERSION =\).*:\1 ${KERNEL_EXTRAVERSION}:" Makefile || die "failed to append EXTRAVERSION to kernel Makefile"
-
- # todo: look at this, haven't seen it used in many cases.
- sed -i -e 's:#export\tINSTALL_PATH:export\tINSTALL_PATH:' Makefile || die "failed to fix-up INSTALL_PATH in kernel Makefile"
-
- # copy the kconfig file into the kernel sources tree
- cp "${WORKDIR}"/debian-kconfig-${PV} "${S}"/.config
-
- ### TWEAK CONFIG ###
-
- # Do not configure Debian devs certificates
- echo 'CONFIG_SYSTEM_TRUSTED_KEYS=""' >> .config
-
- # enable IKCONFIG so that /proc/config.gz can be used for various checks
- # TODO: Maybe not a good idea for USE=hardened, look into this...
- echo "CONFIG_IKCONFIG=y" >> .config
- echo "CONFIG_IKCONFIG_PROC=y" >> .config
-
- if use custom-cflags; then
- MARCH="$(python -c "import portage; print(portage.settings[\"CFLAGS\"])" | sed 's/ /\n/g' | grep "march")"
- if [ -n "$MARCH" ]; then
- sed -i -e 's/-mtune=generic/$MARCH/g' arch/x86/Makefile || die "Canna optimize this kernel anymore, captain!"
- fi
- fi
-
- # only enable debugging symbols etc if USE=debug...
- if use debug; then
- echo "CONFIG_DEBUG_INFO=y" >> .config
- else
- echo "CONFIG_DEBUG_INFO=n" >> .config
- fi
-
- if use dtrace; then
- echo "CONFIG_DTRACE=y" >> .config
- echo "CONFIG_DT_CORE=m" >> .config
- echo "CONFIG_DT_FASTTRAP=m" >> .config
- echo "CONFIG_DT_PROFILE=m" >> .config
- echo "CONFIG_DT_SDT=m" >> .config
- echo "CONFIG_DT_SDT_PERF=y" >> .config
- echo "CONFIG_DT_FBT=m" >> .config
- echo "CONFIG_DT_SYSTRACE=m" >> .config
- echo "CONFIG_DT_DT_TEST=m" >> .config
- echo "CONFIG_DT_DT_PERF=m" >> .config
- echo "CONFIG_DT_DEBUG=n" >> .config
- echo "CONFIG_WAITFD=y" >> .config
- echo "CONFIG_DEBUG_INFO=y" >> .config
- fi
-
- # these options should already be set, but are a hard dependency for ec2, so we ensure they are set if USE=ec2
- if use ec2; then
- echo "CONFIG_BLK_DEV_NVME=y" >> .config
- echo "CONFIG_XEN_BLKDEV_FRONTEND=m" >> .config
- echo "CONFIG_XEN_BLKDEV_BACKEND=m" >> .config
- echo "CONFIG_IXGBEVF=m" >> .config
- fi
-
- # hardening opts
- # TODO: document these
- if use hardened; then
- echo "CONFIG_AUDIT=y" >> .config
- echo "CONFIG_EXPERT=y" >> .config
- echo "CONFIG_SLUB_DEBUG=y" >> .config
- echo "CONFIG_SLAB_MERGE_DEFAULT=n" >> .config
- echo "CONFIG_SLAB_FREELIST_RANDOM=y" >> .config
- echo "CONFIG_SLAB_FREELIST_HARDENED=y" >> .config
- echo "CONFIG_SLAB_CANARY=y" >> .config
- echo "CONFIG_SHUFFLE_PAGE_ALLOCATOR=y" >> .config
- echo "CONFIG_RANDOMIZE_BASE=y" >> .config
- echo "CONFIG_RANDOMIZE_MEMORY=y" >> .config
- echo "CONFIG_HIBERNATION=n" >> .config
- echo "CONFIG_HARDENED_USERCOPY=y" >> .config
- echo "CONFIG_HARDENED_USERCOPY_FALLBACK=n" >> .config
- echo "CONFIG_FORTIFY_SOURCE=y" >> .config
- echo "CONFIG_STACKPROTECTOR=y" >> .config
- echo "CONFIG_STACKPROTECTOR_STRONG=y" >> .config
- echo "CONFIG_ARCH_MMAP_RND_BITS=32" >> .config
- echo "CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16" >> .config
- echo "CONFIG_INIT_ON_FREE_DEFAULT_ON=y" >> .config
- echo "CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y" >> .config
- echo "CONFIG_SLAB_SANITIZE_VERIFY=y" >> .config
- echo "CONFIG_PAGE_SANITIZE_VERIFY=y" >> .config
-
- # gcc plugins
- if ! use clang; then
- echo "CONFIG_GCC_PLUGINS=y" >> .config
- echo "CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y" >> .config
- echo "CONFIG_GCC_PLUGIN_STRUCTLEAK=y" >> .config
- echo "CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL=y" >> .config
- echo "CONFIG_GCC_PLUGIN_STACKLEAK=y" >> .config
- echo "CONFIG_STACKLEAK_TRACK_MIN_SIZE=100" >> .config
- echo "CONFIG_STACKLEAK_METRICS=n" >> .config
- echo "CONFIG_STACKLEAK_RUNTIME_DISABLE=n" >> .config
- echo "CONFIG_GCC_PLUGIN_RANDSTRUCT=y" >> .config
- echo "CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE=n" >> .config
- fi
-
- # main hardening options complete... anything after this point is a focus on disabling potential attack vectors
- # i.e legacy drivers, new complex code that isn't yet proven, or code that we really don't want in a hardened kernel.
- echo 'CONFIG_KEXEC=n' >> .config
- echo "CONFIG_KEXEC_FILE=n" >> .config
- echo 'CONFIG_KEXEC_SIG=n' >> .config
- fi
-
- # mcelog is deprecated, but there are still some valid use cases and requirements for it... so stick it behind a USE flag for optional kernel support.
- if use mcelog; then
- echo "CONFIG_X86_MCELOG_LEGACY=y" >> .config
- fi
-
- # sign kernel modules via
- if use sign-modules; then
- certs_dir=$(get_certs_dir)
- echo
- if [ -z "$certs_dir" ]; then
- eerror "No certs dir found in /etc/kernel/certs; aborting."
- die
- else
- einfo "Using certificate directory of $certs_dir for kernel module signing."
- fi
- echo
- # turn on options for signing modules.
- # first, remove existing configs and comments:
- echo 'CONFIG_MODULE_SIG=""' >> .config
-
- # now add our settings:
- echo 'CONFIG_MODULE_SIG=y' >> .config
- echo 'CONFIG_MODULE_SIG_FORCE=n' >> .config
- echo 'CONFIG_MODULE_SIG_ALL=n' >> .config
- echo 'CONFIG_MODULE_SIG_HASH="sha512"' >> .config
- echo 'CONFIG_MODULE_SIG_KEY="${certs_dir}/signing_key.pem"' >> .config
- echo 'CONFIG_SYSTEM_TRUSTED_KEYRING=y' >> .config
- echo 'CONFIG_SYSTEM_EXTRA_CERTIFICATE=y' >> .config
- echo 'CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE="4096"' >> .config
- echo "CONFIG_MODULE_SIG_SHA512=y" >> .config
-
- # print some info to warn user
- ewarn "This kernel will ALLOW non-signed modules to be loaded with a WARNING."
- ewarn "To enable strict enforcement, YOU MUST add module.sig_enforce=1 as a kernel boot"
- ewarn "parameter (to params in /etc/boot.conf, and re-run boot-update.)"
- echo
- fi
-
- # enable wireguard support within kernel
- if use wireguard; then
- echo 'CONFIG_WIREGUARD=m' >> .config
- # there are some other options, but I need to verify them first, so I'll start with this
- fi
-
- # get config into good state:
- yes "" | make oldconfig >/dev/null 2>&1 || die
- cp .config "${T}"/.config || die
- make -s mrproper || die "make mrproper failed"
-
- # Apply any user patches
- eapply_user
-}
-
-src_configure() {
-
- if use binary; then
-
- tc-export_build_env
- MAKEARGS=(
- V=1
-
- HOSTCC="$(tc-getBUILD_CC)"
- HOSTCXX="$(tc-getBUILD_CXX)"
- HOSTCFLAGS="${BUILD_CFLAGS}"
- HOSTLDFLAGS="${BUILD_LDFLAGS}"
-
- CROSS_COMPILE=${CHOST}-
- AS="$(tc-getAS)"
- CC="$(tc-getCC)"
- LD="$(tc-getLD)"
- AR="$(tc-getAR)"
- NM="$(tc-getNM)"
- STRIP=":"
- OBJCOPY="$(tc-getOBJCOPY)"
- OBJDUMP="$(tc-getOBJDUMP)"
-
- # we need to pass it to override colliding Gentoo envvar
- ARCH=$(tc-arch-kernel)
- )
-
- mkdir -p "${WORKDIR}"/modprep || die
- cp "${T}"/.config "${WORKDIR}"/modprep/ || die
- emake O="${WORKDIR}"/modprep "${MAKEARGS[@]}" olddefconfig || die "kernel configure failed"
- emake O="${WORKDIR}"/modprep "${MAKEARGS[@]}" modules_prepare || die "modules_prepare failed"
- cp -pR "${WORKDIR}"/modprep "${WORKDIR}"/build || die
- fi
-}
-
-src_compile() {
-
- if use binary; then
-
- emake O="${WORKDIR}"/build "${MAKEARGS[@]}" all || "kernel build failed"
- fi
-}
-
-src_install() {
-
- # TODO: Change to SANDBOX_WRITE=".." for installkernel writes
- # Disable sandbox
- export SANDBOX_ON=0
-
- # create sources directory if required
- dodir /usr/src
-
- # copy kernel sources into place
- cp -a "${S}" "${D}"/usr/src/linux-${PV}${KERNEL_EXTRAVERSION} || die "failed to install kernel sources"
-
- # change to installed kernel sources directory
- cd "${D}"/usr/src/linux-${PV}${KERNEL_EXTRAVERSION}
-
- # prepare for real-world use and 3rd-party module building:
- make mrproper || die "failed to prepare kernel sources"
-
- # copy kconfig into place
- cp "${T}"/.config .config || die "failed to copy kconfig from ${TEMPDIR}"
-
- # if we didn't USE=binary - we're done.
- # The kernel source tree is left in an unconfigured state - you can't compile 3rd-party modules against it yet.
- if use binary; then
- make prepare || die
- make scripts || die
-
- local targets=( modules_install )
-
- # ARM / ARM64 requires dtb
- if (use arm || use arm64); then
- targets+=( dtbs_install )
- fi
-
- emake O="${WORKDIR}"/build "${MAKEARGS[@]}" INSTALL_MOD_PATH="${ED}" INSTALL_PATH="${ED}/boot" "${targets[@]}"
- installkernel "${PV}${KERNEL_EXTRAVERSION}" "${WORKDIR}/build/arch/x86_64/boot/bzImage" "${WORKDIR}/build/System.map" "${EROOT}/boot"
-
- # module symlink fix-up:
- rm -rf "${D}"/lib/modules/${PV}${KERNEL_EXTRAVERSION}/source || die "failed to remove old kernel source symlink"
- rm -rf "${D}"/lib/modules/${PV}${KERNEL_EXTRAVERSION}/build || die "failed to remove old kernel build symlink"
-
- # Set-up module symlinks:
- ln -s /usr/src/linux-${PV}${KERNEL_EXTRAVERSION} "${ED}"/lib/modules/${PV}${KERNEL_EXTRAVERSION}/source || die "failed to create kernel source symlink"
- ln -s /usr/src/linux-${PV}${KERNEL_EXTRAVERSION} "${ED}"/lib/modules/${PV}${KERNEL_EXTRAVERSION}/build || die "failed to create kernel build symlink"
-
- # Fixes FL-14
- cp "${WORKDIR}/build/System.map" "${D}"/usr/src/linux-${PV}${KERNEL_EXTRAVERSION}/ || die "failed to install System.map"
- cp "${WORKDIR}/build/Module.symvers" "${D}"/usr/src/linux-${PV}${KERNEL_EXTRAVERSION}/ || die "failed to install Module.symvers"
-
- if use sign-modules; then
- for x in $(find "${D}"/lib/modules -iname *.ko); do
- # $certs_dir defined previously in this function.
- ${WORKDIR}/build/scripts/sign-file sha512 $certs_dir/signing_key.pem $certs_dir/signing_key.x509 $x || die
- done
- # install the sign-file executable for future use.
- exeinto /usr/src/linux-${PV}-${KERNEL_EXTRAVERSION}/scripts
- doexe ${WORKDIR}/build/scripts/sign-file
- fi
- fi
-}
-
-pkg_postinst() {
-
- # TODO: Change to SANDBOX_WRITE=".." for Dracut writes
- export SANDBOX_ON=0
-
- # if USE=symlink...
- if use symlink; then
- # delete the existing symlink if one exists
- if [[ -h "${EROOT}"/usr/src/linux ]]; then
- rm "${EROOT}"/usr/src/linux
- fi
- # and now symlink the newly installed sources
- ewarn ""
- ewarn "WARNING... WARNING... WARNING"
- ewarn ""
- ewarn "/usr/src/linux symlink automatically set to linux-${PV}${KERNEL_EXTRAVERSION}"
- ewarn ""
- ln -sf "${EROOT}"/usr/src/linux-${PV}${KERNEL_EXTRAVERSION} "${EROOT}"/usr/src/linux
- fi
-
- # if there's a modules folder for these sources, generate modules.dep and map files
- if [[ -d ${EROOT}/lib/modules/${PV}${KERNEL_EXTRAVERSION} ]]; then
- depmod -a ${PV}${KERNEL_EXTRAVERSION}
- fi
-
- # NOTE: WIP and not well tested yet.
- #
- # Dracut will build an initramfs when USE=binary.
- #
- # The initramfs will be configurable via USE, i.e.
- # USE=zfs will pass '--zfs' to Dracut
- # USE=-systemd will pass '--omit dracut-systemd systemd systemd-networkd systemd-initrd' to exclude these (Dracut) modules from the initramfs.
- #
- # NOTE 2: this will create a fairly.... minimal, and modular initramfs. It has been tested with things with ZFS and LUKS, and 'works'.
- # Things like network support have not been tested (I am currently unsure how well this works with Gentoo Linux based systems),
- # and may end up requiring network-manager for decent support (this really needs further research).
- if use binary; then
- einfo ""
- einfo ">>> Dracut: building initramfs"
- dracut \
- --stdlog=1 \
- --force \
- --no-hostonly \
- --add "base dm fs-lib i18n kernel-modules rootfs-block shutdown terminfo udev-rules usrmount" \
- --omit "biosdevname bootchart busybox caps convertfs dash debug dmsquash-live dmsquash-live-ntfs fcoe fcoe-uefi fstab-sys gensplash ifcfg img-lib livenet mksh network network-manager qemu qemu-net rpmversion securityfs ssh-client stratis syslog url-lib" \
- $(usex btrfs "-a btrfs" "-o btrfs") \
- $(usex dmraid "-a dmraid" "-o dmraid") \
- $(usex hardened "-o resume" "-a resume") \
- $(usex iscsi "-a iscsi" "-o iscsi") \
- $(usex lvm "-a lvm" "-o lvm") \
- $(usex lvm "--lvmconf" "--nolvmconf") \
- $(usex luks "-a crypt" "-o crypt") \
- $(usex mdadm "--mdadmconf" "--nomdadmconf") \
- $(usex mdadm "-a mdraid" "-o mdraid") \
- $(usex microcode "--early-microcode" "--no-early-microcode") \
- $(usex multipath "-a multipath" "-o multipath") \
- $(usex nbd "-a nbd" "-o nbd") \
- $(usex nfs "-a nfs" "-o nfs") \
- $(usex plymouth "-a plymouth" "-o plymouth") \
- $(usex selinux "-a selinux" "-o selinux") \
- $(usex systemd "-a systemd -a systemd-initrd -a systemd-networkd" "-o systemd -o systemd-initrd -o systemd-networkd") \
- $(usex zfs "-a zfs" "-o zfs") \
- --kver ${PV}${KERNEL_EXTRAVERSION} \
- --kmoddir ${EROOT}/lib/modules/${PV}${KERNEL_EXTRAVERSION} \
- --fwdir ${EROOT}/lib/firmware \
- --kernel-image ${EROOT}/boot/vmlinuz-${PV}${KERNEL_EXTRAVERSION}
- einfo ""
- einfo ">>> Dracut: Finished building initramfs"
- ewarn ""
- ewarn "WARNING... WARNING... WARNING..."
- ewarn ""
- ewarn "Dracut initramfs has been generated!"
- ewarn ""
- ewarn "Required kernel arguments:"
- ewarn ""
- ewarn " root=/dev/ROOT"
- ewarn ""
- ewarn " Where ROOT is the device node for your root partition as the"
- ewarn " one specified in /etc/fstab"
- ewarn ""
- ewarn "Additional kernel cmdline arguments that *may* be required to boot properly..."
- ewarn ""
- ewarn "If you use hibernation:"
- ewarn ""
- ewarn " resume=/dev/SWAP"
- ewarn ""
- ewarn " Where $SWAP is the swap device used by hibernate software of your choice."
- ewarn""
- ewarn " Please consult "man 7 dracut.kernel" for additional kernel arguments."
- fi
-
- # warn about the issues with running a hardened kernel
- if use hardened; then
- ewarn ""
- ewarn "WARNING... WARNING... WARNING..."
- ewarn ""
- ewarn "Hardened patches have been applied to the kernel and KCONFIG options have been set."
- ewarn "These KCONFIG options and patches change kernel behavior."
- ewarn "Changes include:"
- ewarn "Increased entropy for Address Space Layout Randomization"
- ewarn "GCC plugins (if using GCC)"
- ewarn "Memory allocation"
- ewarn "... and more"
- ewarn ""
- ewarn "These changes will stop certain programs from functioning"
- ewarn "e.g. VirtualBox, Skype"
- ewarn "Full information available in $DOCUMENTATION"
- ewarn ""
- fi
-
- # if there are out-of-tree kernel modules detected, warn warn warn
- # TODO: tidy up below
- if use binary && [[ -e "${EROOT}"/var/lib/module-rebuild/moduledb ]]; then
- ewarn ""
- ewarn "WARNING... WARNING... WARNING..."
- ewarn ""
- ewarn "External kernel modules are not yet automatically built"
- ewarn "by USE=binary - emerge @modules-rebuild to do this"
- ewarn "and regenerate your initramfs if you are using ZFS root filesystem"
- ewarn ""
- fi
-
- if use binary; then
- if [[ -e /etc/boot.conf ]]; then
- ego boot update
- fi
- fi
-}
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0001-ctf-generate-CTF-information-for-the-kernel.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0001-ctf-generate-CTF-information-for-the-kernel.patch
deleted file mode 100644
index c9ba20a6c135..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0001-ctf-generate-CTF-information-for-the-kernel.patch
+++ /dev/null
@@ -1,7297 +0,0 @@
-From ee291dd05f9c4904f1c5a110d22cf0c3a5580df6 Mon Sep 17 00:00:00 2001
-From: Nick Alcock <nick.alcock@oracle.com>
-Date: Wed, 14 Nov 2018 19:42:21 +0000
-Subject: [PATCH 01/19] ctf: generate CTF information for the kernel
-
-This introduces a new tool, dwarf2ctf, which runs whenever 'make ctf' is
-run, extracting information on the kernel's types and global variables
-from the DWARF-format debug information in the kernel build tree,
-deduplicating it, and emitting it in Sun's Compact Type Format into a
-mmappable type archive named vmlinux.ctfa, which is installed at 'make
-install' time into /lib/modules/$(uname -r)/kernel/. Out-of-tree
-modules cannot participate in this mechanism since the file is already
-written: CTF information for such modules is instead linked into such
-modules at build time as new sections named .SUNW_ctf (as a result, most
-of the build-time machinery for this is in scripts/Makefile.modpost).
-Care should be taken not to strip such sections into debug RPMs (they
-are small enough that this should not be a problem).
-
-Within the ctfa file, the type information is divided into a shared
-repository, containing all types used by more than one module, CTF for
-the core kernel, and separate CTF for each module built, whether or not
-this module has been compiled in or not: if a file *could* be built as a
-module, it will be considered to be a module from the perspective of CTF
-file emission (and kallmodsyms: see the next commit). This ensures that
-external consumers such as DTrace always find types for a given module
-in the same place, regardless of the local kernel configuration, as long
-as that module is present at all, assisting in portability of D scripts
-between installations. The ctf_ar tool in libdtrace-ctf can be used to
-inspect ctfa files, and the ctf_dump tool can be used to look at the ctf
-files they contain.
-
-This process needs a pair of new files, objects.builtin (which lists all
-object files that are unconditionally built into the kernel and cannot
-be built as modules) and modules_thick.builtin, which maps from the thin
-archives that make up built-in modules to their constituent object
-files. Taken together, these files let dwarf2ctf determine whether a
-given object file linked into vmlinux.o is part of a module, and if so,
-which one.
-
-There is a single manually-maintained blacklist of structure members
-dwarf2ctf cannot handle in scripts/dwarf2ctf/member.blacklist: this is
-used to identify structure members which have different definitions in
-different object files even though they are defined in the same location
-in the same source file, usually due to preprocessor magic. (Currently,
-the only item in this list is present for example purposes only, since
-the file in question was recently removed from the kernel: dwarf2ctf can
-these days identify most members needing blacklisting automatically, and
-will fail with an error if it needs more help. It is quite possible that
-dwarf2ctf will fail on make allyesconfig kernel configurations and other
-extreme cases: I hope to track all such bugs down in time.)
-
-The documentation for dwarf2ctf is currently somewhat outdated: an
-update is planned. It remains largely accurate except for some details
-of the deduplication pass.
-
-This introduces new kernel build-time dependencies on elfutils, zlib,
-glib, and the new libdtrace-ctf package (shared with DTrace userspace).
-No new runtime dependencies are introduced.
-
-v5.6: retain the tristate machinery and scripts/Makefile.modbuiltin,
- since there appears to be no other way to get modules_thick.builtin
- (or anything like it) generated.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
----
- .gitignore | 3 +
- Documentation/dontdiff | 1 +
- Documentation/dwarf2ctf | 1054 ++++++
- Documentation/kbuild/kconfig.rst | 5 +
- Documentation/process/changes.rst | 23 +-
- Makefile | 72 +-
- lib/Kconfig | 12 +
- scripts/Kbuild.include | 6 +
- scripts/Makefile | 1 +
- scripts/Makefile.modbuiltin | 60 +
- scripts/Makefile.modfinal | 141 +-
- scripts/dwarf2ctf/.gitignore | 1 +
- scripts/dwarf2ctf/Makefile | 10 +
- scripts/dwarf2ctf/dwarf2ctf.c | 4962 ++++++++++++++++++++++++++++
- scripts/dwarf2ctf/eu_simple.c | 2 +
- scripts/dwarf2ctf/member.blacklist | 1 +
- scripts/eu_simple.c | 356 ++
- scripts/eu_simple.h | 91 +
- scripts/kconfig/confdata.c | 41 +-
- scripts/move-if-change | 8 +
- scripts/package/mkspec | 12 +
- 21 files changed, 6851 insertions(+), 11 deletions(-)
- create mode 100644 Documentation/dwarf2ctf
- create mode 100644 scripts/Makefile.modbuiltin
- create mode 100644 scripts/dwarf2ctf/.gitignore
- create mode 100644 scripts/dwarf2ctf/Makefile
- create mode 100644 scripts/dwarf2ctf/dwarf2ctf.c
- create mode 100644 scripts/dwarf2ctf/eu_simple.c
- create mode 100644 scripts/dwarf2ctf/member.blacklist
- create mode 100644 scripts/eu_simple.c
- create mode 100644 scripts/eu_simple.h
- create mode 100755 scripts/move-if-change
-
-diff --git a/.gitignore b/.gitignore
-index d01cda8e1177..1c10cd7ce033 100644
---- a/.gitignore
-+++ b/.gitignore
-@@ -48,6 +48,8 @@
- Module.symvers
- modules.builtin
- modules.order
-+modules_thick.builtin
-+objects.builtin
-
- #
- # Top-level generic files
-@@ -58,6 +60,7 @@ modules.order
- /vmlinux
- /vmlinux.32
- /vmlinux.symvers
-+/vmlinux.ctfa
- /vmlinux-gdb.py
- /vmlinuz
- /System.map
-diff --git a/Documentation/dontdiff b/Documentation/dontdiff
-index e361fc95ca29..a763d0fb892e 100644
---- a/Documentation/dontdiff
-+++ b/Documentation/dontdiff
-@@ -181,6 +181,7 @@ modpost
- modules.builtin
- modules.builtin.modinfo
- modules.nsdeps
-+modules_thick.builtin
- modules.order
- modversions.h*
- nconf
-diff --git a/Documentation/dwarf2ctf b/Documentation/dwarf2ctf
-new file mode 100644
-index 000000000000..5cc445fbd227
---- /dev/null
-+++ b/Documentation/dwarf2ctf
-@@ -0,0 +1,1054 @@
-+dwarf2ctf, a type encoder for the Linux kernel
-+=========
-+
-+Many kernel-level debugging and tracing systems need access to the kernel's type
-+information. Since C doesn't support any form of introspection, the data must
-+be extracted in some other way: here, we extract it from the DWARF debugging
-+information generated by the compiler. Unfortunately, this information is very
-+voluminous (just the type information alone adds up to a couple of hundred
-+megabytes in a 'make allyesconfig' kernel): even if users are happy to spend the
-+disk space, the time and memory required to read much of this information in is
-+likely to be prohibitive.
-+
-+This problem is not new -- back in 2004, Sun had the same problem when
-+attempting to give DTrace a view of the type information in the Solaris kernel.
-+Their solution was the Compact ANSI-C Type Format (CTF), a highly compacted
-+representation of C types suitable for debuggers and tracers. They combined
-+this with a highly efficient tool for converting DWARF2 types to CTF, and hacks
-+in the Solaris kernel causing the kernel itself to emit CTF data for its own
-+types.
-+
-+Unfortunately while this tool may be highly efficient it is not adequate for the
-+Linux kernel. It treats every ELF object as an independent entity with an
-+independent set of types -- perfectly all right for the Solaris kernel with a
-+few hundred modules maximum, but very much not for Linux, where distro kernels
-+often compile in thousands of modules. Ideally, we would like to treat all
-+kernel modules, built-in or not, the same way, sharing and deduplicating all
-+globally-visible types across the entire set of visible modules and recording
-+each precisely once.
-+
-+We also want to collect descriptions of global variables and emit descriptions
-+of their name->type mapping as well, since the kernel has no easily accessible
-+ELF section we can extract this information from at runtime (kernel modules must
-+be accessible at runtime for modern Linux systems to work, but the kernel itself
-+could have come from over the network or off a USB key or from a non-mounted
-+partition or an EFI boot partition or who knows where, and could have any name
-+even if it is accessible: so tracing tools should not rely on being able to look
-+inside the kernel image).
-+
-+We do all this with dwarf2ctf, a CTF generation tool that reads in DWARF from a
-+set of object files (usually, every object file in the kernel and all modules)
-+and fills a directory with compressed files containing CTF representations of
-+the types in those object files: the kernel build system regenerates these as
-+necessary and links them directly into kernel modules.
-+
-+Caveats: It is somewhat specific to the form of DWARF output emitted by GCC, and
-+doesn't yet support DWARF-4 type signatures or compressed DWARF at all.
-+
-+We'll look at each part of this system in turn, from the top down, starting with
-+using the kernel type information dwarf2ctf produces in other programs.
-+
-+
-+Using dwarf2ctf output
-+----------------------
-+
-+Using this data is fairly simple. Once you've read the CTF sections from the
-+kernel modules and inflated them (or ignored them if they are empty or, as just
-+mentioned, one byte long), you simply need to look at the ctf_parent_name() for
-+each module, and if it is set to "ctf", call ctf_import() to set the parent of
-+this module to the CTF data you have read from the .ctf.shared_ctf section in
-+the ctf.ko kernel module. The core kernel's types are stored in the
-+.ctf.vmlinux section in the same kernel module, and all built-in kernel modules
-+have their types in .ctf.$module_name. Non-built-in kernel modules just have a
-+.ctf section containing their types, which again might need their parent set to
-+"shared_ctf". (Out-of-tree kernel modules will have no such parent.)
-+
-+Once you've set up the parenthood relationships you can call ctf_close() on the
-+shared type repository and forget about it entirely: it will be refcounted and
-+destroyed when all its children are closed.
-+
-+
-+You should end up with a family of CTF files, one per kernel module built-in or
-+not and one for the core kernel, freely usable for whatever purpose you need.
-+
-+
-+Invocation and build-system connections
-+----------
-+
-+dwarf2ctf's command-line syntax emphasises simplicity over compactness. Linux
-+has nearly-infinitely-long command lines these days, so we can take advantage of
-+this.
-+
-+Two syntaxes are supported. The first shares types across multiple modules and
-+the core kernel; the second is used for out-of-tree module building, and avoids
-+either sharing anything at all across modules or depending on the set of shared
-+types defined for the core kernel.
-+
-+
-+dwarf2ctf outputdir objects.builtin modules.builtin dedup.blacklist \
-+ vmlinux.o module.o ...
-+dwarf2ctf outputdir -e module.o ...
-+
-+where:
-+
-+ - 'outputdir' is the possibly-relative path to a directory in which the
-+ generated CTF files get placed.
-+ - 'objects.builtin' is the name of the file containing the object files that
-+ correspond to always-built-in kernel code (that cannot be built as modules).
-+ - 'modules.builtin' is the name of the file containing the names of
-+ kernel modules presently built in to the kernel.
-+ - 'dedup.blacklist' is a blacklist of modules that should never participate
-+ in deduplication: see 'Duplicate type detection' below.
-+ - the .o filenames are the names of object files comprising the kernel and/or
-+ modules: you can feed in whole modules at once (before linking with .mod.o).
-+ This list is often very, very long (I have seen command-lines in excess of
-+ 60Kb).
-+
-+dwarf2ctf's output consists of a series of gzip-compressed .ctf.new files in the
-+outputdir, which the makefile compares with and if necessary moves over the top
-+of .ctf files with the same basename, so as to avoid relinking things if
-+dwarf2ctf has written out content identical to what it wrote last time it ran.
-+These fall into several classes, partitioned according to the contents of
-+objects.builtin and modules.builtin:
-+
-+ - shared_ctf.builtin.ctf: The shared type repository. Types shared by more
-+ than one of the files below go here.
-+ libdtrace-ctf). See 'Using dwarf2ctf output' below regarding use of this
-+ data.
-+ - vmlinux.builtin.ctf: Types in the core kernel, that cannot be built in to
-+ modules, go here.
-+ - *.builtin.ctf: One of these is generated for the types in each module that
-+ is presently built in to the kernel.
-+ - *.mod.ctf: One of these is generated for each .ko.
-+
-+All the files in the first three classes are linked into the ctf.ko module under
-+various names, an empty module containing nothing but CTF data.
-+
-+
-+A lengthy section of Makefile.modpost, and a short section of the toplevel
-+Makefile, is dedicated to creating these files, and to linking them into the
-+kernel modules. The dependency graph related to dwarf2ctf output is quite
-+complex: modules and objects (ld -r'ed *.o files) are processed by dwarf2ctf to
-+produce a number of files in the .ctf directory, and the final modules depend on
-+the relevant ctf files. The .mod.ctf's go into the .ko's with the same stem
-+name, but ctf.ko receives content from all the CTF files corresponding to
-+built-in modules, and until dwarf2ctf runs and creates those files we cannot
-+tell what those CTF files will be, though we do have a wildcard that matches
-+them all.
-+[
-+GNU Make's 'secondary expansion' feature comes to the rescue here: we can
-+compute a list of expected CTF filenames at runtime, given the names of the
-+modules we are linking in. For the builtin modules, we cheat and touch a stamp
-+file after moving any .ctf.new files back over a .ctf file, then depend on that
-+to see if ctf.ko needs to be relinked.
-+
-+The actual incorporation of the CTF data into the kernel modules happens before
-+module signing (if signing is active), by calling objcopy --add-section on the
-+module in question. This too has some knotty corners.
-+
-+First of all, the module linkage process normally links a module using all the
-+prerequisites of the module's target -- but we have designated all the CTF files
-+as prerequisites of the module's target, and we don't want to link them directly
-+in using ld(1), since they aren't object files. So we have to filter them out in
-+the link line.
-+
-+Secondly, those modules which have no CTF files should acquire empty CTF
-+sections to indicate their lack of unique types -- but objcopy in binutils 2.20
-+and below silently exits if asked to --add-section an empty file. So we use dd
-+to generate a file with a one-byte null in it instead, and teach the users of
-+CTF sections to treat a one-byte-long 'CTF' section as if it were empty.
-+
-+
-+Overview of dwarf2ctf operation
-+--------
-+
-+There are four phases to dwarf2ctf operation: initialization, duplicate type
-+detection, CTF construction, and writeout. Some of these phases can repeat.
-+All but the last phase consists purely of sucking data from object files into
-+GHashTables in memory. (The last two phases could potentially be combined,
-+shrinking the size of one hash and saving memory, but the hash that is shrunk is
-+by no means the largest one, so the extra complexity is probably not worth it.)
-+
-+dwarf2ctf uses several other libraries to do this:
-+
-+ - elfutils, used for DWARF parsing. We could potentially write our own
-+ DWARF parser, but elfutils works and is tested.
-+
-+ - glib, used for the GHashTable. The rest of the kernel uses roll-your-own
-+ hash tables, but dwarf2ctf makes heavy demands of its hashtables: they must
-+ be expanding hashes capable of efficiently storing hundreds of thousands of
-+ items, with amortized log(N) lookup time, and they must support deletion
-+ (though it need not be particularly efficient deletion). This rules out
-+ simple fixed-size bucket hashes like the ones used in other parts of the
-+ kernel build system: GHashTable is already implemented, and works.
-+
-+ - zlib, used to compress the CTF information.
-+
-+ - libdtrace-ctf, which both reads and writes the CTF data. This is a port of
-+ the Solaris CTF library, GPLed and with additional support for the storage
-+ of name->type mappings (meant to represent variables) akin to its existing
-+ ELF symbol->type mappings.
-+
-+dwarf2ctf has a good few important data structures, described at the top of
-+scripts/dwarf2ctf/dwarf2ctf.c.
-+
-+dwarf2ctf has its own trace facility, implemented via the dw_ctf_trace() macro
-+and enabled by compiling with -DDEBUG and setting DWARF2CTF_TRACE in the
-+environment. (The first step is required because some very numerous data
-+structures are greatly expanded when debugging is turned on, which would waste
-+memory if it were done all the time). This produces a huge volume of trace
-+output, several gigabytes when run over an allyesconfig kernel.
-+
-+
-+Unless you're interested in how dwarf2ctf works internally, you can stop reading
-+here. If you are interested, now is a good time to read the comments above
-+main() in scripts/dwarf2ctf/dwarf2ctf.c, which briefly describe dwarf2ctf's data
-+structures and functions.
-+
-+
-+Flow of Control
-+---------------
-+
-+The /* C comments */ point to other sections of this document,
-+
-+Functions named in the /* Utilities */ section of dwarf2ctf.c are not mentioned
-+here for simplicity's sake.
-+
-+[C]: Callback
-+[R]: recursive
-+[1]: Numbers: Mutually-recursive loop
-+|: Several functions which all call the same functions
-+->: Call from array of callbacks (filter_ctf_*() omitted as uninteresting)
-+
-+main()
-+ /* See 'Initialization' */
-+ init_assembly_tab()
-+ init_builtin()
-+ init_dedup_blacklist()
-+ init_member_blacklist()
-+ run()
-+ init_tu_to_modules()
-+ init_ctf_table()
-+
-+ /* Duplicate detection */
-+
-+ scan_duplicates()
-+ process_file() /* Toplevel DWARF walkers */
-+[C] detect_duplicates_init()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] detect_duplicates()
-+[ 1] mark_shared()
-+[R] type_id() /* Type IDs */
-+[C1] mark_shared()
-+[R] mark_seen_contained()
-+[C] detect_duplicates_done()
-+
-+ process_file()
-+[C] detect_duplicates_init()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] detect_duplicates_alias_fixup()
-+[R] type_id()
-+[C] is_named_struct_union_enum()
-+[R] type_id()
-+[C] detect_duplicates_alias_fixup_internal()
-+ mark_shared() (see above)
-+[C] detect_duplicates_done()
-+
-+ /* CTF construction */
-+
-+ process_file()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] construct_ctf()
-+[ 2] construct_ctf_id()
-+[R3] die_to_ctf()
-+ assembly_tab[]
-+[C] -> assemble_ctf_base()
-+ -> assemble_ctf_pointer()
-+ | assemble_ctf_array()
-+ | assemble_ctf_array_dimension()
-+ | assemble_ctf_typedef()
-+ | assemble_ctf_cvr_qual()
-+ | assemble_ctf_variable()
-+ lookup_ctf_type()
-+[ 2] construct_ctf_id()
-+ -> assemble_ctf_enumeration()
-+ -> assemble_ctf_enumerator()
-+ -> assemble_ctf_struct_union()
-+ -> assemble_ctf_su_member()
-+[ 3] die_to_ctf()
-+[ 2] construct_ctf_id()
-+
-+ write_types()
-+
-+Initialization
-+--------------
-+
-+ init_assembly_tab()
-+ init_builtin()
-+ init_dedup_blacklist()
-+ run()
-+ init_tu_to_modules()
-+ init_ctf_table()
-+
-+This happens at the top of main() and run(), and in various functions named
-+init_*(). Of these, init_assembly_tab() and init_builtin() serve only to turn
-+various static arrays and files mentioned on the command line into more useful
-+internal representations (e.g. the assembly filter array of structures is turned
-+into a pair of arrays indexed by DWARF tag), and the blacklisting functions are
-+described in the section on duplicate type detection below.
-+
-+init_ctf_table(), called both at initialization time and later during CTF
-+assembly when new CTF files are found to be needed, creates a new CTF file in
-+memory and either marks it as a child of the shared type repository, or (if it
-+*is* the shared type repository, or deduplication is off and there is only one
-+CTF file being processed and no shared type repository at all) creates a few
-+types in it which CTF has representations of but DWARF does not: a void type,
-+and a generic catchall pointer-to-function-returning-int.
-+
-+That leaves init_tu_to_modules(). This walks over all the top-level
-+compile_unit DIEs in the DWARF debugging information in every object file
-+mentioned in the list of modules and built-in modules, constructing a mapping
-+from translation unit name back to the name of the kernel module it comes from,
-+even if that module is built in to the kernel. This is normally the same as the
-+filename (sans extension), but for built-in kernel modules, the name comes from
-+the modules.builtin file's entry for the translation unit instead, so that the
-+output can land in a .builtin.ctf file rather than being jammed into
-+vmlinux.builtin.ctf with the core kernel's types.
-+
-+This means that dwarf2ctf can operate in terms of the kernel module a type is
-+contained within rather than having to think about the mapping between object
-+file name, translation unit name and module name all the time.
-+
-+
-+Toplevel DWARF walkers
-+----------------------
-+
-+ process_file()
-+[C] (per-TU initialization callback)
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] (per-DIE callback)
-+[C] (per-TU cleanup callback)
-+
-+All routines in dwarf2ctf other than initialization and writeout are DWARF
-+walkers: i.e., they walk over all DWARF DIEs in all object files specified on
-+the command line and do something with every DIE. This job is done by
-+process_file() and its helper process_tu_func(), which not only digs out the
-+corresponding (built-in or non-built-in) module name corresponding to each
-+object file, but also detects and skips translation units it has handled before
-+(in case they are incrementally linked into multiple object files) and allows
-+callbacks to be invoked at the start and end of each translation unit.
-+
-+Even though dwarf2ctf only cares about top-level types, in some situations DWARF
-+can emit top-level types with references to a non-top-level type: if all
-+occurrences of the top-level type are an opaque structure, and the only
-+non-opaque definition is inside a function, references in the same translation
-+unit as the non-opaque definition will point to the definition inside the
-+function (and references outside the translation unit will not point at any
-+definition). Thus, if we want to catch all nuances of globally-visible types,
-+we have to scan types inside functions and lexical blocks inside functions too.
-+
-+To avoid generating a vast number of unnecessary type definitions, the 'assembly
-+table' which describes how to construct a CTF type given a DWARF DIE also
-+contains a description of a set of filters which are passed the current DIE and
-+its parent: if they return false, the DIE is skipped and never passed to the
-+callback function. We also avoid calling the callback for any DWARF DIE whose
-+tag doesn't appear in the assembly table at all: there's no point doing
-+duplicate detection or anything else for a DWARF DIE we won't be generating CTF
-+from. There are currently two filters defined: filter_ctf_file_scope(), which
-+is called for every DWARF DIE whose tag is one we never expect to see a
-+reference to if it is inside a function (except if they relate to a structure or
-+union, as above), and filter_ctf_uninteresting(), which is called for variables
-+to see if they are worthy of recording (top-level named variables with external
-+linkage not part of the internal workings of macros only).
-+
-+
-+Type IDs
-+--------
-+
-+[R] type_id()
-+[C] (optional per-type callback)
-+
-+The only thing dwarf2ctf does which the Sun tool does not is the detection of
-+duplicate and shared types, both within individual kernel modules and across
-+modules. Our ultimate goal is that a type that appears in the source code once
-+appears in the CTF output once as well. This goal has mostly been attained,
-+except for out-of-tree modules, where cross-module type sharing must be disabled
-+to avoid requiring rebuilds of the module whenever the core kernel is rebuilt.
-+
-+The core of this is the concept of a *type ID* and the function type_id() which
-+computes it. A type ID is an identifier for a type which precisely represents
-+that type and only that type. Doing this for types in different headers or at
-+different scopes with the same name without needing to encode knowledge of C
-+scoping rules into dwarf2ctf is an interesting proposition: we can use the line
-+number and filename info provided by DWARF in most user-specified types to help.
-+
-+A type ID is a recursively-constructed string of the following form (fixed
-+elements represented by {}, optional elements by []):
-+
-+//[filename]//[line number]//{type string}
-+
-+Types are *based* upon other types iff they have a DW_AT_type attribute pointing
-+to some other type. All types based upon other types have a type ID that is the
-+type ID of the type upon which they are based, with additional information
-+specific to this type appended to it. The filename and line number is only
-+added for those types which are not based upon other types and which have a
-+filename and line number in the DWARF (lots don't, e.g. base types): the
-+filename is canonicalized with realpath(), though since this is quite slow and
-+type_id() is called a lot, the mapping from DWARF filename to realpath() result
-+is cached. Types that have no filename or line number start with '////'.
-+
-+We use // to separate the filename and line number elements because this is the
-+shortest string other than NUL that cannot appear in a canonicalized POSIX
-+pathname (ignoring Pyramid, Cygwin and other strange systems that actually
-+return // in the result of realpath(): Linux doesn't use it and that's all that
-+matters. Should it start to use it, we can switch delimiter to ///.)
-+
-+Function pointers are not represented (or, rather, are all mapped to the same
-+type ID, the generic catchall function-pointer type mentioned above); array
-+dimensions are represented by [index-type dimension], or [] for flexible array
-+members. Structure members are not represented, since they are not types, but
-+the types of their members *are* represented, as are nested structures (the line
-+number and filename serving, as ever, to disambiguate them from other structures
-+with the same name declared nested inside different structures).
-+
-+The following are some examples of valid type IDs (assuming the kernel source
-+tree is, implausibly, located at /k/, just off the root directory: comments on
-+individual types done /* like C */; the last example is broken across lines for
-+formatting's sake):
-+
-+//fp//* # a pointer to a function, any function
-+////long int
-+////char []
-+////unsigned int typedef __kernel_uid_t typedef __kernel_uid32_t
-+//fp//* typedef __signalfn_t * typedef __sighandler_t
-+////struct nsproxy /* an opaque type */
-+////struct nsproxy * # /* pointer to it */
-+////long unsigned int typedef u64 volatile
-+////long unsigned int volatile const * const
-+////long unsigned int typedef sector_t [////long unsigned int 511]
-+/k/include/linux/types.h//222//struct list_head
-+/k/include/linux/types.h//222//struct list_head *
-+/k/include/linux/types.h//222//struct list_head [////long unsigned int 5]
-+/k/include/linux/types.h//217//struct /* no struct tag */
-+/k/include/linux/types.h//217//struct typedef atomic64_t
-+/k/include/linux/mm_types.h//34//struct page * typedef pgtable_t
-+/k/fs/eventpoll.c//122//struct nested_calls
-+/k/include/linux/sysctl.h//1016//struct ctl_table typedef ctl_table
-+ [////long unsigned int 4] var inotify_table /* A global variable */
-+
-+This scheme means that cv-quals and other modifiers applied to other types are
-+always merged: if there are a dozen typedefs for a single type 'foo' with the
-+same name declared in the same place, they all end up with the same type ID and
-+are only emitted into the CTF once.
-+
-+The type_id() function can also accept a callback, which is called as the
-+recursion unwinds, from base type up to derived type: so it might be called for
-+"////unsigned int", then for "////unsigned int typedef __kernel_uid_t", and so
-+on up to the DIE that was originally passed in. Because type_id() returns a
-+dynamically-allocated string, calls to type_id() made purely for the sake of
-+invoking a callback are normally of the peculiar form "free(type_id(...))".
-+
-+type_id() is a very hot spot, so syscall results are cached in it (such as
-+realpath(), as mentioned above), and when string appending is done, it is done
-+all at once where possible, via str_appendn(), which calls realloc() only once
-+no matter the number of strings being appended.
-+
-+Lots of core data structures in dwarf2ctf consist of hashes mapping type IDs to
-+something else (predominantly CTF file/ID pairs and module names). It would
-+be possible to map from hashes of type IDs, saving some memory, but this would
-+impair debugging so is not yet implemented. (If it is implemented, it should
-+probably be implemented only when DEBUG is not defined.)
-+
-+
-+Duplicate detection
-+-------------------
-+
-+ scan_duplicates()
-+ process_file() /* Toplevel DWARF walkers */
-+[C] detect_duplicates_init()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] detect_duplicates()
-+[ 1] mark_shared()
-+[R] type_id() /* Type IDs */
-+[C1] mark_shared()
-+[ 4] type_id()
-+[ 4] detect_duplicates_typeid()
-+[ 4] detect_duplicates()
-+[R] mark_seen_contained()
-+ member_blacklisted()
-+[C] detect_duplicates_done()
-+
-+ process_file()
-+[C] detect_duplicates_init()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] detect_duplicates_alias_fixup()
-+[R] type_id()
-+[C] is_named_struct_union_enum()
-+[R] type_id()
-+[C] detect_duplicates_alias_fixup_internal()
-+ mark_shared() (see above)
-+[C] detect_duplicates_done()
-+
-+The job of the duplicate detection pass is to fill out the id_to_module hash,
-+which maps type IDs to the module they appear in, with the two special cases
-+that types that appear only in the core kernel are said to appear in the module
-+'vmlinux', and types that appear in more than one module (or in a module and in
-+the core kernel) are said to appear in the module 'shared_ctf', the shared type
-+repository. This is quite a tricky multi-pass process, because we must ensure
-+that the shared type repository is self-contained: all types in the repository
-+must not reference any types outside the repository.
-+
-+Detecting duplicates itself is easy: we consider two types duplicates if they
-+have the same type ID: if they both reside in the same module, the resulting
-+type resides in that module too. However, detecting shared types is harder.
-+We consider that a type belongs in the shared module if any of these conditions
-+is true:
-+
-+ - the type appears multiple times in different modules
-+ - a type for which this type is a base type is shared
-+ - the type is referenced by a structure or union member, and the structure
-+ or union is shared
-+ - the type is a non-opaque type with an opaque variant ('struct foo'), or
-+ vice versa, and either of these variants is shared: these two types will
-+ get different type IDs, so explicit checking is necessary
-+
-+Note that we do *not* consider a type to belong in the shared module merely if
-+*it* has a base type which is shared: indeed, this is the common case for
-+unshared types (even unshared structures tend to have fields of shared types
-+like int).
-+
-+It should be fairly easy to see that sharedness is a contagious property:
-+e.g. if you mark a structure as shared, and one of its members is an
-+otherwise-unshared opaque pointer to a structure, you have to mark that as
-+shared: this causes the non-opaque definition of the structure, and all *its*
-+members, to be shared, and so on. So since dwarf2ctf does not track the members
-+of structures itself (not until the CTF generation phase, anyway), this means
-+walking over the DWARF DIEs multiple times, checking for sharedness over and
-+over until we are done.
-+
-+We partition the problem into two parts, both of which are carried out by
-+process_file() callback functions: detect_duplicates() and
-+detect_duplicates_alias_fixup().
-+
-+
-+detect_duplicates() is called first, once for every DIE in the kernel (via
-+process_file()). This identifies types that are duplicated but not shared, and
-+identifies shared types without consideration of opaque struct/union aliasing.
-+It also flags types that have been seen only once as 'seen': this is checked
-+much later on by the CTF construction phase, since construction of CTF for
-+any type which has not been inspected by the deduplicator is a sign of a bug in
-+the deduplicator.
-+
-+This has several subtleties.
-+
-+If we are running for an out-of-tree module, we must still identify types as
-+duplicated within the module, but must never mark them as shared: out-of-tree
-+modules cannot contribute to the shared type repository nor even use types in
-+it, since they are rebuilt independently from the kernel proper and thus cannot
-+depend on a type currently in the repository remaining there (e.g. perhaps it
-+has only two users, both in modules, and the kernel is rebuilt to not build one
-+of those modules anymore: this should not require rebuilding of any out-of-tree
-+modules).
-+
-+If we mark a structure or union type as seen, we must mark aggregate types that
-+appear directly within that type's DIE as seen as well. This is done by the
-+recursive function mark_seen_contained(). You might wonder what the point of it
-+is: such types surely cannot appear anywhere else, and any duplication will
-+precisely match the duplication of the containing type. The answer is that they
-+can still be referenced as the type of structure members of their containing
-+structure, e.g. in
-+
-+struct foo {
-+ struct bar {
-+ } *baz;
-+ struct bar wombat[16];
-+};
-+
-+Here, a reference to 'struct bar' appears in 'struct foo', and CTF is
-+constructed for it, even though it is not a top-level DIE. In GCC 4.8+, a
-+reference to the 16-element array-of-struct-bar can also appear in 'struct foo':
-+in fact almost anything can appear in there if used nowhere else in the
-+translation unit, even base types. So we look for the appearance of anything
-+which we can assemble into CTF (anything in the assembly_tab) other than
-+members, since members cannot be used as the type of anything else, and mark
-+them all as seen in this module. (Nearly everything in a structure or union is
-+a member, so this ends up skipping almost but not quite everything.)
-+
-+
-+If we find that a type has appeared more than once in different kernel modules
-+(or in a module and in the core kernel), we must mark it as shared. This is
-+done via mark_shared(), which is both a function that can be directly called
-+(e.g. from detect_duplicates()) and a type_id() callback. If it is called
-+directly, it immediately reinvokes itself as a type_id() callback, which calls
-+it for the base type of the type in question and then for all qualifiers up the
-+type ID stack, marking them all as shared if they weren't already.
-+
-+If a structure or union is marked as shared, the types of its members are also
-+marked as shared via a recursive call (even if they have already been so marked:
-+just because this structure is of a type we've already seen, in a location we've
-+already seen, doesn't mean that someone might not have legitimately used
-+#defines to add extra members to the end of it, and we need to mark them as
-+shared too). We track structures that have been seen in this translation unit
-+and avoid recursing into them, to avoid an infinite loop in cases like this:
-+
-+struct one;
-+struct two {
-+ struct one *foo;
-+};
-+
-+struct one {
-+ struct two *foo;
-+}
-+
-+The types being pointers does not help here -- the marking of 'struct one *' as
-+shared will automatically mark 'struct one' as shared too, because otherwise we
-+might have a structure in the shared type repository whose members' types
-+could not be found there.
-+
-+
-+The second pass is the 'alias fixup' pass, implemented by
-+detect_duplicates_alias_fixup(). This pass serves to detect unshared opaque
-+types whose non-opaque equivalents are shared, and vice versa. It is executed
-+repeatedly until no types have been marked as shared for an entire iteration,
-+but is considerably faster per iteration than the first pass, which often
-+consumes more than half of dwarf2ctf's total runtime. We work in one direction
-+only, looking for non-opaque structures, unions or enums which have structure
-+tags. (Structures without tags cannot have opaque variants, and structures
-+which are opaque will have non-opaque cousins somewhere, or can be emitted to
-+the CTF as an opaque structure harmlessly since they truly have no members and
-+are probably manipulated only via casts.)
-+
-+We identify structures, unions or enums with tags via the type_id() callback
-+is_named_struct_union_enum(), but cannot determine if something is an opaque
-+structure at this stage. Instead, we do that after the callback, checking to
-+see if the first four characters of the type ID are "////": this relies on the
-+fact that GCC never gives opaque structures line numbers in DWARF. We do the
-+actual checking and marking of each non-opaque structure using
-+detect_duplicates_alias_fixup_internal(), which is yet another type_id()
-+callback.
-+
-+This function directly synthesises the name which this structure's opaque cousin
-+would have, if it existed, by stripping off the line number and filename and
-+replacing them with '////', and sees if either of these types have been marked
-+as shared while the other has not. If the opaque type is shared, the non-opaque
-+variant can be marked shared using the same recursive mark_shared() function as
-+before (thus marking the types of all its members and types it depends upon as
-+shared too). If it is the opaque type that needs marking shared, this will not
-+work, since mark_shared() takes a DWARF DIE, and we don't have one for the
-+opaque type, just a faked-up type ID. However, since an opaque type doesn't
-+have any members that need recursively tracing, we don't need access to its
-+DWARF DIE to figure them out, and can just mark it as shared directly, via an
-+insert into the id_to_module hash.
-+
-+Since this function is a type_id() callback, it is called not just for
-+structures but for types based on them (e.g. in type_id form, "struct foo const
-+* [43] volatile *"); at every level of this declarator stack, a shared opaque
-+base type will contaminate its non-opaque cousins with sharedness, and vice
-+versa. This handles situations in which, say, the opaque version of "struct foo
-+const * [43]" was used by more than one module and was marked as shared: the
-+marking process will have marked the opaque versions of "struct foo const *
-+[43]", "struct foo const *", "struct foo const" and "struct foo" as shared, but
-+will not have touched any non-opaque versions of these types which may exist
-+until this routine runs. It also handles typedefs to structures with no need
-+for any extra code.
-+
-+This whole alias fixup process needs to be repeated, because whenever a
-+non-opaque type is marked as shared and its member's types traced and marked
-+shared, *those* may themselves be structure types with corresponding opaque or
-+non-opaque variants, and when they are opaque types the non-opaque variant that
-+alias fixup works from may already have passed under the DWARF walker's gaze: so
-+another pass over the kernel's DWARF is necessary to be sure we catch it.
-+mark_shared() thus sets a flag that scan_duplicates() recognizes and uses to
-+trigger another run through the alias fixup pass.
-+
-+
-+There are a very few modules that this algorithm doesn't work for. One example
-+is snd-ens1371, which reads, in toto
-+
-+#define CHIP1371
-+#include "ens1370.c"
-+
-+and ens1370.c (itself a distinct kernel module) then defines a 'struct ensoniq'
-+whose members vary depending on whether CHIP1371 is defined. Obviously, it is
-+impossible to share any such types between kernel modules even though their
-+names are the same and they are defined in the same place in the same source
-+file in both cases. But this sort of trickery is very rare, so we simply
-+implement a 'deduplication blacklist' of modules which will not introduce new
-+types into the shared CTF repository, and who do not participate in alias fixup
-+detection either. Detecting these cases in order to blacklist them is harder:
-+no automated system has yet been implemented, although instances where #defines
-+of this nature introduce new types that are then used by later members will
-+cause assertion failures inside dwarf2ctf which might be a clue. So it is
-+possible that some examples have been missed. (The blacklist only applies to
-+cases where structure members change within a single kernel build, so cases
-+where structures have members whose presence depends on CONFIG_* values are
-+quite all right, as are cases where #defines are introduced by one translation
-+that #includes another that then goes on to define whole new structures: it is
-+only cases where modules #define something that changes the definition of
-+individual possibly-shared types that will need blacklisting.)
-+
-+
-+There are a few even worse cases where a single structure is defined with
-+different members in different translation units within a single module. In
-+this case we can do nothing at all, since our output representation describes
-+only a single type per module: we implement a 'member blacklist' which bans
-+emission of affected members entirely, leaving a description of a structure with
-+an undescribed hole in it.
-+
-+
-+CTF construction
-+----------------
-+
-+ process_file()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] construct_ctf()
-+[ 2] construct_ctf_id()
-+[R3] die_to_ctf()
-+ assembly_tab[]
-+[C] -> assemble_ctf_base()
-+ -> assemble_ctf_pointer()
-+ | assemble_ctf_array()
-+ | assemble_ctf_array_dimension()
-+ | assemble_ctf_typedef()
-+ | assemble_ctf_cvr_qual()
-+ | assemble_ctf_variable()
-+ lookup_ctf_type()
-+[ 2] construct_ctf_id()
-+ -> assemble_ctf_enumeration()
-+ -> assemble_ctf_enumerator()
-+ -> assemble_ctf_struct_union()
-+ -> assemble_ctf_su_member()
-+ member_blacklisted()
-+[ 3] die_to_ctf()
-+[ 2] construct_ctf_id()
-+[C] cleanup_sou_member_count()
-+
-+The next stage after the detection of duplicate and cross-module shared types is
-+to generate CTF. We generate all CTF at once before emitting it: this is
-+potentially somewhat wasteful of memory, but in practice has not proved to be a
-+problem: substantially less memory is used than is used by other parts of the
-+kernel build, unless -DDEBUG is enabled. Its job is to look through the
-+kernel's type DWARF (via process_file(), as usual) and create CTF for every
-+file-or-global-scope type and every externally-visible variable in the CTF file
-+in which the duplicate detection pass has said that type should appear.
-+(Variables are treated exactly like types: it just so happens that they are
-+never shared because no type or variable can depend upon them, so they always go
-+directly into the appropriate module and never into the shared type repository.)
-+
-+At this stage, the 'CTF files' are not actually files but rather ctf_file_t
-+structures maintained by libdtrace-ctf and tracked in the per_module hash, along
-+with other information which varies by module name. We track every single
-+individual type in the CTF file in the id_to_type hash, which maps type IDs to
-+pairs of (CTF file ID, ctf type ID): this lets us use the type IDs described
-+above when considering cross-references within CTF files (e.g. from one CTF type
-+to a type it depends upon).
-+
-+The most important functions in this phase are:
-+
-+ - construct_ctf_id(), the top-level process_file() callback which is given a
-+ DWARF DIE, looks in module_to_ctf_file for the CTF file where this type
-+ should land (creating it if necessary), makes sure a type with this type ID
-+ has not already been created there, calls die_to_ctf() to create the CTF,
-+ notes where it was created in id_to_type, and handles errors.
-+
-+ - die_to_ctf(), a recursive function which calls the assembly function for the
-+ DIE it is given and all its immediate children, with special-case handling
-+ for tagged structures and unions. If you want to create a type but not note
-+ where it was created for future lookups by lookup_ctf_type(), this is what to
-+ call. (This is only done currently for unnamed structures/unions.)
-+
-+ - lookup_ctf_type(), which is called by CTF assembly functions for those
-+ types that depend upon other types: it calls construct_ctf_id() again
-+ to construct the type, and double-checks that all such types appear
-+ either in the module we are constructing types for, or in the shared CTF
-+ module. CTF represents all function pointers the same way, and has a
-+ special type ID for 'void', so we special-case both of these cases.
-+
-+These functions are mostly straightforward (though highly recursive, with all
-+three plus CTF construction functions participating in loop 2 above,
-+die_to_ctf() calling itself directly, and even one situation, the
-+already-mentioned unnamed structures/unions, in which die_to_ctf() is directly
-+called back by a CTF construction function, in loop 3 above.)
-+
-+
-+There are a few subtleties, though. Firstly, error handling. We consider that
-+errors that will lead to unusable CTF are fatal: mostly, these are errors where
-+a bug in the deduplicator has failed to trace types correctly and has left at
-+least one type in the shared module depending on a type in a non-shared module,
-+or has failed to mark a type as shared at all. In all these cases, you'll
-+eventually get an error from lookup_ctf_type() of the general form
-+
-+blah.c:413:foo_t: Internal error: lookup of flob found in different file.
-+
-+The first two parts of this error are the translation unit and line number the
-+type being assembled (usually a structure or union) was found in: foo_t is the
-+name of the type being assembled. The type of the structure being looked up
-+appears nowhere, because we don't know it, but the name of the member is given
-+("flob" above, or "(unnamed)" if we don't know it). If you want more
-+information, you can pass -DDEBUG to the compilation of dwarf2ctf.c in
-+scripts/dwarf2ctf/Makefile, and rerun dwarf2ctf, and you'll get the module and
-+filename in which both the originating and the target types appear. In order to
-+actually track down the bug you'll probably have to run dwarf2ctf with
-+DWARF2CTF_TRACE set in the environment, and look at the place where the target
-+type was deduplicated, and try to figure out why the deduplicator didn't trace
-+the reference to the type in foo_t correctly.
-+
-+There is another kind of error, though: a failure to assemble a single type,
-+perhaps because DWARF was emitted that we don't know how to understand (this is
-+particularly likely in structure assembly, where we are highly dependent on the
-+form of the DWARF that GCC happens to emit for DW_AT_member_location). We pass
-+an 'enum skip_type' around, which has three possible values, one of which is
-+SKIP_ABORT. Before each type is assembled, we call ctf_snapshot() to take a
-+snapshot of the variable-plus-type set in the CTF file we're working over. If a
-+SKIP_ABORT propagates up to construct_ctf_id(), we call ctf_rollback(), which
-+throws away every type constructed since the last ctf_snapshot() -- i.e., the
-+specific erroneous type we've just been working on. (We might have emitted some
-+parts of it and then failed, so we should try to clean up).
-+
-+A SKIP_ABORT is not fatal unless DEBUG is defined: its only effect is to omit
-+one single type from the resulting CTF, which is probably still usable.
-+
-+libdtrace-ctf causes additional problems here. It can only see the types we
-+added once the notably expensive function ctf_update() is called. This takes
-+the in-memory structures and serializes them (all of them, every time). This
-+only affects libctf when structure and union members are added: libctf needs to
-+know the sizes and alignments of the types of those members, which might quite
-+possibly just have been added, e.g. if this structure contains a pointer to its
-+own structure tag. So, when we insert a member in assemble_ctf_su_member(), we
-+note a bad type-ID error and do a ctf_update() on the file we're working over
-+and try again: even then that can fail if the type was added to the shared
-+repository, so we do a ctf_update() on *that* and try again, and only if that
-+fails do we declare a SKIP_ABORT error. (We check the shared repository last
-+because it is very large, so takes longer to serialize than other CTF files do).
-+
-+The need to keep the number of calls to ctf_update() down means we must avoid
-+all access to the CTF types we are assembling if we can possibly get at the same
-+data another way. Hence the member_counts hash, a member of the per_module
-+state, which tracks the number of members in structures with a given C-style
-+name and their CTF IDs. This structure allows us to handle the (valid) C idiom
-+of redeclaring the same structure with a different number of members, merging
-+the definitions across translation units and discarding them (iff the structure
-+was unshared) when we transition into a new module, without ever having to
-+consult the CTF to see how many members we put into it. (We have to use the
-+C-style name here, because by definition the type IDs of such redeclared
-+structures will be different, since a type ID contains a line number and
-+translation unit name.)
-+
-+
-+There's more error-handling complexity inside die_to_ctf(), where errors from
-+libdtrace-ctf are actually reported (there may be multiple of them for a single
-+type, e.g. if we are assembling a structure and several members somehow refer to
-+a type we do not know about).
-+
-+die_to_ctf() itself has the sort of parameter list that can make people swear
-+off C for life. It is largely explained in the description of ctf_assembly_fun.
-+Most parts of it are hardly used in the function itself, just passed down to CTF
-+assembly functions.
-+
-+Finally, we must note the override flag. Both die_to_ctf() and
-+construct_ctf_id() return a CTF ID. This is thrown away by the DWARF walking
-+code (the function construct_ctf() exists just for that purpose), but when
-+called by lookup_ctf_type(), this CTF ID is taken to be the single ID of the CTF
-+type that's just been assembled. Normally this is the same as the CTF ID
-+returned by the CTF assembly function for the top-level DWARF DIE, but there are
-+a few structures for which we want to return the result of some other CTF
-+assembly function.
-+
-+The only currently-existing example is array dimensions, which DWARF represents
-+as a typed array DIE whose child is a dimension, but which CTF represents as an
-+array-with-dimensions that you can't change afterwards. We can't assemble an
-+'array' at the top level because we don't know how big it is, but we have to
-+track the type recorded there somehow. We handle this by having
-+assemble_ctf_array(), the assembly function for the top-level DW_TAG_array_type
-+DIE, simply look up the type of the array's members and return its ID as if it
-+had just constructed it, after which assemble_ctf_array_dimension(), the
-+assembly function for DW_TAG_subrange_type, actually constructs the array,
-+wrapping it around the CTF 'ID' 'assembled' by the parent and setting the
-+override flag to make sure that this is what is really recorded.
-+
-+
-+CTF construction functions
-+--------------------------
-+
-+Each CTF construction function takes a single DWARF DIE and turns it into CTF,
-+somehow. They are laid out in the assembly table described in 'toplevel DWARF
-+walkers' above. They all start the same way, with a series of CTF_DW_ENFORCE or
-+CTF_DW_ENFORCE_NOT assertions. These guard against corrupted DWARF missing some
-+of the attributes we need, or DWARF containing attributes which indicate that we
-+can't handle the content (e.g. DW_AT_signature or DW_AT_specification on
-+structures, which would both indicate this is DWARF 4, which we can't handle
-+yet.)
-+
-+We'll go through these functions one by one, pointing out anything that
-+maintainers should be aware of.
-+
-+
-+assemble_ctf_base() assembles all integral base types (DW_TAG_base_type) and
-+transforms them into the corresponding CTF type. The functions we need to call
-+for this in the CTF API all have the same type signature but have different
-+names; CTF also distinguishes between the various differently-sized
-+floating-point types, so we must figure out from the type size which type a
-+given DWARF base type is referring to. We map from DWARF encoding to a triple
-+of (CTF addition function, CTF integral type, type size) where the latter is
-+optional and depends on the size of the DWARF type we are encoding and the size
-+of various floating_point types on the current system. (This does mean that
-+cross-compilation using dwarf2ctf is likely to fail fairly often: we need
-+machinery to determine the sizeof() types on the target system before that can
-+function.)
-+
-+This sizeof()-based search procedure is why we do not currently support
-+DW_AT_bit_size for base types: we could easily support it for sizes modulo 8,
-+but GCC happens to emit DW_AT_byte_size in this case. In C DW_AT_bit_size is
-+likely to be emitted only for bitfields in structures anyway, not for base
-+types.
-+
-+
-+assemble_ctf_pointer() and assemble_ctf_typedef() are trivial: look up the
-+associated type with lookup_ctf_type() and assemble the appropriate thing.
-+assemble_ctf_cvr_qual() is almost as trivial, but has to figure out which of
-+const, volatile or restrict it was called for and call the corresponding CTF API
-+function. assemble_ctf_enumeration() and assemble_ctf_enumerator() are quite
-+simple too.
-+
-+
-+assemble_ctf_variable() has a couple of extra complexities: we unconditionally
-+set the skip parameter to SKIP_SKIP, suppressing recursion into containing DIEs,
-+since we already know we won't care about any of them. Also, while the
-+deduplication pass unifies opaque and non-opaque structures into the same type,
-+it never makes sure that variables declared in the same header by translation
-+units which have opaque versus non-opaque structures in scope are deduplicated.
-+e.g. you could well end up with these two type IDs, depending on whether
-+<linux/pid_namespace.h> was included before <linux/pid.h> in a given translation
-+unit:
-+
-+////struct pid_namespace var init_pid_ns
-+/path/to/kernel/include/linux/pid_namespace.h//19//struct pid_namespace var init_pid_ns
-+
-+These variables both refer to the same type, but deduplicating them would
-+require an additional deduplication pass. Since variables are always terminal
-+and nothing can refer to them, nothing will ever look up any of those type IDs
-+(since the only thing that looks up type IDs is code that is searching for type
-+that other types depend on). So we don't care about this duplication and
-+running an additional deduplication pass to eliminate it would slow down
-+dwarf2ctf to no good end. It's better just to ignore duplicate errors from
-+ctf_add_variable().
-+
-+
-+assemble_ctf_array() and assemble_ctf_array_dimension() we talked about
-+above. One last subtlety remains, which is that figuring out the actual
-+dimensionality of an array is complicated enough that it has been hived off into
-+a private_subrange_dimension() function, called both from here and from
-+type_id(). Arrays with neither a DW_AT_upper_bound nor a DW_AT_count, and
-+arrays without an indexing type, are best considered flexible arrays; arrays
-+whose upper bound or count is not unsigned or signed integral data are also
-+flexible (perhaps they're using a full-blown location list, but we can't encode
-+that in CTF so we treat it as flexible); and if an upper bound is used, we want
-+to add one to its value before treating it as a count of elements.
-+
-+
-+This leaves structure/union assembly, both of which are assembled by the same
-+pair of functions, assemble_ctf_struct_union for the type itself and
-+assemble_ctf_su_member() for the individual members. As with
-+assemble_ctf_cvr_qual(), we have to look at the tag to figure out which CTF
-+function to use to do the assembly, but we have an extra constraint: it is
-+perfectly idiomatic C to declare a structure repeatedly with a different number
-+of members every time. This is perfectly permissible as long as the leading
-+portions of all declarations match. We do not verify this (we hope that the
-+compiler will diagnose it, which it will unless the conflicting declarations
-+cross modules), though perhaps we should: we simply look up the structure in the
-+CTF and the DWARF and skip assembly of the structure members via SKIP_SKIP if
-+the already-assembled structure has at least as many members as the current one.
-+
-+assemble_ctf_su_member() is by far the most complex of the assembly functions.
-+It has to handle members that already exist, members that need assembly, members
-+that correspond to unnamed structure members, numerous different ways of
-+representing structure offsets and members with no offset at all.
-+
-+The offset computation is quite laborious and by no means complete: a complete
-+implementation would require an interpreter for DWARF location lists, which is
-+total overkill given that in DWARF2 GCC emits a totally stereotyped location
-+list, and in DWARF3+ we don't need location list parsing at all. CTF wants an
-+offset in bits.
-+
-+We have five cases:
-+ - for DW_AT_data_bit_offset, we just use the offset unchanged.
-+
-+ - for DW_AT_data_member_location with an integral form (data2, data4, data8,
-+ udata, or sdata) we just look it up and multiply it by eight, adding the
-+ parent's DW_AT_bit_offset to handle structures nested inside other
-+ structures.
-+
-+ - for DW_AT_data_member_location with a block form, we make sure that the list
-+ is of one particular simple form (DW_OP_plus_uconst and a constant value in
-+ bytes), and abort assembly otherwise. The only case I know of where this
-+ test will trip is C++ virtual bases: if people are using C++ code with
-+ virtual bases inside the kernel they deserve sympathy, but probably not
-+ support in the code. CTF can't represent C++ types in any case.
-+
-+ - for expression location lists, or anything else that we don't understand, we
-+ simply die (we could simply skip the type, but this seems serious enough that
-+ dying is warranted).
-+
-+ - with none of these present, we have no offset: the member is at the same
-+ location as the start of the structure.
-+
-+But where is the 'start of the structure'? That depends on whether this is an
-+unnamed struct/union member (usually a union). If it is, we want to fold all
-+its members directly into the parent structure, with their offsets increased by
-+the offset of the unnamed member as a whole. This is done by directly calling
-+die_to_ctf() with the first child of the anonymous member's type and with all
-+other parameters set as if the parent DIE was the current structure, thus
-+fooling die_to_ctf() into believing that these members are members of the
-+current structure, not of the anonymous one. The offset-increasing magic is
-+done via the parent_bias parameter to die_to_ctf() and all the CTF construction
-+functions: it is ignored by all of them except for assemble_ctf_su_member()
-+itself, which adds the parent bias onto the normally-computed offset, and is
-+otherwise passed down unchanged to all children. This means that even this
-+terribly contrived case works:
-+
-+struct horror {
-+ int spacer;
-+ union {
-+ struct {
-+ int spacer;
-+ struct {
-+ int foo;
-+ int bar;
-+ } b;
-+ } a;
-+ };
-+};
-+
-+In this situation, horror.a.b.bar may have:
-+
-+ - a nonzero parent_bias due to the offset of the anonymous union in 'struct
-+ horror'
-+ - a nonzero offset due to the offset of 'bar' in its containing structure
-+ - if DW_AT_data_member_location with integral form is used, a nonzero
-+ DW_AT_bit_offset of 'b' in 'a'
-+
-+If this is not an anonymous union, we are dealing with only one member: we look
-+up its type and add it reasonably conventionally via ctf_add_member_offset().
-+Even here there are subtleties: we use construct_ctf_id() directly rather than
-+via lookup_ctf_type() so we can get a better error message on failure, and we
-+ignore any duplicate-member errors because this is probably a sign that this
-+structure has already been encountered and we are working through another
-+instance of it with more members.
-+
-+
-+Writeout
-+--------
-+
-+ write_types()
-+
-+This couldn't really be simpler, as the trivial call graph shows. We create an
-+output directory with the requested name, then work over the entire
-+module_to_ctf_file hash, writing out every CTF file into a new suitably-named
-+file via zlib's compressed file I/O functions.
-diff --git a/Documentation/kbuild/kconfig.rst b/Documentation/kbuild/kconfig.rst
-index dce6801d66c9..a9a855f894b3 100644
---- a/Documentation/kbuild/kconfig.rst
-+++ b/Documentation/kbuild/kconfig.rst
-@@ -154,6 +154,11 @@ KCONFIG_AUTOCONFIG
- This environment variable can be set to specify the path & name of the
- "auto.conf" file. Its default value is "include/config/auto.conf".
-
-+KCONFIG_TRISTATE
-+----------------
-+This environment variable can be set to specify the path & name of the
-+"tristate.conf" file. Its default value is "include/config/tristate.conf".
-+
- KCONFIG_AUTOHEADER
- ------------------
- This environment variable can be set to specify the path & name of the
-diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst
-index dac17711dc11..1bce2aab4109 100644
---- a/Documentation/process/changes.rst
-+++ b/Documentation/process/changes.rst
-@@ -56,9 +56,14 @@ iptables 1.4.2 iptables -V
- openssl & libcrypto 1.0.0 openssl version
- bc 1.06.95 bc --version
- Sphinx\ [#f1]_ 1.3 sphinx-build --version
-+elfutils\ [#f2]_ 0.156 eu-readelf --version
-+pkg-config\ [#f2]_ 0.16 pkg-config --version
-+glib\ [#f2]_ 2.x pkg-config --exists glib-2.0 && echo present
-+libdtrace-ctf\ [#f2]_ 1.1
- ====================== =============== ========================================
-
- .. [#f1] Sphinx is needed only to build the Kernel documentation
-+.. [#f2] This is needed at build-time when CTF or DTrace are enabled
-
- Kernel compilation
- ******************
-@@ -94,7 +99,8 @@ pkg-config
- The build system, as of 4.18, requires pkg-config to check for installed
- kconfig tools and to determine flags settings for use in
- 'make {g,x}config'. Previously pkg-config was being used but not
--verified or documented.
-+verified or documented. dwarf2ctf also relies on it during 'make ctf' and
-+while building out-of-tree modules with CONFIG_CTF enabled.
-
- Flex
- ----
-@@ -371,6 +377,21 @@ OpenSSL
-
- - <https://www.openssl.org/>
-
-+elfutils
-+--------
-+
-+- <https://fedorahosted.org/elfutils/>
-+
-+glib 2.x
-+--------
-+
-+- <http://www.gtk.org/>
-+
-+libdtrace-ctf
-+-------------
-+
-+- <https://oss.oracle.com/git/?p=libdtrace-ctf.git>
-+
- System utilities
- ****************
-
-diff --git a/Makefile b/Makefile
-index a6b2e64bcf6c..e94e5bfc9c4f 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1166,7 +1166,7 @@ cmd_link-vmlinux = \
- $(CONFIG_SHELL) $< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)"; \
- $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
-
--vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE
-+vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) modules_thick.builtin FORCE
- +$(call if_changed,link-vmlinux)
-
- targets := vmlinux
-@@ -1406,6 +1406,45 @@ modules.order: $(subdir-modorder) FORCE
-
- targets += modules.order
-
-+ifneq (CONFIG_CTF@,'@')
-+
-+# We need to force everything to be built, since we need the .o files below.
-+KBUILD_BUILTIN := 1
-+
-+# This contains all the object files that are built directly into the
-+# kernel (including built-in modules), for consumption by dwarf2ctf in
-+# Makefile.modpost.
-+# This is made doubly annoying by the presence of '.o' files which are actually
-+# thin ar archives, and the need to support file(1) versions too old to
-+# recognize them as archives at all. (So we assume that everything that is not
-+# an ELF object is an archive.)
-+ifeq ($(SRCARCH),x86)
-+objects.builtin: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),bzImage) FORCE
-+else
-+objects.builtin: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) FORCE
-+endif
-+ @echo $(KBUILD_VMLINUX_OBJS) | \
-+ tr " " "\n" | grep "\.o$$" | xargs -r file | \
-+ grep ELF | cut -d: -f1 > objects.builtin
-+ @for archive in $$(echo $(KBUILD_VMLINUX_OBJS) |\
-+ tr " " "\n" | xargs -r file | grep -v ELF | cut -d: -f1); do \
-+ $(AR) t "$$archive" >> objects.builtin; \
-+ done
-+
-+ctf: vmlinux.ctfa
-+PHONY += ctf
-+
-+# Making CTF needs the builtin files unless out-of-tree.
-+ifeq ($(KBUILD_EXTMOD),)
-+vmlinux.ctfa: modules_thick.builtin objects.builtin
-+endif
-+vmlinux.ctfa:
-+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal vmlinux.ctfa
-+else
-+PHONY += objects.builtin
-+objects.builtin:
-+endif
-+
- # Target to prepare building external modules
- PHONY += modules_prepare
- modules_prepare: prepare
-@@ -1428,6 +1467,9 @@ _modinst_:
- @sed 's:^:kernel/:' modules.order > $(MODLIB)/modules.order
- @cp -f modules.builtin $(MODLIB)/
- @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/
-+ @if [ -f $(objtree)/vmlinux.ctfa ] ; then \
-+ cp -f $(objtree)/vmlinux.ctfa $(MODLIB)/kernel ; \
-+ fi
- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
-
- # This depmod is only for convenience to give the initial
-@@ -1459,6 +1501,23 @@ modules modules_install:
-
- endif # CONFIG_MODULES
-
-+# modules_thick.builtin maps from kernel modules (or rather the object file
-+# names they would have had had they not been built in) to their constituent
-+# object files: dwarf2ctf uses this to determine which modules any given object
-+# file is part of. (We cannot eliminate the slight redundancy here without
-+# double-expansion.)
-+
-+modthickbuiltin-dirs := $(addprefix _modthickbuiltin_, $(build-dirs))
-+
-+modules_thick.builtin: $(modthickbuiltin-dirs)
-+ $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(build-dirs)) > $@
-+
-+PHONY += $(modthickbuiltin-dirs)
-+# tristate.conf is not included from this Makefile. Add it as a prerequisite
-+# here to make it self-healing in case somebody accidentally removes it.
-+$(modthickbuiltin-dirs): include/config/tristate.conf
-+ $(Q)$(MAKE) $(modbuiltin)=$(patsubst _modthickbuiltin_%,%,$@) builtin-file=modules_thick.builtin
-+
- ###
- # Cleaning is done on three levels.
- # make clean Delete most generated files
-@@ -1467,9 +1526,10 @@ endif # CONFIG_MODULES
- # make distclean Remove editor backup files, patch leftover files and the like
-
- # Directories & files removed with 'make clean'
--CLEAN_FILES += include/ksym vmlinux.symvers \
-- modules.builtin modules.builtin.modinfo modules.nsdeps \
-- compile_commands.json
-+CLEAN_FILES += include/ksym .ctf vmlinux.symvers \
-+ modules.builtin modules.builtin.modinfo objects.builtin \
-+ modules.nsdeps compile_commands.json \
-+ .ctf.filelist .ctf.filelist.raw
-
- # Directories & files removed with 'make mrproper'
- MRPROPER_FILES += include/config include/generated \
-@@ -1564,6 +1624,8 @@ help:
- @echo ' (requires a recent binutils and recent build (System.map))'
- @echo ' dir/file.ko - Build module including final link'
- @echo ' modules_prepare - Set up for building external modules'
-+ @echo ' ctf - Generate CTF type information for DTrace, installed by '
-+ @echo ' make modules_install'
- @echo ' tags/TAGS - Generate tags file for editors'
- @echo ' cscope - Generate cscope index'
- @echo ' gtags - Generate GNU GLOBAL index'
-@@ -1825,7 +1887,7 @@ clean: $(clean-dirs)
- -o -name '*.symtypes' -o -name 'modules.order' \
- -o -name '.tmp_*.o.*' \
- -o -name '*.c.[012]*.*' \
-- -o -name '*.ll' \
-+ -o -name '*.ll' -o -name '*.ctfa' \
- -o -name '*.gcno' \) -type f -print | xargs rm -f
-
- # Generate tags for editors
-diff --git a/lib/Kconfig b/lib/Kconfig
-index b46a9fd122c8..e2906daac926 100644
---- a/lib/Kconfig
-+++ b/lib/Kconfig
-@@ -582,6 +582,18 @@ config DIMLIB
- #
- config LIBFDT
- bool
-+#
-+# CTF support is select'ed if needed
-+#
-+config CTF
-+ bool "Compact Type Format generation"
-+ default n
-+ select STRIP_ASM_SYMS
-+ depends on DEBUG_INFO && !DEBUG_INFO_REDUCED && !DEBUG_INFO_SPLIT && !DEBUG_INFO_DWARF4 && DTRACE
-+ help
-+ Emit a compact, compressed description of the kernel's datatypes and
-+ global variables into the vmlinux.ctfa archive (for in-tree modules)
-+ or into .ctf sections in kernel modules (for out-of-tree modules).
-
- config OID_REGISTRY
- tristate
-diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
-index 08e011175b4c..d3c6f0f56e65 100644
---- a/scripts/Kbuild.include
-+++ b/scripts/Kbuild.include
-@@ -157,6 +157,12 @@ ld-ifversion = $(shell [ $(ld-version) $(1) $(2) ] && echo $(3) || echo $(4))
- # $(Q)$(MAKE) $(build)=dir
- build := -f $(srctree)/scripts/Makefile.build obj
-
-+###
-+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj=
-+# Usage:
-+# $(Q)$(MAKE) $(modbuiltin)=dir
-+modbuiltin := -f $(srctree)/scripts/Makefile.modbuiltin obj
-+
- ###
- # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj=
- # Usage:
-diff --git a/scripts/Makefile b/scripts/Makefile
-index b5418ec587fb..041bcf48cc5c 100644
---- a/scripts/Makefile
-+++ b/scripts/Makefile
-@@ -34,6 +34,7 @@ targets += module.lds
-
- subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
- subdir-$(CONFIG_MODVERSIONS) += genksyms
-+subdir-$(CONFIG_CTF) += dwarf2ctf
- subdir-$(CONFIG_SECURITY_SELINUX) += selinux
-
- # Let clean descend into subdirs
-diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin
-new file mode 100644
-index 000000000000..f2c085e8640f
---- /dev/null
-+++ b/scripts/Makefile.modbuiltin
-@@ -0,0 +1,60 @@
-+# SPDX-License-Identifier: GPL-2.0
-+# ==========================================================================
-+# Generating modules_thick.builtin
-+# ==========================================================================
-+
-+src := $(obj)
-+
-+PHONY := __modbuiltin
-+__modbuiltin:
-+
-+include include/config/auto.conf
-+# tristate.conf sets tristate variables to uppercase 'Y' or 'M'
-+# That way, we get the list of built-in modules in obj-Y
-+include include/config/tristate.conf
-+
-+include scripts/Kbuild.include
-+
-+ifdef building_out_of_srctree
-+# Create output directory if not already present
-+_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
-+endif
-+
-+# The filename Kbuild has precedence over Makefile
-+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
-+kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
-+include $(kbuild-file)
-+
-+include scripts/Makefile.lib
-+__subdir-Y := $(patsubst %/,%,$(filter %/, $(obj-Y)))
-+subdir-Y += $(__subdir-Y)
-+subdir-ym := $(sort $(subdir-y) $(subdir-Y) $(subdir-m))
-+subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
-+pathobj-Y := $(addprefix $(obj)/,$(obj-Y))
-+
-+modthickbuiltin-subdirs := $(patsubst %,%/modules_thick.builtin, $(subdir-ym))
-+modthickbuiltin-target := $(obj)/modules_thick.builtin
-+
-+__modbuiltin: $(obj)/$(builtin-file) $(subdir-ym)
-+ @:
-+
-+$(modthickbuiltin-target): $(subdir-ym) FORCE
-+ $(Q) $(foreach mod-o, $(filter %.o,$(obj-Y)),\
-+ printf "%s:" $(addprefix $(obj)/,$(mod-o)) >> $@; \
-+ printf " %s" $(sort $(strip $(addprefix $(obj)/,$($(mod-o:.o=-objs)) \
-+ $($(mod-o:.o=-y)) $($(mod-o:.o=-Y))))) >> $@; \
-+ printf "\n" >> $@; ) \
-+ cat /dev/null $(modthickbuiltin-subdirs) >> $@;
-+
-+PHONY += FORCE
-+
-+FORCE:
-+
-+# Descending
-+# ---------------------------------------------------------------------------
-+
-+PHONY += $(subdir-ym)
-+$(subdir-ym):
-+ $(Q)$(MAKE) $(modbuiltin)=$@ builtin-file=$(builtin-file)
-+
-+.PHONY: $(PHONY)
-diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
-index ae01baf96f4e..920545d75da9 100644
---- a/scripts/Makefile.modfinal
-+++ b/scripts/Makefile.modfinal
-@@ -1,11 +1,21 @@
- # SPDX-License-Identifier: GPL-2.0-only
- # ===========================================================================
--# Module final link
-+# Module final link and CTF generation
- # ===========================================================================
-+# 1) compile all <module>.mod.c files
-+# 2) for external modules, generate CTF for the module (there is an extra,
-+# externally-invoked target that does this for the entire kernel but does
-+# not invoke the rst of the module-building process)
-+# 3) final link of the module to a <module.ko> file
-+
-+# We need secondary expansion for 'module-ctfs-modular-prereq', below.
-+
-+.SECONDEXPANSION:
-
- PHONY := __modfinal
- __modfinal:
-
-+include include/config/auto.conf
- include $(srctree)/scripts/Kbuild.include
-
- # for c_flags
-@@ -27,16 +37,141 @@ quiet_cmd_cc_o_c = CC [M] $@
- %.mod.o: %.mod.c FORCE
- $(call if_changed_dep,cc_o_c)
-
-+# Generate CTF for the entire kernel, or for the module alone if this is a
-+# build of an external module.
-+
-+# These are overridden below for standalone modules only.
-+module-ctfs-modular-prereq =
-+module-ctfs-modular =
-+module-ctf-flags =
-+cmd_touch_ctf =
-+ctf-dir = ///.nonexistent
-+cmd-touch-ctf = @:
-+
-+ifdef CONFIG_CTF
-+
-+# This is quite tricky. If called for non-external-modules, dwarf2ctf needs to
-+# be told about all the built-in objects as well as all the external modules --
-+# but Makefile.modpost only knows about the latter. So the toplevel makefile
-+# emits the names of the built-in objects into a temporary file, which is
-+# then catted and its contents used as prerequisites by this rule.
-+#
-+# We write the names of the object files to be scanned for CTF content into a
-+# file, then use that, to avoid hitting command-line length limits.
-+
-+ifeq ($(KBUILD_EXTMOD),)
-+ctf-dir-mk :=
-+quiet_cmd_ctf = CTFA
-+ cmd_ctf = scripts/dwarf2ctf/dwarf2ctf vmlinux.ctfa $(srctree) objects.builtin modules_thick.builtin $(srctree)/scripts/dwarf2ctf/member.blacklist $(ctf-filelist)
-+ctf-builtins := objects.builtin
-+ctf-builtins-prereq := $(ctf-builtins)
-+ ctf-modules := $(shell find . -name '*.ko' -print)
-+ctf-filelist := .ctf.filelist
-+ctf-filelist-raw := .ctf.filelist.raw
-+ctf-stamp :=
-+
-+else
-+ctf-dir := $(KBUILD_EXTMOD)/.ctf
-+ctf-dir-mk := $(ctf-dir)
-+quiet_cmd_ctf = CTF
-+ cmd_ctf = scripts/dwarf2ctf/dwarf2ctf $(ctf-dir) -e $(ctf-filelist)
-+ctf-builtins := ////.no-builtins
-+ctf-builtins-prereq :=
-+ctf-modules := $(modules:.ko=.o)
-+ctf-filelist := $(ctf-dir)/$(notdir $(M)-extmod).ctf.filelist
-+ctf-filelist-raw := $(ctf-dir)/$(notdir $(M)-extmod).ctf.filelist.raw
-+ctf-stamp = $(ctf-dir)/$(notdir $(M)-extmod).stamp
-+
-+# All the modules' CTF depends on the stamp file.
-+
-+all-module-ctfs = $(addprefix $(ctf-dir)/,$(notdir $(modules:.ko=.mod.ctf)))
-+$(all-module-ctfs): $(ctf-stamp)
-+
-+endif
-+
-+# Split a list up like shell xargs does.
-+define xargs =
-+$(1) $(wordlist 1,1024,$(2))
-+$(if $(word 1025,$(2)),$(call xargs,$(1),$(wordlist 1025,$(words $(2)),$(2))))
-+endef
-+
-+$(ctf-filelist-raw): $(ctf-builtins-prereq) $(ctf-modules)
-+ @rm -f $(ctf-filelist-raw);
-+ @if [ -n "$(ctf-dir-mk)" ]; then \
-+ mkdir -p "$(ctf-dir-mk)"; \
-+ fi
-+ $(call xargs,@printf "%s\n" >> $(ctf-filelist-raw),$^)
-+ @touch $(ctf-filelist-raw)
-+
-+$(ctf-filelist): $(ctf-filelist-raw)
-+ @rm -f $(ctf-filelist);
-+ @cat $(ctf-filelist-raw) | while read -r obj; do \
-+ case $$obj in \
-+ $(ctf-builtins)) cat $$obj >> $(ctf-filelist);; \
-+ *.a) ar t $$obj > $(ctf-filelist);; \
-+ *.builtin) cat $$obj >> $(ctf-filelist);; \
-+ *) echo "$$obj" >> $(ctf-filelist);; \
-+ esac; \
-+ done
-+ @touch $(ctf-filelist)
-+
-+ifeq ($(KBUILD_EXTMOD),)
-+# The CTF depends on the output CTF file list, and that depends
-+# on the .ko files for the modules.
-+vmlinux.ctfa: $(ctf-filelist)
-+ $(call if_changed,ctf)
-+else
-+
-+# The CTF depends on the output CTF file list, and that depends
-+# on the .o files for the modules
-+$(ctf-stamp): $(ctf-filelist)
-+ $(call if_changed,ctf)
-+ @shopt -s nullglob; \
-+ for name in $(ctf-dir)/*.ctf.new; do \
-+ $(srctree)/scripts/move-if-change $$name $${name%.new}; \
-+ done; \
-+ touch $(ctf-stamp)
-+
-+# Expands to the names of the CTF files to be incorporated into this module.
-+# The former is used in prerequisite lists, thanks to secondary expansion.
-+
-+module-ctfs-modular-prereq = $$(addprefix $(ctf-dir)/,$$(notdir $$*.mod.ctf))
-+module-ctfs-modular = $(addprefix $(ctf-dir)/,$(notdir $*.mod.ctf))
-+
-+# Expands to the name of a CTF file, given a target of a module name given to
-+# one of the link rules below.
-+
-+ctf-module-name = $(addprefix $(ctf-dir)/,$(notdir $(basename $@)).mod.ctf)
-+
-+# An objcopy --add-section argument to add the CTF section to a standalone
-+# module.
-+
-+module-ctf-flags = --add-section .ctf=$(ctf-module-name)
-+
-+# We have to put content in our dummy no-CTF files because --add-section
-+# in binutils 2.20 silently fails if asked to add an empty file as a section.
-+
-+cmd_touch_ctf = @for name in $(filter $(ctf-dir)/%,$(module-ctfs-modular)); do \
-+ test -f $$name || dd if=/dev/zero of=$$name bs=1 count=1 2>/dev/null; \
-+ done
-+
-+endif # KBUILD_EXTMOD
-+
-+endif # !CONFIG_CTF
-+
- ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
-
- quiet_cmd_ld_ko_o = LD [M] $@
- cmd_ld_ko_o = \
- $(LD) -r $(KBUILD_LDFLAGS) \
- $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
-- -T scripts/module.lds -o $@ $(filter %.o, $^); \
-+ -T scripts/module.lds $(LDFLAGS_$(modname)) -o $@.tmp \
-+ $(patsubst $(ctf-dir)/%,,$(filter %.o, $^)) && \
-+ $(OBJCOPY) $(module-ctf-flags) $@.tmp $@ && rm -f $@.tmp ; \
- $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
-
--$(modules): %.ko: %.o %.mod.o scripts/module.lds FORCE
-+$(modules): %.ko: %.o %.mod.o scripts/module.lds $(module-ctfs-modular-prereq) FORCE
-+ $(call cmd_touch_ctf)
- +$(call if_changed,ld_ko_o)
-
- targets += $(modules) $(modules:.ko=.mod.o)
-diff --git a/scripts/dwarf2ctf/.gitignore b/scripts/dwarf2ctf/.gitignore
-new file mode 100644
-index 000000000000..e37b47cf3028
---- /dev/null
-+++ b/scripts/dwarf2ctf/.gitignore
-@@ -0,0 +1 @@
-+dwarf2ctf
-diff --git a/scripts/dwarf2ctf/Makefile b/scripts/dwarf2ctf/Makefile
-new file mode 100644
-index 000000000000..2b40419add31
---- /dev/null
-+++ b/scripts/dwarf2ctf/Makefile
-@@ -0,0 +1,10 @@
-+ifdef CONFIG_CTF
-+hostprogs-always-$(CONFIG_CTF) := dwarf2ctf
-+
-+dwarf2ctf-objs := dwarf2ctf.o eu_simple.o
-+
-+HOSTCFLAGS_eu_simple.o := -I$(srctree)/scripts
-+HOSTCFLAGS_dwarf2ctf.o := $(shell pkg-config --cflags glib-2.0) -I$(srctree)/scripts
-+
-+HOSTLDLIBS_dwarf2ctf := -ldtrace-ctf -lelf -ldw $(shell pkg-config --libs glib-2.0) -lz
-+endif
-diff --git a/scripts/dwarf2ctf/dwarf2ctf.c b/scripts/dwarf2ctf/dwarf2ctf.c
-new file mode 100644
-index 000000000000..ecd430174442
---- /dev/null
-+++ b/scripts/dwarf2ctf/dwarf2ctf.c
-@@ -0,0 +1,4962 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * dwarf2ctf.c: Read in DWARF[23] debugging information from some set of ELF
-+ * files, and generate CTF in correspondingly-named files, or in a single
-+ * representation meant for mmapping.
-+ *
-+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#define _GNU_SOURCE 1
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <stddef.h>
-+#include <sys/stat.h>
-+#include <sys/types.h>
-+#include <fcntl.h>
-+#include <limits.h>
-+#include <endian.h>
-+#include <unistd.h>
-+
-+#include <libelf.h>
-+#include <dwarf.h>
-+#include <elfutils/libdwfl.h>
-+#include <elfutils/libdw.h>
-+#include <elfutils/version.h>
-+#include <sys/ctf_api.h>
-+#include <glib.h>
-+
-+#include <eu_simple.h>
-+
-+#ifndef PATH_MAX
-+#define PATH_MAX 1024
-+#endif
-+
-+#define __unused__ __attribute__((__unused__))
-+
-+/*
-+ * If non-NULL, tracing is on.
-+ */
-+static const char *trace;
-+
-+/*
-+ * Trace something.
-+ */
-+#ifdef DEBUG
-+#define dw_ctf_trace(format, ...) do { \
-+ if (trace) \
-+ fprintf(stderr, (format), ## __VA_ARGS__); \
-+} while (0)
-+#else
-+#define dw_ctf_trace(format, ...)
-+#endif
-+
-+/*
-+ * Run dwarf2ctf over a single object file or set thereof.
-+ *
-+ * output_dir is the directory into which the CTF goes, if 'standalone', or the
-+ * CTF archive file name otherwise.
-+ */
-+static void run(char *output, int standalone);
-+
-+/*
-+ * Whether we are deduplicating. We do not deduplicate if run over external
-+ * modules.
-+ */
-+static int deduplicating;
-+
-+/*
-+ * A fully descriptive CTF type ID: both file and type ID in one place.
-+ */
-+struct ctf_full_id {
-+ ctf_file_t *ctf_file;
-+ ctf_id_t ctf_id;
-+#ifdef DEBUG
-+ char module_name[PATH_MAX];
-+ char file_name[PATH_MAX];
-+#endif
-+};
-+
-+/*
-+ * A hash mapping 'atoms' (almost entirely type IDs) to nothing.
-+ */
-+static GHashTable *atoms;
-+
-+/*
-+ * A mapping from the type ID of a DIE (see type_id()) to ctf_full_id_t's
-+ * describing the type with that ID. The type ID is an atom.
-+ *
-+ * This is used to look up types regardless of which CTF file they may reside
-+ * in. Not the same as a DWARF4 type signature because we must encode scope
-+ * information which DWARF4 can encode in its DIE refs.
-+ *
-+ * (TODO: store a hash of the ID rather than the ID itself, to save memory.
-+ * Makes debugging slightly harder though.)
-+ */
-+static GHashTable *id_to_type;
-+
-+/*
-+ * A mapping from the type ID of a DIE (an atom) to the name of the module (and
-+ * thus CTF table) incorporating that type. (Modules in this context, and
-+ * throughout dwarf2ctf, are DTrace modules: a name without suffix or path.)
-+ *
-+ * This is used to merge types identical across modules (e.g. those in global
-+ * header files).
-+ */
-+static GHashTable *id_to_module;
-+
-+/*
-+ * Module-specific state. The module named 'vmlinux' is that corresponding to
-+ * the types in always-built-in translation units; the module named 'shared_ctf'
-+ * (not appearing in this mapping) is that corresponding to types shared between
-+ * more than one module (even between two currently-built-in modules: we do not
-+ * distinguish at this level between built-in modules and non-built-in modules.)
-+ */
-+static GHashTable *per_module;
-+
-+/*
-+ * The data structure that per_module maps module names to.
-+ */
-+struct per_module {
-+ /*
-+ * The CTF file containing the types in this module.
-+ */
-+ ctf_file_t *ctf_file;
-+
-+ /*
-+ * A hash from a "CTF-form" structure name (in the form 's/u NAME') to
-+ * a struct ctf_memb_count (see below).
-+ */
-+ GHashTable *member_counts;
-+};
-+
-+/*
-+ * A count associating a type ID relating to a structure or union with a count
-+ * of members in that structure.
-+ */
-+struct ctf_memb_count {
-+ ctf_id_t ctf_id;
-+ size_t count;
-+};
-+
-+/*
-+ * A mapping from the absolute pathname of a TU to a hashtable mapping
-+ * DIE offsets of child DIEs to DIE offsets of parents. Populated on first
-+ * iteration. Contains only those DIEs that we know are necessary for other
-+ * functions' use of this structure, to keep memory usage down.
-+ */
-+static GHashTable *fn_to_die_to_parent;
-+
-+/*
-+ * Get a ctf_file out of the per_module hash for a given module.
-+ */
-+static ctf_file_t *lookup_ctf_file(const char *module_name);
-+
-+/*
-+ * The names of the object files to run over. Except in -e mode, this comes
-+ * straight from the module filelist passed in.
-+ */
-+static char **object_names;
-+static size_t object_names_cnt;
-+
-+/*
-+ * Populate the object_names list from the module filelist.
-+ */
-+static void init_object_names(const char *object_names_file);
-+
-+/*
-+ * Populate and object_to_module from the objects.builtin and modules.builtin
-+ * file.
-+ */
-+static void init_builtin(const char *builtin_objects_file,
-+ const char *builtin_module_file);
-+
-+/*
-+ * The member blacklist bans fields with specific names in specifically named
-+ * structures, declared in specific source files, from being emitted. The
-+ * mapping is from absolute source file name:structure.member to NULL (this is
-+ * safe because type names cannot contain a colon, and structure names cannot
-+ * contain a period).
-+ */
-+static GHashTable *member_blacklist;
-+
-+/*
-+ * Populate the member blacklist from the member_blacklist file.
-+ */
-+static void init_member_blacklist(const char *member_blacklist_file,
-+ const char *srcdir);
-+
-+/*
-+ * Return 1 if a given DWARF DIE, which must be a DW_TAG_member, appears in the
-+ * member blacklist.
-+ */
-+static int member_blacklisted(Dwarf_Die *die, Dwarf_Die *parent_die);
-+
-+/*
-+ * The variable blacklist, like the others, is an automatically-maintained
-+ * blacklist giving variables in specific modules which should not be emitted.
-+ * (These are variables whose names are ambiguous within a module, and may
-+ * appear multiple times in /proc/kallmodsyms, identical but for address and
-+ * thus indistinguishable.)
-+ *
-+ * The mapping is from module`variable to NULL (safe because variable names
-+ * cannot begin with a backtick, and even if they could DTrace's notation could
-+ * not reference such variables).
-+ */
-+static GHashTable *variable_blacklist;
-+
-+/*
-+ * A mapping from object file name to the name of the module that translation
-+ * unit is part of.
-+ *
-+ * Actual, real, on-disk .ko modules do not appear here, because the translation
-+ * is trivial for them.
-+ */
-+static GHashTable *object_to_module;
-+
-+/*
-+ * Initialize a CTF type table, and possibly fill it with those special types
-+ * that appear in CTF but not in DWARF (such as 'void'). (This filling happens
-+ * only for the type table named "shared_ctf", unless deduplication is turned
-+ * off.)
-+ *
-+ * If this is a local type table, and deduplication is active, make the global
-+ * type table its parent.
-+ */
-+static void init_ctf_table(const char *module_name);
-+
-+/*
-+ * A few useful singleton CTF type IDs in the global type table: a void pointer
-+ * and a function pointer. Constructed by init_ctf_table().
-+ */
-+static ctf_id_t ctf_void_type;
-+static ctf_id_t ctf_funcptr_type;
-+
-+/*
-+ * Initialize the child->parent DIE mapping for a single file.
-+ */
-+static void init_parent_die(const char *file_name, Dwfl *dwfl);
-+
-+/*
-+ * Initialize one layer of a child->parent mapping.
-+ */
-+static int init_parent_die_internal(const char *file_name,
-+ GHashTable *offs, Dwarf_Die *parent,
-+ int depth, int found_subprogram);
-+
-+/*
-+ * Override the presence and value of FORM_u/sdata attributes on DWARF DIEs,
-+ * either adding to it, or replacing it.
-+ *
-+ * (Used so that a caller of construct_ctf_id() that wants a type to be created
-+ * can override aspects of that type.)
-+ *
-+ * The 'chain', if set, causes the various private_*() functions that handle
-+ * overrides to look back along the chain to find a suitable attribute. The
-+ * chain must be set on the last element in the array. The search for
-+ * attributes terminates at the first match.
-+ *
-+ * Note: this is not a particularly generic implementation: a better approach
-+ * would be to keep walking the chain on DIE_OVERRIDE_ADD, and keep adding until
-+ * we are done: but we have only one user of ADD, and it implements the addition
-+ * itself because it is adding to a value from a different DIE: so this added
-+ * generality is not needed yet.
-+ */
-+struct die_override {
-+ int tag;
-+ int attribute;
-+ enum { DIE_OVERRIDE_REPLACE, DIE_OVERRIDE_ADD } op;
-+ Dwarf_Sword value;
-+ struct die_override *chain;
-+};
-+
-+/*
-+ * Compute the type ID of a DWARF DIE (with possibly-overridden attributes) and
-+ * return it in a new dynamically-allocated string.
-+ *
-+ * Optionally, call a callback with the computed ID once we know it (this is a
-+ * recursive process, so the callback can be called multiple times as the ID
-+ * is built up).
-+ *
-+ * An ID of NULL indicates that this DIE has no ID and need not be considered.
-+ */
-+static char *type_id(Dwarf_Die *die, struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data) __attribute__((__warn_unused_result__));
-+
-+/*
-+ * Internal: allows flags to be passed to affect one (and only one) type ID
-+ * recursion, without affecting other type_id()s launched from the 'fun'.
-+ */
-+static char *type_id_internal(Dwarf_Die *die,
-+ struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data,
-+ int flags);
-+
-+/*
-+ * Internal: generate the type ID for a type DIE.
-+ *
-+ * If there are no overrides, look for a bit_size and bit_offset and pass them
-+ * down as well.
-+ */
-+static char *type_id_type_die(Dwarf_Die *die,
-+ Dwarf_Die *type_die,
-+ struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data);
-+
-+/*
-+ * Convert 'long unsigned int' to 'sizetype'. Internal use within type_id().
-+ */
-+#define TI_COLLAPSE_SIZETYPE 0x1
-+
-+/*
-+ * Process a file, calling the dwarf_process function for every type found
-+ * therein (even types in functions). Optionally call tu_init() at the start of
-+ * each translation unit, and tu_done() at the end.
-+ */
-+static void process_file(const char *file_name,
-+ void (*dwarf_process)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ void *data),
-+ void (*tu_init)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *tu_die,
-+ void *data),
-+ void (*tu_done)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *tu_die,
-+ void *data),
-+ void *data);
-+
-+/*
-+ * process_file() helper, walking over the top level and picking up types
-+ * therein.
-+ */
-+static void process_tu_func(const char *module_name,
-+ const char *file_name,
-+ Dwarf *dwarf,
-+ Dwarf_Die *parent_die,
-+ Dwarf_Die *die,
-+ void (*dwarf_process)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ void *data),
-+ void *data);
-+
-+/*
-+ * Records the type ID of interesting types, the files they are contained in,
-+ * and their DWARF offset, so they can be found rapidly.
-+ *
-+ * Used to avoid rescanning files that can contain no duplicates.
-+ */
-+struct dedup_id_file {
-+ char *file_name;
-+ char *id;
-+ Dwarf_Off dieoff;
-+};
-+
-+/*
-+ * The structure used as the data argument for dedup() and
-+ * dedup_alias_fixup().
-+ *
-+ * structs_seen tracks the IDs of structures marked as duplicates within a given
-+ * translation unit, in order that recursion terminates if two such structures
-+ * have pointers to each other.
-+ *
-+ * vars_seen tracks variables seen in this module, mapping from unadorned name
-+ * to a non-NULL pointer (for static, non-'external') or NULL (for non-static or
-+ * 'extern'). If a static variable coexists with any other variable with the
-+ * same name, static or not, the variable is blacklisted. (Non-static
-+ * coexistence is fine, because they are just different references to the same
-+ * variable). Note that management of this variable is a little annoying
-+ * because it varies by module, not by TU, so we can't use tu_init/tu_done to
-+ * manage its lifetime.
-+ *
-+ * named_structs tracks type IDs and contained modules for every type that may
-+ * contain undetected duplicates and thus may require rescanning.
-+ *
-+ * dwfl and dwfl_file_name identify the opened DWARF file (if any) during the
-+ * second duplicates detection pass.
-+ *
-+ * repeat_detection is set by each phase if it considers that another round of
-+ * alias fixup detection is needed.
-+ */
-+struct dedup_state {
-+ const char *file_name;
-+ const char *module_name;
-+ GHashTable *structs_seen;
-+ GList *named_structs;
-+ GHashTable *vars_seen;
-+ char *dwfl_file_name;
-+ Dwarf *dwarf;
-+ Dwfl *dwfl;
-+ int repeat_detection;
-+};
-+
-+/*
-+ * Scan and identify duplicates across the entire set of object files.
-+ */
-+static void scan_dups(void);
-+
-+/*
-+ * Recursively detect duplicate types and types referenced by them, and
-+ * determine which CTF file they should be located in, and request a
-+ * dedup_alias_fixup() pass if any structures are shared.
-+ * Determine the mapping from translation unit name to module name.
-+ */
-+static void dedup(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die, void *data);
-+
-+/*
-+ * Do the underlying marking of a DIE as shared, iff need be. (No variable
-+ * blacklisting, non-opaque structure checks, or anything else needed only by
-+ * top-level DIEs.)
-+ *
-+ * This function may be called multiple times for overridden DIEs that are
-+ * dependent types of bitfields.
-+ */
-+static void dedup_mark_inner_die(const char *module_name, Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data);
-+
-+/*
-+ * Note in the dedup_id_file list that we will rescan a DIE in a later duplicate
-+ * detection pass.
-+ *
-+ * A type_id() callback.
-+ */
-+static void dedup_will_rescan(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data);
-+
-+/*
-+ * Note the variable referenced by this DIE in vars_seen: blacklist it if an
-+ * entry for this variable already exists in vars_seen and this instance is
-+ * static, or if a static entry already exists in vars_seen, whether this
-+ * instance is static or not.
-+ */
-+static void dedup_blacklist_var_dups(Dwarf_Die *die,
-+ struct dedup_state *state);
-+
-+/*
-+ * Detect duplicates and mark seen types for a given type, via a type_id()
-+ * callback: used to detect dependent types (particularly those at child-DIE
-+ * level) as duplicates.
-+ */
-+static void dedup_typeid(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data);
-+
-+/*
-+ * Mark any aggregates contained within a particular type DIE as seen. This is
-+ * needed since even nameless aggregates contained within other aggregates can
-+ * be used as the type of members of the outer aggregate (though they cannot
-+ * possibly be found in a module different from that of their containing
-+ * aggregate, any more than a structure member can).
-+ */
-+static void mark_seen_contained(Dwarf_Die *die, const char *module_name,
-+ struct die_override *overrides, void *data);
-+
-+/*
-+ * Determine if some type (whose ultimate base type is an non-opaque structure,
-+ * alias, or enum) has an opaque equivalent which is shared, and mark it and
-+ * all its bases as shared too if so.
-+ *
-+ * A list_filter() filter function.
-+ */
-+static int dedup_alias_fixup(void *id_file_data, void *data);
-+
-+/*
-+ * Mark a basic type shared by name and intern it in all relevant hashes. (Used
-+ * for marking basic types we don't have a DIE for.)
-+ */
-+static void mark_shared_by_name(ctf_file_t *ctf, ctf_id_t ctf_id,
-+ const char *name);
-+
-+/*
-+ * Determine if a type is a named struct, union, or enum.
-+ *
-+ * A type_id() callback.
-+ */
-+static void is_named_struct_union_enum(Dwarf_Die *die, const char *unused,
-+ struct die_override *overrides,
-+ void *data);
-+
-+/*
-+ * Set up state for dedup(). A tu_init() callback.
-+ */
-+static void dedup_tu_init(const char *module_name, const char *file_name,
-+ Dwarf_Die *tu_die, void *data);
-+
-+/*
-+ * Free state for dedup(). A tu_done() callback.
-+ */
-+static void dedup_tu_done(const char *module_name, const char *file_name,
-+ Dwarf_Die *tu_die, void *data);
-+
-+/*
-+ * Free DWARF state for dedup().
-+ */
-+static void dedup_dwarf_free(struct dedup_state *state);
-+
-+/*
-+ * Determine if a type is duplicated and needs sharing.
-+ */
-+enum needs_sharing { NS_NOT_SHARED, NS_NO_MARKING, NS_NEEDS_SHARING };
-+static enum needs_sharing type_needs_sharing(const char *module_name,
-+ const char *id);
-+
-+/*
-+ * Mark a type (optionally, with an already-known ID) as duplicated and located
-+ * in the shared CTF table.
-+ *
-+ * A type_id() callback (though also called directly).
-+ */
-+static void mark_shared(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data);
-+
-+/*
-+ * Construct CTF out of each type.
-+ */
-+static void construct_ctf(const char *module_name, const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ void *unused __unused__);
-+
-+/*
-+ * Write out the CTF files from the per_module->ctf_file into files in the
-+ * output directory (if standalone), or into the output file (otherwise).
-+ */
-+static void write_types(char *output, int standalone);
-+
-+/*
-+ * Construct CTF out of each type and return that type's ID and file.
-+ */
-+static struct ctf_full_id *construct_ctf_id(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ struct die_override *overrides);
-+
-+/*
-+ * Things to do after a CTF recursion step.
-+ */
-+enum skip_type { SKIP_CONTINUE = 0, SKIP_SKIP, SKIP_ABORT };
-+
-+/*
-+ * Recursive over a given DWARF DIE and its children andconstruct CTF out of it.
-+ *
-+ * Most parameters are shared with the ctf_assembly_fun: see the comment below.
-+ */
-+static ctf_id_t die_to_ctf(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die,
-+ ctf_file_t *ctf, ctf_id_t parent_ctf_id,
-+ struct die_override *overrides, int top_level_type,
-+ int backwards, enum skip_type *skip, int *replace,
-+ const char *id);
-+
-+/*
-+ * Return the next DIE, if that DIE needs to be emitted before this one.
-+ */
-+static Dwarf_Die *die_emit_next_backwards(Dwarf_Die *next, Dwarf_Die *die,
-+ struct die_override *overrides);
-+
-+/*
-+ * Look up a type through its reference: return its ctf_id_t, or
-+ * recursively construct it if need be.
-+ *
-+ * Must be called on a DIE with a type attribute.
-+ */
-+static ctf_id_t lookup_ctf_type(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, ctf_file_t *ctf,
-+ struct die_override *overrides,
-+ const char *locerrstr);
-+
-+/*
-+ * Assemble a given DIE and its children into CTF in some fashion, returning the
-+ * ID of the top-level piece of generated CTF (only relevant for aggregates).
-+ *
-+ * The parent_ctf_id is the ID of the CTF entity that was or is being generated
-+ * from the enclosing DWARF DIE, or 0 if population succeeded but did not yield
-+ * a type ID (e.g. for variable assembly), or -1 on error. The parent_die is
-+ * the parent of the current DWARF DIE, and is always populated (even if just
-+ * with the CU's DIE). The parent_ctf_id is always in the same CTF file as the
-+ * ctf_id, just as the parent DWARF DIE is always in the same DWARF CU: this is
-+ * lexical scope, not dynamic, so referenced types themselves located at the top
-+ * level have the CU as their parent.
-+ *
-+ * Returning an error value (see below) indicates that no CTF was generated from
-+ * this DWARF DIE.
-+ *
-+ * Setting skip to SKIP_ABORT indicates that the translation of this entity
-+ * failed, and the entire top-level type of which it is a part should be
-+ * skipped. Setting it to SKIP_SKIP indicates that this entity does not need to
-+ * be translated (perhaps because it already exists), so recursion into
-+ * sub-entities can be skipped, but translation of the containing type should
-+ * continue. Setting it to SKIP_CONTINUE indicates no error.
-+ *
-+ * Setting 'replace' to 1 in a child DIE indicates that this type should
-+ * entirely *replace* its parent's type (generally because it has wrapped it up
-+ * in something). This replacemenu takes immediate effect for later children of
-+ * the same DIE.
-+ *
-+ * die_to_ctf() calls these functions repeatedly for every child of the
-+ * requested DIE: the CTF ID eventually returned is whatever ID is returned by
-+ * the last such function, and parent_ctf_id is repeatedly replaced with the ID
-+ * returned by the last assembly function. Thus, assembly functions that
-+ * augment an already-present ctf_id should return parent_ctf_id: assembly
-+ * functions that wrap it in a new ctf_id referring to the parent_ctf_id should
-+ * return the new ID. (Assembly functions should never entirely disregard the
-+ * parent_ctf_id.)
-+ */
-+typedef ctf_id_t (*ctf_assembly_fun)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace);
-+
-+#define ASSEMBLY_FUN(name) \
-+ static ctf_id_t assemble_ctf_##name(const char *module_name, \
-+ const char *file_name, \
-+ Dwarf_Die *die, \
-+ Dwarf_Die *parent_die, \
-+ ctf_file_t *ctf, \
-+ ctf_id_t parent_ctf_id, \
-+ const char *locerrstr, \
-+ struct die_override *overrides, \
-+ int top_level_type, \
-+ enum skip_type *skip, \
-+ int *replace)
-+
-+/*
-+ * Defined assembly functions.
-+ */
-+ASSEMBLY_FUN(base);
-+ASSEMBLY_FUN(array);
-+ASSEMBLY_FUN(array_dimension);
-+ASSEMBLY_FUN(cvr_qual);
-+ASSEMBLY_FUN(enumeration);
-+ASSEMBLY_FUN(enumerator);
-+ASSEMBLY_FUN(pointer);
-+ASSEMBLY_FUN(struct_union);
-+ASSEMBLY_FUN(su_member);
-+ASSEMBLY_FUN(typedef);
-+ASSEMBLY_FUN(variable);
-+
-+/*
-+ * An assembly filter is an optional function called with the DIE and parent DIE
-+ * of a top-level type alone, before calling down into the process_file()
-+ * processing function: it can be used to rapidly determine that this DIE is not
-+ * worth processing. (It should return 0 in this case, and nonzero otherwise.)
-+ */
-+typedef int (*ctf_assembly_filter_fun)(const char *file_name,
-+ Dwarf *dwarf,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die);
-+
-+/*
-+ * A CTF assembly filter function which excludes all types not at the global
-+ * scope (i.e. whose immediate parent is not a CU DIE) and which does not have a
-+ * structure or union as its ultimate dependent type. (All structures and
-+ * unions and everything dependent on them must be recorded, even inside
-+ * functions, because GCC may emit references to the opaque variants of those
-+ * types from file scope.)
-+ */
-+static int filter_ctf_file_scope(const char *file_name,
-+ Dwarf *dwarf,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die);
-+
-+/*
-+ * A CTF assembly filter function which excludes all names not at the global
-+ * scope, all static symbols, and all names whose names are unlikely to be
-+ * interesting. (DTrace userspace contains a similar list, but the two lists
-+ * need not be in sync.)
-+ */
-+static int filter_ctf_uninteresting(const char *file_name,
-+ Dwarf *dwarf,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die);
-+
-+/*
-+ * Error return values from CTF assembly functions. These differ only in that
-+ * die_to_ctf() reports the ctf_errmsg() if CTF_NO_ERROR_REPORTED is returned,
-+ * but says nothing in the CTF_ERROR_REPORTED case.
-+ */
-+#define CTF_NO_ERROR_REPORTED CTF_ERR
-+#define CTF_ERROR_REPORTED (-2L)
-+
-+/*
-+ * The total number of type errors encountered.
-+ */
-+static long num_errors;
-+
-+/*
-+ * A mapping from DW_TAG_* to functions which assemble this DW_TAG_* and
-+ * possibly its children into the passed CTF. This table is not used
-+ * directly, but rather assembled into a lookup table.
-+ */
-+static struct assembly_tab_t
-+{
-+ int tag;
-+ ctf_assembly_filter_fun filter;
-+ ctf_assembly_fun fun;
-+} assembly_tab_init[] =
-+{{ DW_TAG_base_type, filter_ctf_file_scope, assemble_ctf_base },
-+ { DW_TAG_array_type, filter_ctf_file_scope, assemble_ctf_array },
-+ { DW_TAG_subrange_type, NULL, assemble_ctf_array_dimension },
-+ { DW_TAG_const_type, filter_ctf_file_scope, assemble_ctf_cvr_qual },
-+ { DW_TAG_restrict_type, filter_ctf_file_scope, assemble_ctf_cvr_qual },
-+ { DW_TAG_enumeration_type, NULL, assemble_ctf_enumeration },
-+ { DW_TAG_enumerator, NULL, assemble_ctf_enumerator },
-+ { DW_TAG_pointer_type, filter_ctf_file_scope, assemble_ctf_pointer },
-+ { DW_TAG_structure_type, NULL, assemble_ctf_struct_union },
-+ { DW_TAG_union_type, NULL, assemble_ctf_struct_union },
-+ { DW_TAG_member, NULL, assemble_ctf_su_member },
-+ { DW_TAG_typedef, NULL, assemble_ctf_typedef },
-+ { DW_TAG_variable, filter_ctf_uninteresting, assemble_ctf_variable },
-+ { DW_TAG_volatile_type, filter_ctf_file_scope, assemble_ctf_cvr_qual },
-+ { 0, NULL }};
-+
-+/*
-+ * The CTF assembly and filter lookup tables, in constructed form.
-+ */
-+static ctf_assembly_fun *assembly_tab;
-+static ctf_assembly_filter_fun *assembly_filter_tab;
-+static size_t assembly_len;
-+
-+/*
-+ * Populate the assembly_tab and assembly_filter_tab from the assembly_tab_init.
-+ */
-+static void init_assembly_tab(void);
-+
-+/*
-+ * A mapping from sizeof() to CTF type encoding.
-+ */
-+struct type_encoding_tab {
-+ size_t size;
-+ int ctf_encoding;
-+};
-+
-+/*
-+ * Given a type encoding table, and a size, return the CTF encoding for that
-+ * type, or 0 if none.
-+ */
-+static int find_ctf_encoding(struct type_encoding_tab *type_tab, size_t size);
-+
-+/*
-+ * Count the number of members of a DWARF aggregate.
-+ */
-+static long count_dwarf_members(Dwarf_Die *die);
-+
-+/*
-+ * Given a DIE that may contain a type attribute, look up the target of that
-+ * attribute and return it, or NULL if none.
-+ */
-+static Dwarf_Die *private_dwarf_type(Dwarf_Die *die, Dwarf_Die *target_die);
-+
-+/*
-+ * Check for existence of an attribute in a DIE, chasing through
-+ * DW_AT_specification if need be.
-+ */
-+static inline int private_dwarf_hasattr(Dwarf_Die *die,
-+ unsigned int search_name);
-+
-+/*
-+ * Return a DIE attribute, chasing through DW_AT_specification if need be.
-+ */
-+static inline Dwarf_Attribute *private_dwarf_attr(Dwarf_Die *die,
-+ unsigned int search_name,
-+ Dwarf_Attribute *result);
-+
-+/*
-+ * Given a DIE that contains a udata attribute, look up that attribute and
-+ * return its value (optionally overridden or modified by the die_overrides).
-+ */
-+static inline Dwarf_Word private_dwarf_udata(Dwarf_Die *die, int attribute,
-+ struct die_override *overrides);
-+
-+/*
-+ * Given a DIE, return its byte size, if known and interpretable, or -1
-+ * otherwise.
-+ */
-+static inline long long private_dwarf_size(Dwarf_Die *die);
-+
-+/*
-+ * Find an override in an override list.
-+ */
-+static struct die_override *
-+private_find_override(Dwarf_Die *die,
-+ int attribute,
-+ struct die_override *overrides);
-+
-+/*
-+ * Determine the dimensions of an array subrange, or 0 if variable.
-+ */
-+static Dwarf_Word private_subrange_dimensions(Dwarf_Die *die);
-+
-+/*
-+ * A string appender working on dynamic strings.
-+ */
-+static char *str_append(char *s, const char *append)
-+ __attribute__((__warn_unused_result__));
-+
-+/*
-+ * A vararg string appender.
-+ */
-+static char *str_appendn(char *s, ...)
-+ __attribute__((__warn_unused_result__, sentinel));
-+
-+/*
-+ * An error-checking strdup().
-+ */
-+static char *xstrdup(const char *s) __attribute__((__nonnull__,
-+ __warn_unused_result__,
-+ __malloc__));
-+
-+/*
-+ * Filter a GList, calling a predicate on it and removing all elements for which
-+ * the predicate returns true, calling the free_func on them if set.
-+ */
-+typedef int (*filter_pred_fun) (void *element, void *data);
-+static GList *list_filter(GList *list, filter_pred_fun fun,
-+ GDestroyNotify free_func, void *data);
-+
-+/*
-+ * Intern an atom in the atoms table and return it, or free it and return the
-+ * existing atom if one is already interned. (Despite the type signature, this
-+ * return value is constant and should not be freed.)
-+ */
-+static void *intern(char *atom);
-+
-+/*
-+ * Figure out the (pathless, suffixless) module name for a given module file (.o
-+ * or .ko), and return it in a new dynamically allocated string.
-+ *
-+ * Takes the object_to_module mapping into account.
-+ */
-+static char *fn_to_module(const char *file_name);
-+
-+/*
-+ * Determine, and cache, absolute filenames.
-+ */
-+static const char *abs_file_name(const char *file_name);
-+
-+/*
-+ * Determine absolute filenames relative to some other directory: do not cache
-+ * them. It is the caller's responsibility to free them.
-+ */
-+static char *rel_abs_file_name(const char *file_name, const char *relative_to);
-+
-+/*
-+ * Free a per_module's contents.
-+ */
-+static void private_per_module_free(void *per_module);
-+
-+/*
-+ * Free a dedup_id_file's contents.
-+ */
-+static void free_dups_id_file(void *id_file);
-+
-+/*
-+ * Free a fn_to_die_to_parent subhash.
-+ */
-+static void private_fn_die_parent_free(void *ptr);
-+
-+/*
-+ * dwarf_dieoffset() with a return type better for printf().
-+ */
-+#define DIEOFFSET(die) (unsigned long) dwarf_dieoffset((die))
-+
-+/*
-+ * A line-shortener with a kernel-familiar name for fprintfing to stderr.
-+ */
-+#define pr_err(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
-+
-+/* Initialization. */
-+
-+int main(int argc, char *argv[])
-+{
-+ char *output;
-+
-+ trace = getenv("DWARF2CTF_TRACE");
-+
-+ if ((argc != 4 && argc != 7) ||
-+ (argc == 4 && strcmp(argv[2], "-e") != 0)) {
-+ pr_err("Syntax: dwarf2ctf output-file srcdir objects.builtin\n");
-+ pr_err(" modules.builtin member.blacklist filelist\n");
-+ pr_err(" or dwarf2ctf output-dir -e filelist\n"
-+ "for external module use\n");
-+ exit(1);
-+ }
-+
-+ output = argv[1];
-+
-+ elf_version(EV_CURRENT);
-+
-+ if (elf_errno()) {
-+ pr_err("Version synchronization fault: %s\n",
-+ elf_errmsg(elf_errno()));
-+ exit(1);
-+ }
-+
-+ init_assembly_tab();
-+ object_to_module = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ free, free);
-+
-+ /*
-+ * When not building an external module, we run over all the arguments
-+ * at once, deduplicating them. In external-module mode, we act as if
-+ * independently invoked with every argument.
-+ */
-+ if (strcmp(argv[2], "-e") != 0) {
-+ const char *srcdir;
-+ char *builtin_objects_file;
-+ char *builtin_module_file;
-+ char *member_blacklist_file;
-+
-+ srcdir = argv[2];
-+ builtin_objects_file = argv[3];
-+ builtin_module_file = argv[4];
-+ member_blacklist_file = argv[5];
-+ deduplicating = 1;
-+
-+ init_builtin(builtin_objects_file, builtin_module_file);
-+ init_member_blacklist(member_blacklist_file, srcdir);
-+ init_object_names(argv[6]);
-+
-+ run(output, 0);
-+ } else {
-+ char *single_object_name;
-+ char **all_object_names;
-+ size_t all_object_names_cnt;
-+ size_t i;
-+
-+ deduplicating = 0;
-+ init_object_names(argv[3]);
-+
-+ /*
-+ * Repeatedly populate object_names with one object name, and
-+ * call run() with that.
-+ */
-+ all_object_names = object_names;
-+ all_object_names_cnt = object_names_cnt;
-+ object_names = &single_object_name;
-+ object_names_cnt = 1;
-+
-+ for (i = 0; i < all_object_names_cnt; i++) {
-+ single_object_name = all_object_names[i];
-+
-+ run(output, 1);
-+ }
-+ }
-+
-+ g_hash_table_destroy(object_to_module);
-+
-+ if (num_errors > 0)
-+ pr_err("%li CTF construction errors.\n", num_errors);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Run dwarf2ctf over a single object file or set thereof.
-+ *
-+ * output is the directory into which the CTF goes, if 'standalone', or the
-+ * CTF archive file name otherwise.
-+ */
-+static void run(char *output, int standalone)
-+{
-+ size_t i;
-+
-+ /*
-+ * Create all the hashes, assemble the translation unit->module list for
-+ * builtin modules, and create the shared CTF file if deduplicating.
-+ */
-+
-+ atoms = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
-+ id_to_type = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ NULL, free);
-+ id_to_module = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ NULL, free);
-+ per_module = g_hash_table_new_full(g_str_hash, g_str_equal, free,
-+ private_per_module_free);
-+ variable_blacklist = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ free, free);
-+ fn_to_die_to_parent = g_hash_table_new_full(g_str_hash,
-+ g_str_equal, free,
-+ private_fn_die_parent_free);
-+
-+ dw_ctf_trace("Initializing...\n");
-+
-+ if (deduplicating)
-+ init_ctf_table("shared_ctf");
-+
-+ scan_dups();
-+
-+ /*
-+ * Now construct CTF out of the types.
-+ */
-+ dw_ctf_trace("CTF construction.\n");
-+ for (i = 0; i < object_names_cnt; i++)
-+ process_file(object_names[i], construct_ctf, NULL, NULL, NULL);
-+
-+ /*
-+ * Finally, emit the types into their .ctf files, and generate the
-+ * necessary linker scripts.
-+ */
-+ dw_ctf_trace("Writeout.\n");
-+ write_types(output, standalone);
-+
-+ g_hash_table_destroy(id_to_type);
-+ g_hash_table_destroy(id_to_module);
-+ g_hash_table_destroy(per_module);
-+ g_hash_table_destroy(variable_blacklist);
-+ g_hash_table_destroy(fn_to_die_to_parent);
-+ g_hash_table_destroy(atoms);
-+}
-+
-+/*
-+ * Populate the object_names list from the module filelist.
-+ */
-+static void init_object_names(const char *object_names_file)
-+{
-+ FILE *f;
-+ char *line = NULL;
-+ size_t line_size = 0;
-+
-+ f = fopen(object_names_file, "r");
-+ if (f == NULL) {
-+ pr_err("Cannot open object names file %s: %s\n",
-+ object_names_file, strerror(errno));
-+ exit(1);
-+ }
-+
-+ /*
-+ * This needs no massaging other than linefeed removal, just reading and
-+ * stashing.
-+ */
-+
-+ while (getline(&line, &line_size, f) >= 0) {
-+ size_t len = strlen(line);
-+
-+ if (len == 0)
-+ continue;
-+
-+ if (line[len-1] == '\n')
-+ line[len-1] = '\0';
-+
-+ object_names = realloc(object_names,
-+ ++object_names_cnt *
-+ sizeof(char *));
-+
-+ if (object_names == NULL) {
-+ pr_err("Out of memory reading %s\n", object_names_file);
-+ exit(1);
-+ }
-+
-+ object_names[object_names_cnt-1] = xstrdup(line);
-+ }
-+ free(line);
-+
-+ if (ferror(f)) {
-+ pr_err("Error reading from %s: %s\n", object_names_file,
-+ strerror(errno));
-+ exit(1);
-+ }
-+
-+ fclose(f);
-+}
-+
-+/*
-+ * Populate object_to_module from the objects.builtin and modules.builtin file.
-+ */
-+static void init_builtin(const char *builtin_objects_file,
-+ const char *builtin_module_file)
-+{
-+ FILE *f;
-+ struct modules_thick_iter *i;
-+ char *line = NULL;
-+ size_t line_size = 0;
-+ char *module_name = NULL;
-+ char **paths;
-+
-+ /*
-+ * Iterate over all modules in modules_thick.builtin and add each to
-+ * object_to_module.
-+ */
-+ i = modules_thick_iter_new(builtin_module_file);
-+ if (i == NULL) {
-+ pr_err("Cannot iterate over builtin module file.\n");
-+ exit(1);
-+ }
-+
-+ while ((paths = modules_thick_iter_next(i, &module_name)) != NULL) {
-+ size_t j;
-+
-+ for (j = 0; paths[j] != NULL; j++) {
-+ dw_ctf_trace("noting built-in module mapping %s -> %s\n",
-+ module_name, paths[j]);
-+ g_hash_table_replace(object_to_module,
-+ strdup(paths[j]),
-+ xstrdup(module_name));
-+ }
-+ free(paths);
-+ }
-+ free(module_name);
-+ modules_thick_iter_free(i);
-+
-+ f = fopen(builtin_objects_file, "r");
-+ if (f == NULL) {
-+ pr_err("Cannot open builtin objects file %s: %s\n",
-+ builtin_objects_file, strerror(errno));
-+ exit(1);
-+ }
-+
-+ /*
-+ * Those entries in builtin.objects that are not already known are
-+ * unconditionally-built-in object files.
-+ */
-+ while (getline(&line, &line_size, f) >= 0) {
-+ size_t len = strlen(line);
-+
-+ if (len == 0)
-+ continue;
-+
-+ if (line[len-1] == '\n')
-+ line[len-1] = '\0';
-+
-+ if (!g_hash_table_lookup(object_to_module, line))
-+ g_hash_table_replace(object_to_module, xstrdup(line),
-+ xstrdup("vmlinux"));
-+ }
-+
-+ if (ferror(f)) {
-+ pr_err("Error reading from %s: %s\n", builtin_objects_file,
-+ strerror(errno));
-+ exit(1);
-+ }
-+
-+ free(line);
-+ fclose(f);
-+}
-+
-+/*
-+ * Translate the assembly lookup table into the assembly_tab and
-+ * assembly_filter_tab arrays.
-+ */
-+static void init_assembly_tab(void)
-+{
-+ struct assembly_tab_t *walk;
-+
-+ for (walk = assembly_tab_init; walk->fun != NULL; walk++) {
-+ if (assembly_len < walk->tag)
-+ assembly_len = walk->tag;
-+ }
-+ assembly_len++;
-+
-+ assembly_tab = calloc(sizeof(ctf_assembly_fun *), assembly_len);
-+ assembly_filter_tab = calloc(sizeof(ctf_assembly_filter_fun *),
-+ assembly_len);
-+ if ((assembly_tab == NULL) || (assembly_filter_tab == NULL)) {
-+ pr_err("Out of memory allocating assembly table\n");
-+ exit(1);
-+ }
-+
-+ for (walk = assembly_tab_init; walk->fun != NULL; walk++) {
-+ assembly_tab[walk->tag] = walk->fun;
-+ assembly_filter_tab[walk->tag] = walk->filter;
-+ }
-+}
-+
-+/*
-+ * Populate the member blacklist from the member_blacklist file.
-+ */
-+static void init_member_blacklist(const char *member_blacklist_file,
-+ const char *srcdir)
-+{
-+ FILE *f;
-+ char *line = NULL;
-+ size_t line_num = 0;
-+ size_t line_size = 0;
-+
-+ /*
-+ * Not having a member blacklist is not an error.
-+ */
-+ f = fopen(member_blacklist_file, "r");
-+ if (f == NULL)
-+ return;
-+
-+ member_blacklist = g_hash_table_new(g_str_hash, g_str_equal);
-+
-+ while (getline(&line, &line_size, f) >= 0) {
-+ size_t len = strlen(line);
-+ char *last_colon;
-+ const char *last_dot;
-+ char *absolutized;
-+
-+ line_num++;
-+
-+ if (len == 0)
-+ continue;
-+
-+ if (line[len-1] == '\n')
-+ line[len-1] = '\0';
-+
-+ last_colon = strrchr(line, ':');
-+ last_dot = strrchr(last_colon + 1, '.');
-+ if (!last_colon || !last_dot) {
-+ pr_err("Syntax error on line %li of %s.\n"
-+ "Syntax: filename:structure.member.\n",
-+ line_num, member_blacklist_file);
-+ continue;
-+ }
-+
-+ *last_colon = '\0';
-+ last_colon++;
-+ absolutized = rel_abs_file_name(line, srcdir);
-+ absolutized = str_appendn(absolutized, ":", last_colon, NULL);
-+
-+ g_hash_table_insert(member_blacklist, absolutized, NULL);
-+ }
-+ free(line);
-+
-+ if (ferror(f)) {
-+ pr_err("Error reading from %s: %s\n", member_blacklist_file,
-+ strerror(errno));
-+ exit(1);
-+ }
-+
-+ fclose(f);
-+}
-+
-+/*
-+ * Return 1 if a given DWARF DIE, which must be a DW_TAG_member, appears in the
-+ * member blacklist.
-+ */
-+static int member_blacklisted(Dwarf_Die *die, Dwarf_Die *parent_die)
-+{
-+ const char *fname = dwarf_decl_file(die);
-+ char *id;
-+ int blacklisted = 0;
-+
-+ /*
-+ * If there is no member blacklist, do nothing.
-+ */
-+ if (!member_blacklist)
-+ return 0;
-+
-+ /*
-+ * Unnamed structure and union members cannot be blacklisted, for now.
-+ */
-+ if ((dwarf_diename(parent_die) == NULL) ||
-+ (dwarf_diename(die) == NULL))
-+ return 0;
-+
-+ /*
-+ * The compiler can define its own structures, which appear in no
-+ * decl_file.
-+ *
-+ * We can't blacklist them with this mechanism, so skip them.
-+ */
-+ if (__builtin_expect(fname == NULL, 0))
-+ return 0;
-+
-+ fname = abs_file_name(fname);
-+
-+ if (dwarf_tag(die) != DW_TAG_member ||
-+ (dwarf_tag(parent_die) != DW_TAG_structure_type &&
-+ dwarf_tag(parent_die) != DW_TAG_union_type)) {
-+ pr_err("Warning: member_blacklisted() called on "
-+ "%s:%s.%s at offset %li, which is not a structure member.\n",
-+ fname, dwarf_diename(parent_die), dwarf_diename(die),
-+ DIEOFFSET(die));
-+ return 0;
-+ }
-+
-+ id = xstrdup(fname);
-+ id = str_appendn(id, ":", dwarf_diename(parent_die), ".",
-+ dwarf_diename(die), NULL);
-+
-+ if (g_hash_table_lookup_extended(member_blacklist, id, NULL, NULL))
-+ blacklisted = 1;
-+
-+ free(id);
-+ return blacklisted;
-+}
-+
-+/*
-+ * Initialize a CTF type table, and possibly fill it with those special types
-+ * that appear in CTF but not in DWARF (such as 'void'). (This filling happens
-+ * only for the type table named "shared_ctf", unless deduplication is turned
-+ * off.)
-+ *
-+ * If this is a local type table, and deduplication is active, make the global
-+ * type table its parent.
-+ */
-+static void init_ctf_table(const char *module_name)
-+{
-+ ctf_file_t *ctf_file;
-+ struct per_module *new_per_mod;
-+ int ctf_err;
-+
-+ ctf_file = ctf_create(&ctf_err);
-+ if (ctf_file == NULL) {
-+ pr_err("Cannot create CTF file: %s\n", strerror(ctf_err));
-+ exit(1);
-+ }
-+ new_per_mod = malloc(sizeof(struct per_module));
-+ if (new_per_mod == NULL) {
-+ pr_err("Out of memory allocating per-module CTF info\n");
-+ exit(1);
-+ }
-+
-+ new_per_mod->ctf_file = ctf_file;
-+ new_per_mod->member_counts = g_hash_table_new_full(g_str_hash,
-+ g_str_equal,
-+ free, free);
-+ g_hash_table_replace(per_module, xstrdup(module_name), new_per_mod);
-+
-+ dw_ctf_trace("Initializing module: %s\n", module_name);
-+ if ((strcmp(module_name, "shared_ctf") == 0) ||
-+ !deduplicating) {
-+ ctf_encoding_t void_encoding = { CTF_INT_SIGNED, 0, 0 };
-+ ctf_encoding_t int_encoding = { CTF_INT_SIGNED, 0,
-+ sizeof(int) * 8 };
-+ ctf_id_t int_type;
-+ ctf_id_t func_type;
-+ ctf_funcinfo_t func_info;
-+
-+ /*
-+ * Global types module, or deduplication is disabled. Add a
-+ * type for 'void *' to point to, and a type for the return
-+ * value of pointers to functions: then add the (single,
-+ * universal) pointer-to-function value.
-+ */
-+ ctf_void_type = ctf_add_integer(ctf_file, CTF_ADD_ROOT,
-+ "void", &void_encoding);
-+ int_type = ctf_add_integer(ctf_file, CTF_ADD_ROOT, "int",
-+ &int_encoding);
-+ mark_shared_by_name(ctf_file, ctf_void_type, "void");
-+ mark_shared_by_name(ctf_file, int_type, "int");
-+
-+ func_info.ctc_return = int_type;
-+ func_info.ctc_argc = 0;
-+ func_info.ctc_flags = 0;
-+ func_type = ctf_add_function(ctf_file, CTF_ADD_ROOT,
-+ &func_info, NULL);
-+ ctf_funcptr_type = ctf_add_pointer(ctf_file, CTF_ADD_ROOT,
-+ func_type);
-+
-+ if (ctf_update(ctf_file) < 0) {
-+ pr_err("Cannot initialize shared CTF file: %s\n",
-+ ctf_errmsg(ctf_errno(ctf_file)));
-+ exit(1);
-+ }
-+ } else {
-+ /*
-+ * Local types module with deduplication enabled: point the
-+ * parent at the global CTF file, which must exist by this
-+ * point.
-+ */
-+ if (ctf_import(ctf_file, lookup_ctf_file("shared_ctf")) < 0) {
-+ pr_err("Cannot set parent of CTF file for module %s: %s\n",
-+ module_name, ctf_errmsg(ctf_errno(ctf_file)));
-+ exit(1);
-+ }
-+ ctf_parent_name_set(ctf_file, "shared_ctf");
-+ }
-+
-+ dw_ctf_trace("Created CTF file for module %s: %p\n",
-+ module_name, ctf_file);
-+}
-+
-+/* DWARF walkers. */
-+
-+/*
-+ * Initialize the child->parent DIE mapping for a single file.
-+ */
-+static void init_parent_die(const char *file_name, Dwfl *dwfl)
-+{
-+ GHashTable *offs;
-+ Dwarf_Die *tu_die = NULL;
-+ Dwarf_Addr junk;
-+
-+ offs = g_hash_table_new(g_direct_hash, g_direct_equal);
-+ if (offs == NULL) {
-+ pr_err("Out of memory creating DIE offset hash\n");
-+ exit(1);
-+ }
-+
-+ while ((tu_die = dwfl_nextcu(dwfl, tu_die, &junk)) != NULL) {
-+ init_parent_die_internal(file_name, offs, tu_die, 0, 0);
-+ }
-+
-+ g_hash_table_insert(fn_to_die_to_parent,
-+ strdup(abs_file_name(file_name)), offs);
-+}
-+
-+/*
-+ * Initialize one layer of a child->parent mapping.
-+ *
-+ * We traverse children of top-level subprograms hunting for anything we know
-+ * how to emit, and record parent->child mappings for all intermediate DIEs.
-+ */
-+static int init_parent_die_internal(const char *file_name,
-+ GHashTable *offs, Dwarf_Die *parent,
-+ int depth, int found_subprogram)
-+{
-+ Dwarf_Die child;
-+ int sib_ret;
-+ Dwarf_Off parent_offset;
-+ const char *err;
-+ int add_parent = 0;
-+
-+ if (dwarf_tag(parent) == DW_TAG_subprogram)
-+ found_subprogram = 1;
-+
-+ switch (dwarf_child(parent, &child)) {
-+ case -1:
-+ err = "child DIEs";
-+ goto err;
-+ case 1: /* This DIE has no children */
-+ goto out;
-+ }
-+
-+ parent_offset = dwarf_dieoffset(parent);
-+
-+ do {
-+ int add_child = 0;
-+
-+ /*
-+ * Add links from the parent to all children for which a
-+ * recursive call says they should be added, and note that we
-+ * should add links to the parent too. Always look down to
-+ * depth 2, since the topmost level is always
-+ * DW_TAG_compile_unit, and we are interested in
-+ * DW_TAG_subprograms one level below that.
-+ */
-+ if (found_subprogram || depth < 2)
-+ add_child = init_parent_die_internal(file_name, offs,
-+ &child, depth+1,
-+ found_subprogram);
-+
-+ if (add_child) {
-+ g_hash_table_insert(offs,
-+ GUINT_TO_POINTER(dwarf_dieoffset(&child)),
-+ GUINT_TO_POINTER(parent_offset));
-+ add_parent = 1;
-+ }
-+ } while ((sib_ret = dwarf_siblingof (&child, &child)) == 0);
-+
-+ if (sib_ret == -1) {
-+ err = "sibling DIEs";
-+ goto err;
-+ }
-+
-+out:
-+ /*
-+ * Emit a link for the next level up if we're under a subprogram and
-+ * either we emitted a child link or the parent is itself something we
-+ * know how to emit (and thus might possibly appear in a type DIE we
-+ * care about).
-+ */
-+ return (found_subprogram &&
-+ (add_parent ||
-+ (dwarf_tag(parent) < assembly_len &&
-+ assembly_tab[dwarf_tag(parent)] != NULL)));
-+err:
-+ pr_err("Cannot fetch %s of DIE at offset %lu in %s: %s\n",
-+ err, DIEOFFSET(parent), file_name,
-+ dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * Type ID computation.
-+ *
-+ * A type ID is a constant, recursively-constructed, dynamically-allocated
-+ * string describing a given DWARF DIE in such a way that any DWARF file
-+ * containing the same type will have the same type ID. (It even works for
-+ * variables! Variables of the same name and referring to the same type have
-+ * the same ID...)
-+ *
-+ * Optionally, call a callback with the computed ID once we know it (this is a
-+ * recursive process, so the callback can be called multiple times as the ID is
-+ * built up).
-+ *
-+ * An ID of NULL indicates that this DIE has no ID and need not be considered.
-+ *
-+ * It is probably an error for two DWARF DIEs representing top-level types to
-+ * return the same ID, but for certain other DIEs (notably those representing
-+ * the members of structures or unions), it is expected that they return the
-+ * same ID as their type DIE.
-+ *
-+ * This function is the hottest hot spot in dwarf2ctf, so is somewhat
-+ * aggressively optimized.
-+ *
-+ * The "overrides" allow the overriding of DWARF attributes, so that the
-+ * machinery notices different DWARF from what actually appears in the
-+ * debuginfo, so that the CTF that is emitted is suitably modified (and possibly
-+ * duplicated). This is mostly used by type_id() to generate different IDs for
-+ * dependent types of bitfields, but can be used for other purposes too, such as
-+ * adjusting the offsets of types in unnamed structures, etc. Overrides are
-+ * passed down if provided: overrides relating to bitfields are only applied by
-+ * type_id() if no other overrides are provided.
-+ *
-+ * In general, you do not need to pass overrides down if you know you will only
-+ * be called directly on top-level DIEs, but otherwise, you should do so.
-+ */
-+static char *type_id(Dwarf_Die *die,
-+ struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data)
-+{
-+ return type_id_internal(die, overrides, fun, data, 0);
-+}
-+
-+/*
-+ * Internal: generate the type ID for a type DIE.
-+ *
-+ * If there are no overrides, look for a bit_size and bit_offset and pass them
-+ * down as well.
-+ */
-+static char *type_id_type_die(Dwarf_Die *die,
-+ Dwarf_Die *type_die,
-+ struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data)
-+{
-+ char *id;
-+
-+ /*
-+ * bit_size and bit_offset go together: we can assume that if a member
-+ * has the one, it has the other.
-+ */
-+
-+ if (private_dwarf_hasattr(die, DW_AT_bit_size)) {
-+ Dwarf_Word size;
-+ Dwarf_Word offset;
-+
-+ size = private_dwarf_udata(die, DW_AT_bit_size, NULL);
-+ offset = private_dwarf_udata(die, DW_AT_bit_offset, NULL);
-+ struct die_override o[] = {
-+ { DW_TAG_base_type,
-+ DW_AT_bit_size,
-+ DIE_OVERRIDE_REPLACE,
-+ size, NULL },
-+ { DW_TAG_base_type,
-+ DW_AT_bit_offset,
-+ DIE_OVERRIDE_REPLACE,
-+ offset, overrides },
-+ {0}
-+ };
-+ id = type_id(type_die, o, fun, data);
-+ } else
-+ id = type_id(type_die, overrides, fun, data);
-+ return id;
-+}
-+
-+/*
-+ * Internal: allows flags to be passed to affect one (and only one) type ID
-+ * recursion, without affecting other type_id()s launched from the 'fun'.
-+ */
-+static char *type_id_internal(Dwarf_Die *die,
-+ struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data,
-+ int flags)
-+{
-+ char *id = NULL;
-+ int no_type_id = 0;
-+ int decorated = 1;
-+
-+ /*
-+ * The ID of a null pointer is NULL.
-+ */
-+ if (die == NULL)
-+ return NULL;
-+
-+ /*
-+ * The ID of a function pointer is '//fp//', as a special case,
-+ * with no location or overrides, ever.
-+ */
-+ if (dwarf_tag(die) == DW_TAG_subroutine_type) {
-+ id = xstrdup("//fp//");
-+ if (fun)
-+ fun(die, id, NULL, data);
-+ return id;
-+ }
-+
-+ /*
-+ * If we have a type DIE, generate it first, passing any overrides down.
-+ * (Base types and enumerations don't have a type DIE that CTF can
-+ * encode the type of in any useful fashion.)
-+ *
-+ * Otherwise, note the location of this DIE, providing scoping
-+ * information for all types based upon this one. Location elements are
-+ * separated by //, an element impossible in a Linux path. The
-+ * blacklist type prefix (if set) follows this (which is a name which,
-+ * while not impossible in a Linux path, is very unlikely.)
-+ *
-+ * Array dimensions get none of this: they must be contained within
-+ * another DIE, so will always have a location attached via that DIE,
-+ * and get their type chased further down (so as to arrange that they
-+ * appear inside an [].)
-+ */
-+ if (dwarf_tag(die) != DW_TAG_subrange_type) {
-+ if ((dwarf_tag(die) != DW_TAG_base_type) &&
-+ (dwarf_tag(die) != DW_TAG_enumeration_type)) {
-+ Dwarf_Die type_die;
-+ Dwarf_Die *diep = private_dwarf_type(die, &type_die);
-+
-+ if (diep)
-+ id = type_id_type_die(die, diep, overrides,
-+ fun, data);
-+ }
-+
-+ /*
-+ * Location information. We use cached realpath() results, and
-+ * call str_appendn() only once, minimizing the number of
-+ * strlen()s.
-+ */
-+ if (id == NULL) {
-+ const char *decl_file_name = dwarf_decl_file(die);
-+ int decl_line_num;
-+ const char *fname = "";
-+ char line_num[21] = ""; /* > than 2^64's digit count */
-+
-+ no_type_id = 1;
-+ if (decl_file_name != NULL)
-+ fname = abs_file_name(decl_file_name);
-+
-+ if (dwarf_decl_line(die, &decl_line_num) >= 0) {
-+ snprintf(line_num, sizeof(line_num), "%i",
-+ decl_line_num);
-+ }
-+ id = str_appendn(id, fname, "//", line_num, "//", NULL);
-+ }
-+ }
-+
-+ /*
-+ * We implement this via a switch statement, rather than a jump table
-+ * like the assembly_tab, simply because most cases are so small that
-+ * splitting them into separate functions would do more harm than good
-+ * to readability.
-+ *
-+ * WARNING: The spaces in the strings in this switch statement are not
-+ * just for appearance: types with spaces in their names are impossible
-+ * in C. If you move those spaces around for appearance's sake, please
-+ * adjust mark_shared_by_name and dedup_alias_fixup(), which
-+ * construct the IDs of basic types, structures, and unions by hand.
-+ */
-+ switch (dwarf_tag(die)) {
-+ case DW_TAG_base_type: {
-+ Dwarf_Word bit_size = -1;
-+ Dwarf_Word type_size = -1;
-+ Dwarf_Word bit_offset = -1;
-+ const char *diename = dwarf_diename(die);
-+
-+ if ((flags & TI_COLLAPSE_SIZETYPE) &&
-+ (strcmp(diename, "long unsigned int") == 0))
-+ diename = "sizetype";
-+
-+ /*
-+ * CTF encodes the size and bitwise-offset of bit-fields in the
-+ * base type, so it must be stored once for each size, even if
-+ * it only appears once for all sizes in the DWARF.
-+ */
-+ if (private_dwarf_hasattr(die, DW_AT_bit_size) ||
-+ private_find_override(die, DW_AT_bit_size,
-+ overrides))
-+ bit_size = private_dwarf_udata(die, DW_AT_bit_size,
-+ overrides);
-+ if (private_dwarf_hasattr(die, DW_AT_bit_offset) ||
-+ private_find_override(die, DW_AT_bit_offset,
-+ overrides))
-+ bit_offset = private_dwarf_udata(die, DW_AT_bit_offset,
-+ overrides);
-+
-+ /*
-+ * Bitfields that occupy their entire containing type are not
-+ * bitfields, but just redundant DWARF. GCC emits these now and
-+ * again, but the dups would trip CTF consistency checks, so
-+ * must be skipped.
-+ */
-+ if (bit_size > -1) {
-+ /*
-+ * This "may be omitted" in DWARF, but GCC doesn't:
-+ * bitfields always get both. (See
-+ * gcc/dwarf2out.c:gen_field_die().)
-+ */
-+ type_size = private_dwarf_udata(die, DW_AT_bit_size,
-+ overrides);
-+ }
-+ if (bit_size != type_size) {
-+ char bitsize[22]; /* > 2^64's digit count */
-+ char bitoffset[22]; /* > 2^64's digit count */
-+
-+ snprintf(bitsize, sizeof(bitsize), "%li", bit_size);
-+ id = str_appendn(id, diename, ":", bitsize, NULL);
-+ if (bit_offset != -1) {
-+ snprintf(bitoffset, sizeof(bitoffset), "%li",
-+ bit_offset);
-+ id = str_appendn(id, ":", bitoffset, NULL);
-+ }
-+ id = str_append(id, " ");
-+ } else {
-+ /*
-+ * Ordinary (non-bit-field) base type.
-+ */
-+ id = str_appendn(id, diename, " ", NULL);
-+ }
-+ break;
-+ }
-+ case DW_TAG_enumeration_type:
-+ id = str_appendn(id, "enum ", dwarf_diename(die), " ", NULL);
-+ break;
-+ case DW_TAG_structure_type:
-+ case DW_TAG_union_type: {
-+ /*
-+ * Incorporate the unaligned sizeof() the structure, if
-+ * statically known (the offset of the last member in the DWARF)
-+ * so that most structures which are redefined on the fly by
-+ * preprocessor defines are disambiguated despite being defined
-+ * in the same place.
-+ *
-+ * Only do this if this is a non-opaque structure/union
-+ * definition: opaque definitions cannot have a size, but if
-+ * they do by some mischance get one, notating it will mess up
-+ * the several other places that manually construct opaque
-+ * structure identifiers (and cannot incorporate a size, since
-+ * they don't know it).
-+ */
-+ const char *sou;
-+
-+ if (strncmp(id, "////", 4) != 0) {
-+ long long size;
-+ char byte_size[24];
-+
-+ size = private_dwarf_size(die);
-+ if (size > -1) {
-+ sprintf(byte_size, "%lli", size);
-+ id = str_appendn(id, byte_size, "//", NULL);
-+ }
-+ }
-+
-+ if (dwarf_tag(die) == DW_TAG_union_type)
-+ sou = "union ";
-+ else
-+ sou = "struct ";
-+
-+ id = str_appendn(id, sou, dwarf_diename(die), " ", NULL);
-+ break;
-+ }
-+ case DW_TAG_variable:
-+ id = str_appendn(id, "var ", dwarf_diename(die), " ", NULL);
-+ break;
-+ case DW_TAG_typedef:
-+ id = str_appendn(id, "typedef ", dwarf_diename(die), " ", NULL);
-+ break;
-+ case DW_TAG_const_type:
-+ id = str_append(id, "const ");
-+ break;
-+ case DW_TAG_restrict_type:
-+ id = str_append(id, "restrict ");
-+ break;
-+ case DW_TAG_volatile_type:
-+ id = str_append(id, "volatile ");
-+ break;
-+ case DW_TAG_pointer_type:
-+ if (no_type_id)
-+ id = str_append(id, "void ");
-+ id = str_append(id, "* ");
-+ break;
-+
-+ case DW_TAG_array_type: {
-+ /*
-+ * No explicit notation: all done per-dimension: so recurse to
-+ * those.
-+ */
-+
-+ int sib_ret;
-+ int dimens = 0;
-+ Dwarf_Die dim_die;
-+
-+ switch (dwarf_child(die, &dim_die)) {
-+ case -1:
-+ pr_err("Corrupt DWARF: Cannot get array dimensions: %s\n",
-+ dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+ case 1: /* No dimensions. */
-+ id = str_append(id, "[] ");
-+ break;
-+ default:
-+ dimens = 1;
-+ }
-+
-+ if (!dimens)
-+ break;
-+
-+ do {
-+ char *sub_id = type_id_internal(&dim_die, overrides,
-+ fun, data,
-+ TI_COLLAPSE_SIZETYPE);
-+ id = str_append(id, sub_id);
-+ free(sub_id);
-+ } while ((sib_ret = dwarf_siblingof(&dim_die, &dim_die)) == 0);
-+
-+ if (sib_ret == -1) {
-+ pr_err("Corrupt DWARF: Cannot get array dimensions: %s\n",
-+ dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+ }
-+ break;
-+ }
-+ case DW_TAG_subrange_type: {
-+ Dwarf_Word nelems = private_subrange_dimensions(die);
-+
-+ id = str_append(id, "[");
-+
-+ if (nelems > 0) {
-+ Dwarf_Die type_die;
-+ char elems[22]; /* bigger than 2^64's digit count */
-+ char *sub_id = type_id_internal(private_dwarf_type(die, &type_die),
-+ overrides, fun, data,
-+ TI_COLLAPSE_SIZETYPE);
-+
-+ snprintf(elems, sizeof(elems), " %li", nelems);
-+ id = str_appendn(id, sub_id, elems, NULL);
-+ free(sub_id);
-+ }
-+ id = str_append(id, "] ");
-+ break;
-+ }
-+ default:
-+ /*
-+ * Some tags (e.g. structure members) get the same ID as their
-+ * associated type. We don't need to call the hook function
-+ * again for such tags.
-+ */
-+ decorated = 0;
-+ }
-+
-+ if (fun && decorated)
-+ fun(die, id, overrides, data);
-+
-+ return id;
-+}
-+
-+/*
-+ * Process a file, calling the dwarf_process function for every top-level type
-+ * found therein. Optionally call tu_init() at the start of each translation
-+ * unit, and tu_done() at the end.
-+ */
-+static void process_file(const char *file_name,
-+ void (*dwarf_process)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ void *data),
-+ void (*tu_init)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *tu_die,
-+ void *data),
-+ void (*tu_done)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *tu_die,
-+ void *data),
-+ void *data)
-+{
-+ const char *err;
-+ char *fn_module_name = fn_to_module(file_name);
-+ const char *module_name = fn_module_name;
-+
-+ Dwfl_Module *mod;
-+ Dwfl *dwfl;
-+ Dwarf *dwarf;
-+ GHashTable *seen_before = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ free, free);
-+ Dwarf_Die *tu_die = NULL;
-+ Dwarf_Addr junk;
-+
-+ if (seen_before == NULL) {
-+ pr_err("Out of memory creating seen_before hash\n");
-+ exit(1);
-+ }
-+
-+ dwfl = simple_dwfl_new(file_name, &mod);
-+ dwarf = dwfl_module_getdwarf(mod, &junk);
-+
-+ /*
-+ * On first traversal, make sure the DIE parent mapping is populated,
-+ * so that filter_ctf_file_scope can use it.
-+ */
-+ if (!g_hash_table_lookup_extended(fn_to_die_to_parent,
-+ abs_file_name(file_name),
-+ NULL, NULL))
-+ init_parent_die(file_name, dwfl);
-+
-+ while ((tu_die = dwfl_nextcu(dwfl, tu_die, &junk)) != NULL) {
-+ const char *tu_name;
-+
-+ if (dwarf_tag(tu_die) != DW_TAG_compile_unit) {
-+ err = "Malformed DWARF: non-compile_unit at top level";
-+ goto fail;
-+ }
-+
-+ tu_name = dwarf_diename(tu_die);
-+
-+ dw_ctf_trace("Processing %s\n", tu_name);
-+
-+ /*
-+ * If we have seen this TU before, skip it. We assume that
-+ * types in multiple identical TUs are always entirely
-+ * identical. This lets us skip cases where the same object
-+ * file is linked in multiple places without scanning every type
-+ * in it. (Note: this may be inaccurate if a TU is built
-+ * repeatedly with different #defines in force. I hope this
-+ * cannot happen, but if it does, a workaround a-la libtool is
-+ * simple: rename or symlink the TU for such repeated builds.)
-+ *
-+ * Otherwise, note the name of the module to which this TU maps,
-+ * if it is not already known: otherwise, extract that name.
-+ *
-+ * This is purely an optimization: it breaks somewhat for
-+ * multifile modules but this has no effect but a slight
-+ * slowdown.
-+ */
-+ if (g_hash_table_lookup_extended(seen_before, tu_name,
-+ NULL, NULL))
-+ continue;
-+
-+ g_hash_table_replace(seen_before, xstrdup(tu_name), NULL);
-+
-+ /*
-+ * We are only interested in top-level definitions within each
-+ * TU.
-+ */
-+ Dwarf_Die die;
-+
-+ switch (dwarf_child(tu_die, &die)) {
-+ case -1:
-+ err = "fetch first child of TU";
-+ goto fail;
-+ case 1: /* No DIEs at all in this TU */
-+ continue;
-+ default: /* Child DIEs exist. */
-+ break;
-+ }
-+
-+ if (tu_init != NULL)
-+ tu_init(module_name, file_name, tu_die, data);
-+
-+ process_tu_func(module_name, file_name, dwarf, tu_die, &die,
-+ dwarf_process, data);
-+
-+ if (tu_done != NULL)
-+ tu_done(module_name, file_name, tu_die, data);
-+ }
-+
-+ free(fn_module_name);
-+ simple_dwfl_free(dwfl);
-+ g_hash_table_destroy(seen_before);
-+
-+ return;
-+
-+ fail:
-+ pr_err("Cannot %s for %s: %s\n", err, module_name,
-+ dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * process_file() helper, walking over the top level and picking up types
-+ * therein.
-+ */
-+static void process_tu_func(const char *module_name,
-+ const char *file_name,
-+ Dwarf *dwarf,
-+ Dwarf_Die *parent_die,
-+ Dwarf_Die *die,
-+ void (*dwarf_process)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ void *data),
-+ void *data)
-+{
-+ const char *err;
-+ int sib_ret;
-+
-+ /*
-+ * We are only interested in definitions for which we can (eventually)
-+ * emit CTF: call the processing function for all such.
-+ */
-+ do {
-+ if ((dwarf_tag(die) < assembly_len) &&
-+ (assembly_filter_tab[dwarf_tag(die)] == NULL ||
-+ assembly_filter_tab[dwarf_tag(die)](file_name, dwarf, die,
-+ parent_die)) &&
-+ (assembly_tab[dwarf_tag(die)] != NULL))
-+ dwarf_process(module_name, file_name, die,
-+ parent_die, data);
-+ } while ((sib_ret = dwarf_siblingof(die, die)) == 0);
-+
-+ if (sib_ret == -1) {
-+ err = "fetch sibling";
-+ goto fail;
-+ }
-+
-+ return;
-+ fail:
-+ pr_err("Cannot %s for %s: %s\n", err, module_name,
-+ dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+}
-+
-+/* Duplicate detection. */
-+
-+/*
-+ * Scan and identify duplicates across the entire set of object files.
-+ */
-+static void scan_dups(void)
-+{
-+ size_t i;
-+
-+ /*
-+ * First, determine which types are referenced by more than one
-+ * translation unit, and construct the mapping from translation unit to
-+ * non-builtin module name.
-+ *
-+ * The first pass detects duplicated types in need of sharing, without
-+ * considering opaque/transparent structure/union aliasing. It requests
-+ * an alias detection pass if any structures, or typedefs to them, are
-+ * newly marked as shared.
-+ *
-+ * We must do this even when deduplication is disabled, because we need
-+ * the TU->module-name mapping, even if in this case it is trivial.
-+ */
-+
-+ struct dedup_state state = {0};
-+
-+ dw_ctf_trace("Duplicate detection: primary pass.\n");
-+
-+ /*
-+ * This is merely flushed between TUs, not recreated: we create it here.
-+ */
-+ state.vars_seen = g_hash_table_new_full(g_str_hash,
-+ g_str_equal,
-+ free, NULL);
-+
-+ for (i = 0; i < object_names_cnt; i++)
-+ process_file(object_names[i], dedup,
-+ dedup_tu_init, dedup_tu_done, &state);
-+
-+ if ((!state.repeat_detection) || !deduplicating)
-+ goto out;
-+
-+ do {
-+ /*
-+ * The second pass recognizes that opaque structures must be
-+ * shared if the transparent equivalents are, and vice versa,
-+ * and re-traces all transparent types that need sharing.
-+ *
-+ * It requests another alias detection pass if any non-opaque
-+ * structures are newly marked as shared.
-+ */
-+ dw_ctf_trace("Duplicate detection: alias fixup pass.\n");
-+
-+ state.repeat_detection = 0;
-+ state.named_structs = list_filter(state.named_structs,
-+ dedup_alias_fixup,
-+ free_dups_id_file, &state);
-+ } while (state.repeat_detection);
-+ out:
-+ g_hash_table_destroy(state.vars_seen);
-+ dedup_dwarf_free(&state);
-+ dw_ctf_trace("Duplicate detection: complete.\n");
-+ dw_ctf_trace("%llu distinct type IDs known.\n",
-+ (unsigned long long) g_hash_table_size(id_to_module));
-+ dw_ctf_trace("%llu variables blacklisted for static/nonstatic conflicts.\n",
-+ (unsigned long long) g_hash_table_size(variable_blacklist));
-+ g_list_free_full(state.named_structs, free_dups_id_file);
-+}
-+
-+/*
-+ * Set up state for dedup(). A tu_init() callback.
-+ */
-+static void dedup_tu_init(const char *module_name, const char *file_name,
-+ Dwarf_Die *tu_die, void *data)
-+{
-+ struct dedup_state *state = data;
-+ struct per_module *per_mod;
-+
-+ /*
-+ * Make sure that even if this module has no types in it we still end up
-+ * generating a CTF file. (Userspace depends on this, since a CTF file
-+ * with no types in means the module is known and typeless, while no CTF
-+ * file at all means the module is not known.)
-+ */
-+
-+ per_mod = g_hash_table_lookup(per_module, module_name);
-+ if (per_mod == NULL) {
-+ init_ctf_table(module_name);
-+ dw_ctf_trace("%s: initialized CTF file.\n", module_name);
-+ }
-+
-+ state->structs_seen = g_hash_table_new(g_str_hash, g_str_equal);
-+ g_hash_table_remove_all(state->vars_seen);
-+ state->module_name = module_name;
-+}
-+
-+/*
-+ * Free state for dedup(). A tu_done() callback.
-+ */
-+static void dedup_tu_done(const char *module_name, const char *file_name,
-+ Dwarf_Die *tu_die, void *data)
-+{
-+ struct dedup_state *state = data;
-+
-+ /*
-+ * We have to annul module_name because it is freed between object files
-+ * by process_file(). Since we use that to track whether vars_seen
-+ * needs reconstructing, that means we have to destroy that as well.
-+ */
-+ g_hash_table_destroy(state->structs_seen);
-+ state->structs_seen = NULL;
-+ state->module_name = NULL;
-+}
-+
-+/*
-+ * Free DWARF state for dedup().
-+ */
-+static void dedup_dwarf_free(struct dedup_state *state)
-+{
-+ if (state->dwfl == NULL)
-+ return;
-+ simple_dwfl_free(state->dwfl);
-+ state->dwfl = NULL;
-+ state->dwarf = NULL;
-+ free(state->dwfl_file_name);
-+ state->dwfl_file_name = NULL;
-+ if (state->structs_seen)
-+ g_hash_table_destroy(state->structs_seen);
-+ state->structs_seen = NULL;
-+}
-+
-+/*
-+ * Duplicate detection.
-+ *
-+ * Scan for duplicate types. A duplicate type is defined as any type which
-+ * appears in more than one module, or, more precisely, any type for which a
-+ * type with the same ID already exists in another module.
-+ *
-+ * This pass also constructs the id_to_module table, so is essential even when
-+ * deduplication is disabled (though then it need be run only once.)
-+ */
-+
-+static void dedup(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die, void *data)
-+{
-+ struct dedup_state *state = data;
-+ int is_sou = 0;
-+ char *id = type_id(die, NULL, is_named_struct_union_enum, &is_sou);
-+
-+ state->file_name = file_name;
-+ /*
-+ * If a DWARF-4 type signature is found, abort. While we can support
-+ * DWARF-4 eventually, support in elfutils is insufficiently robust for
-+ * now (elfutils 0.152).
-+ */
-+ if (private_dwarf_hasattr(die, DW_AT_type)) {
-+ Dwarf_Attribute type_attr;
-+
-+ if ((private_dwarf_attr(die, DW_AT_type, &type_attr) != NULL) &&
-+ (dwarf_whatform(&type_attr) == DW_FORM_ref_sig8)) {
-+ pr_err("Sorry, not yet implemented: %s contains DWARF-4 debugging information.\n",
-+ module_name);
-+ exit(1);
-+ }
-+ }
-+
-+ /*
-+ * Non-anonymous, non-opaque structure/union/enum types in
-+ * non-dedup-blacklisted modules get their names and locations recorded
-+ * for subsequent passes; all type_id()-descendant types are similarly
-+ * noted.
-+ */
-+ if (is_sou && strncmp(id, "////", strlen("////")) != 0)
-+ free(type_id(die, NULL, dedup_will_rescan, state));
-+
-+ /*
-+ * Handle static variable blacklisting. (We still shuffle blacklisted
-+ * variables into the right place in id_to_module because we check for
-+ * blacklisting at the lowest level, by which point we have already
-+ * depended on id_to_module being correctly populated.)
-+ *
-+ * Avoid calling this for recursive dependent-type scans: variables
-+ * cannot be dependent types.
-+ */
-+ if (parent_die != NULL && dwarf_tag(die) == DW_TAG_variable)
-+ dedup_blacklist_var_dups(die, state);
-+
-+ dedup_mark_inner_die(module_name, die, id, NULL, data);
-+ free(id);
-+}
-+
-+/*
-+ * Do the underlying marking of a DIE as shared, iff need be. (No variable
-+ * blacklisting, non-opaque structure checks, or anything else needed only by
-+ * top-level DIEs.)
-+ *
-+ * This function may be called multiple times for overridden DIEs that are
-+ * dependent types of bitfields. (On multiple calls for normal types, the
-+ * second call will enter the NS_NO_MARKING case block and terminate recursion.)
-+ */
-+static void dedup_mark_inner_die(const char *module_name, Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data)
-+{
-+ /*
-+ * If we know of a single module incorporating this type, and it is not
-+ * the same as the module we are currently in, then this type is
-+ * duplicated across modules and belongs in the global type table.
-+ * (This means that duplicated types are repeatedly so marked: this
-+ * is unavoidable, because pass 3 requires re-marking structures that
-+ * have already been marked, to pick up unmarked intermediate types.)
-+ *
-+ * We never consider types in modules on the deduplication blacklist
-+ * to introduce duplicates.
-+ */
-+ switch (type_needs_sharing(module_name, id)) {
-+ case NS_NEEDS_SHARING:
-+ mark_shared(die, NULL, overrides, data);
-+ mark_seen_contained(die, "shared_ctf", overrides, data);
-+ /* Fall through */
-+ case NS_NO_MARKING:
-+ /*
-+ * A duplicated type, but in the same module, or deduplication
-+ * is disabled, so id_to_module is already correct. (When
-+ * deduplication is disabled, we will be running with only one
-+ * module at a time, and id_to_module will be a trivial
-+ * mapping.)
-+ */
-+ return;
-+ case NS_NOT_SHARED:
-+ break;
-+ }
-+
-+ /*
-+ * Record that we have seen this type, and all its dependent types, in
-+ * this module (or in the shared module if need be).
-+ */
-+
-+ dw_ctf_trace("Marking %s as seen in %s\n", id, module_name);
-+ g_hash_table_replace(id_to_module, intern(xstrdup(id)),
-+ xstrdup(module_name));
-+ mark_seen_contained(die, module_name, overrides, data);
-+ free(type_id(die, overrides, dedup_typeid, data));
-+}
-+
-+/*
-+ * Note in the dedup_id_file list that we will rescan a DIE in a later duplicate
-+ * detection pass.
-+ *
-+ * A type_id() callback.
-+ */
-+static void dedup_will_rescan(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data)
-+{
-+ struct dedup_state *state = data;
-+ struct dedup_id_file *id_file;
-+
-+ /*
-+ * We don't care about array index types, which will never be structures
-+ * in C.
-+ */
-+ if (id[0] == '[')
-+ return;
-+
-+ id_file = calloc(1, sizeof(struct dedup_id_file));
-+ if (id_file == NULL) {
-+ pr_err("Out of memory allocating id_file\n");
-+ exit(1);
-+ }
-+ id_file->file_name = intern(xstrdup(state->file_name));
-+ id_file->id = intern(xstrdup(id));
-+ id_file->dieoff = dwarf_dieoffset(die);
-+ state->named_structs = g_list_prepend(state->named_structs, id_file);
-+}
-+
-+/*
-+ * Note the variable referenced by this DIE in vars_seen: blacklist it if an
-+ * entry for this variable already exists in vars_seen and this instance is
-+ * static, or if a static entry already exists in vars_seen, whether this
-+ * instance is static or not.
-+ */
-+static void dedup_blacklist_var_dups(Dwarf_Die *die,
-+ struct dedup_state *state)
-+{
-+ void *static_var;
-+ int blacklist = 0;
-+
-+ if (g_hash_table_lookup_extended(state->vars_seen,
-+ dwarf_diename(die),
-+ NULL, &static_var)) {
-+ if (!private_dwarf_hasattr(die, DW_AT_external) &&
-+ !private_dwarf_hasattr(die, DW_AT_declaration))
-+ blacklist = 1;
-+ if (static_var != NULL)
-+ blacklist = 1;
-+ } else
-+ /*
-+ * We need a non-NULL address here, but that is all we need.
-+ * The address of a random variable will do.
-+ */
-+ g_hash_table_insert(state->vars_seen,
-+ xstrdup(dwarf_diename(die)),
-+ (!private_dwarf_hasattr(die, DW_AT_external) &&
-+ !private_dwarf_hasattr(die, DW_AT_declaration)) ?
-+ &static_var : NULL);
-+
-+ if (blacklist) {
-+ char *var = NULL;
-+ var = str_appendn(var, state->module_name, "`",
-+ dwarf_diename(die), NULL);
-+ g_hash_table_replace(variable_blacklist, var, NULL);
-+ }
-+}
-+
-+/*
-+ * Free a dedup_id_file's contents.
-+ */
-+static void free_dups_id_file(void *data)
-+{
-+ struct dedup_id_file *id_file = data;
-+ free(id_file);
-+}
-+
-+/*
-+ * Determine if a type is duplicated and needs sharing.
-+ */
-+static enum needs_sharing type_needs_sharing(const char *module_name,
-+ const char *id)
-+{
-+ const char *existing_type_module;
-+ existing_type_module = g_hash_table_lookup(id_to_module, id);
-+
-+ /*
-+ * Types not already known about do not need sharing.
-+ *
-+ * Types already in the current modules and any types in external-module
-+ * mode do not even need marking.
-+ */
-+ if (existing_type_module == NULL)
-+ return NS_NOT_SHARED;
-+
-+ if ((strcmp(existing_type_module, module_name) == 0) ||
-+ (strcmp(existing_type_module, "shared_ctf") == 0) ||
-+ !deduplicating)
-+ return NS_NO_MARKING;
-+
-+ return NS_NEEDS_SHARING;
-+}
-+
-+/*
-+ * Detect duplicates and mark seen types for a given type, via a type_id()
-+ * callback: used to detect dependent types (particularly those at child-DIE
-+ * level) as duplicates.
-+ */
-+static void dedup_typeid(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data)
-+{
-+ struct dedup_state *state = data;
-+
-+ dedup_mark_inner_die(state->module_name, die, id, overrides, data);
-+}
-+
-+/*
-+ * Mark any types contained within a particular type DIE as seen. This is
-+ * needed since even nameless types contained within other aggregates can be
-+ * used as the type of members in any of their enclosing aggregates (though they
-+ * cannot possibly be found in a module different from that of their containing
-+ * aggregate, any more than a structure member can).
-+ */
-+static void mark_seen_contained(Dwarf_Die *die, const char *module_name,
-+ struct die_override *overrides,
-+ void *data)
-+{
-+ const char *err;
-+ Dwarf_Die child;
-+
-+ if ((dwarf_tag(die) != DW_TAG_structure_type) &&
-+ (dwarf_tag(die) != DW_TAG_union_type))
-+ return;
-+
-+ switch (dwarf_child(die, &child)) {
-+ case -1:
-+ err = "fetch first child of aggregate";
-+ goto fail;
-+ case 1: /* No DIEs at all in this aggregate */
-+ return;
-+ default: /* Child DIEs exist. */
-+ break;
-+ }
-+
-+ /*
-+ * We iterate over all immediate children and recursively call ourselves
-+ * for all those of type DW_TAG_structure_type and DW_TAG_union_type.
-+ *
-+ * Further, everything with an entry in assembly_tab other than
-+ * non-bitfield members needs marking, since these may be declared at
-+ * structure scope rather than being confined to global scope.
-+ * Non-bitfield members are skipped because they cannot be used as the
-+ * type of another field. These types cannot be duplicates if their
-+ * containing type is not a duplicate, and typedefs cannot occur at this
-+ * level so they cannot be aliased; thus we can mark them directly
-+ * without going back into the top of dedup().
-+ *
-+ * (Bit-field members are not skipped: they use different CTF from their
-+ * non-bitfield equivalents, even though they refer to the same
-+ * top-level DIE. The actual different CTF is handled by type_id()
-+ * itself, but we do have to call it.)
-+ */
-+ int sib_ret;
-+
-+ do
-+ switch (dwarf_tag(&child)) {
-+ case DW_TAG_member: {
-+ /*
-+ * bit_size and bit_offset go together: we can assume
-+ * that if a member has the one, it has the other,
-+ * is a bitfield, and needs recursive marking.
-+ */
-+ if (dwarf_tag(&child) == DW_TAG_member &&
-+ !private_dwarf_hasattr(&child, DW_AT_bit_size))
-+ break;
-+
-+ free(type_id(&child, overrides, dedup_typeid, data));
-+ break;
-+ }
-+ case DW_TAG_structure_type:
-+ case DW_TAG_union_type:
-+ mark_seen_contained(&child, module_name, overrides, data);
-+ /* fall through */
-+ default:
-+ if (dwarf_tag(&child) < assembly_len &&
-+ assembly_tab[dwarf_tag(&child)] != NULL) {
-+
-+ char *id = type_id(&child, overrides, NULL, NULL);
-+
-+ dw_ctf_trace("Marking member %s as seen in "
-+ "%s\n", id, module_name);
-+ g_hash_table_replace(id_to_module, intern(id),
-+ xstrdup(module_name));
-+ }
-+ }
-+ while ((sib_ret = dwarf_siblingof(&child, &child)) == 0);
-+
-+ if (sib_ret == -1) {
-+ err = "iterate over members";
-+ goto fail;
-+ }
-+
-+ return;
-+
-+ fail:
-+ pr_err("Cannot %s while marking aggregates as seen: %s\n",
-+ err, dwfl_errmsg(dwfl_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * Mark a type as duplicated and located in the shared CTF table. Recursive,
-+ * via the type_id() callback mechanism.
-+ *
-+ * A type_id() callback (though also called directly).
-+ */
-+static void mark_shared(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data)
-+{
-+ struct dedup_state *state = data;
-+ const char *existing_module;
-+
-+ /*
-+ * Non-recursive call. Trigger type_id for its recursive callback,
-+ * throwing the result away.
-+ */
-+ if (id == NULL) {
-+ free(type_id(die, overrides, mark_shared, state));
-+ return;
-+ }
-+
-+ existing_module = g_hash_table_lookup(id_to_module, id);
-+
-+ if ((existing_module == NULL) ||
-+ (strcmp(existing_module, "shared_ctf") != 0)) {
-+
-+ dw_ctf_trace("Marking %s as duplicate\n", id);
-+ g_hash_table_replace(id_to_module, intern(xstrdup(id)),
-+ xstrdup("shared_ctf"));
-+
-+ /*
-+ * Newly-marked structures/unions/enums must trigger a new
-+ * duplicate detection pass (even if they are opaque).
-+ */
-+
-+ if (((dwarf_tag(die) == DW_TAG_structure_type) ||
-+ (dwarf_tag(die) == DW_TAG_union_type) ||
-+ (dwarf_tag(die) == DW_TAG_enumeration_type)) &&
-+ (!state->repeat_detection)) {
-+ dw_ctf_trace("Requesting another duplicate detection pass.\n");
-+ state->repeat_detection = 1;
-+ }
-+ }
-+
-+ /*
-+ * If this is a structure or union, mark its members as duplicates too.
-+ *
-+ * Do this even if we've seen this structure before, as this instance of
-+ * the structure may have more members than the last we saw. However,
-+ * if we have seen this structure before *in this translation unit*,
-+ * skip it, to avoid infinite recursion in mutually referential
-+ * structures.
-+ */
-+ if ((dwarf_tag(die) == DW_TAG_structure_type) ||
-+ (dwarf_tag(die) == DW_TAG_union_type)) {
-+ Dwarf_Die child;
-+
-+ if (g_hash_table_lookup_extended(state->structs_seen, id,
-+ NULL, NULL))
-+ return;
-+ g_hash_table_replace(state->structs_seen, intern(xstrdup(id)),
-+ NULL);
-+
-+ switch (dwarf_child(die, &child)) {
-+ case -1:
-+ goto fail;
-+ case 1: /* No DIEs at all in this aggregate */
-+ return;
-+ }
-+
-+ /*
-+ * We are only interested in non-blacklisted children of type
-+ * DW_TAG_member.
-+ */
-+ int sib_ret;
-+
-+ do
-+ if ((dwarf_tag(&child) == DW_TAG_member) &&
-+ !member_blacklisted(&child, die))
-+ free(type_id(&child, overrides,
-+ mark_shared, state));
-+ while ((sib_ret = dwarf_siblingof(&child, &child)) == 0);
-+
-+ if (sib_ret == -1)
-+ goto fail;
-+ }
-+
-+ return;
-+
-+ fail:
-+ pr_err("Cannot mark aggregate %s members as duplicated: %s\n",
-+ dwarf_diename(die), dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * Determine if a type is a named struct, union, or enum.
-+ *
-+ * A type_id() callback.
-+ */
-+static void is_named_struct_union_enum(Dwarf_Die *die, const char *unused,
-+ struct die_override *overrides,
-+ void *data)
-+{
-+ int *is_sou = data;
-+
-+ if (((dwarf_tag(die) == DW_TAG_structure_type) ||
-+ (dwarf_tag(die) == DW_TAG_union_type) ||
-+ (dwarf_tag(die) == DW_TAG_enumeration_type)) &&
-+ (private_dwarf_hasattr(die, DW_AT_name)))
-+ *is_sou = 1;
-+}
-+
-+/*
-+ * Duplicate detection alias fixup pass. Once the first pass is complete, we
-+ * may have marked an opaque 'struct/union/enum foo' for sharing but not caught
-+ * the non-opaque instance, because no users of the non-opaque instance appeared
-+ * in the DWARF after the opaque copy was detected as a duplicate. This pass
-+ * detects such cases, and marks their members as duplicates too.
-+ *
-+ * (The inverse case of a non-opaque structure/union/enum detected as a
-+ * duplicate after the last usage of its opaque alias will be caught by this
-+ * trap too.)
-+ *
-+ * Warning: this routine directly computes type_id()s without access to the
-+ * corresponding type DIE, and as such is dependent on the format of type_id()s.
-+ * (This is why it must run over non-opaque structures: given a non-opaque
-+ * structure, its opaque alias is easy to compute, but the converse is not
-+ * true.)
-+ *
-+ * As a list_filter() filter function, returns nonzero if this structure will
-+ * not need to be checked again (because both its opaque and transparent
-+ * variants are shared).
-+ */
-+static int dedup_alias_fixup(void *id_file_data, void *data)
-+{
-+ struct dedup_id_file *id_file = id_file_data;
-+ struct dedup_state *state = data;
-+
-+ int transparent_shared = 0;
-+ int opaque_shared = 0;
-+ int made_shared = 0;
-+
-+ char *opaque_id;
-+ const char *line_num;
-+ const char *type_size;
-+ const char *type_name;
-+
-+ /*
-+ * Compute the opaque variant corresponding to this transparent type,
-+ * and check to see if either is marked shared, then find the DIE and
-+ * mark both as shared if either is. (Unfortunately this means a double
-+ * recursion in such cases, but this is unavoidable.)
-+ */
-+
-+ line_num = strstr(id_file->id, "//");
-+ if (!line_num) {
-+ pr_err("Internal error: type ID %s is corrupt.\n",
-+ id_file->id);
-+ exit(1);
-+ }
-+
-+ type_size = strstr(line_num + 2, "//");
-+ if (!type_size) {
-+ pr_err("Internal error: type ID %s is corrupt.\n",
-+ id_file->id);
-+ exit(1);
-+ }
-+
-+ type_name = strstr(type_size + 2, "//");
-+ if (!type_name) {
-+ /*
-+ * That's OK: the type size is optional, so what we thought was
-+ * the type size is actually the type name.
-+ */
-+ type_name = type_size;
-+ }
-+ type_name += 2;
-+
-+ opaque_id = xstrdup("////");
-+ opaque_id = str_append(opaque_id, type_name);
-+
-+ const char *transparent_module = g_hash_table_lookup(id_to_module,
-+ id_file->id);
-+ const char *opaque_module = g_hash_table_lookup(id_to_module,
-+ opaque_id);
-+
-+ transparent_shared = ((transparent_module != NULL) &&
-+ (strcmp(transparent_module, "shared_ctf") == 0));
-+
-+ opaque_shared = ((opaque_module != NULL) &&
-+ (strcmp(opaque_module, "shared_ctf") == 0));
-+
-+ /*
-+ * Transparent type needs sharing.
-+ */
-+ if (opaque_shared && !transparent_shared) {
-+ Dwarf_Die die;
-+ Dwfl_Module *mod;
-+ Dwarf_Addr dummy;
-+
-+ /*
-+ * Since we are not using process_file(), we must handle
-+ * translation unit switches by hand, including resetting
-+ * structs_seen. We also need to open the DWARF file, since
-+ * type_id() needs access to the DIE of this type and all its
-+ * dependent types as well.
-+ */
-+
-+ if (state->dwfl != NULL &&
-+ strcmp(state->dwfl_file_name, id_file->file_name) != 0)
-+ dedup_dwarf_free(state);
-+
-+ if (state->dwfl_file_name == NULL) {
-+ state->dwfl = simple_dwfl_new(id_file->file_name, &mod);
-+ state->dwarf = dwfl_module_getdwarf(mod, &dummy);
-+ state->dwfl_file_name = xstrdup(id_file->file_name);
-+ if (state->structs_seen)
-+ g_hash_table_destroy(state->structs_seen);
-+ state->structs_seen = g_hash_table_new(g_str_hash,
-+ g_str_equal);
-+ }
-+ if (!dwarf_offdie(state->dwarf, id_file->dieoff,
-+ &die)) {
-+ pr_err("Cannot look up offset %li in %s for type with ID %s\n",
-+ id_file->dieoff, id_file->file_name, id_file->id);
-+ exit(1);
-+ }
-+ mark_shared(&die, NULL, NULL, state);
-+ made_shared = 1;
-+ }
-+
-+ /*
-+ * We don't have the opaque type's DIE, so we can't use mark_shared():
-+ * this is also good since this triggers another duplicate detection
-+ * pass, and we don't want to trigger another pass merely because of a
-+ * nonshared opaque type (since they don't have members that may have
-+ * structure or union type themselves and thus force more unshared
-+ * types to become shared).
-+ *
-+ * Instead, do it by hand: this is simple, as member recursion is
-+ * guaranteed not to be required for an opaque type.
-+ */
-+ if (transparent_shared && !opaque_shared) {
-+ dw_ctf_trace("Marking %s as duplicate\n", opaque_id);
-+ g_hash_table_replace(id_to_module, intern(xstrdup(opaque_id)),
-+ xstrdup("shared_ctf"));
-+ made_shared = 1;
-+ }
-+
-+ free(opaque_id);
-+
-+ return made_shared || (opaque_shared && transparent_shared);
-+}
-+
-+/*
-+ * Mark a basic type shared by name and intern it in all relevant hashes. (Used
-+ * for marking basic types we don't have a DIE for.)
-+ */
-+static void mark_shared_by_name(ctf_file_t *ctf, ctf_id_t ctf_id,
-+ const char *name)
-+{
-+ struct ctf_full_id static_ctf_id = { ctf, ctf_id };
-+ struct ctf_full_id *full_ctf_id;
-+ char *id = NULL;
-+
-+ full_ctf_id = malloc(sizeof(struct ctf_full_id));
-+ if (full_ctf_id == NULL) {
-+ pr_err("%s: out of memory\n", __func__);
-+ exit(1);
-+ }
-+ *full_ctf_id = static_ctf_id;
-+
-+ id = str_appendn(id, "////", name, " ", NULL);
-+#ifdef DEBUG
-+ strcpy(full_ctf_id->module_name, "shared_ctf");
-+ strcpy(full_ctf_id->file_name, "<built-in type>");
-+#endif
-+ g_hash_table_replace(id_to_module, intern(xstrdup(id)), xstrdup("shared_ctf"));
-+ g_hash_table_replace(id_to_type, intern(id), full_ctf_id);
-+}
-+
-+/*
-+ * Type assembly.
-+ *
-+ * Given a DWARF DIE corresponding to a top-level type, call the appropriate
-+ * construction function, passing it the appropriate ctf_file_t, constructing it
-+ * if necessary, and stashing them in the appropriate hashes. Return the
-+ * ctf_file_t and ctf_id_t of this type.
-+ *
-+ * Indirectly recursively called for types depending on other types, and for
-+ * the types of variables (which for the sake of argument we call 'types' here
-+ * too, since we treat them exactly like types, and dealing with types is our
-+ * most important function). In such calls, the module_name may be 'shared_ctf'
-+ * if this type is in the shared CTF repository.
-+ *
-+ * Select properties of the DIE can be overridden via the overrides array, if
-+ * needed.
-+ */
-+static struct ctf_full_id *construct_ctf_id(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ struct die_override *overrides)
-+{
-+ char *id = type_id(die, overrides, NULL, NULL);
-+ char *ctf_module;
-+ ctf_file_t *ctf;
-+ ctf_snapshot_id_t snapshot;
-+
-+ dw_ctf_trace(" %p: %s: looking up %s: %s\n", &id,
-+ module_name ? module_name : "(no module)",
-+ dwarf_diename(die), id);
-+ /*
-+ * Make sure this type does not already exist. (Recursive chasing for
-+ * referenced types can lead to construct_ctf() being called on them
-+ * more than once.)
-+ */
-+ struct ctf_full_id *ctf_id;
-+
-+ ctf_id = g_hash_table_lookup(id_to_type, id);
-+ if (ctf_id != NULL) {
-+ dw_ctf_trace(" %p: %p:%i found in module %s, file %s\n", &id,
-+ ctf_id->ctf_file, (int) ctf_id->ctf_id,
-+ ctf_id->module_name, ctf_id->file_name);
-+ free(id);
-+ return ctf_id;
-+ }
-+
-+ /*
-+ * Create the CTF file for this type, if it does not exist. Verify that
-+ * the duplicate-detection pass scanned this type, and that this is
-+ * either the current module or the shared CTF module.
-+ */
-+
-+ ctf_module = g_hash_table_lookup(id_to_module, id);
-+
-+ if (ctf_module == NULL) {
-+ pr_err("Internal error: within file %s, module %s, type at DIE offset %lx\n"
-+ "with ID %s was not already noted by dedup().\n",
-+ file_name, module_name, DIEOFFSET(die), id);
-+ pr_err("dedup() is probably buggy.\n");
-+ exit(1);
-+ }
-+
-+ if ((strcmp(ctf_module, module_name) != 0) &&
-+ (strcmp(ctf_module, "shared_ctf") != 0)) {
-+ pr_err("Internal error: within file %s, module %s, type at DIE offset %lx\n"
-+ "with ID %s is in a different non-shared module, %s.\n",
-+ file_name, module_name, DIEOFFSET(die), id, ctf_module);
-+ pr_err("dedup() is probably buggy.\n");
-+ exit(1);
-+ }
-+
-+ ctf = lookup_ctf_file(ctf_module);
-+
-+ /*
-+ * Construct the CTF, then insert the top-level CTF entity into the
-+ * id->type hash so that references from other types can find it, and
-+ * update the CTF container. If conversion failed, roll back all
-+ * changes made since the last successful call to this function.
-+ *
-+ * NOTE: references within DWARF to non-top-level types will currently
-+ * fail, but I'm not sure if these can exist. (The type ID
-+ * representation implicitly assumes that they cannot.)
-+ */
-+
-+ snapshot = ctf_snapshot(ctf);
-+
-+ enum skip_type skip = SKIP_CONTINUE;
-+
-+ dw_ctf_trace("%p: into die_to_ctf() for %s\n", &id, id);
-+ ctf_id_t this_ctf_id = die_to_ctf(ctf_module, file_name, die,
-+ parent_die, ctf, -1, overrides,
-+ 1, 0, &skip, NULL, id);
-+ dw_ctf_trace("%p: out of die_to_ctf()\n", &id);
-+
-+ ctf_id = malloc(sizeof(struct ctf_full_id));
-+ if (ctf_id == NULL) {
-+ pr_err("Out of memory\n");
-+ exit(1);
-+ }
-+
-+ if (skip != SKIP_ABORT) {
-+ ctf_id->ctf_file = ctf;
-+ ctf_id->ctf_id = this_ctf_id;
-+#ifdef DEBUG
-+ strcpy(ctf_id->module_name, ctf_module);
-+ strcpy(ctf_id->file_name, file_name);
-+#endif
-+ dw_ctf_trace(" %lx: %s: new type added, CTF ID %p:%li\n",
-+ DIEOFFSET(die), id, ctf_id->ctf_file,
-+ ctf_id->ctf_id);
-+
-+ g_hash_table_replace(id_to_type, intern(id), ctf_id);
-+ } else {
-+ /*
-+ * Failure. Remove the type from the id_to_type mapping, if it
-+ * is there, and discard any added types from the CTF.
-+ *
-+ * If we have had to ctf_update() due to a new type getting
-+ * used, the rollback will fail: discard instead. It might leave
-+ * some spurious types hanging around but it will clean up as
-+ * much as we can at this point. (This cannot happen when
-+ * LIBDTRACE_CTF_OMISSIBLE_CTF_UPDATE, but it costs nothing to
-+ * leave in: failure is a rare case.)
-+ */
-+
-+ if (ctf_rollback(ctf, snapshot) < 0)
-+ if (ctf_errno(ctf) == ECTF_OVERROLLBACK)
-+ ctf_discard(ctf);
-+
-+ free(ctf_id);
-+ ctf_id = NULL;
-+
-+ g_hash_table_remove(id_to_type, id);
-+ free(id);
-+
-+ dw_ctf_trace(" %p: (failure)\n", &id);
-+ }
-+
-+ return ctf_id;
-+}
-+
-+/*
-+ * Given a DWARF DIE corresponding to a top-level type, or to an aggregate
-+ * member, and the ctf_file_t where it is to be placed, call the appropriate
-+ * construction function to place it and (for aggregates) its siblings there,
-+ * recursing to handle contained aggregates.
-+ *
-+ * The parameters to this function are:
-+ *
-+ * module_name: The kernel module.
-+ * file_name: The object file.
-+ * die: The DWARF DIE.
-+ * parent_die: Its parent, i.e. if a structure member, this is a structure: if
-+ * top-level, this is a CU DIE.
-+ * ctf: The CTF file this object should go into (possibly shared_ctf).
-+ * parent_ctf_id: The CTF ID of the parent DIE, or -1 if none.
-+ * struct die_override: Overrides for DWARF attributes (a NULL-terminated array,
-+ * or NULL).
-+ * top_level_type: 1 if this is a top-level type that can have a name and be
-+ * referred to by other types.
-+ * backwards: if 1, this is an internal call to process a series of bitfields
-+ * with descending bit_offset and identical data_member_location.
-+ * skip: The error-handling / skipping enum.
-+ * replace: if 1, this type should replace its parent type entirely.
-+ * id: the ID of this type.
-+ *
-+ * Note: id is only defined when top_level_type is 1. (We never use it
-+ * in other situations, and computing it is quite expensive.)
-+ */
-+static ctf_id_t die_to_ctf(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die,
-+ ctf_file_t *ctf, ctf_id_t parent_ctf_id,
-+ struct die_override *overrides, int top_level_type,
-+ int backwards, enum skip_type *skip, int *replace,
-+ const char *id)
-+{
-+ int sib_ret = 0;
-+ ctf_id_t this_ctf_id;
-+ int dummy;
-+
-+ do {
-+ const char *id_name;
-+ const char *decl_file_name = dwarf_decl_file(die);
-+ int decl_line_num;
-+ int emitted_backwards = 0;
-+ char locerrstr[1024];
-+ Dwarf_Die next_die;
-+
-+ /*
-+ * If the next DWARF DIE is at the same location as this one but
-+ * with a lower bit_offset, we need to process the set of DIEs
-+ * at this location in *reverse*, because DWARF has the DIEs in
-+ * declaration order, while CTF wants them in in-memory order:
-+ * so recurse to handle the next until we get to an element with
-+ * a sibling at a different data_member_location (safe because
-+ * there can't be that many of them per data_member_location),
-+ * then (at the end of die_to_ctf()) exit the recursion and skip
-+ * over the lot.
-+ *
-+ * We can ignore 'replace' and the return value of die_to_ctf
-+ * because bitfields must be structure or union members and
-+ * cannot be array dimensions.
-+ */
-+ if (die_emit_next_backwards(&next_die, die,
-+ overrides) != NULL) {
-+ ctf_id_t dummy;
-+
-+ dw_ctf_trace("Emitting %s:%s:%lx backwards\n",
-+ module_name, file_name,
-+ DIEOFFSET(&next_die));
-+
-+ dummy = die_to_ctf(module_name, file_name, &next_die,
-+ parent_die, ctf, parent_ctf_id,
-+ overrides, top_level_type, 1, skip,
-+ replace, NULL);
-+ if (*skip == SKIP_ABORT)
-+ return dummy;
-+ emitted_backwards = 1;
-+ }
-+
-+ /*
-+ * Compute a name for our current location, for error messages.
-+ * (The type representation could be used, but is likely to be
-+ * hard for users to comprehend, and should we move to a hashed
-+ * representation would be entirely useless for this purpose.)
-+ */
-+ if ((decl_file_name == NULL) ||
-+ (dwarf_decl_line(die, &decl_line_num) < 0)) {
-+ decl_file_name = "global";
-+ decl_line_num = 0;
-+ }
-+
-+ id_name = dwarf_diename(die);
-+ if (id_name == NULL)
-+ id_name = "(unnamed type)";
-+
-+ snprintf(locerrstr, sizeof(locerrstr), "%s:%i:%s",
-+ decl_file_name, decl_line_num, id_name);
-+
-+ dw_ctf_trace("Working over %s:%s:%s:%lx:%x with CTF file %p\n",
-+ module_name, file_name,
-+ dwarf_diename(die)==NULL?"NULL":dwarf_diename(die),
-+ DIEOFFSET(die), dwarf_tag(die), ctf);
-+
-+ /*
-+ * Only process a given node, or its children, if we know how to
-+ * do so.
-+ */
-+ if ((dwarf_tag(die) >= assembly_len) ||
-+ (assembly_tab[dwarf_tag(die)] == NULL)) {
-+ pr_err("%s:%i: warning: skipping identifier "
-+ "%s with unknown DWARF tag %lx.\n",
-+ decl_file_name, decl_line_num, id_name,
-+ (unsigned long) dwarf_tag(die));
-+ return -1;
-+ }
-+
-+ *skip = SKIP_CONTINUE;
-+
-+ this_ctf_id = assembly_tab[dwarf_tag(die)](module_name,
-+ file_name,
-+ die, parent_die,
-+ ctf, parent_ctf_id,
-+ locerrstr,
-+ overrides,
-+ top_level_type,
-+ skip,
-+ replace ? replace :
-+ &dummy);
-+ dw_ctf_trace("%s: out of assembly function for tag %lx with type ID %li\n",
-+ locerrstr, (unsigned long) dwarf_tag(die),
-+ this_ctf_id);
-+
-+ if (this_ctf_id < 0) {
-+ if ((this_ctf_id == CTF_NO_ERROR_REPORTED) &&
-+ (ctf_errno(ctf) != 0))
-+ pr_err("%s: CTF error in assembly of item with tag %i: %s\n",
-+ locerrstr, dwarf_tag(die),
-+ ctf_errmsg(ctf_errno(ctf)));
-+
-+ num_errors++;
-+#ifdef DEBUG
-+ exit(1);
-+#endif
-+ *skip = SKIP_ABORT;
-+ }
-+
-+ /*
-+ * Add newly-added non-skipped top-level structure or union CTF
-+ * IDs to the type table at once. This allows circular type
-+ * references via pointers in structure/union member DIEs to be
-+ * looked up correctly.
-+ */
-+ if (top_level_type && (*skip == SKIP_CONTINUE) &&
-+ ((dwarf_tag(die) == DW_TAG_structure_type) ||
-+ (dwarf_tag(die) == DW_TAG_union_type))) {
-+ struct ctf_full_id full_ctf_id = { ctf, this_ctf_id };
-+ struct ctf_full_id *ctf_id;
-+
-+#ifdef DEBUG
-+ strcpy(full_ctf_id.module_name, module_name);
-+ strcpy(full_ctf_id.file_name, file_name);
-+#endif
-+
-+ ctf_id = malloc(sizeof(struct ctf_full_id));
-+ if (ctf_id == NULL) {
-+ fprintf(stderr,
-+ "Out of memory allocating type ID\n");
-+ exit(1);
-+ }
-+
-+ dw_ctf_trace(" %s: immediate addition of %s, CTF ID "
-+ "%p:%li in module %s, file %s\n", __func__,
-+ id, full_ctf_id.ctf_file, full_ctf_id.ctf_id,
-+ module_name, file_name);
-+ *ctf_id = full_ctf_id;
-+
-+ g_hash_table_replace(id_to_type, intern(xstrdup(id)),
-+ ctf_id);
-+ }
-+
-+ /*
-+ * Recurse to handle contained DIEs.
-+ */
-+
-+ if ((dwarf_haschildren(die)) && (*skip == SKIP_CONTINUE)) {
-+ Dwarf_Die child_die;
-+ ctf_id_t new_id;
-+ int replace = 0;
-+
-+ if (dwarf_child(die, &child_die) < 0) {
-+ pr_err("%s: Cannot recurse to DWARF DIE children: %s\n",
-+ locerrstr, dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+ }
-+
-+ new_id = die_to_ctf(module_name, file_name, &child_die,
-+ die, ctf, this_ctf_id, overrides, 0,
-+ 0, skip, &replace, NULL);
-+ if (replace)
-+ this_ctf_id = new_id;
-+ }
-+
-+ /*
-+ * If we are walking backwards over a bunch of bitfields, this
-+ * is a recursive walk, not an iterative one: return.
-+ */
-+ if (backwards)
-+ return this_ctf_id;
-+
-+ /*
-+ * We are not walking backwards, but this is the final stage of
-+ * a bunch of backwards emissions: walk forwards until we hit
-+ * the last one again.
-+ */
-+ if (emitted_backwards)
-+ while (die_emit_next_backwards(&next_die, die,
-+ overrides) != NULL)
-+ *die = next_die;
-+
-+ /*
-+ * Walk siblings of non-top-level types only: the sibling walk
-+ * of top-level types is done by process_file(), so that
-+ * construct_ctf_id() gets a chance to put each such type in the
-+ * right CTF file.
-+ */
-+ } while (*skip != SKIP_ABORT && !top_level_type &&
-+ (sib_ret = dwarf_siblingof(die, die)) == 0);
-+
-+ if (sib_ret == -1) {
-+ pr_err("In module %s, failure walking the sibling list: %s\n",
-+ module_name, dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+ }
-+
-+ dw_ctf_trace("New type ID: %p:%li\n", ctf, this_ctf_id);
-+ return this_ctf_id;
-+}
-+
-+/*
-+ * Calls construct_ctf_id() and throws the ID away. Used as a process_file()
-+ * callback.
-+ */
-+static void construct_ctf(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die,
-+ void *unused __unused__)
-+{
-+ construct_ctf_id(module_name, file_name, die, parent_die, NULL);
-+}
-+
-+/*
-+ * Return the next DIE, if that DIE needs to be emitted before this one.
-+ */
-+static Dwarf_Die *die_emit_next_backwards(Dwarf_Die *next, Dwarf_Die *die,
-+ struct die_override *overrides)
-+{
-+ if (dwarf_tag(die) == DW_TAG_member &&
-+ dwarf_siblingof(die, next) == 0 &&
-+ dwarf_tag(next) == DW_TAG_member &&
-+ private_dwarf_hasattr(die, DW_AT_data_member_location) &&
-+ private_dwarf_hasattr(next, DW_AT_data_member_location) &&
-+ private_dwarf_udata(die, DW_AT_data_member_location, overrides) ==
-+ private_dwarf_udata(next, DW_AT_data_member_location, overrides) &&
-+ private_dwarf_hasattr(die, DW_AT_bit_offset) &&
-+ private_dwarf_hasattr(next, DW_AT_bit_offset) &&
-+ private_dwarf_udata(die, DW_AT_bit_offset, overrides) >
-+ private_dwarf_udata(next, DW_AT_bit_offset, overrides))
-+ return next;
-+ return NULL;
-+}
-+
-+/*
-+ * Look up a type through its reference: return its ctf_id, or recursively
-+ * construct it if need be.
-+ */
-+static ctf_id_t lookup_ctf_type(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, ctf_file_t *ctf,
-+ struct die_override *overrides,
-+ const char *locerrstr)
-+{
-+ Dwarf_Die tmp;
-+ Dwarf_Die *type_die = private_dwarf_type(die, &tmp);
-+ Dwarf_Die cu_die;
-+ struct ctf_full_id *type_ref;
-+
-+ /*
-+ * Pointers to functions and void are special cases: there is only one
-+ * of each of these in CTF, so we can use global singletons.
-+ */
-+
-+ if (type_die == NULL)
-+ return ctf_void_type;
-+
-+ if (dwarf_tag(type_die) == DW_TAG_subroutine_type)
-+ return ctf_funcptr_type;
-+
-+ /*
-+ * Look up or construct CTF for this type.
-+ */
-+
-+ dwarf_diecu(type_die, &cu_die, NULL, NULL);
-+
-+ dw_ctf_trace(" %s: Looking up dependent type at offset %lx for type %s at module %s, file %s\n",
-+ locerrstr, DIEOFFSET(type_die),
-+ dwarf_diename(die) ? dwarf_diename(die) : "NULL",
-+ module_name, file_name);
-+
-+ type_ref = construct_ctf_id(module_name, file_name,
-+ type_die, &cu_die, overrides);
-+
-+ /*
-+ * Pass any error back up.
-+ */
-+ if (type_ref == NULL) {
-+ pr_err("%s: type lookup failed.\n", locerrstr);
-+ return -1;
-+ }
-+
-+ if ((type_ref->ctf_file != ctf) &&
-+ type_ref->ctf_file != lookup_ctf_file("shared_ctf")) {
-+#ifdef DEBUG
-+ pr_err("%s: Internal error: lookup of %s found in different file: "
-+ "%s/%s versus %s/%s.\n", locerrstr,
-+ dwarf_diename(die) ? dwarf_diename(die) : "(unnamed)",
-+ type_ref->module_name, type_ref->file_name,
-+ module_name, file_name);
-+#else
-+ pr_err("%s: Internal error: lookup of %s found in different file.\n",
-+ locerrstr, dwarf_diename(die) ? dwarf_diename(die) :
-+ "(unnamed)");
-+#endif
-+ pr_err("dedup() is probably buggy.\n");
-+ exit(1);
-+ }
-+
-+ return type_ref->ctf_id;
-+}
-+
-+/* Assembly functions. */
-+
-+#define CTF_DW_ENFORCE(attribute) do \
-+ if (!private_dwarf_hasattr(die, (DW_AT_##attribute))) { \
-+ pr_err("%s: %s: %lx: skipping type, %s attribute not present.\n", \
-+ locerrstr, __func__, DIEOFFSET(die), \
-+ #attribute); \
-+ *skip = SKIP_ABORT; \
-+ return CTF_ERROR_REPORTED; \
-+ } \
-+ while (0)
-+
-+#define CTF_DW_ENFORCE_NOT(attribute) do \
-+ if (private_dwarf_hasattr(die, (DW_AT_##attribute))) { \
-+ pr_err("%s: %s: %lx: skipping type, %s attribute not supported.\n", \
-+ locerrstr, __func__, DIEOFFSET(die), \
-+ #attribute); \
-+ *skip = SKIP_ABORT; \
-+ return CTF_ERROR_REPORTED; \
-+ } \
-+ while (0)
-+
-+#define ROOT_TYPE(x) (x) ? CTF_ADD_ROOT : CTF_ADD_NONROOT
-+
-+/*
-+ * A CTF assembly filter function which excludes all types not at the global
-+ * scope (i.e. whose immediate parent is not a CU DIE), and all types which
-+ * reference a type which is not at the global scope (thus ruling out local type
-+ * definitions for which the compiler is not consistently emitting all
-+ * intermediate types at the local scope).
-+ */
-+static int filter_ctf_file_scope(const char *file_name, Dwarf *dwarf,
-+ Dwarf_Die *die, Dwarf_Die *parent_die)
-+{
-+ Dwarf_Die type_die;
-+ GHashTable *parents;
-+
-+ /*
-+ * A type not dependent on another is acceptable iff it is at the global
-+ * scope.
-+ */
-+ if (private_dwarf_type(die, &type_die) == NULL)
-+ return (dwarf_tag(parent_die) == DW_TAG_compile_unit);
-+
-+ /*
-+ * No type we reference may have a subprogram DIE as any of its parents.
-+ */
-+ parents = g_hash_table_lookup(fn_to_die_to_parent,
-+ abs_file_name(file_name));
-+
-+ do {
-+ Dwarf_Die parent = type_die;
-+ Dwarf_Off parent_off = 0;
-+
-+ do {
-+ if (parent_off != 0 &&
-+ !dwarf_offdie(dwarf, parent_off, &parent))
-+ break;
-+ if (dwarf_tag(&parent) == DW_TAG_subprogram)
-+ return 0;
-+ } while ((parent_off = GPOINTER_TO_UINT(g_hash_table_lookup(parents,
-+ GUINT_TO_POINTER(dwarf_dieoffset(&parent)))))
-+ != 0);
-+ } while (private_dwarf_type(&type_die, &type_die) != NULL);
-+
-+ return 1;
-+}
-+
-+/*
-+ * A CTF assembly filter function which excludes all names not at the global
-+ * scope, and all names whose names are unlikely to be interesting. (DTrace
-+ * userspace contains a similar list, but the two lists need not be in sync.)
-+ */
-+static int filter_ctf_uninteresting(const char *file_name __unused__,
-+ Dwarf *dwarf __unused__,
-+ Dwarf_Die *die, Dwarf_Die *parent_die)
-+{
-+ const char *sym_name = dwarf_diename(die);
-+
-+ /*
-+ * 'Variables' with no name are not interesting.
-+ */
-+ if (sym_name == NULL)
-+ return 0;
-+
-+#define strstarts(var, x) (strncmp(var, x, strlen(x)) == 0)
-+ return ((dwarf_tag(parent_die) == DW_TAG_compile_unit) &&
-+ !((strcmp(sym_name, "__per_cpu_start") == 0) ||
-+ (strcmp(sym_name, "__per_cpu_end") == 0) ||
-+ (strcmp(sym_name, "_sdt_probes") == 0) ||
-+ (strstarts(sym_name, "__crc_")) ||
-+ (strstarts(sym_name, "__ksymtab_")) ||
-+ (strstarts(sym_name, "__kcrctab_")) ||
-+ (strstarts(sym_name, "__kstrtab_")) ||
-+ (strstarts(sym_name, "__param_")) ||
-+ (strstarts(sym_name, "__syscall_meta__")) ||
-+ (strstarts(sym_name, "__p_syscall_meta__")) ||
-+ (strstarts(sym_name, "__event_")) ||
-+ (strstarts(sym_name, "event_")) ||
-+ (strstarts(sym_name, "ftrace_event_")) ||
-+ (strstarts(sym_name, "types__")) ||
-+ (strstarts(sym_name, "args__")) ||
-+ (strstarts(sym_name, "__tracepoint_")) ||
-+ (strstarts(sym_name, "__tpstrtab_")) ||
-+ (strstarts(sym_name, "__tpstrtab__")) ||
-+ (strstarts(sym_name, "__initcall_")) ||
-+ (strstarts(sym_name, "__setup_")) ||
-+ (strstarts(sym_name, "__pci_fixup_")) ||
-+ (strstr(sym_name, ".") != NULL)));
-+#undef strstarts
-+}
-+
-+/*
-+ * Assemble base types.
-+ */
-+static ctf_id_t assemble_ctf_base(const char *module_name,
-+ const char *file_name, Dwarf_Die *die,
-+ Dwarf_Die *parent_die, ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id, const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type, enum skip_type *skip,
-+ int *replace)
-+{
-+ typedef ctf_id_t (*ctf_add_fun)(ctf_file_t *, uint_t,
-+ const char *, const ctf_encoding_t *);
-+
-+ const char *name = dwarf_diename(die);
-+ Dwarf_Word encoding, size;
-+ ctf_add_fun ctf_add_func;
-+ ctf_encoding_t ctf_encoding;
-+ size_t encoding_search;
-+ struct die_override *bit_size_override, *bit_offset_override;
-+
-+ struct dwarf_encoding_tab {
-+ Dwarf_Word encoding;
-+ ctf_add_fun func;
-+ uint_t encoding_fixed;
-+ struct type_encoding_tab *size_lookup;
-+ };
-+
-+ struct type_encoding_tab float_encoding[] = {
-+ {sizeof(float), CTF_FP_SINGLE },
-+ {sizeof(double), CTF_FP_DOUBLE },
-+ {sizeof(long double), CTF_FP_LDOUBLE },
-+ {0, 0}
-+ };
-+
-+ struct type_encoding_tab float_cplx_encoding[] = {
-+ {sizeof(float), CTF_FP_CPLX },
-+ {sizeof(double), CTF_FP_DCPLX },
-+ {sizeof(long double), CTF_FP_LDCPLX },
-+ {0, 0}
-+ };
-+
-+ struct type_encoding_tab float_imagry_encoding[] = {
-+ {sizeof(float), CTF_FP_IMAGRY },
-+ {sizeof(double), CTF_FP_DIMAGRY },
-+ {sizeof(long double), CTF_FP_LDIMAGRY },
-+ {0, 0}
-+ };
-+
-+ struct dwarf_encoding_tab all_encodings[] = {
-+ {DW_ATE_boolean, ctf_add_integer, CTF_INT_BOOL, NULL},
-+ {DW_ATE_signed, ctf_add_integer, CTF_INT_SIGNED, NULL},
-+ {DW_ATE_signed_char, ctf_add_integer,
-+ CTF_INT_SIGNED | CTF_INT_CHAR, NULL},
-+ {DW_ATE_unsigned, ctf_add_integer, 0, NULL},
-+ {DW_ATE_unsigned_char, ctf_add_integer, CTF_INT_CHAR, NULL},
-+ {DW_ATE_float, ctf_add_float, 0, float_encoding},
-+ {DW_ATE_complex_float, ctf_add_float, 0, float_cplx_encoding},
-+ {DW_ATE_imaginary_float, ctf_add_float, 0,
-+ float_imagry_encoding},
-+ {0, 0, 0, 0}
-+ };
-+
-+ CTF_DW_ENFORCE(name);
-+ CTF_DW_ENFORCE(encoding);
-+ CTF_DW_ENFORCE(byte_size);
-+ CTF_DW_ENFORCE_NOT(endianity);
-+
-+ encoding = private_dwarf_udata(die, DW_AT_encoding, overrides);
-+ size = private_dwarf_udata(die, DW_AT_byte_size, overrides);
-+
-+ for (encoding_search = 0; all_encodings[encoding_search].func != 0;
-+ encoding_search++) {
-+ if (all_encodings[encoding_search].encoding == encoding) {
-+ ctf_add_func = all_encodings[encoding_search].func;
-+ if (all_encodings[encoding_search].size_lookup != NULL)
-+ ctf_encoding.cte_format =
-+ find_ctf_encoding(all_encodings[encoding_search].size_lookup,
-+ size);
-+ else
-+ ctf_encoding.cte_format =
-+ all_encodings[encoding_search].encoding_fixed;
-+ break;
-+ }
-+ }
-+
-+ if (all_encodings[encoding_search].func == 0) {
-+ pr_err("%s: skipping type, base type %li not yet implemented.\n",
-+ locerrstr, (long) encoding);
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ /*
-+ * Handle bitfields. Only look at overrides, since bitfields can only
-+ * be members of structures in C, thus derived from the referencing DIE.
-+ * Bitfields are never top-level types in C, even though they are in
-+ * DWARF.
-+ */
-+ bit_size_override = private_find_override(die, DW_AT_bit_size,
-+ overrides);
-+ bit_offset_override = private_find_override(die, DW_AT_bit_offset,
-+ overrides);
-+ if (bit_size_override) {
-+ ctf_encoding.cte_bits = bit_size_override->value;
-+ top_level_type = 0;
-+ } else
-+ ctf_encoding.cte_bits = size * 8;
-+
-+ if (bit_offset_override) {
-+#if __BYTE_ORDER == __BIG_ENDIAN
-+ ctf_encoding.cte_offset = bit_offset_override->value;
-+#else
-+ /*
-+ * The figure here counts from the left to the leftmost edge of
-+ * the bitfield: we want to count from the right to the
-+ * rightmost edge.
-+ */
-+ ctf_encoding.cte_offset = (size * 8) -
-+ bit_offset_override->value - ctf_encoding.cte_bits;
-+ dw_ctf_trace("Endianizing cte_offset from %x to %x\n",
-+ (unsigned int) bit_offset_override->value,
-+ ctf_encoding.cte_offset);
-+#endif
-+ } else
-+ ctf_encoding.cte_offset = 0;
-+
-+#ifdef DEBUG
-+ if (bit_size_override || bit_offset_override)
-+ dw_ctf_trace("Bitfield overrides: bit size %i; bit offset %i\n",
-+ ctf_encoding.cte_bits, ctf_encoding.cte_offset);
-+#endif
-+
-+ return ctf_add_func(ctf, ROOT_TYPE(top_level_type), name,
-+ &ctf_encoding);
-+}
-+
-+/*
-+ * Assemble pointer types.
-+ */
-+static ctf_id_t assemble_ctf_pointer(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die,
-+ ctf_file_t *ctf, ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip, int *replace)
-+{
-+ ctf_id_t type_ref;
-+
-+ type_ref = lookup_ctf_type(module_name, file_name, die, ctf,
-+ overrides, locerrstr);
-+ if (type_ref < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ /*
-+ * Pointers to functions are all the same type in CTF: don't bother
-+ * adding it over again.
-+ */
-+ if (type_ref == ctf_funcptr_type)
-+ return type_ref;
-+
-+ return ctf_add_pointer(ctf, ROOT_TYPE(top_level_type), type_ref);
-+}
-+
-+/*
-+ * Assemble array types. This function looks up the array type, but does not do
-+ * any array construction: that is left to assemble_ctf_array_dimension().
-+ */
-+static ctf_id_t assemble_ctf_array(const char *module_name,
-+ const char *file_name, Dwarf_Die *die,
-+ Dwarf_Die *parent_die, ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip, int *replace)
-+{
-+ ctf_id_t type_ref;
-+
-+ CTF_DW_ENFORCE_NOT(ordering);
-+ CTF_DW_ENFORCE_NOT(bit_stride);
-+ CTF_DW_ENFORCE_NOT(byte_stride);
-+
-+ type_ref = lookup_ctf_type(module_name, file_name, die, ctf,
-+ overrides, locerrstr);
-+ if (type_ref < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+ return type_ref;
-+}
-+
-+/*
-+ * Assemble an array dimension, wrapping an array round the parent_ctf_id and
-+ * replacing it.
-+ */
-+static ctf_id_t assemble_ctf_array_dimension(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ ctf_arinfo_t arinfo;
-+
-+ CTF_DW_ENFORCE_NOT(bit_size);
-+ CTF_DW_ENFORCE_NOT(byte_size);
-+ CTF_DW_ENFORCE_NOT(bit_stride);
-+ CTF_DW_ENFORCE_NOT(byte_stride);
-+ CTF_DW_ENFORCE_NOT(lower_bound);
-+ CTF_DW_ENFORCE_NOT(threads_scaled);
-+
-+ arinfo.ctr_contents = parent_ctf_id;
-+
-+ arinfo.ctr_index = lookup_ctf_type(module_name, file_name,
-+ die, ctf, overrides, locerrstr);
-+ if (arinfo.ctr_index < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ arinfo.ctr_nelems = private_subrange_dimensions(die);
-+
-+ /*
-+ * For each array dimension, construct an appropriate array of the
-+ * type-so-far, overriding the parent type.
-+ */
-+
-+ *replace = 1;
-+ return ctf_add_array(ctf, ROOT_TYPE(top_level_type), &arinfo);
-+}
-+
-+/*
-+ * Assemble an enumeration.
-+ */
-+static ctf_id_t assemble_ctf_enumeration(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ const char *name = dwarf_diename(die);
-+
-+ return ctf_add_enum(ctf, ROOT_TYPE(top_level_type), name);
-+}
-+
-+/*
-+ * Assemble an enumeration value.
-+ */
-+static ctf_id_t assemble_ctf_enumerator(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ const char *name = dwarf_diename(die);
-+ Dwarf_Word value;
-+ int err;
-+
-+ CTF_DW_ENFORCE(name);
-+ CTF_DW_ENFORCE(const_value);
-+ CTF_DW_ENFORCE_NOT(bit_stride);
-+ CTF_DW_ENFORCE_NOT(byte_stride);
-+
-+ value = private_dwarf_udata(die, DW_AT_const_value, overrides);
-+ err = ctf_add_enumerator(ctf, parent_ctf_id, name, value);
-+
-+ if (err != 0)
-+ return err;
-+
-+ return parent_ctf_id;
-+}
-+
-+/*
-+ * Assemble a typedef.
-+ */
-+static ctf_id_t assemble_ctf_typedef(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ const char *name = dwarf_diename(die);
-+ ctf_id_t type_ref;
-+
-+ CTF_DW_ENFORCE(name);
-+
-+ type_ref = lookup_ctf_type(module_name, file_name, die, ctf,
-+ overrides, locerrstr);
-+ if (type_ref < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ return ctf_add_typedef(ctf, ROOT_TYPE(top_level_type), name, type_ref);
-+}
-+
-+/*
-+ * Assemble a const/volatile/restrict qualifier.
-+ */
-+static ctf_id_t assemble_ctf_cvr_qual(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ ctf_id_t (*ctf_cvr_fun)(ctf_file_t *fp, uint_t flag, ctf_id_t ref);
-+ ctf_id_t type_ref;
-+
-+ switch (dwarf_tag(die)) {
-+ case DW_TAG_const_type: ctf_cvr_fun = ctf_add_const; break;
-+ case DW_TAG_volatile_type: ctf_cvr_fun = ctf_add_volatile; break;
-+ case DW_TAG_restrict_type: ctf_cvr_fun = ctf_add_restrict; break;
-+ default:
-+ pr_err("%s: internal error: assemble_ctf_cvr_qual() called with\n"
-+ "non-const/volatile/restrict: %i\n", locerrstr, dwarf_tag(die));
-+ exit(1);
-+ }
-+
-+ type_ref = lookup_ctf_type(module_name, file_name, die, ctf,
-+ overrides, locerrstr);
-+ if (type_ref < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ return ctf_cvr_fun(ctf, ROOT_TYPE(top_level_type), type_ref);
-+}
-+
-+/*
-+ * Assemble a structure or union type. This assembles only the type itself, not
-+ * its constituent members: that is done by assemble_ctf_su_member().
-+ *
-+ * We assume that if a structure or union type is discovered with more members
-+ * than an earlier-discovered type, that it is compatible with that earlier type
-+ * and a superset of it.
-+ *
-+ * FIXME: in debug mode we should not assume this.
-+ */
-+static ctf_id_t assemble_ctf_struct_union(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ ctf_id_t (*ctf_add_sou)(ctf_file_t *fp, uint_t flag, const char *name,
-+ size_t size);
-+
-+ const char *name = dwarf_diename(die);
-+ int is_union = (dwarf_tag(die) == DW_TAG_union_type);
-+ struct ctf_memb_count *member_count = NULL;
-+ ctf_id_t id;
-+ long long size;
-+
-+ /*
-+ * FIXME: these both need handling for DWARF4 support.
-+ */
-+ CTF_DW_ENFORCE_NOT(specification);
-+ CTF_DW_ENFORCE_NOT(signature);
-+
-+ /*
-+ * Figure out the size of the type (if possible) and force it into the
-+ * CTF to ensure that struct/union padding is added appropriately.
-+ *
-+ * If we don't know it, force a size of zero, which is interpreted as
-+ * being equivalent to a call to the unsized struct/union addition
-+ * function, letting libdtrace-ctf figure out a likely size as best it
-+ * can.
-+ */
-+ size = private_dwarf_size(die);
-+ if (size < 0)
-+ size = 0;
-+
-+ /*
-+ * Possibly we should ignore this entire structure, if we already know
-+ * of one with the same name and at least as many members. If we
-+ * already know of one and it is shorter, we want to use its ID rather
-+ * than creating a new one.
-+ *
-+ * Note; by this point, the deduplicator has long run: thus we know for
-+ * sure what module a potentially-shared type will end up in, and
-+ * there's no need to double-check the shared CTF repository for types.
-+ * We also know that the module must exist in the per_module hash.
-+ */
-+
-+ if (name != NULL) {
-+ char *structized_name = NULL;
-+ struct per_module *ctf_pm;
-+
-+ structized_name = str_appendn(structized_name,
-+ is_union ? "u " : "s ",
-+ name, NULL);
-+
-+ ctf_pm = g_hash_table_lookup(per_module, module_name);
-+ member_count = g_hash_table_lookup(ctf_pm->member_counts,
-+ structized_name);
-+
-+ if (member_count) {
-+ free(structized_name);
-+ dw_ctf_trace("%s: already exists (with ID %li) with %zi members\n"
-+ "versus current %li members\n",
-+ locerrstr, member_count->ctf_id,
-+ member_count->count,
-+ count_dwarf_members(die));
-+
-+ if (member_count->count < count_dwarf_members(die))
-+ return member_count->ctf_id;
-+
-+ *skip = SKIP_SKIP;
-+ return member_count->ctf_id;
-+ }
-+
-+ /*
-+ * Not in existence yet. Create it.
-+ */
-+ member_count = malloc(sizeof(struct ctf_memb_count));
-+ if (member_count == NULL) {
-+ pr_err("Out of memory allocating structure/union member count\n");
-+ exit(1);
-+ }
-+ member_count->count = 0;
-+ g_hash_table_insert(ctf_pm->member_counts,
-+ structized_name, member_count);
-+ }
-+
-+ dw_ctf_trace("%s: adding structure %s\n", locerrstr, name);
-+
-+ if (is_union)
-+ ctf_add_sou = ctf_add_union_sized;
-+ else
-+ ctf_add_sou = ctf_add_struct_sized;
-+
-+ id = ctf_add_sou(ctf, ROOT_TYPE(top_level_type), name, size);
-+
-+ if (member_count != NULL)
-+ member_count->ctf_id = id;
-+
-+ return id;
-+}
-+
-+/*
-+ * Figure out the offset of this type, in bits. (This is split in two
-+ * for bitfields, where the bitfield itself gets represented elsewhere,
-+ * in the CTF type of the member itself.)
-+ *
-+ * DW_AT_data_bit_offset is the simple case. DW_AT_data_member_location
-+ * is trickier, and, alas, the DWARF2 variation is the complex one.
-+ */
-+static int ctf_su_offset(Dwarf_Die *die, const char *locerrstr,
-+ struct die_override *overrides, ulong_t *offset,
-+ ulong_t *bit_offset)
-+{
-+ struct die_override *o;
-+
-+ if (private_dwarf_hasattr(die, DW_AT_data_bit_offset))
-+ *offset = private_dwarf_udata(die, DW_AT_data_bit_offset, NULL);
-+ else if (private_dwarf_hasattr(die, DW_AT_data_member_location)) {
-+ Dwarf_Attribute location_attr;
-+
-+ private_dwarf_attr(die, DW_AT_data_member_location,
-+ &location_attr);
-+
-+ switch (dwarf_whatform(&location_attr)) {
-+ case DW_FORM_data1:
-+ case DW_FORM_data2:
-+ case DW_FORM_data4:
-+ case DW_FORM_data8:
-+ case DW_FORM_udata:
-+ case DW_FORM_sdata:
-+ {
-+ /*
-+ * Byte offset, with bit_offset of containing
-+ * structure/union added, if present.
-+ *
-+ * (No overrides supported here, yet, due to lack of
-+ * sdata overrides and the desire for consistency.
-+ * We can add them if we start passing down
-+ * DW_AT_data_member_location overrides.)
-+ */
-+ if (dwarf_whatform(&location_attr) == DW_FORM_sdata) {
-+ Dwarf_Sword location;
-+
-+ dwarf_formsdata(&location_attr, &location);
-+ *offset = location * 8;
-+ } else {
-+ Dwarf_Word location;
-+
-+ dwarf_formudata(&location_attr, &location);
-+ *offset = location * 8;
-+ }
-+ break;
-+ }
-+ case DW_FORM_block1:
-+ case DW_FORM_block2:
-+ case DW_FORM_block4:
-+ {
-+ Dwarf_Op *location;
-+ size_t nlocs;
-+
-+ /*
-+ * DWARF 2 block-based data_member_location. This can
-+ * be quite complicated in some situations (notably C++
-+ * virtual bases), but for normal structure members it
-+ * is simple. FIXME for userspace tracing of C++.
-+ *
-+ * This is thoroughly specific to the forms of DWARF2
-+ * emitted by GCC. We don't need to feel guilty about
-+ * this because elfutils does just the same thing.
-+ */
-+
-+ if (dwarf_getlocation(&location_attr, &location,
-+ &nlocs) < 0) {
-+ pr_err("%s: offset not a valid location expression: %s\n",
-+ locerrstr, dwarf_errmsg(dwarf_errno()));
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ if ((nlocs != 1) ||
-+ ((location[0].atom != DW_OP_plus_uconst) &&
-+ (location[0].atom != DW_OP_constu))) {
-+ pr_err("%s: complex location lists not supported:\n"
-+ "either C++ or non-GCC output: skipped\n", locerrstr);
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ *offset = location[0].number * 8;
-+ break;
-+ }
-+ case DW_FORM_exprloc:
-+ {
-+ /*
-+ * We need a full DWARF expression list interpreter to
-+ * handle this.
-+ */
-+ pr_err("DWARF 4 expression location lists not supported.\n");
-+ exit(1);
-+ }
-+ default:
-+ {
-+ pr_err("%s: expression location lists in form %u not supported.\n",
-+ locerrstr, dwarf_whatform(&location_attr));
-+ exit(1);
-+ }
-+ }
-+ }
-+
-+ /*
-+ * Handle the bit offset.
-+ */
-+ if (private_dwarf_hasattr(die, DW_AT_bit_offset)) {
-+ Dwarf_Attribute bit_attr;
-+ Dwarf_Word bit;
-+
-+ private_dwarf_attr(die, DW_AT_bit_offset,
-+ &bit_attr);
-+ dwarf_formudata(&bit_attr, &bit);
-+ *bit_offset = bit;
-+ }
-+
-+ /*
-+ * Handle the offset value override. It does not matter which method
-+ * has been used to get the value. At this point offset is always
-+ * the bit distance of the member from the structure/union start.
-+ *
-+ * The DW_AT_data_bit_offset override is always used to pass the offset
-+ * around, so that we don't need to add special override handling for
-+ * various forms of the DW_AT_data_member_location as a special case.
-+ * This is safe as it is not possible to have both attributes attached
-+ * to the same DIE per the DWARF4 standard, and if we have one attached
-+ * as an override to a DIE that has the other, we will only ever need to
-+ * use one (since no DIE can be both an unnamed struct/union and a
-+ * bitfield at the same time).
-+ */
-+ o = private_find_override(die, DW_AT_data_bit_offset, overrides);
-+ if (o != NULL) {
-+ if (o->op == DIE_OVERRIDE_REPLACE)
-+ *offset = o->value;
-+ else
-+ *offset += o->value;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Assemble a structure or union member.
-+ *
-+ * We only assemble a member of a given name if a member by that name does not
-+ * already exist, and if the member is not blacklisted.
-+ */
-+static ctf_id_t assemble_ctf_su_member(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ ulong_t offset = 0;
-+ ulong_t bit_offset = 0;
-+ struct ctf_full_id *new_type;
-+ Dwarf_Attribute type_attr;
-+ Dwarf_Die type_die;
-+ Dwarf_Die cu_die;
-+ int err;
-+ struct ctf_memb_count *member_count;
-+ const char *struct_name = dwarf_diename(parent_die);
-+
-+ CTF_DW_ENFORCE(type);
-+
-+ /*
-+ * Increment the member count of named structures. This is the number
-+ * of members in the DWARF, not in the CTF: blacklisted members are
-+ * counted too.
-+ */
-+ if (struct_name != NULL) {
-+ int is_union = (dwarf_tag(parent_die) == DW_TAG_union_type);
-+ char *structized_name = NULL;
-+ struct per_module *ctf_pm;
-+
-+ structized_name = str_appendn(structized_name,
-+ is_union ? "u " : "s ",
-+ struct_name, NULL);
-+
-+ ctf_pm = g_hash_table_lookup(per_module, module_name);
-+ member_count = g_hash_table_lookup(ctf_pm->member_counts,
-+ structized_name);
-+ member_count->count++;
-+ free(structized_name);
-+ }
-+
-+ /*
-+ * If this member is blacklisted, just skip it.
-+ */
-+ if (member_blacklisted(die, parent_die)) {
-+ dw_ctf_trace("%s: blacklisted, skipping.\n", locerrstr);
-+ return parent_ctf_id;
-+ }
-+
-+ /*
-+ * Find the associated type so we can either add a member with that type
-+ * (if it is named) or add its members directly (for unnamed types,
-+ * which must be unnamed structs/unions): then figure out the member's
-+ * offset.
-+ */
-+ private_dwarf_attr(die, DW_AT_type, &type_attr);
-+ if (dwarf_formref_die(&type_attr, &type_die) == NULL) {
-+ pr_err("%s: nonexistent type reference.\n"
-+ "Corrupted DWARF, cannot continue.\n", locerrstr);
-+ exit(1);
-+ }
-+ dwarf_diecu(&type_die, &cu_die, NULL, NULL);
-+
-+ err = ctf_su_offset(die, locerrstr, overrides, &offset, &bit_offset);
-+ if (err < 0) {
-+ *skip = SKIP_ABORT;
-+ return err;
-+ }
-+
-+ /*
-+ * If this is an unnamed struct/union, call directly back to
-+ * die_to_ctf() to add this struct's members to the current structure,
-+ * merging it seamlessly with its parent (excepting only the member
-+ * offsets). Use DW_AT_data_bit_offset because it does not require
-+ * the complexity of DW_AT_data_member_location to be faked.
-+ */
-+ if (!private_dwarf_hasattr(die, DW_AT_name)) {
-+ Dwarf_Die child_die;
-+ int dummy = 0;
-+
-+ if ((dwarf_tag(&type_die) != DW_TAG_structure_type) &&
-+ (dwarf_tag(&type_die) != DW_TAG_union_type)) {
-+ pr_err("%s:%lx: not supported: anonymous structure member\n"
-+ "not a structure or union.\n", locerrstr,
-+ DIEOFFSET(die));
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ /*
-+ * Anonymous structure or union with no members. Silently skip.
-+ */
-+ switch (dwarf_child(&type_die, &child_die)) {
-+ case -1:
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ case 1: /* No DIEs at all in this aggregate */
-+ return parent_ctf_id;
-+ default: /* Child DIEs exist. */
-+ break;
-+ }
-+
-+ /*
-+ * Add override that will adjust offset of the anonymous
-+ * struct/union members during inlining. The bit_offset is
-+ * ignored here as it is not expected that a nested
-+ * structure/union will start on a non-byte-aligned boundary.
-+ */
-+ struct die_override o[] = {{ dwarf_tag(&child_die),
-+ DW_AT_data_bit_offset,
-+ DIE_OVERRIDE_ADD,
-+ offset, overrides }, {0}};
-+
-+ die_to_ctf(module_name, file_name, &child_die, parent_die, ctf,
-+ parent_ctf_id, o, 0, 0, skip, &dummy, NULL);
-+
-+ return parent_ctf_id;
-+ }
-+
-+ /*
-+ * Get the CTF ID of this member's type, by recursive lookup.
-+ *
-+ * If this is a bitfield, we want to note that said type's size and
-+ * bit-offset should be adjusted.
-+ */
-+ if (private_dwarf_hasattr(die, DW_AT_bit_size)) {
-+ struct die_override o[] = {
-+ { DW_TAG_base_type,
-+ DW_AT_bit_size,
-+ DIE_OVERRIDE_REPLACE,
-+ private_dwarf_udata(die, DW_AT_bit_size,
-+ NULL),
-+ NULL },
-+ { DW_TAG_base_type,
-+ DW_AT_bit_offset,
-+ DIE_OVERRIDE_REPLACE,
-+ bit_offset,
-+ overrides },
-+ {0}
-+ };
-+
-+ new_type = construct_ctf_id(module_name, file_name, &type_die,
-+ &cu_die, o);
-+ } else {
-+ if (bit_offset != 0) {
-+ pr_err("%s:%s: error in member %s: No DW_AT_bit_size, but nonzero bit offset\n"
-+ "of %lx in overall offset of %lx\n", locerrstr,
-+ dwarf_diename(&cu_die), dwarf_diename(die),
-+ bit_offset, offset);
-+ return CTF_ERROR_REPORTED;
-+ }
-+ new_type = construct_ctf_id(module_name, file_name, &type_die,
-+ &cu_die, NULL);
-+ }
-+
-+ if (new_type == NULL) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ if ((new_type->ctf_file != ctf) &&
-+ (new_type->ctf_file != lookup_ctf_file("shared_ctf"))) {
-+ pr_err("%s:%s: internal error: referenced type lookup for member %s\n"
-+ "yields a different CTF file: %p versus %p\n",
-+ locerrstr, dwarf_diename(&cu_die), dwarf_diename(die),
-+ ctf, new_type->ctf_file);
-+ pr_err("dedup() is probably buggy.\n");
-+ exit(1);
-+ }
-+
-+ if (ctf_add_member_offset(ctf, parent_ctf_id, dwarf_diename(die),
-+ new_type->ctf_id, offset) < 0) {
-+ /*
-+ * If we have seen this member before, as part of another
-+ * definition somewhere else, that's fine. We cannot recurse
-+ * from this point, so we can just return the parent CTF ID, the
-+ * ID of the containing structure.
-+ */
-+ if (ctf_errno(ctf) == ECTF_DUPLICATE)
-+ return parent_ctf_id;
-+
-+ /*
-+ * We have special handling for cases where CTF doesn't know of
-+ * either this member's type or the enclosing structure: when
-+ * libdtrace-ctf is old enough to need it, we try a ctf_update()
-+ * in case this is recently added, but no special handling for
-+ * other errors, which the caller must report.
-+ */
-+
-+ if (ctf_errno(ctf) != ECTF_BADID &&
-+ ctf_errno(ctf) != ECTF_NOTSOU)
-+ return CTF_NO_ERROR_REPORTED;
-+
-+#ifndef LIBDTRACE_CTF_OMISSIBLE_CTF_UPDATE
-+ ctf_file_t *shared_ctf;
-+
-+ /*
-+ * Try an update of the current CTF file first, to bring the
-+ * type ID table up to date: if that doesn't work, try an update
-+ * of the shared table. (If none is needed, this is cheap.)
-+ */
-+
-+ if (ctf_update(new_type->ctf_file) < 0) {
-+ pr_err("Cannot update CTF file: %s\n",
-+ ctf_errmsg(ctf_errno(ctf)));
-+ exit(1);
-+ }
-+
-+ if (ctf_add_member_offset(ctf, parent_ctf_id,
-+ dwarf_diename(die),
-+ new_type->ctf_id,
-+ offset) == 0)
-+ return parent_ctf_id;
-+
-+ shared_ctf = lookup_ctf_file("shared_ctf");
-+ if (ctf_update(shared_ctf) < 0) {
-+ pr_err("Cannot update shared CTF: %s\n",
-+ ctf_errmsg(ctf_errno(shared_ctf)));
-+ exit(1);
-+ }
-+
-+ if (ctf_add_member_offset(ctf, parent_ctf_id,
-+ dwarf_diename(die),
-+ new_type->ctf_id,
-+ offset) == 0)
-+ return parent_ctf_id;
-+#endif
-+#ifdef DEBUG
-+ pr_err("%s: Internal error: %s %s:%s:%p:%i\n"
-+ "on member addition to ctf_file %p.\n",
-+ locerrstr, ctf_errmsg(ctf_errno(ctf)),
-+ new_type->module_name, new_type->file_name,
-+ new_type->ctf_file, (int) new_type->ctf_id, ctf);
-+#else
-+ pr_err("%s: Internal error: %s %p:%i\n"
-+ "on member addition to ctf_file %p.\n",
-+ locerrstr, ctf_errmsg(ctf_errno(ctf)),
-+ new_type->ctf_file, (int) new_type->ctf_id,
-+ ctf);
-+#endif
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ return parent_ctf_id;
-+}
-+
-+/*
-+ * Assemble a variable.
-+ */
-+static ctf_id_t assemble_ctf_variable(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ const char *name = dwarf_diename(die);
-+ char *blacklist_name = NULL;
-+ ctf_id_t type_ref;
-+ int err;
-+
-+ CTF_DW_ENFORCE(name);
-+
-+ /*
-+ * If blacklisted, just skip it.
-+ */
-+ blacklist_name = str_appendn(blacklist_name, module_name, "`",
-+ dwarf_diename(die), NULL);
-+ if (g_hash_table_lookup_extended(variable_blacklist, blacklist_name,
-+ NULL, NULL)) {
-+ dw_ctf_trace("%s: variable %s is blacklisted for static/non-static ambiguity.\n",
-+ file_name, blacklist_name);
-+ free(blacklist_name);
-+ return 0;
-+ }
-+ free(blacklist_name);
-+
-+ type_ref = lookup_ctf_type(module_name, file_name, die, ctf,
-+ overrides, locerrstr);
-+ if (type_ref < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ /*
-+ * This isn't a type: full DWARF child recursion and type-id addition is
-+ * not called for.
-+ */
-+ *skip = SKIP_SKIP;
-+
-+ err = ctf_add_variable(ctf, name, type_ref);
-+
-+ if (err == 0)
-+ dw_ctf_trace("%p: Added variable %s, type %i\n", ctf, name,
-+ (int)type_ref);
-+
-+ /*
-+ * Variable references to opaque versus non-opaque structures could only
-+ * get deduplicated with yet another deduplication pass. This seems
-+ * pointlessly expensive when nothing can refer to them: just skip
-+ * duplicates instead.
-+ */
-+ if ((err < 0) && (ctf_errno(ctf) == ECTF_DUPLICATE))
-+ return 0;
-+
-+ return err;
-+
-+}
-+
-+/* Writeout. */
-+
-+static void write_types(char *output, int standalone)
-+{
-+ GHashTableIter module_iter;
-+ char *module;
-+ struct per_module *per_mod;
-+ ctf_file_t **ctfs;
-+ const char **names;
-+ size_t i = 0;
-+ size_t ctf_count = g_hash_table_size(per_module);
-+
-+ /*
-+ * Work over all the modules and write their compressed CTF data out.
-+ * Standalone modules get placed in files in the output directory named
-+ * with names ending in .mod.ctf.new, and the makefile moves .ctf.new
-+ * over the top of .ctf iff it has changed; built-in modules and the
-+ * core kernel and shared type repository are placed into a CTF archive.
-+ */
-+ if (standalone) {
-+ if ((mkdir(output, 0777) < 0) && errno != EEXIST) {
-+ perror("Cannot create .ctf directory");
-+ exit(1);
-+ }
-+ } else {
-+ ctfs = calloc(ctf_count, sizeof(ctf_file_t *));
-+ names = calloc(ctf_count, sizeof(char *));
-+ if (!ctfs || !names)
-+ pr_err("Out of memory in CTF writeout\n");
-+ }
-+
-+ /*
-+ * Write the files out (in standalone mode), or construct the arrays of
-+ * module names and files to put in the archive (otherwise).
-+ */
-+ g_hash_table_iter_init(&module_iter, per_module);
-+ while (g_hash_table_iter_next(&module_iter, (void **) &module,
-+ (void **)&per_mod)) {
-+ int fd;
-+
-+ dw_ctf_trace("Writing out %s\n", module);
-+
-+ if (ctf_update(per_mod->ctf_file) < 0) {
-+ pr_err("Cannot serialize CTF file %s: %s\n",
-+ module, ctf_errmsg(ctf_errno(per_mod->ctf_file)));
-+ exit(1);
-+ }
-+
-+ if (!standalone) {
-+ names[i] = module;
-+ ctfs[i] = per_mod->ctf_file;
-+ i++;
-+ } else {
-+ char *path = NULL;
-+
-+ path = str_appendn(path, output, "/", module,
-+ ".mod.ctf.new", NULL);
-+
-+ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
-+ 0666);
-+ if (fd < 0) {
-+ pr_err("Cannot open CTF file %s for writing: %s\n",
-+ path, strerror(errno));
-+ exit(1);
-+ }
-+ if (ctf_compress_write(per_mod->ctf_file, fd) < 0) {
-+ pr_err("Cannot write to CTF file %s: "
-+ "%s\n", path,
-+ ctf_errmsg(ctf_errno(per_mod->ctf_file)));
-+ exit(1);
-+ }
-+ if (close(fd) != 0) {
-+ pr_err("Cannot close CTF file %s: %s\n",
-+ path, strerror(errno));
-+ exit(1);
-+ }
-+ free(path);
-+ }
-+ }
-+
-+ if (!standalone) {
-+ int err;
-+
-+ err = ctf_arc_write(output, ctfs, ctf_count, names, 4096);
-+ if (err != 0) {
-+ pr_err("Cannot write to CTF archive %s: %s\n",
-+ output, err < ECTF_BASE ? strerror(err) :
-+ ctf_errmsg(err));
-+ exit(1);
-+ }
-+ free(names);
-+ free(ctfs);
-+ }
-+}
-+
-+/* Utilities. */
-+
-+/*
-+ * Given a DIE that may contain a type attribute, look up the target of that
-+ * attribute and return it, or NULL if none.
-+ */
-+static Dwarf_Die *private_dwarf_type(Dwarf_Die *die, Dwarf_Die *target_die)
-+{
-+ Dwarf_Attribute type_ref_attr;
-+
-+ if (private_dwarf_attr(die, DW_AT_type, &type_ref_attr) != NULL) {
-+ if (dwarf_formref_die(&type_ref_attr, target_die) == NULL) {
-+ pr_err("Corrupt DWARF at offset %lx: ref with no target.\n",
-+ DIEOFFSET(die));
-+ exit(1);
-+ }
-+ return target_die;
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * Check for existence of an attribute in a DIE, chasing through
-+ * DW_AT_specification if need be.
-+ */
-+static inline int private_dwarf_hasattr(Dwarf_Die *die,
-+ unsigned int search_name)
-+{
-+ int hasattr = 0;
-+ Dwarf_Attribute spec_ref_attr;
-+ Dwarf_Die spec_die;
-+
-+ /*
-+ * DW_AT_declaration is not forwarded, because non-declarations can
-+ * reference declarations via DW_AT_specification, without implying that
-+ * the referencing DIE is a declaration.
-+ */
-+ hasattr = dwarf_hasattr(die, search_name);
-+ if (hasattr || (search_name == DW_AT_declaration))
-+ return hasattr;
-+
-+ if (dwarf_attr(die, DW_AT_specification, &spec_ref_attr) != NULL) {
-+ if (dwarf_formref_die(&spec_ref_attr, &spec_die) == NULL) {
-+ pr_err("Corrupt DWARF at offset %lx: ref with no target.\n",
-+ DIEOFFSET(die));
-+ exit(1);
-+ }
-+ return dwarf_hasattr(&spec_die, search_name);
-+ }
-+ return hasattr;
-+}
-+
-+/*
-+ * Return a DIE attribute, chasing through DW_AT_specification if need be.
-+ */
-+static inline Dwarf_Attribute *private_dwarf_attr(Dwarf_Die *die,
-+ unsigned int search_name,
-+ Dwarf_Attribute *result)
-+{
-+ Dwarf_Attribute spec_ref_attr;
-+ Dwarf_Die spec_die;
-+ Dwarf_Attribute *ret;
-+
-+ ret = dwarf_attr(die, search_name, result);
-+ if (ret != NULL || (search_name == DW_AT_declaration))
-+ return ret;
-+
-+ if (dwarf_attr(die, DW_AT_specification, &spec_ref_attr) != NULL) {
-+ if (dwarf_formref_die(&spec_ref_attr, &spec_die) == NULL) {
-+ pr_err("Corrupt DWARF at offset %lx: ref with no target.\n",
-+ DIEOFFSET(die));
-+ exit(1);
-+ }
-+ return dwarf_attr(&spec_die, search_name, result);
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * Given a DIE that contains a udata attribute, look up that attribute and
-+ * return its value (optionally overridden or modified by the die_overrides).
-+ */
-+static inline Dwarf_Word private_dwarf_udata(Dwarf_Die *die, int attribute,
-+ struct die_override *overrides)
-+{
-+ Dwarf_Attribute attr;
-+ Dwarf_Word value;
-+ struct die_override *override;
-+
-+ override = private_find_override(die, attribute, overrides);
-+
-+ if (override && override->op == DIE_OVERRIDE_REPLACE)
-+ return override->value;
-+
-+ private_dwarf_attr(die, attribute, &attr);
-+ dwarf_formudata(&attr, &value);
-+
-+ if (override)
-+ value += override->value;
-+
-+ return value;
-+}
-+
-+/*
-+ * Given a DIE, return its byte size, if known and interpretable, or -1
-+ * otherwise.
-+ */
-+static inline long long
-+private_dwarf_size(Dwarf_Die *die)
-+{
-+ Dwarf_Attribute size_attr;
-+
-+ if (private_dwarf_hasattr(die, DW_AT_byte_size)) {
-+ private_dwarf_attr(die, DW_AT_byte_size, &size_attr);
-+
-+ switch (dwarf_whatform(&size_attr)) {
-+ case DW_FORM_data1:
-+ case DW_FORM_data2:
-+ case DW_FORM_data4:
-+ case DW_FORM_data8:
-+ case DW_FORM_udata: {
-+ Dwarf_Word dw_size;
-+
-+ dwarf_formudata(&size_attr, &dw_size);
-+ return dw_size;
-+ }
-+ case DW_FORM_sdata: {
-+ Dwarf_Sword dw_size;
-+
-+ dwarf_formsdata(&size_attr, &dw_size);
-+ return dw_size;
-+ }
-+ }
-+ }
-+
-+ /*
-+ * exprloc or other type we don't know how to interpret yet.
-+ */
-+ return -1;
-+}
-+
-+/*
-+ * Find an override in an override list, walking up the chained overrides if
-+ * need be, until one is found.
-+ */
-+static struct die_override *
-+private_find_override(Dwarf_Die *die,
-+ int attribute,
-+ struct die_override *overrides)
-+{
-+ size_t i;
-+
-+ if (overrides == NULL)
-+ return NULL;
-+
-+ while (overrides) {
-+ struct die_override *chain = NULL;
-+ for (i = 0; overrides[i].tag != 0; i++) {
-+ chain = overrides[i].chain;
-+ if ((overrides[i].tag == dwarf_tag(die)) &&
-+ (overrides[i].attribute == attribute))
-+ return &overrides[i];
-+ }
-+ overrides = chain;
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * Determine the dimensions of an array subrange, or 0 if variable.
-+ */
-+static Dwarf_Word private_subrange_dimensions(Dwarf_Die *die)
-+{
-+ int flexible_array = 0;
-+ Dwarf_Attribute nelem_attr;
-+ Dwarf_Word nelems;
-+
-+ if (((private_dwarf_attr(die, DW_AT_upper_bound,
-+ &nelem_attr) == NULL) &&
-+ (private_dwarf_attr(die, DW_AT_count,
-+ &nelem_attr) == NULL)) ||
-+ (!private_dwarf_hasattr(die, DW_AT_type)))
-+ flexible_array = 1;
-+
-+ if (!flexible_array)
-+ switch (dwarf_whatform(&nelem_attr)) {
-+ case DW_FORM_data1:
-+ case DW_FORM_data2:
-+ case DW_FORM_data4:
-+ case DW_FORM_data8:
-+ case DW_FORM_udata:
-+ break;
-+ default:
-+ flexible_array = 1;
-+ }
-+
-+ if (flexible_array)
-+ return 0;
-+
-+ dwarf_formudata(&nelem_attr, &nelems);
-+
-+ /*
-+ * Upper bounds indicate that we have one more element than that, since
-+ * C starts counting at zero.
-+ */
-+ if (private_dwarf_hasattr(die, DW_AT_upper_bound))
-+ nelems++;
-+
-+ return nelems;
-+}
-+
-+/*
-+ * Intern an atom in the atoms table and return it, or free it and return the
-+ * existing atom if one is already interned. (Despite the type signature, this
-+ * return value is constant and should not be freed.)
-+ */
-+static void *intern(char *atom)
-+{
-+ void *foo;
-+
-+ if (!g_hash_table_lookup_extended(atoms, atom, &foo, NULL)) {
-+ g_hash_table_insert(atoms, atom, NULL);
-+ foo = atom;
-+ } else
-+ free(atom);
-+
-+ return foo;
-+}
-+
-+/*
-+ * An error checking strdup().
-+ */
-+static char *xstrdup(const char *s)
-+{
-+ char *s2 = strdup(s);
-+
-+ if (s2 == NULL) {
-+ pr_err("%s: Out of memory\n", __func__);
-+ exit(1);
-+ }
-+
-+ return s2;
-+}
-+
-+/*
-+ * A string appender working on dynamic strings.
-+ */
-+static char *str_append(char *s, const char *append)
-+{
-+ size_t s_len = 0;
-+
-+ if (append == NULL)
-+ return s;
-+
-+ if (s != NULL)
-+ s_len = strlen(s);
-+
-+ size_t append_len = strlen(append);
-+
-+ s = realloc(s, s_len + append_len + 1);
-+
-+ if (s == NULL) {
-+ pr_err("Out of memory appending a string of length %li to one of length %li\n",
-+ strlen(append), s_len);
-+ exit(1);
-+ }
-+
-+ memcpy(s + s_len, append, append_len);
-+ s[s_len+append_len] = '\0';
-+
-+ return s;
-+}
-+
-+/*
-+ * A vararg string appender.
-+ */
-+static char *str_appendn(char *s, ...)
-+{
-+ va_list ap;
-+ const char *append;
-+ size_t len, s_len = 0;
-+
-+ va_start(ap, s);
-+ if (s)
-+ s_len = strlen(s);
-+ len = s_len;
-+
-+ append = va_arg(ap, const char *);
-+ while (append != NULL) {
-+ len += strlen(append);
-+ append = va_arg(ap, char *);
-+ }
-+ va_end(ap);
-+
-+ s = realloc(s, len + 1);
-+ if (s == NULL) {
-+ pr_err("Out of memory appending a string of length %li to one of length %li\n",
-+ len - s_len, s_len);
-+ exit(1);
-+ }
-+
-+ va_start(ap, s);
-+ append = va_arg(ap, const char *);
-+ while (append != NULL) {
-+ size_t append_len = strlen(append);
-+
-+ memcpy(s + s_len, append, append_len);
-+ s_len += append_len;
-+
-+ append = va_arg(ap, char *);
-+ }
-+ s[len] = '\0';
-+ va_end(ap);
-+
-+ return s;
-+}
-+
-+/*
-+ * Filter a GList, calling a predicate on it and removing all elements for which
-+ * the predicate returns true, calling the free_func on them if set.
-+ */
-+static GList *list_filter(GList *list, filter_pred_fun fun,
-+ GDestroyNotify free_func, void *data)
-+{
-+ GList *cur = list;
-+
-+ while (cur) {
-+ GList *next = cur->next;
-+
-+ if (fun(cur->data, data)) {
-+ if (free_func)
-+ free_func(cur->data);
-+ list = g_list_delete_link(list, cur);
-+ }
-+ cur = next;
-+ }
-+
-+ return list;
-+}
-+
-+/*
-+ * Figure out the (pathless, suffixless) module name for a given module file (.o
-+ * or .ko), and return it in a new dynamically allocated string.
-+ *
-+ * Takes the object_to_module mapping into account.
-+ */
-+static char *fn_to_module(const char *file_name)
-+{
-+ char *module_name;
-+ char *chop, *dash;
-+
-+ module_name = g_hash_table_lookup(object_to_module, file_name);
-+ if (module_name != NULL)
-+ return xstrdup(module_name);
-+
-+ chop = strrchr(file_name, '/');
-+ if (chop != NULL)
-+ module_name = xstrdup(++chop);
-+ else
-+ module_name = xstrdup(file_name);
-+
-+ chop = strrchr(module_name, '.');
-+ if (chop != NULL)
-+ *chop = '\0';
-+
-+ dash = module_name;
-+ while (dash != NULL) {
-+ dash = strchr(dash, '-');
-+ if (dash != NULL)
-+ *dash = '_';
-+ }
-+
-+ return module_name;
-+}
-+
-+/*
-+ * Determine, and cache, absolute filenames. This is called in very hot
-+ * paths, notably type_id(), and must be kept fast.
-+ */
-+static const char *abs_file_name(const char *file_name)
-+{
-+ static GHashTable *abs_file_names;
-+ const char *abs_name;
-+
-+ if (abs_file_names == NULL)
-+ abs_file_names = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ free, free);
-+
-+ abs_name = g_hash_table_lookup(abs_file_names, file_name);
-+
-+ if (abs_name == NULL) {
-+ char abspath[PATH_MAX] = "";
-+
-+ if (realpath(file_name, abspath) == NULL)
-+ strcpy(abspath, file_name);
-+ g_hash_table_replace(abs_file_names,
-+ xstrdup(file_name), xstrdup(abspath));
-+
-+ abs_name = g_hash_table_lookup(abs_file_names, file_name);
-+ }
-+
-+ return abs_name;
-+}
-+
-+/*
-+ * Determine absolute filenames relative to some other directory. This does not
-+ * need to be fast. The returned name is dynamically allocated, and must be
-+ * freed by the caller.
-+ */
-+static char *rel_abs_file_name(const char *file_name, const char *relative_to)
-+{
-+ int dir = -1;
-+ static int warned = 0;
-+ char *abspath;
-+ /*
-+ * If we can't get this name relatively, we might as well *try* to do it
-+ * absolutely: but print a warning.
-+ */
-+ dir = open(".", O_RDONLY | O_DIRECTORY);
-+ if (dir < 0) {
-+ if (!warned) {
-+ perror("Cannot open current directory");
-+ warned = 1;
-+ }
-+ } else {
-+ if (chdir(relative_to) < 0)
-+ if (!warned) {
-+ pr_err("Cannot change directory to "
-+ "%s: %s\n", relative_to,
-+ strerror(errno));
-+ warned = 1;
-+ }
-+ }
-+
-+ abspath = realpath(file_name, NULL);
-+ if (abspath == NULL)
-+ abspath = xstrdup(file_name);
-+
-+ if ((dir > -1) && (fchdir(dir) < 0)) {
-+ perror("Cannot return to original directory after relative realpath()");
-+ exit(1);
-+ }
-+
-+ close(dir);
-+
-+ return abspath;
-+}
-+
-+/*
-+ * Given a type encoding table, and a size, return the CTF encoding for that
-+ * type, or 0 if none.
-+ */
-+static int find_ctf_encoding(struct type_encoding_tab *type_tab, size_t size)
-+{
-+ size_t i;
-+
-+ for (i = 0; type_tab[i].size != 0; i++) {
-+ if (type_tab[i].size == size)
-+ return type_tab[i].ctf_encoding;
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * Count the number of members of a DWARF aggregate.
-+ */
-+static long count_dwarf_members(Dwarf_Die *d)
-+{
-+ const char *err;
-+ Dwarf_Die die;
-+
-+ switch (dwarf_child(d, &die)) {
-+ case -1:
-+ err = "fetch first child of aggregate";
-+ goto fail;
-+ case 1: /* No DIEs at all in this aggregate */
-+ return 0;
-+ default: /* Child DIEs exist. */
-+ break;
-+ }
-+
-+ /*
-+ * We are only interested in children of type DW_TAG_member.
-+ */
-+ int sib_ret;
-+ long count = 0;
-+
-+ do
-+ if (dwarf_tag(&die) == DW_TAG_member)
-+ count++;
-+ while ((sib_ret = dwarf_siblingof(&die, &die)) == 0);
-+
-+ if (sib_ret == -1) {
-+ err = "count members";
-+ goto fail;
-+ }
-+
-+ return count;
-+
-+ fail:
-+ pr_err("Cannot %s: %s\n", err, dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * Free a per_module's contents.
-+ */
-+static void private_per_module_free(void *per_module)
-+{
-+ struct per_module *per_mod = per_module;
-+
-+ ctf_close(per_mod->ctf_file);
-+ g_hash_table_destroy(per_mod->member_counts);
-+ free(per_module);
-+}
-+
-+/*
-+ * Free a fn_to_die_to_parent subhash.
-+ */
-+static void private_fn_die_parent_free(void *ptr)
-+{
-+ g_hash_table_destroy((GHashTable *) ptr);
-+}
-+
-+/*
-+ * Get a ctf_file out of the per_module hash for a given module.
-+ */
-+static ctf_file_t *lookup_ctf_file(const char *module_name)
-+{
-+ struct per_module *per_mod;
-+
-+ per_mod = g_hash_table_lookup(per_module, module_name);
-+ if (per_mod == NULL)
-+ return NULL;
-+ return per_mod->ctf_file;
-+}
-diff --git a/scripts/dwarf2ctf/eu_simple.c b/scripts/dwarf2ctf/eu_simple.c
-new file mode 100644
-index 000000000000..49886e5e5411
---- /dev/null
-+++ b/scripts/dwarf2ctf/eu_simple.c
-@@ -0,0 +1,2 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+#include "../eu_simple.c"
-diff --git a/scripts/dwarf2ctf/member.blacklist b/scripts/dwarf2ctf/member.blacklist
-new file mode 100644
-index 000000000000..85122def7b5f
---- /dev/null
-+++ b/scripts/dwarf2ctf/member.blacklist
-@@ -0,0 +1 @@
-+include/linux/netfilter/ipset/ip_set_ahash.h:ip_set_hash.next
-diff --git a/scripts/eu_simple.c b/scripts/eu_simple.c
-new file mode 100644
-index 000000000000..e2736f29d001
---- /dev/null
-+++ b/scripts/eu_simple.c
-@@ -0,0 +1,356 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Convenience wrappers for functions in elfutils.
-+ *
-+ * (C) 2014, 2017 Oracle, Inc. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#include <errno.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+
-+#include <elfutils/libdwfl.h>
-+#include <elfutils/version.h>
-+
-+#include <eu_simple.h>
-+
-+#define __unused__ __attribute__((__unused__))
-+
-+/*
-+ * A version of dwfl_report_elf() that compensates for parameter changes in
-+ * newer elfutils.
-+ */
-+static Dwfl_Module *private_dwfl_report_elf(Dwfl *dwfl, const char *name,
-+ const char *file_name, int fd,
-+ GElf_Addr base)
-+{
-+#if _ELFUTILS_PREREQ(0,156)
-+ return dwfl_report_elf(dwfl, name, file_name, fd, base, 0);
-+#else
-+ return dwfl_report_elf(dwfl, name, file_name, fd, base);
-+#endif
-+}
-+
-+/*
-+ * Stub libdwfl callback, use only the ELF handle passed in.
-+ */
-+static int no_debuginfo(Dwfl_Module *mod __unused__,
-+ void **userdata __unused__,
-+ const char *modname __unused__,
-+ Dwarf_Addr base __unused__,
-+ const char *file_name __unused__,
-+ const char *debuglink_file __unused__,
-+ GElf_Word debuglink_crc __unused__,
-+ char **debuginfo_file_name __unused__)
-+{
-+ return -1;
-+}
-+
-+/*
-+ * Wrap up dwfl_new() complexities.
-+ */
-+Dwfl *simple_dwfl_new(const char *file_name, Dwfl_Module **module)
-+{
-+ const char *err;
-+
-+ static Dwfl_Callbacks cb = {
-+ .find_debuginfo = no_debuginfo,
-+ .section_address = dwfl_offline_section_address
-+ };
-+ Dwfl *dwfl = dwfl_begin(&cb);
-+ Dwfl_Module *mod;
-+
-+ if (dwfl == NULL) {
-+ err = "initialize libdwfl";
-+ goto fail;
-+ }
-+
-+ mod = private_dwfl_report_elf(dwfl, "", file_name, -1, 0);
-+ if (mod == NULL) {
-+ err = "open object file with libdwfl";
-+ goto fail;
-+ }
-+ if (module)
-+ *module = mod;
-+
-+ if (dwfl_report_end(dwfl, NULL, NULL) != 0) {
-+ err = "finish opening object file with libdwfl";
-+ goto fail;
-+ }
-+
-+ return dwfl;
-+ fail:
-+ fprintf(stderr, "Cannot %s for %s: %s\n", err, file_name,
-+ dwfl_errmsg(dwfl_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * A variant of simple_dwfl_new() that iterates over multiple object files.
-+ * (Used for thin archives.)
-+ *
-+ * Takes ownership of the paths, until free.
-+ */
-+struct simple_dwfl_multi *
-+simple_dwfl_new_multi(char **paths)
-+{
-+ struct simple_dwfl_multi *multi;
-+
-+ multi = malloc(sizeof(struct simple_dwfl_multi));
-+ if (multi == NULL)
-+ return NULL;
-+
-+ multi->paths = paths;
-+ multi->i = -1;
-+ multi->dwfl = NULL;
-+ multi->last_die = NULL;
-+
-+ return multi;
-+}
-+
-+/*
-+ * A variant of dwfl_nextcu() that crosses file boundaries as needed,
-+ * using the state in the simple_dwfl_multi.
-+ */
-+Dwarf_Die *
-+simple_dwfl_nextcu(struct simple_dwfl_multi *multi)
-+{
-+ Dwarf_Addr junk;
-+
-+ /*
-+ * Switch object files as needed (and always, the first time).
-+ */
-+
-+ if (multi->i >= 0)
-+ multi->last_die = dwfl_nextcu(multi->dwfl, multi->last_die,
-+ &junk);
-+
-+ while (multi->last_die == NULL) {
-+ simple_dwfl_free(multi->dwfl);
-+ if (multi->paths[++multi->i] == NULL) {
-+ multi->i = -1;
-+ multi->dwfl = NULL;
-+ multi->last_die = NULL;
-+ return NULL;
-+ }
-+
-+ multi->dwfl = simple_dwfl_new(multi->paths[multi->i], NULL);
-+ multi->last_die = dwfl_nextcu(multi->dwfl, multi->last_die,
-+ &junk);
-+ }
-+ return multi->last_die;
-+}
-+
-+/*
-+ * Free a simple_dwfl_new_multi: return its contained paths so the caller can
-+ * free them again. (They are not changed, so the caller can just hang on to
-+ * them if preferred.)
-+ */
-+char **
-+simple_dwfl_free_multi(struct simple_dwfl_multi *multi)
-+{
-+ char **paths = multi->paths;
-+ simple_dwfl_free(multi->dwfl);
-+ free(multi);
-+ return paths;
-+}
-+
-+/*
-+ * The converse of simple_dwfl_new().
-+ */
-+void simple_dwfl_free(Dwfl *dwfl)
-+{
-+ if (dwfl != NULL) {
-+ dwfl_report_end(dwfl, NULL, NULL);
-+ dwfl_end(dwfl);
-+ }
-+}
-+
-+
-+/*
-+ * Read a modules_thick.builtin file and translate it into a stream of
-+ * arguments suitable for simple_dwfl_new_multi().
-+ */
-+
-+/*
-+ * Construct a modules_thick.builtin iterator.
-+ */
-+struct modules_thick_iter *
-+modules_thick_iter_new(const char *modules_thick_file)
-+{
-+ struct modules_thick_iter *i;
-+
-+ i = calloc(1, sizeof(struct modules_thick_iter));
-+ if (i == NULL)
-+ return NULL;
-+
-+ i->f = fopen(modules_thick_file, "r");
-+
-+ if (i->f == NULL) {
-+ fprintf(stderr, "Cannot open builtin module file %s: %s\n",
-+ modules_thick_file, strerror(errno));
-+ return NULL;
-+ }
-+
-+ return i;
-+}
-+
-+/*
-+ * Iterate, returning a new null-terminated array of object file names, and a
-+ * new dynamically-allocated module name. (The module name passed in is freed.)
-+ *
-+ * The array of object file names should be freed by the caller: the strings it
-+ * points to are owned by the iterator, and should not be freed.
-+ */
-+
-+char ** __attribute__((__nonnull__))
-+modules_thick_iter_next(struct modules_thick_iter *i, char **module_name)
-+{
-+ size_t npaths = 1;
-+ char **module_paths;
-+ char *last_slash;
-+ char *last_dot;
-+ char *trailing_linefeed;
-+ char *object_name = i->line;
-+ char *dash;
-+ int composite = 0;
-+
-+ /*
-+ * Read in all module entries, computing the suffixless, pathless name
-+ * of the module and building the next arrayful of object file names for
-+ * return.
-+ *
-+ * Modules can consist of multiple files: in this case, the portion
-+ * before the colon is the path to the module (as before): the portion
-+ * after the colon is a space-separated list of files that should be *
-+ * considered part of this module. In this case, the portion before the
-+ * name is an "object file" that does not actually exist: it is merged
-+ * into built-in.a without ever being written out.
-+ *
-+ * All module names have - translated to _, to match what is done to the
-+ * names of the same things when built as modules.
-+ */
-+
-+ /*
-+ * Reinvocation of exhausted iterator. Return NULL, once.
-+ */
-+retry:
-+ if (getline(&i->line, &i->line_size, i->f) < 0) {
-+ if (ferror(i->f)) {
-+ fprintf(stderr, "Error reading from modules_thick file:"
-+ " %s\n", strerror(errno));
-+ exit(1);
-+ }
-+ rewind(i->f);
-+ return NULL;
-+ }
-+
-+ if (i->line[0] == '\0')
-+ goto retry;
-+
-+ /*
-+ * Slice the line in two at the colon, if any. If there is anything
-+ * past the ': ', this is a composite module. (We allow for no colon
-+ * for robustness, even though one should always be present.)
-+ */
-+ if (strchr(i->line, ':') != NULL) {
-+ char *name_start;
-+
-+ object_name = strchr(i->line, ':');
-+ *object_name = '\0';
-+ object_name++;
-+ name_start = object_name + strspn(object_name, " \n");
-+ if (*name_start != '\0') {
-+ composite = 1;
-+ object_name = name_start;
-+ }
-+ }
-+
-+ /*
-+ * Figure out the module name.
-+ */
-+ last_slash = strrchr(i->line, '/');
-+ last_slash = (!last_slash) ? i->line :
-+ last_slash + 1;
-+ free(*module_name);
-+ *module_name = strdup(last_slash);
-+ dash = *module_name;
-+
-+ while (dash != NULL) {
-+ dash = strchr(dash, '-');
-+ if (dash != NULL)
-+ *dash = '_';
-+ }
-+
-+ last_dot = strrchr(*module_name, '.');
-+ if (last_dot != NULL)
-+ *last_dot = '\0';
-+
-+ trailing_linefeed = strchr(object_name, '\n');
-+ if (trailing_linefeed != NULL)
-+ *trailing_linefeed = '\0';
-+
-+ /*
-+ * Multifile separator? Object file names explicitly stated:
-+ * slice them up and shuffle them in.
-+ *
-+ * The array size may be an overestimate if any object file
-+ * names start or end with spaces (very unlikely) but cannot be
-+ * an underestimate. (Check for it anyway.)
-+ */
-+ if (composite) {
-+ char *one_object;
-+
-+ for (npaths = 0, one_object = object_name;
-+ one_object != NULL;
-+ npaths++, one_object = strchr(one_object + 1, ' '));
-+ }
-+
-+ module_paths = malloc((npaths + 1) * sizeof(char *));
-+ if (!module_paths) {
-+ fprintf(stderr, "%s: out of memory on module %s\n", __func__,
-+ *module_name);
-+ exit(1);
-+ }
-+
-+ if (composite) {
-+ char *one_object;
-+ size_t i = 0;
-+
-+ while ((one_object = strsep(&object_name, " ")) != NULL) {
-+ if (i >= npaths) {
-+ fprintf(stderr, "%s: num_objs overflow on module "
-+ "%s: this is a bug.\n", __func__,
-+ *module_name);
-+ exit(1);
-+ }
-+
-+ module_paths[i++] = one_object;
-+ }
-+ } else
-+ module_paths[0] = i->line; /* untransformed module name */
-+
-+ module_paths[npaths] = NULL;
-+
-+ return module_paths;
-+}
-+
-+/*
-+ * Free an iterator. Can be called while iteration is underway, so even
-+ * state that is freed at the end of iteration must be freed here too.
-+ */
-+void
-+modules_thick_iter_free(struct modules_thick_iter *i)
-+{
-+ if (i == NULL)
-+ return;
-+ fclose(i->f);
-+ free(i->line);
-+ free(i);
-+}
-diff --git a/scripts/eu_simple.h b/scripts/eu_simple.h
-new file mode 100644
-index 000000000000..8ef9f9655077
---- /dev/null
-+++ b/scripts/eu_simple.h
-@@ -0,0 +1,91 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Simplifying wrappers for functions in elfutils, and functions to
-+ * feed them data.
-+ *
-+ * (C) 2014, 2017 Oracle, Inc. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_EU_SIMPLE_H
-+#define _LINUX_EU_SIMPLE_H
-+
-+#include <stdio.h>
-+#include <stddef.h>
-+#include <elfutils/libdwfl.h>
-+
-+/*
-+ * Iteration state for simple_dwfl_new_multi().
-+ */
-+struct simple_dwfl_multi {
-+ char **paths;
-+ ssize_t i;
-+ Dwfl *dwfl;
-+ Dwarf_Die *last_die;
-+};
-+
-+/*
-+ * Wrap up dwfl_new() complexities.
-+ */
-+Dwfl *simple_dwfl_new(const char *file_name, Dwfl_Module **module);
-+
-+/*
-+ * A variant of simple_dwfl_new() that iterates over multiple object files.
-+ * (Used for thin archives.)
-+ *
-+ * Takes ownership of the paths, until free.
-+ */
-+struct simple_dwfl_multi *simple_dwfl_new_multi(char **paths);
-+
-+/*
-+ * A variant of dwfl_nextcu() that crosses file boundaries as needed,
-+ * using the state in the simple_dwfl_multi.
-+ */
-+Dwarf_Die *simple_dwfl_nextcu(struct simple_dwfl_multi *multi);
-+
-+/*
-+ * Free a simple_dwfl_new_multi: return its contained paths so the caller
-+ * free them again. (They are not changed, so the caller can just hang on to
-+ * them if preferred.)
-+ */
-+char **simple_dwfl_free_multi(struct simple_dwfl_multi *multi);
-+
-+/*
-+ * The converse of simple_dwfl_new().
-+ */
-+void simple_dwfl_free(Dwfl *dwfl);
-+
-+/*
-+ * modules_thick.builtin iteration state.
-+ */
-+struct modules_thick_iter {
-+ FILE *f;
-+ char *line;
-+ size_t line_size;
-+};
-+
-+/*
-+ * Construct a modules_thick.builtin iterator.
-+ */
-+struct modules_thick_iter *
-+modules_thick_iter_new(const char *modules_thick_file);
-+
-+/*
-+ * Iterate, returning a new null-terminated array of object file names, and a
-+ * new dynamically-allocated module name. (The module name passed in is freed.)
-+ *
-+ * The array of object file names should be freed by the caller: the strings it
-+ * points to are owned by the iterator, and should not be freed.
-+ */
-+
-+char ** __attribute__((__nonnull__))
-+modules_thick_iter_next(struct modules_thick_iter *i, char **module_name);
-+
-+void
-+modules_thick_iter_free(struct modules_thick_iter *i);
-+
-+#endif
-diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
-index a39d93e3c6ae..12445a834698 100644
---- a/scripts/kconfig/confdata.c
-+++ b/scripts/kconfig/confdata.c
-@@ -710,6 +710,25 @@ static struct conf_printer header_printer_cb =
- .print_comment = header_print_comment,
- };
-
-+/*
-+ * Tristate printer
-+ *
-+ * This printer is used when generating the `include/config/tristate.conf' file.
-+ */
-+static void
-+tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
-+{
-+
-+ if (sym->type == S_TRISTATE && *value != 'n')
-+ fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
-+}
-+
-+static struct conf_printer tristate_printer_cb =
-+{
-+ .print_symbol = tristate_print_symbol,
-+ .print_comment = kconfig_print_comment,
-+};
-+
- static void conf_write_symbol(FILE *fp, struct symbol *sym,
- struct conf_printer *printer, void *printer_arg)
- {
-@@ -1043,7 +1062,7 @@ int conf_write_autoconf(int overwrite)
- struct symbol *sym;
- const char *name;
- const char *autoconf_name = conf_get_autoconfig_name();
-- FILE *out, *out_h;
-+ FILE *out, *tristate, *out_h;
- int i;
-
- if (!overwrite && is_present(autoconf_name))
-@@ -1058,6 +1077,13 @@ int conf_write_autoconf(int overwrite)
- if (!out)
- return 1;
-
-+ tristate = fopen(".tmpconfig_tristate", "w");
-+ if (!tristate) {
-+ fclose(out);
-+ fclose(tristate);
-+ return 1;
-+ }
-+
- out_h = fopen(".tmpconfig.h", "w");
- if (!out_h) {
- fclose(out);
-@@ -1065,6 +1091,7 @@ int conf_write_autoconf(int overwrite)
- }
-
- conf_write_heading(out, &kconfig_printer_cb, NULL);
-+ conf_write_heading(tristate, &tristate_printer_cb, NULL);
- conf_write_heading(out_h, &header_printer_cb, NULL);
-
- for_all_symbols(i, sym) {
-@@ -1072,11 +1099,13 @@ int conf_write_autoconf(int overwrite)
- if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
- continue;
-
-- /* write symbols to auto.conf and autoconf.h */
-+ /* write symbols to auto.conf, tristate and header files */
- conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
-+ conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
- conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
- }
- fclose(out);
-+ fclose(tristate);
- fclose(out_h);
-
- name = getenv("KCONFIG_AUTOHEADER");
-@@ -1087,6 +1116,14 @@ int conf_write_autoconf(int overwrite)
- if (rename(".tmpconfig.h", name))
- return 1;
-
-+ name = getenv("KCONFIG_TRISTATE");
-+ if (!name)
-+ name = "include/config/tristate.conf";
-+ if (make_parent_dir(name))
-+ return 1;
-+ if (rename(".tmpconfig_tristate", name))
-+ return 1;
-+
- if (make_parent_dir(autoconf_name))
- return 1;
- /*
-diff --git a/scripts/move-if-change b/scripts/move-if-change
-new file mode 100755
-index 000000000000..eb745af5d972
---- /dev/null
-+++ b/scripts/move-if-change
-@@ -0,0 +1,8 @@
-+#!/bin/sh
-+# SPDX-License-Identifier: GPL-2.0+
-+
-+if test -r "$2" && cmp -s "$1" "$2"; then
-+ rm -f "$1"
-+else
-+ mv -f "$1" "$2"
-+fi
-diff --git a/scripts/package/mkspec b/scripts/package/mkspec
-index 7c477ca7dc98..e9ff22c6fb4c 100755
---- a/scripts/package/mkspec
-+++ b/scripts/package/mkspec
-@@ -27,6 +27,13 @@ if grep -q CONFIG_DRM=y .config; then
- PROVIDES=kernel-drm
- fi
-
-+# set CTF when configured
-+if grep -q CONFIG_CTF=y .config; then
-+ C=
-+else
-+ C=DEL
-+fi
-+
- PROVIDES="$PROVIDES kernel-$KERNELRELEASE"
- __KERNELRELEASE=$(echo $KERNELRELEASE | sed -e "s/-/_/g")
- EXCLUDES="$RCS_TAR_IGNORE --exclude=*vmlinux* --exclude=*.mod \
-@@ -38,6 +45,7 @@ EXCLUDES="$RCS_TAR_IGNORE --exclude=*vmlinux* --exclude=*.mod \
- # Labels:
- # $S: this line is enabled only when building source package
- # $M: this line is enabled only when CONFIG_MODULES is enabled
-+# $C: this line is enabled only when CONFIG_CTF is enabled
- sed -e '/^DEL/d' -e 's/^\t*//' <<EOF
- Name: kernel
- Summary: The Linux Kernel
-@@ -48,6 +56,8 @@ sed -e '/^DEL/d' -e 's/^\t*//' <<EOF
- Vendor: The Linux Community
- URL: https://www.kernel.org
- $S Source: kernel-$__KERNELRELEASE.tar.gz
-+$C BuildRequires: libdtrace-ctf >= 0.5.0
-+$C BuildRequires: libdtrace-ctf-devel >= 0.5.0
- Provides: $PROVIDES
- %define __spec_install_post /usr/lib/rpm/brp-compress || :
- %define debug_package %{nil}
-@@ -74,12 +84,14 @@ $S$M AutoReqProv: no
- $S$M %description -n kernel-devel
- $S$M This package provides kernel headers and makefiles sufficient to build modules
- $S$M against the $__KERNELRELEASE kernel package.
-+$C Requires: libdtrace-ctf >= 0.5.0
- $S$M
- $S %prep
- $S %setup -q
- $S
- $S %build
- $S $MAKE %{?_smp_mflags} KBUILD_BUILD_VERSION=%{release}
-+$S$C $MAKE %{?_smp_mflags} ctf
- $S
- %install
- mkdir -p %{buildroot}/boot
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch
deleted file mode 100644
index 63777d375446..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch
+++ /dev/null
@@ -1,1050 +0,0 @@
-From 6ded42dd15783a073c9a15ad4abae87bcf234c40 Mon Sep 17 00:00:00 2001
-From: Nick Alcock <nick.alcock@oracle.com>
-Date: Wed, 14 Nov 2018 20:09:28 +0000
-Subject: [PATCH 02/19] kallsyms: introduce new /proc/kallmodsyms including
- builtin modules too
-
-/proc/kallsyms is very useful for tracers and other tools that need to
-map kernel symbols to addresses (sinful though it is to export such
-addresses to userspace). However, for some uses it does not suffice.
-We would like to be able to establish a mapping between module name and
-kernel symbol that only changes when the kernel source code is changed:
-if the kernel is recompiled so that some module becomes built in, it is
-a desirable property for portability of tracing scripts that can include
-module names if the name of this module does not change.
-
-i.e., as with the previous dwarf2ctf commit, we would like to report
-e.g. ext4 symbols as residing in [ext4] even if ext4 happens to be built
-into the kernel: it is enough that it *could* be built as a module.
-
-We use machinery shared with dwarf2ctf (in eu_simple.c) in conjunction
-with a link map to compute the mapping from the address ranges
-associated with built-in object files in vmlinux.o to module names, then
-drop a list of these modules and pointers into that list into new
-kallsyms sections (kallsyms_modules and kallsyms_symbol_modules).
-
-We also need symbol sizes to determine whether a given probe hit is
-within a symbol or outside it (possibly miles outside it in a gap
-between symbols). Adding that is much simpler, with only one new
-section, kallsyms_sizes.
-
-The resulting file looks like this:
-
-ffffffff8b013d20 409 t pt_buffer_setup_aux
-ffffffff8b014130 11f T intel_pt_interrupt
-ffffffff8b014250 2d T cpu_emergency_stop_pt
-ffffffff8b014280 13a t rapl_pmu_event_init [intel_rapl_perf]
-ffffffff8b0143c0 bb t rapl_event_update [intel_rapl_perf]
-ffffffff8b014480 10 t rapl_pmu_event_read [intel_rapl_perf]
-ffffffff8b014490 a3 t rapl_cpu_offline [intel_rapl_perf]
-ffffffff8b014540 24 t __rapl_event_show [intel_rapl_perf]
-ffffffff8b014570 f2 t rapl_pmu_event_stop [intel_rapl_perf]
-
-This is emitted even if intel_rapl_perf is built into the kernel.
-
-As with /proc/kallsyms, non-root usage produces addresses that are
-all-zero. (I am amenable to producing all-zero sizes, too, but without
-the addresses this seems like pure paranoia.)
-
-Programs that consume /proc/kallmodsyms should note that unlike
-/proc/kallsyms, kernel symbols for built-in modules may appear
-interspersed with other symbols that are part of different modules or
-part of no module at all.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- Makefile | 2 +-
- include/linux/kallsyms.h | 21 +++
- include/linux/module.h | 7 +-
- init/Kconfig | 10 ++
- kernel/kallsyms.c | 163 +++++++++++++--------
- kernel/module.c | 4 +-
- scripts/Makefile | 10 ++
- scripts/kallsyms.c | 301 +++++++++++++++++++++++++++++++++++++--
- scripts/link-vmlinux.sh | 22 ++-
- 9 files changed, 466 insertions(+), 74 deletions(-)
-
-diff --git a/Makefile b/Makefile
-index e94e5bfc9c4f..c21d2a09c9ca 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1406,7 +1406,7 @@ modules.order: $(subdir-modorder) FORCE
-
- targets += modules.order
-
--ifneq (CONFIG_CTF@,'@')
-+ifneq (CONFIG_CTF@CONFIG_KALLMODSYMS,'@')
-
- # We need to force everything to be built, since we need the .o files below.
- KBUILD_BUILTIN := 1
-diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
-index 481273f0c72d..1246b75f5c57 100644
---- a/include/linux/kallsyms.h
-+++ b/include/linux/kallsyms.h
-@@ -8,6 +8,7 @@
-
- #include <linux/errno.h>
- #include <linux/kernel.h>
-+#include <linux/module.h>
- #include <linux/stddef.h>
- #include <linux/mm.h>
- #include <linux/module.h>
-@@ -72,6 +73,24 @@ static inline void *dereference_symbol_descriptor(void *ptr)
- }
-
- #ifdef CONFIG_KALLSYMS
-+/* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
-+struct kallsym_iter {
-+ loff_t pos;
-+ loff_t pos_arch_end;
-+ loff_t pos_mod_end;
-+ loff_t pos_ftrace_mod_end;
-+ loff_t pos_bpf_end;
-+ unsigned long value;
-+ unsigned int nameoff; /* If iterating in core kernel symbols. */
-+ unsigned long size;
-+ char type;
-+ char name[KSYM_NAME_LEN];
-+ char module_name[MODULE_NAME_LEN];
-+ int builtin_module;
-+ int exported;
-+ int show_value;
-+};
-+
- /* Lookup the address for a symbol. Returns 0 if not found. */
- unsigned long kallsyms_lookup_name(const char *name);
-
-@@ -101,6 +120,8 @@ int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *
- /* How and when do we show kallsyms values? */
- extern bool kallsyms_show_value(const struct cred *cred);
-
-+extern void kallsyms_iter_reset(struct kallsym_iter *, loff_t);
-+extern int kallsyms_iter_update(struct kallsym_iter *, loff_t);
- #else /* !CONFIG_KALLSYMS */
-
- static inline unsigned long kallsyms_lookup_name(const char *name)
-diff --git a/include/linux/module.h b/include/linux/module.h
-index 6264617bab4d..d44fe50d7c7f 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -599,7 +599,8 @@ struct symsearch {
- /* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
- symnum out of range. */
- int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
-- char *name, char *module_name, int *exported);
-+ char *name, char *module_name, unsigned long *size,
-+ int *exported);
-
- /* Look for this name: can be of form module:name. */
- unsigned long module_kallsyms_lookup_name(const char *name);
-@@ -780,8 +781,8 @@ static inline int lookup_module_symbol_attrs(unsigned long addr, unsigned long *
- }
-
- static inline int module_get_kallsym(unsigned int symnum, unsigned long *value,
-- char *type, char *name,
-- char *module_name, int *exported)
-+ char *type, char *name, char *module_name,
-+ unsigned long *size, int *exported)
- {
- return -ERANGE;
- }
-diff --git a/init/Kconfig b/init/Kconfig
-index 0872a5a2e759..05d377ccc0e0 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1472,6 +1472,16 @@ config POSIX_TIMERS
-
- If unsure say y.
-
-+config KALLMODSYMS
-+ default y
-+ bool "Enable support for /proc/kallmodsyms" if EXPERT
-+ depends on KALLSYMS
-+ help
-+ This option enables the /proc/kallmodsyms file, which maps symbols
-+ to addresses and their associated modules. This support requires
-+ a fairly recent elfutils: 0.152 -- 0.172 have been tested.
-+ elfutils before 0.142 will definitely not work.
-+
- config PRINTK
- default y
- bool "Enable support for printk" if EXPERT
-diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
-index fe9de067771c..7371f8f9cf74 100644
---- a/kernel/kallsyms.c
-+++ b/kernel/kallsyms.c
-@@ -33,6 +33,7 @@
- */
- extern const unsigned long kallsyms_addresses[] __weak;
- extern const int kallsyms_offsets[] __weak;
-+extern const unsigned long kallsyms_sizes[] __weak;
- extern const u8 kallsyms_names[] __weak;
-
- /*
-@@ -47,6 +48,8 @@ __section(".rodata") __attribute__((weak));
-
- extern const char kallsyms_token_table[] __weak;
- extern const u16 kallsyms_token_index[] __weak;
-+extern const char kallsyms_modules[] __weak;
-+extern const u32 kallsyms_symbol_modules[] __weak;
-
- extern const unsigned int kallsyms_markers[] __weak;
-
-@@ -195,12 +198,24 @@ int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
- return module_kallsyms_on_each_symbol(fn, data);
- }
-
-+/*
-+ * The caller passes in an address, and we return an index to the symbol --
-+ * potentially also size and offset information.
-+ * But an address might map to multiple symbols because:
-+ * - some symbols might have zero size
-+ * - some symbols might be aliases of one another
-+ * - some symbols might span (encompass) others
-+ * The symbols should already be ordered so that, for a particular address,
-+ * we first have the zero-size ones, then the biggest, then the smallest.
-+ * So we find the index by:
-+ * - finding the last symbol with the target address
-+ * - backing the index up so long as both the address and size are unchanged
-+ */
- static unsigned long get_symbol_pos(unsigned long addr,
- unsigned long *symbolsize,
- unsigned long *offset)
- {
-- unsigned long symbol_start = 0, symbol_end = 0;
-- unsigned long i, low, high, mid;
-+ unsigned long low, high, mid;
-
- /* This kernel should never had been booted. */
- if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
-@@ -221,36 +236,17 @@ static unsigned long get_symbol_pos(unsigned long addr,
- }
-
- /*
-- * Search for the first aliased symbol. Aliased
-- * symbols are symbols with the same address.
-+ * Search for the first aliased symbol.
- */
-- while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low))
-+ while (low
-+ && kallsyms_sym_address(low-1) == kallsyms_sym_address(low)
-+ && kallsyms_sizes[low-1] == kallsyms_sizes[low])
- --low;
-
-- symbol_start = kallsyms_sym_address(low);
--
-- /* Search for next non-aliased symbol. */
-- for (i = low + 1; i < kallsyms_num_syms; i++) {
-- if (kallsyms_sym_address(i) > symbol_start) {
-- symbol_end = kallsyms_sym_address(i);
-- break;
-- }
-- }
--
-- /* If we found no next symbol, we use the end of the section. */
-- if (!symbol_end) {
-- if (is_kernel_inittext(addr))
-- symbol_end = (unsigned long)_einittext;
-- else if (IS_ENABLED(CONFIG_KALLSYMS_ALL))
-- symbol_end = (unsigned long)_end;
-- else
-- symbol_end = (unsigned long)_etext;
-- }
--
- if (symbolsize)
-- *symbolsize = symbol_end - symbol_start;
-+ *symbolsize = kallsyms_sizes[low];
- if (offset)
-- *offset = addr - symbol_start;
-+ *offset = addr - kallsyms_sym_address(low);
-
- return low;
- }
-@@ -270,6 +266,7 @@ int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
- return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) ||
- !!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
- }
-+EXPORT_SYMBOL_GPL(kallsyms_lookup_size_offset);
-
- /*
- * Lookup an address
-@@ -432,22 +429,6 @@ int sprint_backtrace(char *buffer, unsigned long address)
- return __sprint_symbol(buffer, address, -1, 1);
- }
-
--/* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
--struct kallsym_iter {
-- loff_t pos;
-- loff_t pos_arch_end;
-- loff_t pos_mod_end;
-- loff_t pos_ftrace_mod_end;
-- loff_t pos_bpf_end;
-- unsigned long value;
-- unsigned int nameoff; /* If iterating in core kernel symbols. */
-- char type;
-- char name[KSYM_NAME_LEN];
-- char module_name[MODULE_NAME_LEN];
-- int exported;
-- int show_value;
--};
--
- int __weak arch_get_kallsym(unsigned int symnum, unsigned long *value,
- char *type, char *name)
- {
-@@ -473,7 +454,9 @@ static int get_ksymbol_mod(struct kallsym_iter *iter)
- int ret = module_get_kallsym(iter->pos - iter->pos_arch_end,
- &iter->value, &iter->type,
- iter->name, iter->module_name,
-- &iter->exported);
-+ &iter->size, &iter->exported);
-+ iter->builtin_module = 0;
-+
- if (ret < 0) {
- iter->pos_mod_end = iter->pos;
- return 0;
-@@ -536,10 +519,22 @@ static int get_ksymbol_kprobe(struct kallsym_iter *iter)
- static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
- {
- unsigned off = iter->nameoff;
-+ u32 mod_index = 0;
-+
-+ if (kallsyms_symbol_modules)
-+ mod_index = kallsyms_symbol_modules[iter->pos];
-
-- iter->module_name[0] = '\0';
-+ if (mod_index == 0 || kallsyms_modules == NULL) {
-+ iter->module_name[0] = '\0';
-+ iter->builtin_module = 0;
-+ } else {
-+ strcpy(iter->module_name, &kallsyms_modules[mod_index]);
-+ iter->builtin_module = 1;
-+ }
-+ iter->exported = 0;
- iter->value = kallsyms_sym_address(iter->pos);
-
-+ iter->size = kallsyms_sizes[iter->pos];
- iter->type = kallsyms_get_symbol_type(off);
-
- off = kallsyms_expand_symbol(off, iter->name, ARRAY_SIZE(iter->name));
-@@ -547,7 +542,7 @@ static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
- return off - iter->nameoff;
- }
-
--static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
-+void kallsyms_iter_reset(struct kallsym_iter *iter, loff_t new_pos)
- {
- iter->name[0] = '\0';
- iter->nameoff = get_symbol_offset(new_pos);
-@@ -559,6 +554,7 @@ static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
- iter->pos_bpf_end = 0;
- }
- }
-+EXPORT_SYMBOL_GPL(kallsyms_iter_reset);
-
- /*
- * The end position (last + 1) of each additional kallsyms section is recorded
-@@ -589,7 +585,7 @@ static int update_iter_mod(struct kallsym_iter *iter, loff_t pos)
- }
-
- /* Returns false if pos at or past end of file. */
--static int update_iter(struct kallsym_iter *iter, loff_t pos)
-+int kallsyms_iter_update(struct kallsym_iter *iter, loff_t pos)
- {
- /* Module symbols can be accessed randomly. */
- if (pos >= kallsyms_num_syms)
-@@ -597,26 +593,27 @@ static int update_iter(struct kallsym_iter *iter, loff_t pos)
-
- /* If we're not on the desired position, reset to new position. */
- if (pos != iter->pos)
-- reset_iter(iter, pos);
-+ kallsyms_iter_reset(iter, pos);
-
- iter->nameoff += get_ksymbol_core(iter);
- iter->pos++;
-
- return 1;
- }
-+EXPORT_SYMBOL_GPL(kallsyms_iter_update);
-
- static void *s_next(struct seq_file *m, void *p, loff_t *pos)
- {
- (*pos)++;
-
-- if (!update_iter(m->private, *pos))
-+ if (!kallsyms_iter_update(m->private, *pos))
- return NULL;
- return p;
- }
-
- static void *s_start(struct seq_file *m, loff_t *pos)
- {
-- if (!update_iter(m->private, *pos))
-+ if (!kallsyms_iter_update(m->private, *pos))
- return NULL;
- return m->private;
- }
-@@ -625,7 +622,7 @@ static void s_stop(struct seq_file *m, void *p)
- {
- }
-
--static int s_show(struct seq_file *m, void *p)
-+static int s_show_internal(struct seq_file *m, void *p, int builtin_modules)
- {
- void *value;
- struct kallsym_iter *iter = m->private;
-@@ -636,7 +633,9 @@ static int s_show(struct seq_file *m, void *p)
-
- value = iter->show_value ? (void *)iter->value : NULL;
-
-- if (iter->module_name[0]) {
-+ if ((iter->builtin_module == 0 && iter->module_name[0]) ||
-+ (iter->builtin_module != 0 && iter->module_name[0] &&
-+ builtin_modules != 0)) {
- char type;
-
- /*
-@@ -645,14 +644,32 @@ static int s_show(struct seq_file *m, void *p)
- */
- type = iter->exported ? toupper(iter->type) :
- tolower(iter->type);
-- seq_printf(m, "%px %c %s\t[%s]\n", value,
-- type, iter->name, iter->module_name);
-- } else
-+ if (builtin_modules)
-+ seq_printf(m, "%px %lx %c %s\t[%s]\n", value,
-+ iter->size, type, iter->name,
-+ iter->module_name);
-+ else
-+ seq_printf(m, "%px %c %s\t[%s]\n", value,
-+ type, iter->name, iter->module_name);
-+ } else if (builtin_modules)
-+ seq_printf(m, "%px %lx %c %s\n", value, iter->size,
-+ iter->type, iter->name);
-+ else
- seq_printf(m, "%px %c %s\n", value,
- iter->type, iter->name);
- return 0;
- }
-
-+static int s_show(struct seq_file *m, void *p)
-+{
-+ return s_show_internal(m, p, 0);
-+}
-+
-+static int s_mod_show(struct seq_file *m, void *p)
-+{
-+ return s_show_internal(m, p, 1);
-+}
-+
- static const struct seq_operations kallsyms_op = {
- .start = s_start,
- .next = s_next,
-@@ -695,7 +712,15 @@ bool kallsyms_show_value(const struct cred *cred)
- }
- }
-
--static int kallsyms_open(struct inode *inode, struct file *file)
-+static const struct seq_operations kallmodsyms_op = {
-+ .start = s_start,
-+ .next = s_next,
-+ .stop = s_stop,
-+ .show = s_mod_show
-+};
-+
-+static int kallsyms_open_internal(struct inode *inode, struct file *file,
-+ const struct seq_operations *ops)
- {
- /*
- * We keep iterator in m->private, since normal case is to
-@@ -703,10 +728,10 @@ static int kallsyms_open(struct inode *inode, struct file *file)
- * using get_symbol_offset for every symbol.
- */
- struct kallsym_iter *iter;
-- iter = __seq_open_private(file, &kallsyms_op, sizeof(*iter));
-+ iter = __seq_open_private(file, ops, sizeof(*iter));
- if (!iter)
- return -ENOMEM;
-- reset_iter(iter, 0);
-+ kallsyms_iter_reset(iter, 0);
-
- /*
- * Instead of checking this on every s_show() call, cache
-@@ -716,6 +741,16 @@ static int kallsyms_open(struct inode *inode, struct file *file)
- return 0;
- }
-
-+static int kallsyms_open(struct inode *inode, struct file *file)
-+{
-+ return kallsyms_open_internal(inode, file, &kallsyms_op);
-+}
-+
-+static int kallmodsyms_open(struct inode *inode, struct file *file)
-+{
-+ return kallsyms_open_internal(inode, file, &kallmodsyms_op);
-+}
-+
- #ifdef CONFIG_KGDB_KDB
- const char *kdb_walk_kallsyms(loff_t *pos)
- {
-@@ -723,10 +758,10 @@ const char *kdb_walk_kallsyms(loff_t *pos)
- if (*pos == 0) {
- memset(&kdb_walk_kallsyms_iter, 0,
- sizeof(kdb_walk_kallsyms_iter));
-- reset_iter(&kdb_walk_kallsyms_iter, 0);
-+ kallsyms_iter_reset(&kdb_walk_kallsyms_iter, 0);
- }
- while (1) {
-- if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
-+ if (!kallsyms_iter_update(&kdb_walk_kallsyms_iter, *pos))
- return NULL;
- ++*pos;
- /* Some debugging symbols have no name. Ignore them. */
-@@ -743,9 +778,17 @@ static const struct proc_ops kallsyms_proc_ops = {
- .proc_release = seq_release_private,
- };
-
-+static const struct proc_ops kallmodsyms_proc_ops = {
-+ .proc_open = kallmodsyms_open,
-+ .proc_read = seq_read,
-+ .proc_lseek = seq_lseek,
-+ .proc_release = seq_release_private,
-+};
-+
- static int __init kallsyms_init(void)
- {
- proc_create("kallsyms", 0444, NULL, &kallsyms_proc_ops);
-+ proc_create("kallmodsyms", 0444, NULL, &kallmodsyms_proc_ops);
- return 0;
- }
- device_initcall(kallsyms_init);
-diff --git a/kernel/module.c b/kernel/module.c
-index e20499309b2a..9e471dbedc83 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -4241,7 +4241,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
- }
-
- int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
-- char *name, char *module_name, int *exported)
-+ char *name, char *module_name, unsigned long *size,
-+ int *exported)
- {
- struct module *mod;
-
-@@ -4260,6 +4261,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
- strlcpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN);
- strlcpy(module_name, mod->name, MODULE_NAME_LEN);
- *exported = is_exported(name, *value, mod);
-+ *size = kallsyms->symtab[symnum].st_size;
- preempt_enable();
- return 0;
- }
-diff --git a/scripts/Makefile b/scripts/Makefile
-index 041bcf48cc5c..efa1ff4dff95 100644
---- a/scripts/Makefile
-+++ b/scripts/Makefile
-@@ -12,6 +12,16 @@ hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
- hostprogs-always-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
- hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
-
-+kallsyms-objs := kallsyms.o
-+
-+ifeq ($(CONFIG_KALLMODSYMS),y)
-+kallsyms-objs += eu_simple.o
-+
-+HOSTCFLAGS_eu_simple.o := -I$(srctree)/scripts
-+HOSTCFLAGS_kallsyms.o := $(shell pkg-config --cflags glib-2.0) -I$(srctree)/scripts
-+HOSTLDLIBS_kallsyms := $(shell pkg-config --libs glib-2.0) -ldw
-+endif
-+
- HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
- HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
- HOSTLDLIBS_sign-file = -lcrypto
-diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
-index 7ecd2ccba531..884ac793bdf4 100644
---- a/scripts/kallsyms.c
-+++ b/scripts/kallsyms.c
-@@ -5,7 +5,10 @@
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
-- * Usage: nm -n vmlinux | scripts/kallsyms [--all-symbols] > symbols.S
-+ * Usage: nm -n -S vmlinux | scripts/kallsyms [--all-symbols]
-+ * [--symbol-prefix=<prefix char>]
-+ * [--builtin=modules_thick.builtin]
-+ * > symbols.S
- *
- * Table compression uses all the unused char codes on the symbols and
- * maps these to the most used substrings (tokens). For instance, it might
-@@ -18,12 +21,27 @@
- *
- */
-
-+#define _GNU_SOURCE 1
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <limits.h>
-+#include <errno.h>
-+#include <unistd.h>
-+
-+#include "../include/generated/autoconf.h"
-+
-+#ifdef CONFIG_KALLMODSYMS
-+#include <libelf.h>
-+#include <dwarf.h>
-+#include <elfutils/libdwfl.h>
-+#include <elfutils/libdw.h>
-+#include <glib.h>
-+
-+#include <eu_simple.h>
-+#endif
-
- #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
-
-@@ -31,9 +49,13 @@
-
- struct sym_entry {
- unsigned long long addr;
-+ unsigned long long size;
- unsigned int len;
- unsigned int start_pos;
- unsigned int percpu_absolute;
-+#ifdef CONFIG_KALLMODSYMS
-+ unsigned int module;
-+#endif
- unsigned char sym[];
- };
-
-@@ -67,11 +89,33 @@ static int token_profit[0x10000];
- static unsigned char best_table[256][2];
- static unsigned char best_table_len[256];
-
-+#ifdef CONFIG_KALLMODSYMS
-+/*
-+ * The builtin module names. The "offset" points to the name as if
-+ * all builtin module names were concatenated to a single string.
-+ */
-+static unsigned int builtin_module_size; /* number allocated */
-+static unsigned int builtin_module_len; /* number assigned */
-+static char **builtin_modules; /* array of module names */
-+static unsigned int *builtin_module_offsets; /* offset */
-+
-+/*
-+ * An ordered list of address ranges and how they map to built-in modules.
-+ */
-+struct addrmap_entry {
-+ unsigned long long addr;
-+ unsigned long long size;
-+ unsigned int module;
-+};
-+static struct addrmap_entry *addrmap;
-+static int addrmap_num, addrmap_alloced;
-+#endif
-
- static void usage(void)
- {
- fprintf(stderr, "Usage: kallsyms [--all-symbols] "
-- "[--base-relative] < in.map > out.S\n");
-+ "[--base-relative] [--builtin=modules_thick.builtin] "
-+ "< in.map > out.S\n");
- exit(1);
- }
-
-@@ -99,6 +143,8 @@ static bool is_ignored_symbol(const char *name, char type)
- "kallsyms_markers",
- "kallsyms_token_table",
- "kallsyms_token_index",
-+ "kallsyms_symbol_modules",
-+ "kallsyms_modules",
- /* Exclude linker generated symbols which vary between passes */
- "_SDA_BASE_", /* ppc */
- "_SDA2_BASE_", /* ppc */
-@@ -189,6 +235,20 @@ static void check_symbol_range(const char *sym, unsigned long long addr,
- }
- }
-
-+#ifdef CONFIG_KALLMODSYMS
-+static int addrmap_compare(const void *keyp, const void *rangep)
-+{
-+ unsigned long long addr = *((const unsigned long long *)keyp);
-+ const struct addrmap_entry *range = (const struct addrmap_entry *)rangep;
-+
-+ if (addr < range->addr)
-+ return -1;
-+ if (addr < range->addr + range->size)
-+ return 0;
-+ return 1;
-+}
-+#endif
-+
- static struct sym_entry *read_symbol(FILE *in)
- {
- char name[500], type;
-@@ -196,9 +256,14 @@ static struct sym_entry *read_symbol(FILE *in)
- unsigned int len;
- struct sym_entry *sym;
- int rc;
--
-- rc = fscanf(in, "%llx %c %499s\n", &addr, &type, name);
-- if (rc != 3) {
-+ unsigned long long size;
-+#ifdef CONFIG_KALLMODSYMS
-+ struct addrmap_entry *range;
-+ unsigned int module;
-+#endif
-+
-+ rc = fscanf(in, "%llx %llx %c %499s\n", &addr, &size, &type, name);
-+ if (rc != 4) {
- if (rc != EOF && fgets(name, 500, in) == NULL)
- fprintf(stderr, "Read error or end of file.\n");
- return NULL;
-@@ -220,6 +285,16 @@ static struct sym_entry *read_symbol(FILE *in)
- check_symbol_range(name, addr, text_ranges, ARRAY_SIZE(text_ranges));
- check_symbol_range(name, addr, &percpu_range, 1);
-
-+#ifdef CONFIG_KALLMODSYMS
-+ /* look up the builtin module this is part of (if any) */
-+ range = (struct addrmap_entry *) bsearch(&addr,
-+ addrmap, addrmap_num, sizeof(*addrmap), &addrmap_compare);
-+ if (range)
-+ module = builtin_module_offsets[range->module];
-+ else
-+ module = 0;
-+#endif
-+
- /* include the type field in the symbol name, so that it gets
- * compressed together */
-
-@@ -236,6 +311,10 @@ static struct sym_entry *read_symbol(FILE *in)
- sym->sym[0] = type;
- strcpy(sym_name(sym), name);
- sym->percpu_absolute = 0;
-+ sym->size = size;
-+#ifdef CONFIG_KALLMODSYMS
-+ sym->module = module;
-+#endif
-
- return sym;
- }
-@@ -445,6 +524,11 @@ static void write_src(void)
- printf("\n");
- }
-
-+ output_label("kallsyms_sizes");
-+ for (i = 0; i < table_cnt; i++)
-+ printf("\tPTR\t%#llx\n", table[i]->size);
-+ printf("\n");
-+
- output_label("kallsyms_num_syms");
- printf("\t.long\t%u\n", table_cnt);
- printf("\n");
-@@ -494,8 +578,22 @@ static void write_src(void)
- for (i = 0; i < 256; i++)
- printf("\t.short\t%d\n", best_idx[i]);
- printf("\n");
--}
-
-+#ifdef CONFIG_KALLMODSYMS
-+ output_label("kallsyms_modules");
-+ for (i = 0; i < builtin_module_len; i++)
-+ printf("\t.asciz\t\"%s\"\n", builtin_modules[i]);
-+ printf("\n");
-+
-+ for (i = 0; i < builtin_module_len; i++)
-+ free(builtin_modules[i]);
-+
-+ output_label("kallsyms_symbol_modules");
-+ for (i = 0; i < table_cnt; i++)
-+ printf("\t.int\t%d\n", table[i]->module);
-+ printf("\n");
-+#endif
-+}
-
- /* table lookup compression functions */
-
-@@ -697,6 +795,18 @@ static int compare_symbols(const void *a, const void *b)
- if (sa->addr < sb->addr)
- return -1;
-
-+ /* zero-size markers before nonzero-size symbols */
-+ if (sa->size > 0 && sb->size == 0)
-+ return 1;
-+ if (sa->size == 0 && sb->size > 0)
-+ return -1;
-+
-+ /* sort by size (large size preceding symbols it encompasses) */
-+ if (sa->size < sb->size)
-+ return 1;
-+ if (sa->size > sb->size)
-+ return -1;
-+
- /* sort by "weakness" type */
- wa = (sa->sym[0] == 'w') || (sa->sym[0] == 'W');
- wb = (sb->sym[0] == 'w') || (sb->sym[0] == 'W');
-@@ -756,23 +866,198 @@ static void record_relative_base(void)
- }
- }
-
-+#ifdef CONFIG_KALLMODSYMS
-+/* Built-in module list computation. */
-+
-+/*
-+ * Expand the builtin modules list.
-+ */
-+static void expand_builtin_modules(void)
-+{
-+ builtin_module_size += 50;
-+
-+ builtin_modules = realloc(builtin_modules,
-+ sizeof(*builtin_modules) *
-+ builtin_module_size);
-+ builtin_module_offsets = realloc(builtin_module_offsets,
-+ sizeof(*builtin_module_offsets) *
-+ builtin_module_size);
-+
-+ if (!builtin_modules || !builtin_module_offsets) {
-+ fprintf(stderr, "kallsyms failure: out of memory.\n");
-+ exit(EXIT_FAILURE);
-+ }
-+}
-+
-+/*
-+ * Add a single built-in module (possibly composed of many files) to the
-+ * modules list. Take the offset of the current module and return it
-+ * (purely for simplicity's sake in the caller).
-+ */
-+static size_t add_builtin_module(const char *module_name, char **module_paths,
-+ GHashTable *obj2mod, size_t offset)
-+{
-+ gpointer val = GUINT_TO_POINTER(builtin_module_len);
-+
-+ /* map the module's object paths to the module offset */
-+ while (*module_paths) {
-+ g_hash_table_insert(obj2mod, strdup(*module_paths), val);
-+ module_paths++;
-+ }
-+
-+ /* add the module name */
-+ if (builtin_module_size <= builtin_module_len)
-+ expand_builtin_modules();
-+ builtin_modules[builtin_module_len] = strdup(module_name);
-+ builtin_module_offsets[builtin_module_len] = offset;
-+ builtin_module_len++;
-+
-+ return (offset + strlen(module_name) + 1);
-+}
-+
-+/*
-+ * Read the linker map.
-+ */
-+static void read_linker_map(GHashTable *obj2mod)
-+{
-+ unsigned long long addr, size;
-+ char obj[PATH_MAX+1];
-+ FILE *f = fopen(".tmp_vmlinux.ranges", "r");
-+
-+ if (!f) {
-+ fprintf(stderr, "Cannot open '.tmp_vmlinux.ranges'.\n");
-+ exit(1);
-+ }
-+
-+ addrmap_num = 0;
-+ addrmap_alloced = 4096;
-+ addrmap = malloc(sizeof(*addrmap) * addrmap_alloced);
-+ if (!addrmap)
-+ goto oom;
-+
-+ /*
-+ * For each address range (addr,size) and object, add to addrmap
-+ * the range and the built-in module to which the object maps.
-+ */
-+ while (fscanf(f, "%llx %llx %s\n", &addr, &size, obj) == 3) {
-+ int m = GPOINTER_TO_UINT(g_hash_table_lookup(obj2mod, obj));
-+
-+ if (addr == 0 || size == 0 || m == 0)
-+ continue;
-+
-+ if (addrmap_num >= addrmap_alloced) {
-+ addrmap_alloced *= 2;
-+ addrmap = realloc(addrmap,
-+ sizeof(*addrmap) * addrmap_alloced);
-+ if (!addrmap)
-+ goto oom;
-+ }
-+
-+ addrmap[addrmap_num].addr = addr;
-+ addrmap[addrmap_num].size = size;
-+ addrmap[addrmap_num].module = m;
-+ addrmap_num++;
-+ }
-+ fclose(f);
-+ return;
-+
-+oom:
-+ fprintf(stderr, "kallsyms: out of memory\n");
-+ exit(1);
-+}
-+
-+/*
-+ * Read the list of built-in modules. Construct:
-+ * - builtin_modules: array of module names
-+ * - builtin_module_offsets: array of offsets to find module names
-+ * - obj2mod: mapping from each object-file path to a module index
-+ * (which can be used in the arrays)
-+ * Finally, read the linker map.
-+ */
-+static void read_modules(const char *modules_builtin)
-+{
-+ struct modules_thick_iter *i;
-+ size_t offset = 0;
-+ char *module_name = NULL;
-+ char **module_paths;
-+ GHashTable *obj2mod;
-+
-+ obj2mod = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
-+ if (!obj2mod) {
-+ fprintf(stderr, "kallsyms: out of memory\n");
-+ exit(1);
-+ }
-+
-+ /*
-+ * builtin_modules[0] is a null entry signifying a symbol that cannot be
-+ * modular.
-+ */
-+ builtin_module_size = 50;
-+ builtin_modules = malloc(sizeof(*builtin_modules) *
-+ builtin_module_size);
-+ builtin_module_offsets = malloc(sizeof(*builtin_module_offsets) *
-+ builtin_module_size);
-+ if (!builtin_modules || !builtin_module_offsets) {
-+ fprintf(stderr, "kallsyms: out of memory\n");
-+ exit(1);
-+ }
-+ builtin_modules[0] = strdup("");
-+ builtin_module_offsets[0] = 0;
-+ builtin_module_len = 1;
-+ offset++;
-+
-+ /*
-+ * Iterate over all modules in modules_thick.builtin and add each.
-+ */
-+ i = modules_thick_iter_new(modules_builtin);
-+ if (i == NULL) {
-+ fprintf(stderr, "Cannot iterate over builtin modules.\n");
-+ exit(1);
-+ }
-+
-+ while ((module_paths = modules_thick_iter_next(i, &module_name)) != NULL) {
-+ offset = add_builtin_module(module_name, module_paths,
-+ obj2mod, offset);
-+ free(module_paths);
-+ module_paths = NULL;
-+ }
-+
-+ free(module_name);
-+ modules_thick_iter_free(i);
-+
-+ /*
-+ * Read linker map.
-+ */
-+ read_linker_map(obj2mod);
-+
-+ g_hash_table_destroy(obj2mod);
-+}
-+#else
-+static void read_modules(const char *unused) {}
-+#endif /* CONFIG_KALLMODSYMS */
-+
- int main(int argc, char **argv)
- {
-- if (argc >= 2) {
-+ const char *modules_builtin = "modules_thick.builtin";
-+
-+ if (argc >= 1) {
- int i;
- for (i = 1; i < argc; i++) {
-- if(strcmp(argv[i], "--all-symbols") == 0)
-+ if (strcmp(argv[i], "--all-symbols") == 0)
- all_symbols = 1;
- else if (strcmp(argv[i], "--absolute-percpu") == 0)
- absolute_percpu = 1;
- else if (strcmp(argv[i], "--base-relative") == 0)
- base_relative = 1;
-+ else if (strncmp(argv[i], "--builtin=", 10) == 0)
-+ modules_builtin = &argv[i][10];
- else
- usage();
- }
- } else if (argc != 1)
- usage();
-
-+ read_modules(modules_builtin);
- read_map(stdin);
- shrink_table();
- if (absolute_percpu)
-diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
-index 6eded325c837..bc533252fa3c 100755
---- a/scripts/link-vmlinux.sh
-+++ b/scripts/link-vmlinux.sh
-@@ -109,6 +109,7 @@ vmlinux_link()
- --start-group \
- ${KBUILD_VMLINUX_LIBS} \
- --end-group \
-+ -Map=.tmp_vmlinux.map \
- ${@}"
-
- ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
-@@ -122,6 +123,7 @@ vmlinux_link()
- -Wl,--start-group \
- ${KBUILD_VMLINUX_LIBS} \
- -Wl,--end-group \
-+ -Wl,-Map=.tmp_vmlinux.map \
- ${@}"
-
- ${CC} ${CFLAGS_vmlinux} \
-@@ -174,6 +176,19 @@ kallsyms()
- {
- local kallsymopt;
-
-+ # read the linker map to identify ranges of addresses:
-+ # - for each *.o file, report address, size, pathname
-+ # - most such lines will have four fields
-+ # - but sometimes there is a line break after the first field
-+ # - start reading at "Linker script and memory map"
-+ # - stop reading at ".brk"
-+ ${AWK} '
-+ /\.o$/ && start==1 { print $(NF-2), $(NF-1), $NF }
-+ /^Linker script and memory map/ { start = 1 }
-+ /^\.brk/ { exit(0) }
-+ ' .tmp_vmlinux.map | sort > .tmp_vmlinux.ranges
-+
-+ # get kallsyms options
- if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
- kallsymopt="${kallsymopt} --all-symbols"
- fi
-@@ -186,8 +201,13 @@ kallsyms()
- kallsymopt="${kallsymopt} --base-relative"
- fi
-
-+ # "nm -S" does not print symbol size when size is 0
-+ # Therefore use awk to regularize the data:
-+ # - when there are only three fields, add an explicit "0"
-+ # - when there are already four fields, pass through as is
- info KSYMS ${2}
-- ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${2}
-+ ${NM} -n -S ${1} | ${AWK} 'NF==3 {print $1, 0, $2, $3}; NF==4' | \
-+ scripts/kallsyms ${kallsymopt} > ${2}
- }
-
- # Perform one step in kallsyms generation, including temporary linking of
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch
deleted file mode 100644
index b02ead6a9736..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch
+++ /dev/null
@@ -1,809 +0,0 @@
-From 7cbd018b36da6838efe3adba191adf3acd4ef9bd Mon Sep 17 00:00:00 2001
-From: Nick Alcock <nick.alcock@oracle.com>
-Date: Wed, 14 Nov 2018 20:28:51 +0000
-Subject: [PATCH 03/19] waitfd: new syscall implementing waitpid() over fds
-
-This syscall, originally due to Casey Dahlin but significantly modified
-since, is called quite like waitid():
-
- fd = waitfd(P_PID, some_pid, WEXITED | WSTOPPED, 0);
-
-This returns a file descriptor which becomes ready whenever waitpid()
-would return, and when read() returns the return value waitpid() would
-have returned. (Alternatively, you can use it as a pure indication that
-waitpid() is callable without hanging, and then call waitpid()). See the
-example in tools/testing/selftests/waitfd/.
-
-The original reason for rejection of this patch back in 2009 was that it
-was redundant to waitpid()ing in a separate thread and transmitting
-process information to another thread that polls: but this is only the
-case for the conventional child-process use of waitpid(). Other
-waitpid() uses, such as ptrace() returns, are targetted on a single
-thread, so without waitfd or something like it, it is impossible to have
-a thread that both accepts requests for servicing from other threads
-over an fd *and* manipulates the state of a ptrace()d process in
-response to those requests without ugly CPU-chewing polling (accepting
-requests requires blocking in poll() or select(): handling the ptraced
-process requires blocking in waitpid()).
-
-There is one ugliness in this patch which I would appreciate suggestions
-to improve (due to me, not due to Casey, don't blame him). The poll()
-machinery expects to be used with files, or things enough like files
-that the wake_up key contains an indication as to whether this wakeup
-corresponds to a POLLIN / POLLOUT / POLLERR event on this fd. You can
-override this in your poll_queue_proc, but the poll() and epoll() queue
-procs both have this interpretation.
-
-Unfortunately, this is not true for waitfds, which wait on the the
-wait_chldexit waitqueue, whose key is a pointer to the task_struct of
-the task being killed. We can't do anything with this key, but we
-certainly don't want the poll machinery treating it as a bitmask and
-checking it against poll events!
-
-So we introduce a new poll_wait() analogue, poll_wait_fixed(). This is used
-for poll_wait() calls which know they must wait on waitqueues whose keys are
-not a typecast representation of poll events, and passes in an extra
-argument to the poll_queue_proc, which if nonzero is the event which a
-wakeup on this waitqueue should be considered as equivalent to. The
-poll_queue_proc can then skip adding entirely if that fixed event is not
-included in the set to be caught by this poll().
-
-We also add a new poll_table_entry.fixed_key. The poll_queue_proc can
-record the fixed key it is passed in here, and reuse it at wakeup time to
-track that a nonzero fixed key was passed in to poll_wait_fixed() and that
-the key should be ignored in preference to fixed_key.
-
-With this in place, you can say, e.g. (as waitfd does)
-
- poll_wait_fixed(file, &current->signal->wait_chldexit, wait,
- POLLIN);
-
-and the key passed to wakeups on the wait_chldexit waitqueue will be
-ignored: the fd will always be treated as having raised POLLIN, waking
-up poll()s and epoll()s that have specified that event. (Obviously, a
-poll function that calls this should return the same value from the poll
-function as was passed to poll_wait_fixed(), or, as usual, zero if this
-was a spurious wakeup.)
-
-I do not like this scheme: it's sufficiently arcane that I had to go
-back to my old commit messages to figure out what it was doing and
-why. But I don't see another way to cause poll() to return on
-appropriate activity on waitqueues that do not actually correspond to
-files. (I do wonder how signalfd works. It doesn't seem to need any of
-this and I don't understand why not. I would be overjoyed to remove the
-whole invasive poll_wait_fixed() mess, but I'm not sure what to replace
-it with.)
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/entry/syscalls/syscall_32.tbl | 3 +
- arch/x86/entry/syscalls/syscall_64.tbl | 3 +
- drivers/vfio/virqfd.c | 3 +-
- drivers/vhost/vhost.c | 2 +-
- fs/Makefile | 1 +
- fs/aio.c | 2 +-
- fs/eventpoll.c | 22 +++-
- fs/io_uring.c | 5 +-
- fs/select.c | 21 +++-
- fs/waitfd.c | 130 ++++++++++++++++++++++++
- include/linux/poll.h | 14 ++-
- include/linux/syscalls.h | 3 +
- include/uapi/asm-generic/unistd.h | 5 +-
- init/Kconfig | 16 +++
- kernel/exit.c | 13 ++-
- kernel/sys_ni.c | 1 +
- mm/memcontrol.c | 2 +-
- net/9p/trans_fd.c | 3 +-
- tools/testing/selftests/waitfd/Makefile | 28 +++++
- tools/testing/selftests/waitfd/waitfd.c | 116 +++++++++++++++++++++
- virt/kvm/eventfd.c | 2 +-
- 21 files changed, 376 insertions(+), 19 deletions(-)
- create mode 100644 fs/waitfd.c
- create mode 100644 tools/testing/selftests/waitfd/Makefile
- create mode 100644 tools/testing/selftests/waitfd/waitfd.c
-
-diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
-index 0d0667a9fbd7..5605708e4c31 100644
---- a/arch/x86/entry/syscalls/syscall_32.tbl
-+++ b/arch/x86/entry/syscalls/syscall_32.tbl
-@@ -445,3 +445,6 @@
- 438 i386 pidfd_getfd sys_pidfd_getfd
- 439 i386 faccessat2 sys_faccessat2
- 440 i386 process_madvise sys_process_madvise
-+# This one is a temporary number, designed for no clashes.
-+# Nothing but DTrace should use it.
-+473 i386 waitfd sys_waitfd
-diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
-index 379819244b91..4f4e0585c65f 100644
---- a/arch/x86/entry/syscalls/syscall_64.tbl
-+++ b/arch/x86/entry/syscalls/syscall_64.tbl
-@@ -362,6 +362,9 @@
- 438 common pidfd_getfd sys_pidfd_getfd
- 439 common faccessat2 sys_faccessat2
- 440 common process_madvise sys_process_madvise
-+# This one is a temporary number, designed for no clashes.
-+# Nothing but DTrace should use it.
-+473 common waitfd sys_waitfd
-
- #
- # Due to a historical design error, certain syscalls are numbered differently
-diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c
-index 997cb5d0a657..6bfafa889af2 100644
---- a/drivers/vfio/virqfd.c
-+++ b/drivers/vfio/virqfd.c
-@@ -76,7 +76,8 @@ static int virqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void
- }
-
- static void virqfd_ptable_queue_proc(struct file *file,
-- wait_queue_head_t *wqh, poll_table *pt)
-+ wait_queue_head_t *wqh, poll_table *pt,
-+ unsigned long unused)
- {
- struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
- add_wait_queue(wqh, &virqfd->wait);
-diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
-index a262e12c6dc2..31128cadd1b2 100644
---- a/drivers/vhost/vhost.c
-+++ b/drivers/vhost/vhost.c
-@@ -152,7 +152,7 @@ static void vhost_flush_work(struct vhost_work *work)
- }
-
- static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
-- poll_table *pt)
-+ poll_table *pt, unsigned long unused)
- {
- struct vhost_poll *poll;
-
-diff --git a/fs/Makefile b/fs/Makefile
-index 999d1a23f036..ad5fc1399484 100644
---- a/fs/Makefile
-+++ b/fs/Makefile
-@@ -31,6 +31,7 @@ obj-$(CONFIG_SIGNALFD) += signalfd.o
- obj-$(CONFIG_TIMERFD) += timerfd.o
- obj-$(CONFIG_EVENTFD) += eventfd.o
- obj-$(CONFIG_USERFAULTFD) += userfaultfd.o
-+obj-$(CONFIG_WAITFD) += waitfd.o
- obj-$(CONFIG_AIO) += aio.o
- obj-$(CONFIG_IO_URING) += io_uring.o
- obj-$(CONFIG_IO_WQ) += io-wq.o
-diff --git a/fs/aio.c b/fs/aio.c
-index 6a21d8919409..3485fe7913ef 100644
---- a/fs/aio.c
-+++ b/fs/aio.c
-@@ -1718,7 +1718,7 @@ struct aio_poll_table {
-
- static void
- aio_poll_queue_proc(struct file *file, struct wait_queue_head *head,
-- struct poll_table_struct *p)
-+ struct poll_table_struct *p, unsigned long fixed_event)
- {
- struct aio_poll_table *pt = container_of(p, struct aio_poll_table, pt);
-
-diff --git a/fs/eventpoll.c b/fs/eventpoll.c
-index 117b1c395ae4..e3c9f4ea9ec6 100644
---- a/fs/eventpoll.c
-+++ b/fs/eventpoll.c
-@@ -157,6 +157,9 @@ struct epitem {
- /* Number of active wait queue attached to poll operations */
- int nwait;
-
-+ /* fd always raises this fixed event. */
-+ unsigned long fixed_event;
-+
- /* List containing poll wait queues */
- struct list_head pwqlist;
-
-@@ -867,7 +870,7 @@ static int ep_eventpoll_release(struct inode *inode, struct file *file)
- static __poll_t ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
- void *priv);
- static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
-- poll_table *pt);
-+ poll_table *pt, unsigned long fixed_event);
-
- /*
- * Differs from ep_eventpoll_poll() in that internal callers already have
-@@ -1283,6 +1286,13 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v
- if (!(epi->event.events & EPOLLEXCLUSIVE))
- ewake = 1;
-
-+ /*
-+ * If this fd type has a hardwired event which should override the key
-+ * (e.g. if it is waiting on a non-file waitqueue), jam it in here.
-+ */
-+ if (epi->fixed_event)
-+ key = (void *)epi->fixed_event;
-+
- if (pollflags & POLLFREE) {
- /*
- * If we race with ep_remove_wait_queue() it can miss
-@@ -1307,11 +1317,17 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v
- * target file wakeup lists.
- */
- static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
-- poll_table *pt)
-+ poll_table *pt, unsigned long fixed_event)
- {
- struct epitem *epi = ep_item_from_epqueue(pt);
- struct eppoll_entry *pwq;
-
-+ if (fixed_event & !(epi->event.events & fixed_event))
-+ return;
-+
-+ if (fixed_event)
-+ epi->fixed_event = fixed_event;
-+
- if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, GFP_KERNEL))) {
- init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
- pwq->whead = whead;
-@@ -1512,6 +1528,7 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
- ep_set_ffd(&epi->ffd, tfile, fd);
- epi->event = *event;
- epi->nwait = 0;
-+ epi->fixed_event = 0;
- epi->next = EP_UNACTIVE_PTR;
- if (epi->event.events & EPOLLWAKEUP) {
- error = ep_create_wakeup_source(epi);
-@@ -2410,7 +2427,6 @@ static int __init eventpoll_init(void)
- * We can have many thousands of epitems, so prevent this from
- * using an extra cache line on 64-bit (and smaller) CPUs
- */
-- BUILD_BUG_ON(sizeof(void *) <= 8 && sizeof(struct epitem) > 128);
-
- /* Allocates slab cache used to allocate "struct epitem" items */
- epi_cache = kmem_cache_create("eventpoll_epi", sizeof(struct epitem),
-diff --git a/fs/io_uring.c b/fs/io_uring.c
-index fd12d9327ee5..0d0162ab5301 100644
---- a/fs/io_uring.c
-+++ b/fs/io_uring.c
-@@ -5109,7 +5109,8 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
- }
-
- static void io_async_queue_proc(struct file *file, struct wait_queue_head *head,
-- struct poll_table_struct *p)
-+ struct poll_table_struct *p,
-+ unsigned long fixed_event)
- {
- struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
- struct async_poll *apoll = pt->req->apoll;
-@@ -5405,7 +5406,7 @@ static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
- }
-
- static void io_poll_queue_proc(struct file *file, struct wait_queue_head *head,
-- struct poll_table_struct *p)
-+ struct poll_table_struct *p, unsigned long fixed_event)
- {
- struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
-
-diff --git a/fs/select.c b/fs/select.c
-index 37aaa8317f3a..ec91d05beb7d 100644
---- a/fs/select.c
-+++ b/fs/select.c
-@@ -116,7 +116,7 @@ struct poll_table_page {
- * poll table.
- */
- static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
-- poll_table *p);
-+ poll_table *p, unsigned long fixed_event);
-
- void poll_initwait(struct poll_wqueues *pwq)
- {
-@@ -212,6 +212,14 @@ static int pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key
- struct poll_table_entry *entry;
-
- entry = container_of(wait, struct poll_table_entry, wait);
-+
-+ /*
-+ * If this fd type has a hardwired key which should override the key
-+ * (e.g. if it is waiting on a non-file waitqueue), jam it in here.
-+ */
-+ if (entry->fixed_key)
-+ key = (void *)entry->fixed_key;
-+
- if (key && !(key_to_poll(key) & entry->key))
- return 0;
- return __pollwake(wait, mode, sync, key);
-@@ -219,15 +227,22 @@ static int pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key
-
- /* Add a new entry */
- static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
-- poll_table *p)
-+ poll_table *p, unsigned long fixed_event)
- {
- struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
-- struct poll_table_entry *entry = poll_get_entry(pwq);
-+ struct poll_table_entry *entry;
-+
-+ if (fixed_event && !(p->_key & fixed_event))
-+ return;
-+
-+ entry = poll_get_entry(pwq);
- if (!entry)
- return;
-+
- entry->filp = get_file(filp);
- entry->wait_address = wait_address;
- entry->key = p->_key;
-+ entry->fixed_key = fixed_event;
- init_waitqueue_func_entry(&entry->wait, pollwake);
- entry->wait.private = pwq;
- add_wait_queue(wait_address, &entry->wait);
-diff --git a/fs/waitfd.c b/fs/waitfd.c
-new file mode 100644
-index 000000000000..311f84d7b85f
---- /dev/null
-+++ b/fs/waitfd.c
-@@ -0,0 +1,130 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * fs/waitfd.c
-+ *
-+ * Copyright (C) 2008 Red Hat, Casey Dahlin <cdahlin@redhat.com>
-+ *
-+ * Largely derived from fs/signalfd.c
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/poll.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/kernel.h>
-+#include <linux/signal.h>
-+#include <linux/list.h>
-+#include <linux/anon_inodes.h>
-+#include <linux/syscalls.h>
-+
-+long kernel_wait4(pid_t upid, int __user *stat_addr,
-+ int options, struct rusage __user *ru);
-+
-+struct waitfd_ctx {
-+ int options;
-+ pid_t upid;
-+};
-+
-+static int waitfd_release(struct inode *inode, struct file *file)
-+{
-+ kfree(file->private_data);
-+ return 0;
-+}
-+
-+static unsigned int waitfd_poll(struct file *file, poll_table *wait)
-+{
-+ struct waitfd_ctx *ctx = file->private_data;
-+ long value;
-+
-+ poll_wait_fixed(file, &current->signal->wait_chldexit, wait,
-+ POLLIN);
-+
-+ value = kernel_wait4(ctx->upid, NULL, ctx->options | WNOHANG | WNOWAIT,
-+ NULL);
-+ if (value > 0 || value == -ECHILD)
-+ return POLLIN | POLLRDNORM;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Returns a multiple of the size of a stat_addr, or a negative error code. The
-+ * "count" parameter must be at least sizeof(int).
-+ */
-+static ssize_t waitfd_read(struct file *file, char __user *buf, size_t count,
-+ loff_t *ppos)
-+{
-+ struct waitfd_ctx *ctx = file->private_data;
-+ int __user *stat_addr = (int *)buf;
-+ int flags = ctx->options;
-+ ssize_t ret, total = 0;
-+
-+ count /= sizeof(int);
-+ if (!count)
-+ return -EINVAL;
-+
-+ if (file->f_flags & O_NONBLOCK)
-+ flags |= WNOHANG;
-+
-+ do {
-+ ret = kernel_wait4(ctx->upid, stat_addr, flags, NULL);
-+ if (ret == 0)
-+ ret = -EAGAIN;
-+ if (ret == -ECHILD)
-+ ret = 0;
-+ if (ret <= 0)
-+ break;
-+
-+ stat_addr++;
-+ total += sizeof(int);
-+ } while (--count);
-+
-+ return total ? total : ret;
-+}
-+
-+static const struct file_operations waitfd_fops = {
-+ .release = waitfd_release,
-+ .poll = waitfd_poll,
-+ .read = waitfd_read,
-+ .llseek = noop_llseek,
-+};
-+
-+SYSCALL_DEFINE4(waitfd, int __maybe_unused, which, pid_t, upid, int, options,
-+ int __maybe_unused, flags)
-+{
-+ int ufd;
-+ struct waitfd_ctx *ctx;
-+
-+ /*
-+ * Options validation from kernel_wait4(), minus WNOWAIT, which is
-+ * only used by our polling implementation. If WEXITED or WSTOPPED
-+ * are provided, silently remove them (for backward compatibility with
-+ * older callers).
-+ */
-+ options &= ~(WEXITED | WSTOPPED);
-+ if (options & ~(WNOHANG|WUNTRACED|WCONTINUED|
-+ __WNOTHREAD|__WCLONE|__WALL))
-+ return -EINVAL;
-+
-+ ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
-+ if (!ctx)
-+ return -ENOMEM;
-+
-+ ctx->options = options;
-+ ctx->upid = upid;
-+
-+ ufd = anon_inode_getfd("[waitfd]", &waitfd_fops, ctx,
-+ O_RDWR | flags | ((options & WNOHANG) ?
-+ O_NONBLOCK | 0 : 0));
-+ /*
-+ * Use the fd's nonblocking state from now on, since that can change.
-+ */
-+ ctx->options &= ~WNOHANG;
-+
-+ if (ufd < 0)
-+ kfree(ctx);
-+
-+ return ufd;
-+}
-diff --git a/include/linux/poll.h b/include/linux/poll.h
-index 1cdc32b1f1b0..1c06718f39bc 100644
---- a/include/linux/poll.h
-+++ b/include/linux/poll.h
-@@ -34,7 +34,8 @@ struct poll_table_struct;
- /*
- * structures and helpers for f_op->poll implementations
- */
--typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
-+typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *,
-+ struct poll_table_struct *, unsigned long fixed_event);
-
- /*
- * Do not touch the structure directly, use the access functions
-@@ -48,7 +49,15 @@ typedef struct poll_table_struct {
- static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
- {
- if (p && p->_qproc && wait_address)
-- p->_qproc(filp, wait_address, p);
-+ p->_qproc(filp, wait_address, p, 0);
-+}
-+
-+static inline void poll_wait_fixed(struct file *filp,
-+ wait_queue_head_t *wait_address, poll_table *p,
-+ unsigned long fixed_event)
-+{
-+ if (p && p->_qproc && wait_address)
-+ p->_qproc(filp, wait_address, p, fixed_event);
- }
-
- /*
-@@ -93,6 +102,7 @@ static inline __poll_t vfs_poll(struct file *file, struct poll_table_struct *pt)
- struct poll_table_entry {
- struct file *filp;
- __poll_t key;
-+ unsigned long fixed_key;
- wait_queue_entry_t wait;
- wait_queue_head_t *wait_address;
- };
-diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
-index aea0ce9f3b74..0db3a09986d7 100644
---- a/include/linux/syscalls.h
-+++ b/include/linux/syscalls.h
-@@ -1366,6 +1366,9 @@ long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
- long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
- unsigned int nsops,
- const struct old_timespec32 __user *timeout);
-+#ifdef CONFIG_DTRACE
-+asmlinkage long sys_waitfd(int which, pid_t upid, int options, int flags);
-+#endif
-
- int __sys_getsockopt(int fd, int level, int optname, char __user *optval,
- int __user *optlen);
-diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
-index 2056318988f7..58238d6fbbcb 100644
---- a/include/uapi/asm-generic/unistd.h
-+++ b/include/uapi/asm-generic/unistd.h
-@@ -860,8 +860,11 @@ __SYSCALL(__NR_faccessat2, sys_faccessat2)
- #define __NR_process_madvise 440
- __SYSCALL(__NR_process_madvise, sys_process_madvise)
-
-+#define __NR_waitfd 473
-+__SYSCALL(__NR_waitfd, sys_waitfd)
-+
- #undef __NR_syscalls
--#define __NR_syscalls 441
-+#define __NR_syscalls 474
-
- /*
- * 32 bit systems traditionally used different
-diff --git a/init/Kconfig b/init/Kconfig
-index 05d377ccc0e0..5a86bbbf43e0 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1562,6 +1562,22 @@ config EPOLL
- Disabling this option will cause the kernel to be built without
- support for epoll family of system calls.
-
-+config WAITFD
-+ bool "Enable waitfd() system call" if EXPERT
-+ select ANON_INODES
-+ default n
-+ help
-+ Enable the waitfd() system call that allows receiving child state
-+ changes from a file descriptor. This permits use of poll() to
-+ monitor waitpid() output simultaneously with other fd state changes,
-+ even if the waitpid() output is coming from thread-targetted sources
-+ such as ptrace().
-+
-+ Note: this system call is not upstream: its syscall number is not
-+ finalized, so the call itself should only be used with caution.
-+
-+ If unsure, say N.
-+
- config SIGNALFD
- bool "Enable signalfd() system call" if EXPERT
- default y
-diff --git a/kernel/exit.c b/kernel/exit.c
-index d13d67fc5f4e..5c5859a9ba75 100644
---- a/kernel/exit.c
-+++ b/kernel/exit.c
-@@ -1586,7 +1586,10 @@ long kernel_wait4(pid_t upid, int __user *stat_addr, int options,
- enum pid_type type;
- long ret;
-
-- if (options & ~(WNOHANG|WUNTRACED|WCONTINUED|
-+ /*
-+ * As for wait4(), except that waitfd() additionally needs WNOWAIT.
-+ */
-+ if (options & ~(WNOHANG|WNOWAIT|WUNTRACED|WCONTINUED|
- __WNOTHREAD|__WCLONE|__WALL))
- return -EINVAL;
-
-@@ -1641,7 +1644,13 @@ SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
- int, options, struct rusage __user *, ru)
- {
- struct rusage r;
-- long err = kernel_wait4(upid, stat_addr, options, ru ? &r : NULL);
-+ long err;
-+
-+ if (options & ~(WNOHANG|WUNTRACED|WCONTINUED|
-+ __WNOTHREAD|__WCLONE|__WALL))
-+ return -EINVAL;
-+
-+ err = kernel_wait4(upid, stat_addr, options, ru ? &r : NULL);
-
- if (err > 0) {
- if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
-diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
-index f27ac94d5fa7..53900d50a8af 100644
---- a/kernel/sys_ni.c
-+++ b/kernel/sys_ni.c
-@@ -391,6 +391,7 @@ COND_SYSCALL(subpage_prot);
- * include/uapi/asm-generic/unistd.h and wanted by >= 1 arch
- */
-
-+COND_SYSCALL(waitfd);
- /* __ARCH_WANT_SYSCALL_NO_FLAGS */
- COND_SYSCALL(epoll_create);
- COND_SYSCALL(inotify_init);
-diff --git a/mm/memcontrol.c b/mm/memcontrol.c
-index 8fc23d53f550..a5d4a1d4f868 100644
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -4839,7 +4839,7 @@ static int memcg_event_wake(wait_queue_entry_t *wait, unsigned mode,
- }
-
- static void memcg_event_ptable_queue_proc(struct file *file,
-- wait_queue_head_t *wqh, poll_table *pt)
-+ wait_queue_head_t *wqh, poll_table *pt, unsigned long unused)
- {
- struct mem_cgroup_event *event =
- container_of(pt, struct mem_cgroup_event, pt);
-diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
-index 8f528e783a6c..d4890a86c0ce 100644
---- a/net/9p/trans_fd.c
-+++ b/net/9p/trans_fd.c
-@@ -545,7 +545,8 @@ static int p9_pollwake(wait_queue_entry_t *wait, unsigned int mode, int sync, vo
- */
-
- static void
--p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
-+p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p,
-+ unsigned long unused)
- {
- struct p9_conn *m = container_of(p, struct p9_conn, pt);
- struct p9_poll_wait *pwait = NULL;
-diff --git a/tools/testing/selftests/waitfd/Makefile b/tools/testing/selftests/waitfd/Makefile
-new file mode 100644
-index 000000000000..f85c80b54f05
---- /dev/null
-+++ b/tools/testing/selftests/waitfd/Makefile
-@@ -0,0 +1,28 @@
-+uname_M := $(shell uname -m 2>/dev/null || echo not)
-+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
-+ifeq ($(ARCH),i386)
-+ ARCH := X86
-+ CFLAGS := -DCONFIG_X86_32 -D__i386__
-+endif
-+ifeq ($(ARCH),x86_64)
-+ ARCH := X86
-+ CFLAGS := -DCONFIG_X86_64 -D__x86_64__
-+endif
-+
-+CFLAGS += -I../../../../arch/x86/include/generated/
-+CFLAGS += -I../../../../include/
-+CFLAGS += -I../../../../usr/include/
-+CFLAGS += -I../../../../arch/x86/include/
-+
-+all:
-+ifeq ($(ARCH),X86)
-+ gcc $(CFLAGS) waitfd.c -o waitfd
-+else
-+ echo "Not an x86 target, can't build waitfd selftest"
-+endif
-+
-+run_tests: all
-+ @./waitfd || echo "waitfd: [FAIL]"
-+
-+clean:
-+ rm -fr ./waitfd
-diff --git a/tools/testing/selftests/waitfd/waitfd.c b/tools/testing/selftests/waitfd/waitfd.c
-new file mode 100644
-index 000000000000..2df60bbdbb35
---- /dev/null
-+++ b/tools/testing/selftests/waitfd/waitfd.c
-@@ -0,0 +1,116 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/* waitfd testcase. */
-+
-+#define _GNU_SOURCE 1
-+#include <linux/unistd.h>
-+#include <sys/syscall.h>
-+#include <sys/ptrace.h>
-+#include <sys/types.h>
-+#include <sys/wait.h>
-+#include <errno.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <string.h>
-+#include <poll.h>
-+
-+int waitfd(int which, pid_t upid, int options, int flags)
-+{
-+ return syscall(__NR_waitfd, which, upid, options, flags);
-+}
-+
-+void sleeper(void)
-+{
-+ sleep(10);
-+ exit(0);
-+}
-+
-+int main (void)
-+{
-+ pid_t die_pid, ptrace_pid;
-+ int die_fd, ptrace_fd;
-+ int status;
-+ struct pollfd pfd[2];
-+ int procs_left = 2;
-+
-+ memset(pfd, 0, sizeof(pfd));
-+
-+ /*
-+ * Fork off two children, one of which waits for a ptrace().
-+ * Both just sleep after that. Make sure we can use __WNOTHREAD,
-+ * __WALL, and WUNTRACED without getting an -EINVAL.
-+ */
-+
-+ die_pid = fork();
-+
-+ if (die_pid == 0)
-+ sleeper();
-+
-+ ptrace_pid = fork();
-+ if (ptrace_pid == 0) {
-+ ptrace(PTRACE_TRACEME, 0, 0, 0);
-+ sleeper();
-+ }
-+
-+ die_fd = waitfd(P_PID, die_pid, 0, 0);
-+ ptrace_fd = waitfd(P_PID, ptrace_pid, __WNOTHREAD | __WALL | WUNTRACED, 0);
-+
-+ if (die_fd < 0 || ptrace_fd < 0) {
-+ perror("Cannot waitfd()");
-+ exit(1);
-+ }
-+
-+ pfd[0].fd = die_fd;
-+ pfd[0].events = POLLIN;
-+ pfd[1].fd = ptrace_fd;
-+ pfd[1].events = POLLIN;
-+
-+ /*
-+ * Hit the ptrace PID with a signal
-+ */
-+ kill(ptrace_pid, SIGABRT);
-+
-+ while (procs_left > 0) {
-+ ssize_t bytes;
-+
-+ if (poll(pfd, 2, -1) < 0)
-+ perror ("poll() failed");
-+
-+ if (pfd[0].revents != 0) {
-+ bytes = read(die_fd, &status, sizeof(int));
-+ if (bytes < sizeof(int)) {
-+ fprintf(stderr, "Only read %zi bytes\n", bytes);
-+ exit(1);
-+ }
-+
-+ printf("die_fd returned %i via waitfd read: revents are %x\n",
-+ status, pfd[0].revents);
-+ pfd[0].fd *= -1;
-+ procs_left--;
-+ }
-+
-+ if (pfd[1].revents != 0) {
-+ pid_t check_pid;
-+ status = 0;
-+ check_pid = waitpid(ptrace_pid, &status, __WNOTHREAD |
-+ __WALL | WUNTRACED | WNOHANG);
-+ if (check_pid < 0) {
-+ fprintf(stderr, "waitpid() failed: %s\n",
-+ strerror(errno));
-+ exit(1);
-+ }
-+ if (check_pid != ptrace_pid) {
-+ fprintf(stderr, "waitfd() said PID %i was ready, but waitpid() says it isn't: %i\n",
-+ ptrace_pid, check_pid);
-+ exit(1);
-+ }
-+ printf("ptrace_fd returned status %i via waitpid; revents are %x\n",
-+ status, pfd[1].revents);
-+ pfd[1].fd *= -1;
-+ procs_left--;
-+ }
-+ }
-+
-+ return 0;
-+}
-diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
-index c2323c27a28b..8da91bb7015c 100644
---- a/virt/kvm/eventfd.c
-+++ b/virt/kvm/eventfd.c
-@@ -232,7 +232,7 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
-
- static void
- irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh,
-- poll_table *pt)
-+ poll_table *pt, unsigned long unused)
- {
- struct kvm_kernel_irqfd *irqfd =
- container_of(pt, struct kvm_kernel_irqfd, pt);
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0004-dtrace-core-and-x86.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0004-dtrace-core-and-x86.patch
deleted file mode 100644
index 1d4614df0d62..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0004-dtrace-core-and-x86.patch
+++ /dev/null
@@ -1,8052 +0,0 @@
-From 6b71ecc990f6b40c944f31ec14a75032e4e09235 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 22:21:36 +0000
-Subject: [PATCH 04/19] dtrace: core and x86
-
-This implements DTrace's core kernel (linked-in) components,
-including platform-dependent portions for x86. (Most of this
-machinery is not used until the next commit.)
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- Makefile | 7 +-
- arch/x86/Kconfig | 3 +
- arch/x86/include/asm/dtrace_arch.h | 28 +
- arch/x86/include/asm/dtrace_cpuinfo.h | 14 +
- arch/x86/include/asm/dtrace_util.h | 16 +
- arch/x86/kernel/dtrace_util.c | 244 ++++
- arch/x86/mm/fault.c | 28 +-
- fs/exec.c | 5 +
- include/asm-generic/qrwlock.h | 24 +
- include/dtrace/dtrace_impl.h | 1236 +++++++++++++++++
- include/dtrace/dtrace_impl_defines.h | 173 +++
- include/dtrace/provider.h | 971 +++++++++++++
- include/dtrace/provider_defines.h | 41 +
- include/dtrace/types.h | 131 ++
- include/linux/cpuhotplug.h | 1 +
- include/linux/cyclic.h | 49 +
- include/linux/dtrace/cpu_defines.h | 61 +
- include/linux/dtrace_cpu.h | 53 +
- include/linux/dtrace_cpu_defines.h | 2 +
- include/linux/dtrace_os.h | 120 ++
- include/linux/dtrace_psinfo.h | 59 +
- include/linux/dtrace_task.h | 38 +
- include/linux/dtrace_task_impl.h | 28 +
- include/linux/dtrace_types.h | 13 +
- include/linux/ktime.h | 8 +
- include/linux/module.h | 3 +
- include/linux/mutex.h | 16 +
- include/linux/rwlock.h | 7 +
- include/linux/sched.h | 4 +
- include/linux/spinlock_up.h | 5 +
- include/uapi/linux/dtrace/Kbuild | 35 +
- include/uapi/linux/dtrace/actions.h | 14 +
- include/uapi/linux/dtrace/actions_defines.h | 181 +++
- include/uapi/linux/dtrace/arg.h | 42 +
- include/uapi/linux/dtrace/arg_defines.h | 21 +
- include/uapi/linux/dtrace/buffer.h | 43 +
- include/uapi/linux/dtrace/buffer_defines.h | 21 +
- include/uapi/linux/dtrace/conf.h | 35 +
- include/uapi/linux/dtrace/conf_defines.h | 21 +
- include/uapi/linux/dtrace/cpu_defines.h | 17 +
- include/uapi/linux/dtrace/dif.h | 60 +
- include/uapi/linux/dtrace/dif_defines.h | 288 ++++
- include/uapi/linux/dtrace/difo.h | 57 +
- include/uapi/linux/dtrace/difo_defines.h | 21 +
- include/uapi/linux/dtrace/dof.h | 196 +++
- include/uapi/linux/dtrace/dof_defines.h | 192 +++
- include/uapi/linux/dtrace/dtrace.h | 33 +
- include/uapi/linux/dtrace/enabling.h | 76 +
- include/uapi/linux/dtrace/enabling_defines.h | 25 +
- include/uapi/linux/dtrace/fasttrap.h | 56 +
- include/uapi/linux/dtrace/fasttrap_defines.h | 25 +
- include/uapi/linux/dtrace/fasttrap_ioctl.h | 19 +
- include/uapi/linux/dtrace/faults.h | 20 +
- include/uapi/linux/dtrace/faults_defines.h | 39 +
- include/uapi/linux/dtrace/helpers.h | 101 ++
- include/uapi/linux/dtrace/helpers_defines.h | 21 +
- include/uapi/linux/dtrace/ioctl.h | 47 +
- include/uapi/linux/dtrace/metadesc.h | 81 ++
- include/uapi/linux/dtrace/metadesc_defines.h | 24 +
- include/uapi/linux/dtrace/options.h | 20 +
- include/uapi/linux/dtrace/options_defines.h | 72 +
- include/uapi/linux/dtrace/stability.h | 52 +
- include/uapi/linux/dtrace/stability_defines.h | 53 +
- include/uapi/linux/dtrace/status.h | 50 +
- include/uapi/linux/dtrace/universal.h | 47 +
- init/Kconfig | 2 +
- init/main.c | 10 +
- kernel/Makefile | 1 +
- kernel/dtrace/Kconfig | 54 +
- kernel/dtrace/Makefile | 12 +
- kernel/dtrace/cyclic.c | 526 +++++++
- kernel/dtrace/dtrace_cpu.c | 61 +
- kernel/dtrace/dtrace_os.c | 332 +++++
- kernel/dtrace/dtrace_psinfo.c | 212 +++
- kernel/dtrace/dtrace_task.c | 237 ++++
- kernel/exit.c | 4 +
- kernel/fork.c | 23 +
- kernel/module.c | 14 +
- kernel/sched/core.c | 10 +
- kernel/sched/sched.h | 4 +
- kernel/time/timekeeping.c | 2 +
- scripts/coccinelle/dtrace/enum-elision.cocci | 29 +
- .../coccinelle/dtrace/typedef-elision.cocci | 83 ++
- scripts/package/mkspec | 1 +
- 84 files changed, 7106 insertions(+), 4 deletions(-)
- create mode 100644 arch/x86/include/asm/dtrace_arch.h
- create mode 100644 arch/x86/include/asm/dtrace_cpuinfo.h
- create mode 100644 arch/x86/include/asm/dtrace_util.h
- create mode 100644 arch/x86/kernel/dtrace_util.c
- create mode 100644 include/dtrace/dtrace_impl.h
- create mode 100644 include/dtrace/dtrace_impl_defines.h
- create mode 100644 include/dtrace/provider.h
- create mode 100644 include/dtrace/provider_defines.h
- create mode 100644 include/dtrace/types.h
- create mode 100644 include/linux/cyclic.h
- create mode 100644 include/linux/dtrace/cpu_defines.h
- create mode 100644 include/linux/dtrace_cpu.h
- create mode 100644 include/linux/dtrace_cpu_defines.h
- create mode 100644 include/linux/dtrace_os.h
- create mode 100644 include/linux/dtrace_psinfo.h
- create mode 100644 include/linux/dtrace_task.h
- create mode 100644 include/linux/dtrace_task_impl.h
- create mode 100644 include/linux/dtrace_types.h
- create mode 100644 include/uapi/linux/dtrace/Kbuild
- create mode 100644 include/uapi/linux/dtrace/actions.h
- create mode 100644 include/uapi/linux/dtrace/actions_defines.h
- create mode 100644 include/uapi/linux/dtrace/arg.h
- create mode 100644 include/uapi/linux/dtrace/arg_defines.h
- create mode 100644 include/uapi/linux/dtrace/buffer.h
- create mode 100644 include/uapi/linux/dtrace/buffer_defines.h
- create mode 100644 include/uapi/linux/dtrace/conf.h
- create mode 100644 include/uapi/linux/dtrace/conf_defines.h
- create mode 100644 include/uapi/linux/dtrace/cpu_defines.h
- create mode 100644 include/uapi/linux/dtrace/dif.h
- create mode 100644 include/uapi/linux/dtrace/dif_defines.h
- create mode 100644 include/uapi/linux/dtrace/difo.h
- create mode 100644 include/uapi/linux/dtrace/difo_defines.h
- create mode 100644 include/uapi/linux/dtrace/dof.h
- create mode 100644 include/uapi/linux/dtrace/dof_defines.h
- create mode 100644 include/uapi/linux/dtrace/dtrace.h
- create mode 100644 include/uapi/linux/dtrace/enabling.h
- create mode 100644 include/uapi/linux/dtrace/enabling_defines.h
- create mode 100644 include/uapi/linux/dtrace/fasttrap.h
- create mode 100644 include/uapi/linux/dtrace/fasttrap_defines.h
- create mode 100644 include/uapi/linux/dtrace/fasttrap_ioctl.h
- create mode 100644 include/uapi/linux/dtrace/faults.h
- create mode 100644 include/uapi/linux/dtrace/faults_defines.h
- create mode 100644 include/uapi/linux/dtrace/helpers.h
- create mode 100644 include/uapi/linux/dtrace/helpers_defines.h
- create mode 100644 include/uapi/linux/dtrace/ioctl.h
- create mode 100644 include/uapi/linux/dtrace/metadesc.h
- create mode 100644 include/uapi/linux/dtrace/metadesc_defines.h
- create mode 100644 include/uapi/linux/dtrace/options.h
- create mode 100644 include/uapi/linux/dtrace/options_defines.h
- create mode 100644 include/uapi/linux/dtrace/stability.h
- create mode 100644 include/uapi/linux/dtrace/stability_defines.h
- create mode 100644 include/uapi/linux/dtrace/status.h
- create mode 100644 include/uapi/linux/dtrace/universal.h
- create mode 100644 kernel/dtrace/Kconfig
- create mode 100644 kernel/dtrace/Makefile
- create mode 100644 kernel/dtrace/cyclic.c
- create mode 100644 kernel/dtrace/dtrace_cpu.c
- create mode 100644 kernel/dtrace/dtrace_os.c
- create mode 100644 kernel/dtrace/dtrace_psinfo.c
- create mode 100644 kernel/dtrace/dtrace_task.c
- create mode 100644 scripts/coccinelle/dtrace/enum-elision.cocci
- create mode 100644 scripts/coccinelle/dtrace/typedef-elision.cocci
-
-diff --git a/Makefile b/Makefile
-index c21d2a09c9ca..fb9393fa10f0 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1106,15 +1106,15 @@ core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
-
- vmlinux-dirs := $(patsubst %/,%,$(filter %/, \
- $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
-- $(libs-y) $(libs-m)))
-+ $(libs-y) $(libs-m) $(dtrace-y) $(dtrace-m)))
-
- vmlinux-alldirs := $(sort $(vmlinux-dirs) Documentation \
- $(patsubst %/,%,$(filter %/, $(core-) \
-- $(drivers-) $(libs-))))
-+ $(drivers-) $(libs-) $(dtrace-))))
-
- subdir-modorder := $(addsuffix modules.order,$(filter %/, \
- $(core-y) $(core-m) $(libs-y) $(libs-m) \
-- $(drivers-y) $(drivers-m)))
-+ $(drivers-y) $(drivers-m) $(dtrace-y) $(dtrace-m)))
-
- build-dirs := $(vmlinux-dirs)
- clean-dirs := $(vmlinux-alldirs)
-@@ -1129,6 +1129,7 @@ else
- KBUILD_VMLINUX_LIBS := $(patsubst %/,%/lib.a, $(libs-y))
- endif
- KBUILD_VMLINUX_OBJS += $(patsubst %/,%/built-in.a, $(drivers-y))
-+KBUILD_VMLINUX_OBJS += $(patsubst %/,%/built-in.a, $(dtrace-y))
-
- export KBUILD_VMLINUX_OBJS KBUILD_VMLINUX_LIBS
- export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 3a5ecb1039bf..372e81191f8e 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -371,6 +371,9 @@ config PGTABLE_LEVELS
- default 3 if X86_PAE
- default 2
-
-+config ARCH_SUPPORTS_DTRACE
-+ def_bool y if X86_64
-+
- config CC_HAS_SANE_STACKPROTECTOR
- bool
- default $(success,$(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC)) if 64BIT
-diff --git a/arch/x86/include/asm/dtrace_arch.h b/arch/x86/include/asm/dtrace_arch.h
-new file mode 100644
-index 000000000000..74e27f08a873
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_arch.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _X86_DTRACE_ARCH_H
-+#define _X86_DTRACE_ARCH_H
-+
-+/* Number of arguments stored inside the mstate. */
-+#define DTRACE_MSTATE_ARGS_MAX 6
-+
-+typedef uint8_t asm_instr_t;
-+
-+typedef int (*prov_exit_f)(void);
-+
-+/*
-+ * Structure to hold DTrace specific information about modules (including the
-+ * core kernel module). Note that each module (and the main kernel) already
-+ * has one field that relates to probing:
-+ * - pdata: pointer to a dtrace_module struct (for DTrace)
-+ */
-+struct dtrace_module {
-+ int enabled_cnt;
-+ prov_exit_f prov_exit; /* Called with module_mutex held */
-+};
-+
-+#endif /* _X86_DTRACE_ARCH_H */
-diff --git a/arch/x86/include/asm/dtrace_cpuinfo.h b/arch/x86/include/asm/dtrace_cpuinfo.h
-new file mode 100644
-index 000000000000..47024e169ec4
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_cpuinfo.h
-@@ -0,0 +1,14 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/* Copyright (C) 2013-2014 Oracle, Inc. */
-+
-+#ifndef _ASM_X86_DTRACE_CPUINFO_H_
-+#define _ASM_X86_DTRACE_CPUINFO_H_
-+
-+#include <asm/processor.h>
-+
-+typedef struct cpuinfo_x86 cpuinfo_arch_t;
-+
-+#define dtrace_cpuinfo_chip(ci) ((ci)->phys_proc_id)
-+
-+#endif /* _ASM_X86_DTRACE_CPUINFO_H_ */
-diff --git a/arch/x86/include/asm/dtrace_util.h b/arch/x86/include/asm/dtrace_util.h
-new file mode 100644
-index 000000000000..4d9843bbc95b
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_util.h
-@@ -0,0 +1,16 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _X86_DTRACE_UTIL_H
-+#define _X86_DTRACE_UTIL_H
-+
-+#ifndef __ASSEMBLY__
-+
-+#include <asm/dtrace_arch.h>
-+#include <asm/ptrace.h>
-+
-+#endif
-+
-+#endif /* _X86_DTRACE_UTIL_H */
-diff --git a/arch/x86/kernel/dtrace_util.c b/arch/x86/kernel/dtrace_util.c
-new file mode 100644
-index 000000000000..d3d552c062f7
---- /dev/null
-+++ b/arch/x86/kernel/dtrace_util.c
-@@ -0,0 +1,244 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_util.c
-+ * DESCRIPTION: Dynamic Tracing: Architecture utility functions
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/kdebug.h>
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/memory.h>
-+#include <linux/notifier.h>
-+#include <linux/ptrace.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+#include <linux/sched/task_stack.h>
-+#include <asm/insn.h>
-+#include <asm/pgtable.h>
-+#include <asm/ptrace.h>
-+#include <asm/text-patching.h>
-+#include <asm/dtrace_arch.h>
-+#include <asm/dtrace_util.h>
-+
-+int dtrace_instr_size(const asm_instr_t *addr)
-+{
-+ struct insn insn;
-+
-+ kernel_insn_init(&insn, addr, MAX_INSN_SIZE);
-+ insn_get_length(&insn);
-+
-+ return insn_complete(&insn) ? insn.length : -1;
-+}
-+EXPORT_SYMBOL(dtrace_instr_size);
-+
-+/*
-+ * Move the instruction pointer forward to the next instruction, effectiely
-+ * skipping the current one.
-+ */
-+static void dtrace_skip_instruction(struct pt_regs *regs)
-+{
-+ int delta;
-+
-+ delta = dtrace_instr_size((asm_instr_t *)regs->ip);
-+ BUG_ON(delta <= 0);
-+
-+ regs->ip += delta;
-+}
-+
-+void dtrace_handle_badaddr(struct pt_regs *regs)
-+{
-+ unsigned long addr = read_cr2();
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = addr;
-+
-+ dtrace_skip_instruction(regs);
-+}
-+
-+/*
-+ * Trap notification handler.
-+ */
-+int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
-+ void *args)
-+{
-+ struct die_args *dargs = args;
-+
-+ switch (val) {
-+ case DIE_PAGE_FAULT: {
-+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
-+ return NOTIFY_DONE;
-+
-+ dtrace_handle_badaddr(dargs->regs);
-+
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ }
-+ case DIE_GPF: {
-+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
-+ return NOTIFY_DONE;
-+
-+ dtrace_handle_badaddr(dargs->regs);
-+
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ }
-+ /* fallthrough */
-+ default:
-+ return NOTIFY_DONE;
-+ }
-+}
-+
-+static inline int dtrace_bad_address(void *addr)
-+{
-+ unsigned long dummy;
-+
-+ return get_kernel_nofault(dummy, (unsigned long *)addr);
-+}
-+
-+static int dtrace_user_addr_is_exec(uintptr_t addr)
-+{
-+ struct mm_struct *mm = current->mm;
-+ pgd_t *pgd;
-+
-+#if CONFIG_PGTABLE_LEVELS > 3
-+ p4d_t *p4d;
-+#endif
-+
-+ pud_t *pud;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+ unsigned long flags;
-+ int ret = 0;
-+
-+ if (mm == NULL)
-+ return 0;
-+
-+ addr &= PAGE_MASK;
-+
-+ local_irq_save(flags);
-+
-+ pgd = pgd_offset(mm, addr);
-+ if (dtrace_bad_address(pgd))
-+ goto out;
-+ if (pgd_none(*pgd) || !pgd_present(*pgd))
-+ goto out;
-+
-+#if CONFIG_PGTABLE_LEVELS > 3
-+ p4d = p4d_offset(pgd, addr);
-+ if (dtrace_bad_address(p4d))
-+ goto out;
-+ if (p4d_none(*p4d) || !p4d_present(*p4d))
-+ goto out;
-+
-+ pud = pud_offset(p4d, addr);
-+#else
-+ pud = pud_offset(pgd, addr);
-+#endif
-+
-+ if (dtrace_bad_address(pud))
-+ goto out;
-+ if (pud_none(*pud) || !pud_present(*pud))
-+ goto out;
-+ if (unlikely(pud_large(*pud))) {
-+ pte = (pte_t *)pud;
-+ if (dtrace_bad_address(pte))
-+ goto out;
-+
-+ ret = pte_exec(*pte);
-+ goto out;
-+ }
-+
-+ pmd = pmd_offset(pud, addr);
-+ if (dtrace_bad_address(pmd))
-+ goto out;
-+ if (pmd_none(*pmd))
-+ goto out;
-+ if (unlikely(pmd_large(*pmd) || !pmd_present(*pmd))) {
-+ pte = (pte_t *)pmd;
-+ if (dtrace_bad_address(pte))
-+ goto out;
-+
-+ ret = pte_exec(*pte);
-+ goto out;
-+ }
-+
-+ pte = pte_offset_map(pmd, addr);
-+ if (dtrace_bad_address(pte))
-+ goto out;
-+ if (pte_protnone(*pte))
-+ goto out;
-+ if ((pte_flags(*pte) & (_PAGE_PRESENT|_PAGE_USER|_PAGE_SPECIAL)) !=
-+ (_PAGE_PRESENT|_PAGE_USER))
-+ goto out;
-+
-+ ret = pte_exec(*pte);
-+
-+out:
-+ local_irq_restore(flags);
-+
-+ return ret;
-+}
-+
-+void dtrace_user_stacktrace(struct stacktrace_state *st)
-+{
-+ struct pt_regs *regs = current_pt_regs();
-+ uint64_t *pcs = st->pcs;
-+ int limit = st->limit;
-+ unsigned long *bos;
-+ unsigned long *sp = (unsigned long *)user_stack_pointer(regs);
-+ int ret;
-+
-+ if (!user_mode(regs))
-+ goto out;
-+
-+ if (current->dt_task == NULL)
-+ goto out;
-+
-+ bos = current->dt_task->dt_ustack;
-+
-+ st->depth = 1;
-+ if (pcs)
-+ *pcs++ = (uint64_t)instruction_pointer(regs);
-+ limit--;
-+
-+ if (!limit)
-+ goto out;
-+
-+ while (sp <= bos && limit) {
-+ unsigned long pc;
-+
-+ pagefault_disable();
-+ ret = __copy_from_user_inatomic(&pc, sp, sizeof(pc));
-+ pagefault_enable();
-+
-+ if (ret)
-+ break;
-+
-+ if (dtrace_user_addr_is_exec(pc)) {
-+ if (pcs)
-+ *pcs++ = pc;
-+ limit--;
-+ st->depth++;
-+ }
-+
-+ sp++;
-+ }
-+
-+out:
-+ if (pcs) {
-+ while (limit--)
-+ *pcs++ = 0;
-+ }
-+}
-+
-+void dtrace_mod_pdata_init(struct dtrace_module *pdata)
-+{
-+}
-+
-+void dtrace_mod_pdata_cleanup(struct dtrace_module *pdata)
-+{
-+}
-diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
-index 82bf37a5c9ec..5b16183100d0 100644
---- a/arch/x86/mm/fault.c
-+++ b/arch/x86/mm/fault.c
-@@ -18,6 +18,7 @@
- #include <linux/uaccess.h> /* faulthandler_disabled() */
- #include <linux/efi.h> /* efi_recover_from_page_fault()*/
- #include <linux/mm_types.h>
-+#include <linux/dtrace_os.h> /* dtrace_no_pf */
-
- #include <asm/cpufeature.h> /* boot_cpu_has, ... */
- #include <asm/traps.h> /* dotraplinkage, ... */
-@@ -680,6 +681,16 @@ no_context(struct pt_regs *regs, unsigned long error_code,
- (((unsigned long)tsk->stack - 1 - address < PAGE_SIZE) ||
- address - ((unsigned long)tsk->stack + THREAD_SIZE) < PAGE_SIZE)) {
- unsigned long stack = __this_cpu_ist_top_va(DF) - sizeof(void *);
-+
-+ /*
-+ * Allow for the possibility that we know what we are doing and
-+ * ignore this fault. E.g. the address may come from a source
-+ * we cannot trust and it is OK if we cannot access it.
-+ */
-+ if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code,
-+ 14, SIGKILL) == NOTIFY_STOP)
-+ return;
-+
- /*
- * We're likely to be running with very little stack space
- * left. It's plausible that we'd hit this condition but
-@@ -728,8 +739,13 @@ no_context(struct pt_regs *regs, unsigned long error_code,
- oops:
- /*
- * Oops. The kernel tried to access some bad page. We'll have to
-- * terminate things with extreme prejudice:
-+ * terminate things with extreme prejudice, unless a notifier decides
-+ * to let this one slide.
- */
-+ if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-+ SIGKILL) == NOTIFY_STOP)
-+ return;
-+
- flags = oops_begin();
-
- show_fault_oops(regs, error_code, address);
-@@ -1223,10 +1239,20 @@ void do_user_addr_fault(struct pt_regs *regs,
- tsk = current;
- mm = tsk->mm;
-
-+ /*
-+ * From here on, we know this must be a fault in userspace.
-+ */
-+
- /* kprobes don't want to hook the spurious faults: */
- if (unlikely(kprobe_page_fault(regs, X86_TRAP_PF)))
- return;
-
-+ /*
-+ * DTrace doesn't want to either.
-+ */
-+ if (unlikely(dtrace_no_pf(regs)))
-+ return;
-+
- /*
- * Reserved bits are never expected to be set on
- * entries in the user portion of the page tables.
-diff --git a/fs/exec.c b/fs/exec.c
-index ca89e0e3ef10..4340b2803004 100644
---- a/fs/exec.c
-+++ b/fs/exec.c
-@@ -64,6 +64,7 @@
- #include <linux/compat.h>
- #include <linux/vmalloc.h>
- #include <linux/io_uring.h>
-+#include <linux/dtrace_os.h>
-
- #include <linux/uaccess.h>
- #include <asm/mmu_context.h>
-@@ -1822,6 +1823,10 @@ static int bprm_execve(struct linux_binprm *bprm,
- goto out;
-
- /* execve succeeded */
-+
-+ /* Update DTrace per-task data. */
-+ dtrace_task_exec(current);
-+
- current->fs->in_exec = 0;
- current->in_execve = 0;
- rseq_execve(current);
-diff --git a/include/asm-generic/qrwlock.h b/include/asm-generic/qrwlock.h
-index 3aefde23dcea..addbb3c7d953 100644
---- a/include/asm-generic/qrwlock.h
-+++ b/include/asm-generic/qrwlock.h
-@@ -30,6 +30,26 @@
- extern void queued_read_lock_slowpath(struct qrwlock *lock);
- extern void queued_write_lock_slowpath(struct qrwlock *lock);
-
-+#ifdef CONFIG_DTRACE
-+/**
-+ * queued_peek_read_can_lock -- would read_trylock() be likely to succeed?
-+ * @lock: Pointer to queue rwlock structure
-+ */
-+static inline int queued_peek_read_can_lock(struct qrwlock *lock)
-+{
-+ return !(atomic_read(&lock->cnts) & _QW_WMASK);
-+}
-+
-+/**
-+ * queued_peek_write_can_lock -- would write_trylock() be likely to succeed?
-+ * @lock: Pointer to queue rwlock structure
-+ */
-+static inline int queued_peek_write_can_lock(struct qrwlock *lock)
-+{
-+ return !atomic_read(&lock->cnts);
-+}
-+#endif /* CONFIG_DTRACE */
-+
- /**
- * queued_read_trylock - try to acquire read lock of a queue rwlock
- * @lock : Pointer to queue rwlock structure
-@@ -120,6 +140,10 @@ static inline void queued_write_unlock(struct qrwlock *lock)
- * Remapping rwlock architecture specific functions to the corresponding
- * queue rwlock functions.
- */
-+#ifdef CONFIG_DTRACE
-+#define arch_peek_read_can_lock(l) queued_peek_read_can_lock(l)
-+#define arch_peek_write_can_lock(l) queued_peek_write_can_lock(l)
-+#endif /* CONFIG_DTRACE */
- #define arch_read_lock(l) queued_read_lock(l)
- #define arch_write_lock(l) queued_write_lock(l)
- #define arch_read_trylock(l) queued_read_trylock(l)
-diff --git a/include/dtrace/dtrace_impl.h b/include/dtrace/dtrace_impl.h
-new file mode 100644
-index 000000000000..2420103c765c
---- /dev/null
-+++ b/include/dtrace/dtrace_impl.h
-@@ -0,0 +1,1236 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Implementation
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_IMPL_H
-+#define _LINUX_DTRACE_IMPL_H
-+
-+#include <linux/cyclic.h>
-+#include <linux/idr.h>
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/dif.h>
-+#include <linux/dtrace/difo_defines.h>
-+#include <linux/dtrace/metadesc.h>
-+#include <linux/dtrace/stability.h>
-+#include <linux/dtrace/helpers.h>
-+#include <dtrace/types.h>
-+#include <dtrace/provider.h>
-+#include <dtrace/dtrace_impl_defines.h>
-+
-+struct dtrace_provider {
-+ struct dtrace_pattr dtpv_attr;
-+ struct dtrace_ppriv dtpv_priv;
-+ struct dtrace_pops dtpv_pops;
-+ char *dtpv_name;
-+ void *dtpv_arg;
-+ uint_t dtpv_defunct;
-+ struct dtrace_provider *dtpv_next;
-+};
-+
-+struct dtrace_predicate {
-+ struct dtrace_difo *dtp_difo;
-+ dtrace_cacheid_t dtp_cacheid;
-+ int dtp_refcnt;
-+};
-+
-+struct dtrace_statvar {
-+ uint64_t dtsv_data;
-+ size_t dtsv_size;
-+ int dtsv_refcnt;
-+ struct dtrace_difv dtsv_var;
-+};
-+
-+struct dtrace_action {
-+ dtrace_actkind_t dta_kind;
-+ uint16_t dta_intuple;
-+ uint32_t dta_refcnt;
-+ struct dtrace_difo *dta_difo;
-+ struct dtrace_recdesc dta_rec;
-+ struct dtrace_action *dta_prev;
-+ struct dtrace_action *dta_next;
-+};
-+
-+struct dtrace_ecb;
-+
-+struct dtrace_probe {
-+ dtrace_id_t dtpr_id;
-+ struct dtrace_ecb *dtpr_ecb;
-+ struct dtrace_ecb *dtpr_ecb_last;
-+ void *dtpr_arg;
-+ dtrace_cacheid_t dtpr_predcache;
-+ int dtpr_aframes;
-+ struct dtrace_provider *dtpr_provider;
-+ char *dtpr_mod;
-+ char *dtpr_func;
-+ char *dtpr_name;
-+ struct dtrace_probe *dtpr_nextmod;
-+ struct dtrace_probe *dtpr_prevmod;
-+ struct dtrace_probe *dtpr_nextfunc;
-+ struct dtrace_probe *dtpr_prevfunc;
-+ struct dtrace_probe *dtpr_nextname;
-+ struct dtrace_probe *dtpr_prevname;
-+ dtrace_genid_t dtpr_gen;
-+};
-+
-+struct dtrace_state;
-+
-+struct dtrace_ecb {
-+ dtrace_epid_t dte_epid;
-+ uint32_t dte_alignment;
-+ size_t dte_needed;
-+ size_t dte_size;
-+ struct dtrace_predicate *dte_predicate;
-+ struct dtrace_action *dte_action;
-+ struct dtrace_ecb *dte_next;
-+ struct dtrace_state *dte_state;
-+ uint32_t dte_cond;
-+ struct dtrace_probe *dte_probe;
-+ struct dtrace_action *dte_action_last;
-+ uint64_t dte_uarg;
-+};
-+
-+struct dtrace_key {
-+ uint64_t dttk_value;
-+ uint64_t dttk_size;
-+};
-+
-+struct dtrace_tuple {
-+ uint32_t dtt_nkeys;
-+ uint32_t dtt_pad;
-+ struct dtrace_key dtt_key[1];
-+};
-+
-+struct dtrace_dynvar {
-+ uint64_t dtdv_hashval;
-+ struct dtrace_dynvar *dtdv_next;
-+ void *dtdv_data;
-+ struct dtrace_tuple dtdv_tuple;
-+};
-+
-+struct dtrace_dstate_percpu {
-+ struct dtrace_dynvar *dtdsc_free;
-+ struct dtrace_dynvar *dtdsc_dirty;
-+ struct dtrace_dynvar *dtdsc_rinsing;
-+ struct dtrace_dynvar *dtdsc_clean;
-+ uint64_t dtdsc_drops;
-+ uint64_t dtdsc_dirty_drops;
-+ uint64_t dtdsc_rinsing_drops;
-+#ifdef CONFIG_64BIT
-+ uint64_t dtdsc_pad;
-+#else
-+ uint64_t dtdsc_pad[2];
-+#endif
-+};
-+
-+struct dtrace_dynhash {
-+ struct dtrace_dynvar *dtdh_chain;
-+ uintptr_t dtdh_lock;
-+#ifdef CONFIG_64BIT
-+ uintptr_t dtdh_pad[6];
-+#else
-+ uintptr_t dtdh_pad[14];
-+#endif
-+};
-+
-+struct dtrace_dstate {
-+ void *dtds_base;
-+ size_t dtds_size;
-+ size_t dtds_hashsize;
-+ size_t dtds_chunksize;
-+ struct dtrace_dynhash *dtds_hash;
-+ enum dtrace_dstate_state dtds_state;
-+ struct dtrace_dstate_percpu *dtds_percpu;
-+};
-+
-+struct dtrace_vstate {
-+ struct dtrace_state *dtvs_state;
-+ struct dtrace_statvar **dtvs_globals;
-+ int dtvs_nglobals;
-+ struct dtrace_difv *dtvs_tlocals;
-+ int dtvs_ntlocals;
-+ struct dtrace_statvar **dtvs_locals;
-+ int dtvs_nlocals;
-+ struct dtrace_dstate dtvs_dynvars;
-+};
-+
-+/*
-+ * DTrace Machine State
-+ *
-+ * In the process of processing a fired probe, DTrace needs to track and/or
-+ * cache some per-CPU state associated with that particular firing. This is
-+ * state that is always discarded after the probe firing has completed, and
-+ * much of it is not specific to any DTrace consumer, remaining valid across
-+ * all ECBs. This state is tracked in the dtrace_mstate structure.
-+ */
-+
-+struct dtrace_mstate {
-+ uintptr_t dtms_scratch_base;
-+ uintptr_t dtms_scratch_ptr;
-+ size_t dtms_scratch_size;
-+ uint32_t dtms_present;
-+ uint64_t dtms_arg[7];
-+ dtrace_epid_t dtms_epid;
-+ ktime_t dtms_timestamp;
-+ int dtms_stackdepth;
-+ int dtms_ustackdepth;
-+ struct dtrace_probe *dtms_probe;
-+ uintptr_t dtms_caller;
-+ uint64_t dtms_ucaller;
-+ int dtms_ipl;
-+ int dtms_fltoffs;
-+ uintptr_t dtms_strtok;
-+ uint32_t dtms_access;
-+ struct dtrace_difo *dtms_difo;
-+};
-+
-+struct dtrace_buffer {
-+ uint64_t dtb_offset;
-+ uint64_t dtb_size;
-+ uint32_t dtb_flags;
-+ uint32_t dtb_drops;
-+ caddr_t dtb_tomax;
-+ caddr_t dtb_xamot;
-+ uint32_t dtb_xamot_flags;
-+ uint32_t dtb_xamot_drops;
-+ uint64_t dtb_xamot_offset;
-+ uint32_t dtb_errors;
-+ uint32_t dtb_xamot_errors;
-+#ifndef CONFIG_64BIT
-+ uint64_t dtb_pad1;
-+#endif
-+};
-+
-+struct dtrace_speculation {
-+ enum dtrace_speculation_state dtsp_state;
-+ int dtsp_cleaning;
-+ struct dtrace_buffer *dtsp_buffer;
-+};
-+
-+struct dtrace_aggregation {
-+ struct dtrace_action dtag_action;
-+ dtrace_aggid_t dtag_id;
-+ struct dtrace_ecb *dtag_ecb;
-+ struct dtrace_action *dtag_first;
-+ uint32_t dtag_base;
-+ uint8_t dtag_hasarg;
-+ uint64_t dtag_initial;
-+ void (*dtag_aggregate)(uint64_t *, uint64_t, uint64_t);
-+};
-+
-+struct dtrace_cred {
-+ const struct cred *dcr_cred;
-+ uint8_t dcr_destructive;
-+ uint8_t dcr_visible;
-+ uint16_t dcr_action;
-+};
-+
-+struct dtrace_state {
-+ dev_t dts_dev;
-+ int dts_necbs;
-+ struct dtrace_ecb **dts_ecbs;
-+ dtrace_epid_t dts_epid;
-+ size_t dts_needed;
-+ struct dtrace_state *dts_anon;
-+ enum dtrace_activity dts_activity;
-+ struct dtrace_vstate dts_vstate;
-+ struct dtrace_buffer *dts_buffer;
-+ struct dtrace_buffer *dts_aggbuffer;
-+ struct dtrace_speculation *dts_speculations;
-+ int dts_nspeculations;
-+ struct idr dts_agg_idr;
-+ int dts_naggs;
-+ uint64_t dts_errors;
-+ uint32_t dts_speculations_busy;
-+ uint32_t dts_speculations_unavail;
-+ uint32_t dts_stkstroverflows;
-+ uint32_t dts_dblerrors;
-+ uint32_t dts_reserve;
-+ cyclic_id_t dts_cleaner;
-+ cyclic_id_t dts_deadman;
-+ ktime_t dts_laststatus;
-+ ktime_t dts_alive;
-+ char dts_speculates;
-+ char dts_destructive;
-+ int dts_nformats;
-+ char **dts_formats;
-+ dtrace_optval_t dts_options[DTRACEOPT_MAX];
-+ struct dtrace_cred dts_cred;
-+ size_t dts_nretained;
-+};
-+
-+struct dtrace_enabling {
-+ struct dtrace_ecbdesc **dten_desc;
-+ int dten_ndesc;
-+ int dten_maxdesc;
-+ struct dtrace_vstate *dten_vstate;
-+ dtrace_genid_t dten_probegen;
-+ struct dtrace_ecbdesc *dten_current;
-+ int dten_error;
-+ int dten_primed;
-+ struct dtrace_enabling *dten_prev;
-+ struct dtrace_enabling *dten_next;
-+};
-+
-+typedef int dtrace_probekey_f(const char *, const char *, int);
-+
-+struct dtrace_probekey {
-+ const char *dtpk_prov;
-+ dtrace_probekey_f *dtpk_pmatch;
-+ const char *dtpk_mod;
-+ dtrace_probekey_f *dtpk_mmatch;
-+ const char *dtpk_func;
-+ dtrace_probekey_f *dtpk_fmatch;
-+ const char *dtpk_name;
-+ dtrace_probekey_f *dtpk_nmatch;
-+ dtrace_id_t dtpk_id;
-+};
-+
-+struct dtrace_hashbucket {
-+ struct dtrace_hashbucket *dthb_next;
-+ struct dtrace_probe *dthb_chain;
-+ int dthb_len;
-+};
-+
-+struct dtrace_hash {
-+ struct dtrace_hashbucket **dth_tab;
-+ int dth_size;
-+ int dth_mask;
-+ int dth_nbuckets;
-+ uintptr_t dth_nextoffs;
-+ uintptr_t dth_prevoffs;
-+ uintptr_t dth_stroffs;
-+};
-+
-+/*
-+ * DTrace supports safe loads from probe context; if the address turns out to
-+ * be invalid, a bit will be set by the kernel indicating that DTrace
-+ * encountered a memory error, and DTrace will propagate the error to the user
-+ * accordingly. However, there may exist some regions of memory in which an
-+ * arbitrary load can change system state, and from which it is impossible to
-+ * recover from such a load after it has been attempted. Examples of this may
-+ * include memory in which programmable I/O registers are mapped (for which a
-+ * read may have some implications for the device) or (in the specific case of
-+ * UltraSPARC-I and -II) the virtual address hole. The platform is required
-+ * to make DTrace aware of these toxic ranges; DTrace will then check that
-+ * target addresses are not in a toxic range before attempting to issue a
-+ * safe load.
-+ */
-+struct dtrace_toxrange {
-+ uintptr_t dtt_base;
-+ uintptr_t dtt_limit;
-+};
-+
-+/*
-+ * DTrace Helper Implementation
-+ *
-+ * A description of the helper architecture may be found in <linux/dtrace.h>.
-+ * Each process contains a pointer to its helpers in its dtrace_helpers
-+ * member. This is a pointer to a dtrace_helpers structure, which contains an
-+ * array of pointers to dtrace_helper structures, helper variable state (shared
-+ * among a process's helpers) and a generation count. (The generation count is
-+ * used to provide an identifier when a helper is added so that it may be
-+ * subsequently removed.) The dtrace_helper structure is self-explanatory,
-+ * containing pointers to the objects needed to execute the helper. Note that
-+ * helpers are _duplicated_ across fork(2), and destroyed on exec(2). No more
-+ * than dtrace_helpers_max are allowed per-process.
-+ */
-+struct dtrace_helper_action {
-+ int dtha_generation; /* helper action generation */
-+ int dtha_nactions; /* number of actions */
-+ struct dtrace_difo *dtha_predicate; /* helper action predicate */
-+ struct dtrace_difo **dtha_actions; /* array of actions */
-+ struct dtrace_helper_action *dtha_next; /* next helper action */
-+};
-+
-+struct dtrace_helper_provider {
-+ int dthp_generation; /* helper provider generation */
-+ uint32_t dthp_ref; /* reference count */
-+ struct dof_helper dthp_prov; /* DOF w/ provider and probes */
-+};
-+
-+struct dtrace_helpers {
-+ struct dtrace_helper_action **dthps_actions; /* helper actions array */
-+ struct dtrace_vstate dthps_vstate; /* helper action var. state */
-+ struct dtrace_helper_provider **dthps_provs; /* providers array */
-+ uint_t dthps_nprovs; /* count of providers */
-+ uint_t dthps_maxprovs; /* provider array size */
-+ int dthps_generation; /* current generation */
-+ pid_t dthps_pid; /* pid of associated proc */
-+ int dthps_deferred; /* helper in deferred list */
-+ struct dtrace_helpers *dthps_next; /* next pointer */
-+ struct dtrace_helpers *dthps_prev; /* prev pointer */
-+};
-+
-+/*
-+ * DTrace Helper Action Tracing
-+ *
-+ * Debugging helper actions can be arduous. To ease the development and
-+ * debugging of helpers, DTrace contains a tracing-framework-within-a-tracing-
-+ * framework: helper tracing. If dtrace_helptrace_enabled is non-zero (which
-+ * it is by default on DEBUG kernels), all helper activity will be traced to a
-+ * global, in-kernel ring buffer. Each entry includes a pointer to the specific
-+ * helper, the location within the helper, and a trace of all local variables.
-+ * The ring buffer may be displayed in a human-readable format with the
-+ * ::dtrace_helptrace mdb(1) dcmd.
-+ */
-+struct dtrace_helptrace {
-+ struct dtrace_helper_action *dtht_helper; /* helper action */
-+ int dtht_where; /* where in helper action */
-+ int dtht_nlocals; /* number of locals */
-+ int dtht_fault; /* type of fault (if any) */
-+ int dtht_fltoffs; /* DIF offset */
-+ uint64_t dtht_illval; /* faulting value */
-+ uint64_t dtht_locals[1]; /* local variables */
-+};
-+
-+extern struct mutex dtrace_lock;
-+extern struct mutex dtrace_provider_lock;
-+extern struct mutex dtrace_meta_lock;
-+
-+extern dtrace_genid_t dtrace_probegen;
-+extern struct kmem_cache *dtrace_probe_cachep;
-+
-+extern struct dtrace_pops dtrace_provider_ops;
-+
-+extern int dtrace_opens;
-+extern int dtrace_err_verbose;
-+
-+extern struct dtrace_toxrange *dtrace_toxrange;
-+extern int dtrace_toxranges;
-+
-+extern void dtrace_nullop(void);
-+extern int dtrace_enable_nullop(void);
-+extern int dtrace_istoxic(uintptr_t, size_t);
-+
-+/*
-+ * DTrace Probe Context Functions
-+ */
-+
-+extern void dtrace_panic(const char *, ...);
-+extern int dtrace_assfail(const char *, const char *, int);
-+extern void dtrace_aggregate_min(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_max(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_quantize(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_lquantize(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_llquantize(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_avg(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_stddev(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_count(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_sum(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate(struct dtrace_aggregation *,
-+ struct dtrace_buffer *,
-+ intptr_t, struct dtrace_buffer *, uint64_t,
-+ uint64_t);
-+
-+/*
-+ * DTrace Probe Hashing Functions
-+ */
-+
-+extern struct dtrace_hash *dtrace_hash_create(uintptr_t, uintptr_t, uintptr_t);
-+extern void dtrace_hash_destroy(struct dtrace_hash *);
-+extern int dtrace_hash_add(struct dtrace_hash *, struct dtrace_probe *);
-+extern struct dtrace_probe *dtrace_hash_lookup(struct dtrace_hash *,
-+ struct dtrace_probe *);
-+extern int dtrace_hash_collisions(struct dtrace_hash *, struct dtrace_probe *);
-+extern void dtrace_hash_remove(struct dtrace_hash *, struct dtrace_probe *);
-+
-+/*
-+ * DTrace Speculation Functions
-+ */
-+extern int dtrace_speculation(struct dtrace_state *);
-+extern void dtrace_speculation_commit(struct dtrace_state *, processorid_t,
-+ dtrace_specid_t);
-+extern void dtrace_speculation_discard(struct dtrace_state *, processorid_t,
-+ dtrace_specid_t);
-+extern void dtrace_speculation_clean(struct dtrace_state *);
-+extern struct dtrace_buffer *dtrace_speculation_buffer(struct dtrace_state *,
-+ processorid_t,
-+ dtrace_specid_t);
-+
-+/*
-+ * DTrace Non-Probe Context Utility Functions
-+ */
-+
-+/*
-+ * DTrace Matching Functions
-+ */
-+extern struct dtrace_hash *dtrace_bymod;
-+extern struct dtrace_hash *dtrace_byfunc;
-+extern struct dtrace_hash *dtrace_byname;
-+
-+extern int dtrace_match_priv(const struct dtrace_probe *, uint32_t, kuid_t);
-+extern int dtrace_match_probe(const struct dtrace_probe *,
-+ const struct dtrace_probekey *, uint32_t,
-+ kuid_t);
-+extern int dtrace_match_glob(const char *, const char *, int);
-+extern int dtrace_match_string(const char *, const char *, int);
-+extern int dtrace_match_nul(const char *, const char *, int);
-+extern int dtrace_match_nonzero(const char *, const char *, int);
-+extern int dtrace_match(const struct dtrace_probekey *, uint32_t, kuid_t,
-+ int (*matched)(struct dtrace_probe *, void *), void *);
-+extern void dtrace_probekey(const struct dtrace_probedesc *,
-+ struct dtrace_probekey *);
-+
-+/*
-+ * DTrace Provider-to-Framework API Functions
-+ */
-+
-+extern struct dtrace_provider *dtrace_provider;
-+extern struct dtrace_meta *dtrace_meta_pid;
-+extern struct dtrace_helpers *dtrace_deferred_pid;
-+
-+/*
-+ * DTrace Privilege Check Functions
-+ */
-+extern int dtrace_priv_proc_destructive(struct dtrace_state *);
-+extern int dtrace_priv_proc_control(struct dtrace_state *);
-+extern int dtrace_priv_proc(struct dtrace_state *);
-+extern int dtrace_priv_kernel(struct dtrace_state *);
-+
-+/*
-+ * DTrace Probe Management Functions
-+ */
-+
-+extern int dtrace_probe_enable(const struct dtrace_probedesc *,
-+ struct dtrace_enabling *);
-+extern void dtrace_probe_description(const struct dtrace_probe *,
-+ struct dtrace_probedesc *);
-+extern void dtrace_probe_provide(struct dtrace_probedesc *,
-+ struct dtrace_provider *);
-+extern int dtrace_probe_init(void);
-+extern void dtrace_probe_exit(void);
-+extern void dtrace_probe_remove_id(dtrace_id_t);
-+extern struct dtrace_probe *dtrace_probe_lookup_id(dtrace_id_t);
-+extern struct dtrace_probe *dtrace_probe_get_next(dtrace_id_t *);
-+extern int dtrace_probe_for_each(int (*)(int, void *, void *), void *);
-+
-+/*
-+ * DTrace Kernel Hooks
-+ */
-+extern void (*dtrace_modload)(struct module *);
-+extern void (*dtrace_modunload)(struct module *);
-+
-+extern uint8_t dtrace_load8(uintptr_t);
-+extern uint16_t dtrace_load16(uintptr_t);
-+extern uint32_t dtrace_load32(uintptr_t);
-+extern uint64_t dtrace_load64(uintptr_t);
-+#ifdef CONFIG_64BIT
-+#define dtrace_loadptr dtrace_load64
-+#else
-+#define dtrace_loadptr dtrace_load32
-+#endif
-+
-+
-+extern void dtrace_bzero(void *, size_t);
-+
-+extern int dtrace_vcanload(void *, struct dtrace_diftype *,
-+ struct dtrace_mstate *,
-+ struct dtrace_vstate *);
-+extern int dtrace_canload(uintptr_t, size_t, struct dtrace_mstate *,
-+ struct dtrace_vstate *);
-+
-+extern int dtrace_difo_validate(struct dtrace_difo *, struct dtrace_vstate *,
-+ uint_t, const struct cred *);
-+extern int dtrace_difo_validate_helper(struct dtrace_difo *);
-+extern int dtrace_difo_cacheable(struct dtrace_difo *);
-+extern void dtrace_difo_hold(struct dtrace_difo *);
-+extern void dtrace_difo_init(struct dtrace_difo *, struct dtrace_vstate *);
-+extern struct dtrace_difo *dtrace_difo_duplicate(struct dtrace_difo *,
-+ struct dtrace_vstate *);
-+extern void dtrace_difo_release(struct dtrace_difo *, struct dtrace_vstate *);
-+
-+extern uint64_t dtrace_vtime_references;
-+
-+extern uint64_t dtrace_dif_emulate(struct dtrace_difo *,
-+ struct dtrace_mstate *,
-+ struct dtrace_vstate *,
-+ struct dtrace_state *);
-+
-+/*
-+ * DTrace Format Functions
-+ */
-+extern uint16_t dtrace_format_add(struct dtrace_state *, char *);
-+extern void dtrace_format_remove(struct dtrace_state *, uint16_t);
-+extern void dtrace_format_destroy(struct dtrace_state *);
-+
-+/*
-+ * DTrace Predicate Functions
-+ */
-+extern struct dtrace_predicate *dtrace_predicate_create(struct dtrace_difo *);
-+extern void dtrace_predicate_hold(struct dtrace_predicate *);
-+extern void dtrace_predicate_release(struct dtrace_predicate *,
-+ struct dtrace_vstate *);
-+
-+/*
-+ * DTrace Action Description Functions
-+ */
-+extern struct dtrace_actdesc *dtrace_actdesc_create(dtrace_actkind_t, uint32_t,
-+ uint64_t, uint64_t);
-+extern void dtrace_actdesc_hold(struct dtrace_actdesc *);
-+extern void dtrace_actdesc_release(struct dtrace_actdesc *,
-+ struct dtrace_vstate *);
-+
-+/*
-+ * DTrace Helper Functions
-+ */
-+extern void dtrace_helpers_destroy(struct task_struct *);
-+extern void dtrace_helpers_duplicate(struct task_struct *,
-+ struct task_struct *);
-+extern uint64_t dtrace_helper(int, struct dtrace_mstate *,
-+ struct dtrace_state *,
-+ uint64_t, uint64_t);
-+
-+/*
-+ * DTrace ECB Functions
-+ */
-+extern struct dtrace_ecb *dtrace_ecb_create_cache;
-+
-+extern int dtrace_ecb_create_enable(struct dtrace_probe *, void *);
-+extern void dtrace_ecb_disable(struct dtrace_ecb *);
-+extern void dtrace_ecb_destroy(struct dtrace_ecb *);
-+extern void dtrace_ecb_resize(struct dtrace_ecb *);
-+extern int dtrace_ecb_enable(struct dtrace_ecb *);
-+extern struct dtrace_ecb *dtrace_epid2ecb(struct dtrace_state *,
-+ dtrace_epid_t);
-+extern struct dtrace_aggregation *dtrace_aggid2agg(struct dtrace_state *,
-+ dtrace_aggid_t);
-+
-+/*
-+ * DTrace Buffer Functions
-+ *
-+ * DTrace Buffers
-+ *
-+ * Principal buffers, aggregation buffers, and speculative buffers are all
-+ * managed with the dtrace_buffer structure. By default, this structure
-+ * includes twin data buffers -- dtb_tomax and dtb_xamot -- that serve as the
-+ * active and passive buffers, respectively. For speculative buffers,
-+ * dtb_xamot will be NULL; for "ring" and "fill" buffers, dtb_xamot will point
-+ * to a scratch buffer. For all buffer types, the dtrace_buffer structure is
-+ * always allocated on a per-CPU basis; a single dtrace_buffer structure is
-+ * never shared among CPUs. (That is, there is never true sharing of the
-+ * dtrace_buffer structure; to prevent false sharing of the structure, it must
-+ * always be aligned to the coherence granularity -- generally 64 bytes.)
-+ *
-+ * One of the critical design decisions of DTrace is that a given ECB always
-+ * stores the same quantity and type of data. This is done to assure that the
-+ * only metadata required for an ECB's traced data is the EPID. That is, from
-+ * the EPID, the consumer can determine the data layout. (The data buffer
-+ * layout is shown schematically below.) By assuring that one can determine
-+ * data layout from the EPID, the metadata stream can be separated from the
-+ * data stream -- simplifying the data stream enormously.
-+ *
-+ * base of data buffer ---> +------+--------------------+------+
-+ * | EPID | data | EPID |
-+ * +------+--------+------+----+------+
-+ * | data | EPID | data |
-+ * +---------------+------+-----------+
-+ * | data, cont. |
-+ * +------+--------------------+------+
-+ * | EPID | data | |
-+ * +------+--------------------+ |
-+ * | || |
-+ * | || |
-+ * | \/ |
-+ * : :
-+ * . .
-+ * . .
-+ * . .
-+ * : :
-+ * | |
-+ * limit of data buffer ---> +----------------------------------+
-+ *
-+ * When evaluating an ECB, dtrace_probe() determines if the ECB's needs of the
-+ * principal buffer (both scratch and payload) exceed the available space. If
-+ * the ECB's needs exceed available space (and if the principal buffer policy
-+ * is the default "switch" policy), the ECB is dropped, the buffer's drop count
-+ * is incremented, and processing advances to the next ECB. If the ECB's needs
-+ * can be met with the available space, the ECB is processed, but the offset in
-+ * the principal buffer is only advanced if the ECB completes processing
-+ * without error.
-+ *
-+ * When a buffer is to be switched (either because the buffer is the principal
-+ * buffer with a "switch" policy or because it is an aggregation buffer), a
-+ * cross call is issued to the CPU associated with the buffer. In the cross
-+ * call context, interrupts are disabled, and the active and the inactive
-+ * buffers are atomically switched. This involves switching the data pointers,
-+ * copying the various state fields (offset, drops, errors, etc.) into their
-+ * inactive equivalents, and clearing the state fields. Because interrupts are
-+ * disabled during this procedure, the switch is guaranteed to appear atomic to
-+ * dtrace_probe().
-+ *
-+ * DTrace Ring Buffering
-+ *
-+ * To process a ring buffer correctly, one must know the oldest valid record.
-+ * Processing starts at the oldest record in the buffer and continues until
-+ * the end of the buffer is reached. Processing then resumes starting with
-+ * the record stored at offset 0 in the buffer, and continues until the
-+ * youngest record is processed. If trace records are of a fixed-length,
-+ * determining the oldest record is trivial:
-+ *
-+ * - If the ring buffer has not wrapped, the oldest record is the record
-+ * stored at offset 0.
-+ *
-+ * - If the ring buffer has wrapped, the oldest record is the record stored
-+ * at the current offset.
-+ *
-+ * With variable length records, however, just knowing the current offset
-+ * doesn't suffice for determining the oldest valid record: assuming that one
-+ * allows for arbitrary data, one has no way of searching forward from the
-+ * current offset to find the oldest valid record. (That is, one has no way
-+ * of separating data from metadata.) It would be possible to simply refuse to
-+ * process any data in the ring buffer between the current offset and the
-+ * limit, but this leaves (potentially) an enormous amount of otherwise valid
-+ * data unprocessed.
-+ *
-+ * To effect ring buffering, we track two offsets in the buffer: the current
-+ * offset and the _wrapped_ offset. If a request is made to reserve some
-+ * amount of data, and the buffer has wrapped, the wrapped offset is
-+ * incremented until the wrapped offset minus the current offset is greater
-+ * than or equal to the reserve request. This is done by repeatedly looking
-+ * up the ECB corresponding to the EPID at the current wrapped offset, and
-+ * incrementing the wrapped offset by the size of the data payload
-+ * corresponding to that ECB. If this offset is greater than or equal to the
-+ * limit of the data buffer, the wrapped offset is set to 0. Thus, the
-+ * current offset effectively "chases" the wrapped offset around the buffer.
-+ * Schematically:
-+ *
-+ * base of data buffer ---> +------+--------------------+------+
-+ * | EPID | data | EPID |
-+ * +------+--------+------+----+------+
-+ * | data | EPID | data |
-+ * +---------------+------+-----------+
-+ * | data, cont. |
-+ * +------+---------------------------+
-+ * | EPID | data |
-+ * current offset ---> +------+---------------------------+
-+ * | invalid data |
-+ * wrapped offset ---> +------+--------------------+------+
-+ * | EPID | data | EPID |
-+ * +------+--------+------+----+------+
-+ * | data | EPID | data |
-+ * +---------------+------+-----------+
-+ * : :
-+ * . .
-+ * . ... valid data ... .
-+ * . .
-+ * : :
-+ * +------+-------------+------+------+
-+ * | EPID | data | EPID | data |
-+ * +------+------------++------+------+
-+ * | data, cont. | leftover |
-+ * limit of data buffer ---> +-------------------+--------------+
-+ *
-+ * If the amount of requested buffer space exceeds the amount of space
-+ * available between the current offset and the end of the buffer:
-+ *
-+ * (1) all words in the data buffer between the current offset and the limit
-+ * of the data buffer (marked "leftover", above) are set to
-+ * DTRACE_EPIDNONE
-+ *
-+ * (2) the wrapped offset is set to zero
-+ *
-+ * (3) the iteration process described above occurs until the wrapped offset
-+ * is greater than the amount of desired space.
-+ *
-+ * The wrapped offset is implemented by (re-)using the inactive offset.
-+ * In a "switch" buffer policy, the inactive offset stores the offset in
-+ * the inactive buffer; in a "ring" buffer policy, it stores the wrapped
-+ * offset.
-+ *
-+ * DTrace Scratch Buffering
-+ *
-+ * Some ECBs may wish to allocate dynamically-sized temporary scratch memory.
-+ * To accommodate such requests easily, scratch memory may be allocated in
-+ * the buffer beyond the current offset plus the needed memory of the current
-+ * ECB. If there isn't sufficient room in the buffer for the requested amount
-+ * of scratch space, the allocation fails and an error is generated. Scratch
-+ * memory is tracked in the dtrace_mstate_t and is automatically freed when
-+ * the ECB ceases processing. Note that ring buffers cannot allocate their
-+ * scratch from the principal buffer -- lest they needlessly overwrite older,
-+ * valid data. Ring buffers therefore have their own dedicated scratch buffer
-+ * from which scratch is allocated.
-+ */
-+
-+extern void dtrace_buffer_switch(struct dtrace_buffer *);
-+extern void dtrace_buffer_activate(struct dtrace_state *);
-+extern int dtrace_buffer_alloc(struct dtrace_buffer *, size_t, int,
-+ processorid_t);
-+extern void dtrace_buffer_drop(struct dtrace_buffer *);
-+extern intptr_t dtrace_buffer_reserve(struct dtrace_buffer *, size_t, size_t,
-+ struct dtrace_state *,
-+ struct dtrace_mstate *);
-+extern void dtrace_buffer_polish(struct dtrace_buffer *);
-+extern void dtrace_buffer_free(struct dtrace_buffer *);
-+
-+/*
-+ * DTrace framework/probe data synchronization
-+ * -------------------------------------------
-+ *
-+ * The dtrace_sync() facility is used to synchronize global DTrace framework
-+ * data with DTrace probe context. The framework updates data and then calls
-+ * dtrace_sync(). dtrace_sync() loops until it observes all CPUs have been out
-+ * of probe context at least once. This ensures all consumers are using the
-+ * updated data.
-+ *
-+ * DTrace probes have several requirements. First DTrace probe context cannot
-+ * block. DTrace probes execute with interrupts disabled. Locks cannot be
-+ * acquired in DTrace probe context. A second requirement is that DTrace
-+ * probes need to be as high performance as possible to minimize the effect of
-+ * enabled probes.
-+ *
-+ * DTrace framework data changes have their own requirements. DTrace data
-+ * changes/syncs are extremely infrequent compared to DTrace probe firings.
-+ * Probes can be in commonly executed code. A good trade-off is to favor
-+ * DTrace probe context performance over DTrace sync performance.
-+ *
-+ * To meet the above requirements, the DTrace data synchronization algorithm
-+ * is lock-less. The DTrace probe path is wait-free. The DTrace probe path
-+ * is memory-barrier-free in the common case to minimize probe effect.
-+ * dtrace_probe has been made membar free in the common case by adding a read
-+ * in dtrace_probe and adding an additional write and membar to dtrace_sync().
-+ *
-+ * A simple algorithm is to have dtrace_probe set a flag for its CPU when
-+ * entering DTrace probe context and clear the flag when it exits DTrace probe
-+ * context. A producer of DTrace framework data checks the flag to detect and
-+ * synchronize with probe context. Unfortunately memory ordering issues
-+ * complicate the implementation. Memory barriers are required in probe
-+ * context for this simple approach to work.
-+ *
-+ * A simple implementation to sync with one CPU that works with any memory
-+ * ordering model is:
-+ *
-+ * DTrace probe:
-+ * 1. CPU->in_probe_context = B_TRUE;
-+ * 2. dtrace_membar_enter()// membar #StoreLoad|#StoreStore
-+ * 3. access framework shared data// critical section
-+ * 4. dtrace_membar_exit()// membar #LoadStore|#StoreStore
-+ * 5. CPU->in_probe_context = B_FALSE;
-+ *
-+ * DTrace framework dtrace_sync:
-+ * 0. update framework shared data
-+ * 1. dtrace_membar_enter()// membar #StoreLoad|#StoreStore
-+ * 2. while (CPU->in_probe_context == B_TRUE)
-+ * 3. spin
-+ * 4. dtrace_membar_exit()// membar #LoadStore|#StoreStore
-+ * 5. produce shared dtrace data
-+ *
-+ * A note on memory ordering
-+ * -------------------------
-+ *
-+ * dtrace_membar_enter() guarantees later loads cannot complete before earlier
-+ * stores, and it guarantees later stores cannot complete before earlier stores.
-+ * dtrace_membar_enter() is, in SPARC parlance, a membar #StoreLoad|#StoreStore.
-+ *
-+ * dtrace_membar_exit() guarantees later stores cannot complete before earlier
-+ * loads, and it guarantees later stores cannot complete before earlier stores.
-+ * dtrace_membar_exit() is, in SPARC parlance, a membar #LoadStore|#StoreStore.
-+ *
-+ * Please see the SPARC and Intel processor guides on memory ordering.
-+ * All sun4v and Fujitsu processors are TSO (Total Store Order). Modern
-+ * supported Intel and AMD processors have similar load and store ordering
-+ * to SPARC. All processors currently supported by Solaris have these memory
-+ * ordering properties:
-+ * 1) Loads are ordered with respect to earlier loads.
-+ * 2) Stores are ordered with respect to earlier stores.
-+ * 3a) SPARC Atomic load-store behaves as if it were followed by a
-+ * MEMBAR #LoadLoad, #LoadStore, and #StoreStore.
-+ * 3b) X86 Atomic operations serialize load and store.
-+ * 4) Stores cannot bypass earlier loads.
-+ *
-+ * The above implementation details allow the membars to be simplified thus:
-+ * A) dtrace_membar_enter() can be reduced to "membar #StoreLoad" on sparc.
-+ * See property number 4 above.
-+ * Since dtrace_membar_enter() is an atomic operation on x86, it cannot be
-+ * reduced further.
-+ * B) dtrace_membar_exit() becomes a NOP on both SPARC and x86.
-+ * See properties 2 and 4.
-+ *
-+ *
-+ * Elimination of membar #StoreLoad from dtrace probe context
-+ * ----------------------------------------------------------
-+ *
-+ * Furthermore it is possible to eliminate all memory barriers from the common
-+ * dtrace_probe() entry case. The only membar needed in dtrace_probe is there
-+ * to prevent Loads of global DTrace framework data from passing the Store to
-+ * the "in_probe_context" flag (i.e. the dtrace_membar_enter()).
-+ * A Load at the beginning of the algorithm is also ordered with these later
-+ * Loads and Stores: the membar #StoreLoad can be replaced with a early Load of
-+ * a "sync_request" flag and a conditional branch on the flag value.
-+ *
-+ * dtrace_sync() first Stores to the "sync_request" flag, and dtrace_probe()
-+ * starts by Loading the flag. This Load in dtrace_probe() of "sync_request"
-+ * is ordered with its later Store to the "in_probe_context" flag and
-+ * dtrace_probe's later Loads of DTrace framework data. dtrace_probe() only
-+ * needs a membar #StoreLoad iff the "sync_request" flag is set.
-+ *
-+ * Optimized Synchronization Algorithm
-+ * -----------------------------------
-+ *
-+ * DTrace probe:
-+ * + 1a. request_flag = CPU->sync_request // Load
-+ * 1b. CPU->in_probe_context = B_TRUE // Store
-+ * + 2. if request_flag > 0
-+ * dtrace_membar_enter() // membar #StoreLoad
-+ * 3. access framework shared data // critical section
-+ * -
-+ * 5. CPU->in_probe_context = B_FALSE // Store
-+ *
-+ * DTrace framework dtrace_sync:
-+ * + 1a. atomically add 1 to CPU->sync_request // Store and
-+ * 1b. dtrace_membar_enter() // membar #StoreLoad
-+ * 2. while (CPU->in_probe_context == B_TRUE) // Load
-+ * 3. spin
-+ * + 4a. atomically subtract 1 from CPU->sync_request // Load + Store
-+ * -
-+ * 5. produce shared dtrace data
-+ *
-+ * This algorithm has been proven correct by analysis of all interleaving
-+ * scenarios of the above operations with the hardware memory ordering
-+ * described above.
-+ *
-+ * The Load and store of the flag pair is very inexpensive. The cacheline with
-+ * the flag pair is never accessed by a different CPU except by dtrace_sync.
-+ * dtrace_sync is very uncommon compared to typical probe firings. The removal
-+ * of membars from DTrace probe context at the expense of a Load and Store and
-+ * a conditional branch is a good performance win.
-+ *
-+ * As implemented there is one pair of flags per CPU. The flags are in one
-+ * cacheline; they could be split into two cachelines if dtrace_sync was more
-+ * common. dtrace_sync loops over all NCPU sets of flags. dtrace_sync lazily
-+ * only does one dtrace_membar_enter() (step 1b) after setting all NCPU
-+ * sync_request flags.
-+ *
-+ * Sample aliasing could cause dtrace_sync() to always sample a CPU's
-+ * in_probe_context flag when the CPU is in probe context even if the CPU
-+ * left and returned to probe context one or more times since the last sample.
-+ * cpuc_in_probe_ctxt is implemented as an even/odd counter instead of a
-+ * boolean flag. cpuc_in_probe_ctxt is odd when in probe context and even
-+ * when not in probe context. Probe context increments cpuc_in_probe_ctxt when
-+ * entering and exiting. dtrace_probe() handles re-entry by not increment the
-+ * counter for re-enterant entry and exit.
-+ */
-+
-+/*
-+ * dtrace_membar_exit() is a NOP on current SPARC and X86 hardware.
-+ * It is defined as an inline asm statement to prevent the C optimizer from
-+ * moving C statements around the membar.
-+ */
-+#define dtrace_membar_exit() \
-+ __asm__ __volatile__("" ::: "memory")
-+
-+/*
-+ * dtrace_membar_enter() does not need an explicit membar #StoreStore because
-+ * modern SPARC hardware is TSO: stores are ordered with other stores.
-+ */
-+#define dtrace_membar_enter() \
-+ mb()
-+
-+#define dtrace_safe_smt_pause() \
-+ cpu_relax()
-+
-+/*
-+ * Used by dtrace_probe() to flag entry to the the critical section.
-+ * dtrace_probe() context may be consuming DTrace framework data.
-+ *
-+ * cpuc_in_probe_ctxt is odd when in probe context and even when not in
-+ * probe context. The flag must not be incremented when re-entering from
-+ * probe context.
-+ */
-+#define DTRACE_SYNC_ENTER_CRITICAL(cookie, re_entry) \
-+{ \
-+ uint64_t requests; \
-+ uint64_t count; \
-+ \
-+ preempt_disable(); \
-+ local_irq_save(cookie); \
-+ \
-+ requests = atomic64_read(&this_cpu_core->cpuc_sync_requests); \
-+ \
-+ /* Increment flag iff it is even */ \
-+ count = atomic64_read(&this_cpu_core->cpuc_in_probe_ctx); \
-+ re_entry = count & 0x1; \
-+ atomic64_set(&this_cpu_core->cpuc_in_probe_ctx, count | 0x1); \
-+ ASSERT(DTRACE_SYNC_IN_CRITICAL(smp_processor_id())); \
-+ \
-+ /* \
-+ * Later Loads are ordered with respect to the Load of \
-+ * cpuc_sync_requests. The Load is also guaranteed to complete \
-+ * before the store to cpuc_in_probe_ctxt. Thus a member_enter \
-+ * is only needed when requests is not 0. This is very \
-+ * uncommon. \
-+ */ \
-+ if (requests > 0) { \
-+ dtrace_membar_enter(); \
-+ } \
-+}
-+
-+/*
-+ * Used by dtrace_probe() to flag exit from the critical section.
-+ * dtrace_probe context is no longer using DTrace framework data.
-+ */
-+#define DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry) \
-+{ \
-+ dtrace_membar_exit(); \
-+ ASSERT((re_entry | 0x1) == 0x1); \
-+ \
-+ /* \
-+ * flag must not be incremented when returning to probe context.\
-+ */ \
-+ atomic64_add(~re_entry & 0x1, &this_cpu_core->cpuc_in_probe_ctx); \
-+ ASSERT(re_entry == \
-+ (atomic64_read(&this_cpu_core->cpuc_in_probe_ctx) & 0x1)); \
-+ local_irq_restore(cookie); \
-+ preempt_enable(); \
-+}
-+
-+/*
-+ * Used by dtrace_sync to inform dtrace_probe it needs to synchronize with
-+ * dtrace_sync. dtrace_probe consumes the cpuc_sync_requests flag to determine
-+ * if it needs a membar_enter. Not called from probe context.
-+ *
-+ * cpuc_sync_requests must be updated atomically by dtrace_sync because there
-+ * may be multiple dtrace_sync operations executing at the same time.
-+ * cpuc_sync_requests is a simple count of the number of concurrent
-+ * dtrace_sync requests.
-+ */
-+#define DTRACE_SYNC_START(cpuid) \
-+{ \
-+ atomic64_add(1, &(per_cpu_core(cpuid))->cpuc_sync_requests); \
-+ ASSERT(atomic64_read(&per_cpu_core(cpuid)->cpuc_sync_requests) > 0); \
-+}
-+
-+/*
-+ * Used by dtrace_sync to flag dtrace_probe that it no longer needs to
-+ * synchronize with dtrace_sync. Not called from probe context.
-+ */
-+#define DTRACE_SYNC_END(cpuid) \
-+{ \
-+ atomic64_add(-1, &(per_cpu_core(cpuid))->cpuc_sync_requests); \
-+ ASSERT(atomic64_read(&per_cpu_core(cpuid)->cpuc_sync_requests) >= 0); \
-+}
-+
-+/*
-+ * The next two macros are used by dtrace_sync to check if the target CPU is in
-+ * DTrace probe context. cpuc_in_probe_ctxt is a monotonically increasing
-+ * count which dtrace_probe() increments when entering and exiting probe
-+ * context. The flag is odd when in probe context, and even when not in probe
-+ * context.
-+ */
-+#define DTRACE_SYNC_IN_CRITICAL(cpuid) \
-+ (atomic64_read(&per_cpu_core(cpuid)->cpuc_in_probe_ctx) & 0x1)
-+
-+/*
-+ * Used to check if the target CPU left and then entered probe context again.
-+ */
-+#define DTRACE_SYNC_CRITICAL_COUNT(cpuid) \
-+ (atomic64_read(&per_cpu_core(cpuid)->cpuc_in_probe_ctx))
-+
-+/*
-+ * The next three macros are bitmap operations used by dtrace_sync to keep track
-+ * of which CPUs it still needs to synchronize with.
-+ */
-+#define DTRACE_SYNC_OUTSTANDING(cpuid, bitmap) \
-+ (cpumask_test_cpu(cpuid, bitmap) == 1)
-+
-+#define DTRACE_SYNC_NEEDED(cpuid, bitmap) \
-+ cpumask_set_cpu(cpuid, bitmap)
-+
-+#define DTRACE_SYNC_DONE(cpuid, bitmap) \
-+ cpumask_clear_cpu(cpuid, bitmap)
-+
-+extern uint64_t dtrace_sync_sample_count;
-+extern void dtrace_sync(void);
-+
-+/*
-+ * DTrace Enabling Functions
-+ */
-+extern struct dtrace_enabling *dtrace_retained;
-+extern dtrace_genid_t dtrace_retained_gen;
-+
-+extern struct dtrace_enabling *dtrace_enabling_create(struct dtrace_vstate *);
-+extern void dtrace_enabling_add(struct dtrace_enabling *,
-+ struct dtrace_ecbdesc *);
-+extern void dtrace_enabling_dump(struct dtrace_enabling *);
-+extern void dtrace_enabling_destroy(struct dtrace_enabling *);
-+extern int dtrace_enabling_retain(struct dtrace_enabling *);
-+extern int dtrace_enabling_replicate(struct dtrace_state *,
-+ struct dtrace_probedesc *,
-+ struct dtrace_probedesc *);
-+extern void dtrace_enabling_retract(struct dtrace_state *);
-+extern int dtrace_enabling_match(struct dtrace_enabling *, int *);
-+extern void dtrace_enabling_matchall(void);
-+extern void dtrace_enabling_prime(struct dtrace_state *);
-+extern void dtrace_enabling_provide(struct dtrace_provider *);
-+
-+/*
-+ * DOF functions
-+ */
-+extern void dtrace_dof_error(struct dof_hdr *, const char *);
-+extern struct dof_hdr *dtrace_dof_create(struct dtrace_state *);
-+extern struct dof_hdr *dtrace_dof_copyin(void __user *, int *);
-+extern struct dof_hdr *dtrace_dof_property(const char *);
-+extern void dtrace_dof_destroy(struct dof_hdr *);
-+extern int dtrace_dof_slurp(struct dof_hdr *, struct dtrace_vstate *,
-+ const struct cred *, struct dtrace_enabling **,
-+ uint64_t, int);
-+extern int dtrace_dof_options(struct dof_hdr *, struct dtrace_state *);
-+extern void dtrace_helper_provide(struct dof_helper *dhp, pid_t pid);
-+extern int dtrace_helper_slurp(struct dof_hdr *, struct dof_helper *);
-+extern int dtrace_helper_destroygen(int);
-+
-+/*
-+ * DTrace Anonymous Enabling Functions
-+ */
-+struct dtrace_anon {
-+ struct dtrace_state *dta_state;
-+ struct dtrace_enabling *dta_enabling;
-+ processorid_t dta_beganon;
-+};
-+
-+extern struct dtrace_anon dtrace_anon;
-+
-+extern struct dtrace_state *dtrace_anon_grab(void);
-+extern void dtrace_anon_property(void);
-+
-+/*
-+ * DTrace Consumer State Functions
-+ */
-+extern struct kmem_cache *dtrace_state_cachep;
-+extern size_t dtrace_strsize_default;
-+
-+extern ktime_t dtrace_deadman_timeout;
-+extern int dtrace_destructive_disallow;
-+
-+extern dtrace_id_t dtrace_probeid_begin;
-+extern dtrace_id_t dtrace_probeid_end;
-+extern dtrace_id_t dtrace_probeid_error;
-+
-+extern struct dtrace_dynvar dtrace_dynhash_sink;
-+
-+extern struct user_namespace *init_user_namespace;
-+
-+extern int dtrace_dstate_init(struct dtrace_dstate *, size_t);
-+extern void dtrace_dstate_fini(struct dtrace_dstate *);
-+extern void dtrace_vstate_fini(struct dtrace_vstate *);
-+extern struct dtrace_state *dtrace_state_create(struct file *);
-+extern int dtrace_state_go(struct dtrace_state *, processorid_t *);
-+extern int dtrace_state_stop(struct dtrace_state *, processorid_t *);
-+extern int dtrace_state_option(struct dtrace_state *, dtrace_optid_t,
-+ dtrace_optval_t);
-+extern void dtrace_state_destroy(struct dtrace_state *);
-+
-+/*
-+ * DTrace Utility Functions
-+ */
-+extern int dtrace_isglob(const char *);
-+extern int dtrace_gmatch(const char *, const char *);
-+extern void *dtrace_vzalloc(unsigned long);
-+extern void *dtrace_vzalloc_try(unsigned long);
-+extern char *dtrace_strdup(const char *);
-+extern int dtrace_strncmp(char *, char *, size_t);
-+extern size_t dtrace_strlen(const char *, size_t);
-+extern int dtrace_badattr(const struct dtrace_attribute *);
-+extern int dtrace_badname(const char *);
-+extern void dtrace_cred2priv(const struct cred *, uint32_t *, kuid_t *);
-+
-+extern void ctf_forceload(void);
-+
-+#define dtrace_membar_producer() smp_wmb()
-+#define dtrace_membar_consumer() smp_rmb()
-+
-+typedef unsigned long dtrace_icookie_t;
-+
-+extern struct mutex cpu_lock;
-+
-+extern void dtrace_toxic_ranges(void (*)(uintptr_t, uintptr_t));
-+extern void dtrace_vpanic(const char *, va_list);
-+extern int dtrace_getipl(void);
-+
-+extern dtrace_icookie_t dtrace_interrupt_disable(void);
-+extern void dtrace_interrupt_enable(dtrace_icookie_t);
-+
-+typedef void (*dtrace_xcall_t)(void *);
-+
-+extern void dtrace_xcall(processorid_t, dtrace_xcall_t, void *);
-+
-+extern uintptr_t dtrace_fulword(void *);
-+extern uint8_t dtrace_fuword8(void *);
-+extern uint16_t dtrace_fuword16(void *);
-+extern uint32_t dtrace_fuword32(void *);
-+extern uint64_t dtrace_fuword64(void *);
-+
-+extern void dtrace_probe_error(struct dtrace_state *, dtrace_epid_t, int, int,
-+ int, uintptr_t);
-+
-+extern void dtrace_getpcstack(uint64_t *, int, int, uint32_t *);
-+extern void dtrace_getupcstack(uint64_t *, int);
-+extern unsigned long dtrace_getufpstack(uint64_t *, uint64_t *, int);
-+extern uintptr_t dtrace_getfp(void);
-+extern uint64_t dtrace_getarg(int, int);
-+extern int dtrace_getstackdepth(struct dtrace_mstate *, int);
-+extern int dtrace_getustackdepth(void);
-+extern ulong_t dtrace_getreg(struct task_struct *, uint_t);
-+extern void dtrace_copyin(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+extern void dtrace_copyout(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+extern void dtrace_copyinstr(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+extern void dtrace_copyoutstr(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+
-+/*
-+ * Plaforms that support a fast path to obtain the caller implement the
-+ * dtrace_caller() function.
-+ *
-+ * The first argument is the number of frames that should be skipped when
-+ * looking for a caller address. The 2nd argument is a dummy argument that
-+ * is necessary for SPARC.
-+ *
-+ * On x86 this is effectively a NOP.
-+ *
-+ * On SPARC it is possible to retrieve the caller address from the register
-+ * windows without flushing them to the stack. This involves performing
-+ * explicit rotation of the register windows. Modification of the windowing
-+ * mechanism state alters all %i, %o, and %l registers so we are can only use
-+ * %g registers to store temporary data.
-+ *
-+ * On Linux a lot of %g registers are already allocated for specific purposes.
-+ * Saving temporaries to the stack would be a violation of the fast path code
-+ * logic. Therefore, the function prototype declares a 2nd argument that serves
-+ * as a temporary value. A compiler will not expect that the value in %o1
-+ * will survive the call and therefore dtrace_caller() can use %o1 as a
-+ * temporary register.
-+ */
-+extern uintptr_t dtrace_caller(int, int);
-+
-+extern void dtrace_copyin_arch(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+extern void dtrace_copyinstr_arch(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+
-+extern void pdata_init(struct dtrace_module *, struct module *);
-+extern void pdata_cleanup(struct dtrace_module *, struct module *);
-+
-+extern void debug_enter(char *);
-+
-+#endif /* _LINUX_DTRACE_IMPL_H */
-diff --git a/include/dtrace/dtrace_impl_defines.h b/include/dtrace/dtrace_impl_defines.h
-new file mode 100644
-index 000000000000..19b57f6188a0
---- /dev/null
-+++ b/include/dtrace/dtrace_impl_defines.h
-@@ -0,0 +1,173 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Implementation Defines
-+ *
-+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_IMPL_DEFINES_H
-+#define _LINUX_DTRACE_IMPL_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/preempt.h>
-+#include <asm/ptrace.h>
-+
-+typedef typeof(instruction_pointer((struct pt_regs *)0)) pc_t;
-+
-+enum dtrace_activity {
-+ DTRACE_ACTIVITY_INACTIVE = 0,
-+ DTRACE_ACTIVITY_WARMUP,
-+ DTRACE_ACTIVITY_ACTIVE,
-+ DTRACE_ACTIVITY_DRAINING,
-+ DTRACE_ACTIVITY_COOLDOWN,
-+ DTRACE_ACTIVITY_STOPPED,
-+ DTRACE_ACTIVITY_KILLED
-+};
-+
-+enum dtrace_dstate_state {
-+ DTRACE_DSTATE_CLEAN = 0,
-+ DTRACE_DSTATE_EMPTY,
-+ DTRACE_DSTATE_DIRTY,
-+ DTRACE_DSTATE_RINSING
-+};
-+
-+enum dtrace_dynvar_op {
-+ DTRACE_DYNVAR_ALLOC,
-+ DTRACE_DYNVAR_NOALLOC,
-+ DTRACE_DYNVAR_DEALLOC
-+};
-+
-+#define DTRACE_MSTATE_ARGS 0x00000001
-+#define DTRACE_MSTATE_PROBE 0x00000002
-+#define DTRACE_MSTATE_EPID 0x00000004
-+#define DTRACE_MSTATE_TIMESTAMP 0x00000008
-+#define DTRACE_MSTATE_STACKDEPTH 0x00000010
-+#define DTRACE_MSTATE_CALLER 0x00000020
-+#define DTRACE_MSTATE_IPL 0x00000040
-+#define DTRACE_MSTATE_FLTOFFS 0x00000080
-+#define DTRACE_MSTATE_USTACKDEPTH 0x00000100
-+#define DTRACE_MSTATE_UCALLER 0x00000200
-+
-+#define DTRACE_PROBEKEY_MAXDEPTH 8
-+
-+enum dtrace_speculation_state {
-+ DTRACESPEC_INACTIVE = 0,
-+ DTRACESPEC_ACTIVE,
-+ DTRACESPEC_ACTIVEONE,
-+ DTRACESPEC_ACTIVEMANY,
-+ DTRACESPEC_COMMITTING,
-+ DTRACESPEC_COMMITTINGMANY,
-+ DTRACESPEC_DISCARDING
-+};
-+
-+#define DTRACE_HELPER_ACTION_USTACK 0
-+#define DTRACE_NHELPER_ACTIONS 1
-+
-+#define DTRACE_HELPTRACE_NEXT (-1)
-+#define DTRACE_HELPTRACE_DONE (-2)
-+#define DTRACE_HELPTRACE_ERR (-3)
-+
-+#undef ASSERT
-+#ifdef CONFIG_DT_DEBUG
-+# define ASSERT(x) ((void)((x) || dtrace_assfail(#x, __FILE__, __LINE__)))
-+#else
-+# define ASSERT(x) ((void)0)
-+#endif
-+
-+/*
-+ * DTrace Probe Hashing
-+ */
-+
-+#define DTRACE_HASHNEXT(hash, probe) \
-+ (struct dtrace_probe **)((uintptr_t)(probe) + (hash)->dth_nextoffs)
-+#define DTRACE_HASHPREV(hash, probe) \
-+ (struct dtrace_probe **)((uintptr_t)(probe) + (hash)->dth_prevoffs)
-+
-+/*
-+ * DTrace Probe Management
-+ */
-+#define DTRACE_ANCHORED(probe) ((probe)->dtpr_func[0] != '\0')
-+#define DTRACE_FLAGS2FLT(flags) \
-+ (((flags) & CPU_DTRACE_BADADDR) ? DTRACEFLT_BADADDR : \
-+ ((flags) & CPU_DTRACE_ILLOP) ? DTRACEFLT_ILLOP : \
-+ ((flags) & CPU_DTRACE_DIVZERO) ? DTRACEFLT_DIVZERO : \
-+ ((flags) & CPU_DTRACE_KPRIV) ? DTRACEFLT_KPRIV : \
-+ ((flags) & CPU_DTRACE_UPRIV) ? DTRACEFLT_UPRIV : \
-+ ((flags) & CPU_DTRACE_TUPOFLOW) ? DTRACEFLT_TUPOFLOW : \
-+ ((flags) & CPU_DTRACE_BADALIGN) ? DTRACEFLT_BADALIGN : \
-+ ((flags) & CPU_DTRACE_NOSCRATCH) ? DTRACEFLT_NOSCRATCH : \
-+ ((flags) & CPU_DTRACE_BADSTACK) ? DTRACEFLT_BADSTACK : \
-+ DTRACEFLT_UNKNOWN)
-+
-+/*
-+ * Test whether alloc_sz bytes will fit in the scratch region. We isolate
-+ * alloc_sz on the righthand side of the comparison in order to avoid overflow
-+ * or underflow in the comparison with it. This is simpler than the INRANGE
-+ * check above, because we know that the dtms_scratch_ptr is valid in the
-+ * range. Allocations of size zero are allowed.
-+ */
-+#define DTRACE_INSCRATCH(mstate, alloc_sz) \
-+ ((mstate)->dtms_scratch_base + (mstate)->dtms_scratch_size - \
-+ (mstate)->dtms_scratch_ptr >= (alloc_sz))
-+
-+/*
-+ * Buffering.
-+ */
-+
-+#define DTRACEBUF_RING 0x0001 /* bufpolicy set to "ring" */
-+#define DTRACEBUF_FILL 0x0002 /* bufpolicy set to "fill" */
-+#define DTRACEBUF_NOSWITCH 0x0004 /* do not switch buffer */
-+#define DTRACEBUF_WRAPPED 0x0008 /* ring buffer has wrapped */
-+#define DTRACEBUF_DROPPED 0x0010 /* drops occurred */
-+#define DTRACEBUF_ERROR 0x0020 /* errors occurred */
-+#define DTRACEBUF_FULL 0x0040 /* "fill" buffer is full */
-+#define DTRACEBUF_CONSUMED 0x0080 /* buffer has been consumed */
-+#define DTRACEBUF_INACTIVE 0x0100 /* buffer is not yet active */
-+
-+#define DTRACE_STORE(type, tomax, offset, what) \
-+ do { \
-+ *((type *)((uintptr_t)(tomax) + (uintptr_t)(offset))) = (type)(what); \
-+ } while (0)
-+
-+#define KERNELBASE (uintptr_t)_text
-+
-+#ifdef CONFIG_DT_DEBUG_MUTEX
-+# define real_mutex_lock(x) mutex_lock(x)
-+# define real_mutex_unlock(x) mutex_unlock(x)
-+
-+# define mutex_lock(x) do { \
-+ pr_debug("mutex_lock(%s) at %s::%d for %p (PID %d)\n", \
-+ __stringify(x), \
-+ __FILE__, __LINE__, current, \
-+ current ? current->pid : -1); \
-+ real_mutex_lock(x); \
-+ } while (0)
-+# define mutex_unlock(x) do { \
-+ pr_debug("mutex_unlock(%s) at %s::%d for %p (PID %d)\n", \
-+ __stringify(x), \
-+ __FILE__, __LINE__, current, \
-+ current ? current->pid : -1); \
-+ real_mutex_unlock(x); \
-+ } while (0)
-+#endif
-+
-+#define MUTEX_HELD(lock) mutex_owned(lock)
-+
-+#define PDATA(mp) ((struct dtrace_module *)mp->pdata)
-+
-+#endif /* _LINUX_DTRACE_IMPL_DEFINES_H */
-diff --git a/include/dtrace/provider.h b/include/dtrace/provider.h
-new file mode 100644
-index 000000000000..9eeb147f0363
---- /dev/null
-+++ b/include/dtrace/provider.h
-@@ -0,0 +1,971 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Provider API
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _DTRACE_PROVIDER_H
-+#define _DTRACE_PROVIDER_H
-+
-+/*
-+ * The following functions are implemented by the DTrace framework and are
-+ * used to implement separate in-kernel DTrace providers.
-+ *
-+ * The provider API has two halves: the API that the providers consume from
-+ * DTrace, and the API that providers make available to DTrace.
-+ *
-+ * 1 Framework-to-Provider API
-+ *
-+ * 1.1 Overview
-+ *
-+ * The Framework-to-Provider API is represented by the dtrace_pops structure
-+ * that the provider passes to the framework when registering itself. This
-+ * structure consists of the following members:
-+ *
-+ * dtps_provide() <-- Provide all probes, all modules
-+ * dtps_provide_module() <-- Provide all probes in specified module
-+ * dtps_enable() <-- Enable specified probe
-+ * dtps_disable() <-- Disable specified probe
-+ * dtps_suspend() <-- Suspend specified probe
-+ * dtps_resume() <-- Resume specified probe
-+ * dtps_getargdesc() <-- Get the argument description for args[X]
-+ * dtps_getargval() <-- Get the value for an argX or args[X] variable
-+ * dtps_usermode() <-- Find out if the probe was fired in user mode
-+ * dtps_destroy() <-- Destroy all state associated with this probe
-+ * dtps_destroy_module() <-- Destroy per-module data
-+ *
-+ * 1.2 void dtps_provide(void *arg, const struct dtrace_probedesc *spec)
-+ *
-+ * 1.2.1 Overview
-+ *
-+ * Called to indicate that the provider should provide all probes. If the
-+ * specified description is non-NULL, dtps_provide() is being called because
-+ * no probe matched a specified probe -- if the provider has the ability to
-+ * create custom probes, it may wish to create a probe that matches the
-+ * specified description.
-+ *
-+ * 1.2.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is a pointer to a probe description that the provider may
-+ * wish to consider when creating custom probes. The provider is expected to
-+ * call back into the DTrace framework via dtrace_probe_create() to create
-+ * any necessary probes. dtps_provide() may be called even if the provider
-+ * has made available all probes; the provider should check the return value
-+ * of dtrace_probe_create() to handle this case. Note that the provider need
-+ * not implement both dtps_provide() and dtps_provide_module(); see
-+ * "Arguments and Notes" for dtrace_register(), below.
-+ *
-+ * 1.2.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.2.4 Caller's context
-+ *
-+ * dtps_provide() is typically called from open() or ioctl() context, but may
-+ * be called from other contexts as well. The DTrace framework is locked in
-+ * such a way that providers may not register or unregister. This means that
-+ * the provider may not call any DTrace API that affects its registration with
-+ * the framework, including dtrace_register(), dtrace_unregister(),
-+ * dtrace_invalidate(), and dtrace_condense(). However, the context is such
-+ * that the provider may (and indeed, is expected to) call probe-related
-+ * DTrace routines, including dtrace_probe_create(), dtrace_probe_lookup(),
-+ * and dtrace_probe_arg().
-+ *
-+ * 1.3 void dtps_provide_module(void *arg, struct modctl *mp)
-+ *
-+ * 1.3.1 Overview
-+ *
-+ * Called to indicate that the provider should provide all probes in the
-+ * specified module.
-+ *
-+ * 1.3.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is a pointer to a modctl structure that indicates the
-+ * module for which probes should be created.
-+ *
-+ * 1.3.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.3.4 Caller's context
-+ *
-+ * dtps_provide_module() may be called from open() or ioctl() context, but
-+ * may also be called from a module loading context. mod_lock is held, and
-+ * the DTrace framework is locked in such a way that providers may not
-+ * register or unregister. This means that the provider may not call any
-+ * DTrace API that affects its registration with the framework, including
-+ * dtrace_register(), dtrace_unregister(), dtrace_invalidate(), and
-+ * dtrace_condense(). However, the context is such that the provider may (and
-+ * indeed, is expected to) call probe-related DTrace routines, including
-+ * dtrace_probe_create(), dtrace_probe_lookup(), and dtrace_probe_arg(). Note
-+ * that the provider need not implement both dtps_provide() and
-+ * dtps_provide_module(); see "Arguments and Notes" for dtrace_register(),
-+ * below.
-+ *
-+ * 1.4 int dtps_enable(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.4.1 Overview
-+ *
-+ * Called to enable the specified probe.
-+ *
-+ * 1.4.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the probe to be enabled. The third
-+ * argument is the probe argument as passed to dtrace_probe_create().
-+ * dtps_enable() will be called when a probe transitions from not being
-+ * enabled at all to having one or more ECB. The number of ECBs associated
-+ * with the probe may change without subsequent calls into the provider.
-+ * When the number of ECBs drops to zero, the provider will be explicitly
-+ * told to disable the probe via dtps_disable(). dtrace_probe() should never
-+ * be called for a probe identifier that hasn't been explicitly enabled via
-+ * dtps_enable().
-+ *
-+ * 1.4.3 Return value
-+ *
-+ * On success, dtps_enable() should return 0. On failure, -1 should be
-+ * returned.
-+ *
-+ * 1.4.4 Caller's context
-+ *
-+ * The DTrace framework is locked in such a way that it may not be called
-+ * back into at all. cpu_lock is held. mod_lock is not held and may not
-+ * be acquired.
-+ *
-+ * 1.5 void dtps_disable(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.5.1 Overview
-+ *
-+ * Called to disable the specified probe.
-+ *
-+ * 1.5.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the probe to be disabled. The third
-+ * argument is the probe argument as passed to dtrace_probe_create().
-+ * dtps_disable() will be called when a probe transitions from being enabled
-+ * to having zero ECBs. dtrace_probe() should never be called for a probe
-+ * identifier that has been explicitly enabled via dtps_disable().
-+ *
-+ * 1.5.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.5.4 Caller's context
-+ *
-+ * The DTrace framework is locked in such a way that it may not be called
-+ * back into at all. cpu_lock is held. mod_lock is not held and may not
-+ * be acquired.
-+ *
-+ * 1.6 void dtps_suspend(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.6.1 Overview
-+ *
-+ * Called to suspend the specified enabled probe. This entry point is for
-+ * providers that may need to suspend some or all of their probes when CPUs
-+ * are being powered on or when the boot monitor is being entered for a
-+ * prolonged period of time.
-+ *
-+ * 1.6.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the probe to be suspended. The
-+ * third argument is the probe argument as passed to dtrace_probe_create().
-+ * dtps_suspend will only be called on an enabled probe. Providers that
-+ * provide a dtps_suspend entry point will want to take roughly the action
-+ * that it takes for dtps_disable.
-+ *
-+ * 1.6.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.6.4 Caller's context
-+ *
-+ * Interrupts are disabled. The DTrace framework is in a state such that the
-+ * specified probe cannot be disabled or destroyed for the duration of
-+ * dtps_suspend(). As interrupts are disabled, the provider is afforded
-+ * little latitude; the provider is expected to do no more than a store to
-+ * memory.
-+ *
-+ * 1.7 void dtps_resume(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.7.1 Overview
-+ *
-+ * Called to resume the specified enabled probe. This entry point is for
-+ * providers that may need to resume some or all of their probes after the
-+ * completion of an event that induced a call to dtps_suspend().
-+ *
-+ * 1.7.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the probe to be resumed. The
-+ * third argument is the probe argument as passed to dtrace_probe_create().
-+ * dtps_resume will only be called on an enabled probe. Providers that
-+ * provide a dtps_resume entry point will want to take roughly the action
-+ * that it takes for dtps_enable.
-+ *
-+ * 1.7.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.7.4 Caller's context
-+ *
-+ * Interrupts are disabled. The DTrace framework is in a state such that the
-+ * specified probe cannot be disabled or destroyed for the duration of
-+ * dtps_resume(). As interrupts are disabled, the provider is afforded
-+ * little latitude; the provider is expected to do no more than a store to
-+ * memory.
-+ *
-+ * 1.8 void dtps_getargdesc(void *arg, dtrace_id_t id, void *parg,
-+ * struct dtrace_argdesc *desc)
-+ *
-+ * 1.8.1 Overview
-+ *
-+ * Called to retrieve the argument description for an args[X] variable.
-+ *
-+ * 1.8.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the current probe. The third
-+ * argument is the probe argument as passed to dtrace_probe_create(). The
-+ * fourth argument is a pointer to the argument description. This
-+ * description is both an input and output parameter: it contains the
-+ * index of the desired argument in the dtargd_ndx field, and expects
-+ * the other fields to be filled in upon return. If there is no argument
-+ * corresponding to the specified index, the dtargd_ndx field should be set
-+ * to DTRACE_ARGNONE.
-+ *
-+ * 1.8.3 Return value
-+ *
-+ * None. The dtargd_ndx, dtargd_native, dtargd_xlate and dtargd_mapping
-+ * members of the dtrace_argdesc structure are all output values.
-+ *
-+ * 1.8.4 Caller's context
-+ *
-+ * dtps_getargdesc() is called from ioctl() context. mod_lock is held, and
-+ * the DTrace framework is locked in such a way that providers may not
-+ * register or unregister. This means that the provider may not call any
-+ * DTrace API that affects its registration with the framework, including
-+ * dtrace_register(), dtrace_unregister(), dtrace_invalidate(), and
-+ * dtrace_condense().
-+ *
-+ * 1.9 uint64_t dtps_getargval(void *arg, dtrace_id_t id, void *parg,
-+ * int argno, int aframes)
-+ *
-+ * 1.9.1 Overview
-+ *
-+ * Called to retrieve a value for an argX or args[X] variable.
-+ *
-+ * 1.9.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the current probe. The third
-+ * argument is the probe argument as passed to dtrace_probe_create(). The
-+ * fourth argument is the number of the argument (the X in the example in
-+ * 1.9.1). The fifth argument is the number of stack frames that were used
-+ * to get from the actual place in the code that fired the probe to
-+ * dtrace_probe() itself, the so-called artificial frames. This argument may
-+ * be used to descend an appropriate number of frames to find the correct
-+ * values. If this entry point is left NULL, the dtrace_getarg() built-in
-+ * function is used.
-+ *
-+ * 1.9.3 Return value
-+ *
-+ * The value of the argument.
-+ *
-+ * 1.9.4 Caller's context
-+ *
-+ * This is called from within dtrace_probe() meaning that interrupts
-+ * are disabled. No locks should be taken within this entry point.
-+ *
-+ * 1.10 int dtps_usermode(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.10.1 Overview
-+ *
-+ * Called to determine if the probe was fired in a user context.
-+ *
-+ * 1.10.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the current probe. The third
-+ * argument is the probe argument as passed to dtrace_probe_create(). This
-+ * entry point must not be left NULL for providers whose probes allow for
-+ * mixed mode tracing, that is to say those probes that can fire during
-+ * kernel- _or_ user-mode execution
-+ *
-+ * 1.10.3 Return value
-+ *
-+ * A boolean value.
-+ *
-+ * 1.10.4 Caller's context
-+ *
-+ * This is called from within dtrace_probe() meaning that interrupts
-+ * are disabled. No locks should be taken within this entry point.
-+ *
-+ * 1.11 void dtps_destroy(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.11.1 Overview
-+ *
-+ * Called to destroy the specified probe.
-+ *
-+ * 1.11.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the probe to be destroyed. The third
-+ * argument is the probe argument as passed to dtrace_probe_create(). The
-+ * provider should free all state associated with the probe. The framework
-+ * guarantees that dtps_destroy() is only called for probes that have either
-+ * been disabled via dtps_disable() or were never enabled via dtps_enable().
-+ * Once dtps_disable() has been called for a probe, no further call will be
-+ * made specifying the probe.
-+ *
-+ * 1.11.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.11.4 Caller's context
-+ *
-+ * The DTrace framework is locked in such a way that it may not be called
-+ * back into at all. mod_lock is held. cpu_lock is not held, and may not be
-+ * acquired.
-+ *
-+ * 1.12 void dtps_destroy_module(void *arg, struct modctl *mp)
-+ *
-+ * 1.12.1 Overview
-+ *
-+ * Called to notify provider that it can remove any per-module data.
-+ *
-+ * 1.12.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is a pointer to a struct module structure that points to
-+ * the module for which data may be cleared.
-+ *
-+ * 1.12.3 Return value
-+ *
-+ * None.
-+ *
-+ *
-+ * 2 Provider-to-Framework API
-+ *
-+ * 2.1 Overview
-+ *
-+ * The Provider-to-Framework API provides the mechanism for the provider to
-+ * register itself with the DTrace framework, to create probes, to lookup
-+ * probes and (most importantly) to fire probes. The Provider-to-Framework
-+ * consists of:
-+ *
-+ * dtrace_register() <-- Register a provider with the DTrace framework
-+ * dtrace_unregister() <-- Remove a provider's DTrace registration
-+ * dtrace_meta_register() <-- Register a metaprovider with the DTrace framework
-+ * dtrace_meta_unregister()<-- Remove a metaprovider's DTrace registration
-+ * dtrace_invalidate() <-- Invalidate the specified provider
-+ * dtrace_condense() <-- Remove a provider's unenabled probes
-+ * dtrace_attached() <-- Indicates whether or not DTrace has attached
-+ * dtrace_probe_create() <-- Create a DTrace probe
-+ * dtrace_probe_lookup() <-- Lookup a DTrace probe based on its name
-+ * dtrace_probe_arg() <-- Return the probe argument for a specific probe
-+ * dtrace_probe() <-- Fire the specified probe
-+ *
-+ * 2.2 int dtrace_register(const char *name, const struct dtrace_pattr *pap,
-+ * uint32_t priv, struct cred *cr, const struct dtrace_pops *pops,
-+ * void *arg, dtrace_provider_id_t *idp)
-+ *
-+ * 2.2.1 Overview
-+ *
-+ * dtrace_register() registers the calling provider with the DTrace
-+ * framework. It should generally be called by DTrace providers in their
-+ * attach(9E) entry point.
-+ *
-+ * 2.2.2 Arguments and Notes
-+ *
-+ * The first argument is the name of the provider. The second argument is a
-+ * pointer to the stability attributes for the provider. The third argument
-+ * is the privilege flags for the provider, and must be some combination of:
-+ *
-+ * DTRACE_PRIV_NONE <= All users may enable probes from this provider
-+ *
-+ * DTRACE_PRIV_PROC <= Any user with privilege of PRIV_DTRACE_PROC may
-+ * enable probes from this provider
-+ *
-+ * DTRACE_PRIV_USER <= Any user with privilege of PRIV_DTRACE_USER may
-+ * enable probes from this provider
-+ *
-+ * DTRACE_PRIV_KERNEL <= Any user with privilege of PRIV_DTRACE_KERNEL
-+ * may enable probes from this provider
-+ *
-+ * DTRACE_PRIV_OWNER <= This flag places an additional constraint on
-+ * the privilege requirements above. These probes
-+ * require either (a) a user ID matching the user
-+ * ID of the cred passed in the fourth argument
-+ * or (b) the PRIV_PROC_OWNER privilege.
-+ *
-+ * Note that these flags designate the _visibility_ of the probes, not
-+ * the conditions under which they may or may not fire.
-+ *
-+ * The fourth argument is the credential that is associated with the provider.
-+ * This argument should be NULL if the privilege flags don't include
-+ * DTRACE_PRIV_OWNER. If non-NULL, the framework stashes the uid represented
-+ * by this credential for use at probe-time, in implicit predicates. These
-+ * limit visibility of the probes to users which have sufficient privilege to
-+ * access them.
-+ *
-+ * The fifth argument is a DTrace provider operations vector, which provides
-+ * the implementation for the Framework-to-Provider API. (See Section 1,
-+ * above.) This must be non-NULL, and each member must be non-NULL. The
-+ * exceptions to this are (1) the dtps_provide() and dtps_provide_module()
-+ * members (if the provider so desires, _one_ of these members may be left
-+ * NULL -- denoting that the provider only implements the other) and (2)
-+ * the dtps_suspend() and dtps_resume() members, which must either both be
-+ * NULL or both be non-NULL.
-+ *
-+ * The sixth argument is a cookie to be specified as the first argument for
-+ * each function in the Framework-to-Provider API. This argument may have
-+ * any value.
-+ *
-+ * The final argument is a pointer to dtrace_provider_id_t. If
-+ * dtrace_register() successfully completes, the provider identifier will be
-+ * stored in the memory pointed to be this argument. This argument must be
-+ * non-NULL.
-+ *
-+ * 2.2.3 Return value
-+ *
-+ * On success, dtrace_register() returns 0 and stores the new provider's
-+ * identifier into the memory pointed to by the idp argument. On failure,
-+ * dtrace_register() returns an errno:
-+ *
-+ * EINVAL The arguments passed to dtrace_register() were somehow invalid.
-+ * This may because a parameter that must be non-NULL was NULL,
-+ * because the name was invalid (either empty or an illegal
-+ * provider name) or because the attributes were invalid.
-+ *
-+ * No other failure code is returned.
-+ *
-+ * 2.2.4 Caller's context
-+ *
-+ * dtrace_register() may induce calls to dtrace_provide(); the provider must
-+ * hold no locks across dtrace_register() that may also be acquired by
-+ * dtrace_provide(). cpu_lock and mod_lock must not be held.
-+ *
-+ * 2.3 int dtrace_unregister(dtrace_provider_id_t id)
-+ *
-+ * 2.3.1 Overview
-+ *
-+ * Unregisters the specified provider from the DTrace framework. It should
-+ * generally be called by DTrace providers in their detach(9E) entry point.
-+ *
-+ * 2.3.2 Arguments and Notes
-+ *
-+ * The only argument is the provider identifier, as returned from a
-+ * successful call to dtrace_register(). As a result of calling
-+ * dtrace_unregister(), the DTrace framework will call back into the provider
-+ * via the dtps_destroy() entry point. Once dtrace_unregister() successfully
-+ * completes, however, the DTrace framework will no longer make calls through
-+ * the Framework-to-Provider API.
-+ *
-+ * 2.3.3 Return value
-+ *
-+ * On success, dtrace_unregister returns 0. On failure, dtrace_unregister()
-+ * returns an errno:
-+ *
-+ * EBUSY There are currently processes that have the DTrace pseudodevice
-+ * open, or there exists an anonymous enabling that hasn't yet
-+ * been claimed.
-+ *
-+ * No other failure code is returned.
-+ *
-+ * 2.3.4 Caller's context
-+ *
-+ * Because a call to dtrace_unregister() may induce calls through the
-+ * Framework-to-Provider API, the caller may not hold any lock across
-+ * dtrace_register() that is also acquired in any of the Framework-to-
-+ * Provider API functions. Additionally, mod_lock may not be held.
-+ *
-+ * 2.4 void dtrace_invalidate(dtrace_provider_id_t id)
-+ *
-+ * 2.4.1 Overview
-+ *
-+ * Invalidates the specified provider. All subsequent probe lookups for the
-+ * specified provider will fail, but its probes will not be removed.
-+ *
-+ * 2.4.2 Arguments and note
-+ *
-+ * The only argument is the provider identifier, as returned from a
-+ * successful call to dtrace_register(). In general, a provider's probes
-+ * always remain valid; dtrace_invalidate() is a mechanism for invalidating
-+ * an entire provider, regardless of whether or not probes are enabled or
-+ * not. Note that dtrace_invalidate() will _not_ prevent already enabled
-+ * probes from firing -- it will merely prevent any new enablings of the
-+ * provider's probes.
-+ *
-+ * 2.5 int dtrace_condense(dtrace_provider_id_t id)
-+ *
-+ * 2.5.1 Overview
-+ *
-+ * Removes all the unenabled probes for the given provider. This function is
-+ * not unlike dtrace_unregister(), except that it doesn't remove the
-+ * provider just as many of its associated probes as it can.
-+ *
-+ * 2.5.2 Arguments and Notes
-+ *
-+ * As with dtrace_unregister(), the sole argument is the provider identifier
-+ * as returned from a successful call to dtrace_register(). As a result of
-+ * calling dtrace_condense(), the DTrace framework will call back into the
-+ * given provider's dtps_destroy() entry point for each of the provider's
-+ * unenabled probes.
-+ *
-+ * 2.5.3 Return value
-+ *
-+ * Currently, dtrace_condense() always returns 0. However, consumers of this
-+ * function should check the return value as appropriate; its behavior may
-+ * change in the future.
-+ *
-+ * 2.5.4 Caller's context
-+ *
-+ * As with dtrace_unregister(), the caller may not hold any lock across
-+ * dtrace_condense() that is also acquired in the provider's entry points.
-+ * Also, mod_lock may not be held.
-+ *
-+ * 2.6 int dtrace_attached()
-+ *
-+ * 2.6.1 Overview
-+ *
-+ * Indicates whether or not DTrace has attached.
-+ *
-+ * 2.6.2 Arguments and Notes
-+ *
-+ * For most providers, DTrace makes initial contact beyond registration.
-+ * That is, once a provider has registered with DTrace, it waits to hear
-+ * from DTrace to create probes. However, some providers may wish to
-+ * proactively create probes without first being told by DTrace to do so.
-+ * If providers wish to do this, they must first call dtrace_attached() to
-+ * determine if DTrace itself has attached. If dtrace_attached() returns 0,
-+ * the provider must not make any other Provider-to-Framework API call.
-+ *
-+ * 2.6.3 Return value
-+ *
-+ * dtrace_attached() returns 1 if DTrace has attached, 0 otherwise.
-+ *
-+ * 2.7 int dtrace_probe_create(dtrace_provider_id_t id, const char *mod,
-+ * const char *func, const char *name, int aframes, void *arg)
-+ *
-+ * 2.7.1 Overview
-+ *
-+ * Creates a probe with specified module name, function name, and name.
-+ *
-+ * 2.7.2 Arguments and Notes
-+ *
-+ * The first argument is the provider identifier, as returned from a
-+ * successful call to dtrace_register(). The second, third, and fourth
-+ * arguments are the module name, function name, and probe name,
-+ * respectively. Of these, module name and function name may both be NULL
-+ * (in which case the probe is considered to be unanchored), or they may both
-+ * be non-NULL. The name must be non-NULL, and must point to a non-empty
-+ * string.
-+ *
-+ * The fifth argument is the number of artificial stack frames that will be
-+ * found on the stack when dtrace_probe() is called for the new probe. These
-+ * artificial frames will be automatically be pruned should the stack() or
-+ * stackdepth() functions be called as part of one of the probe's ECBs. If
-+ * the parameter doesn't add an artificial frame, this parameter should be
-+ * zero.
-+ *
-+ * The final argument is a probe argument that will be passed back to the
-+ * provider when a probe-specific operation is called. (e.g., via
-+ * dtps_enable(), dtps_disable(), etc.)
-+ *
-+ * Note that it is up to the provider to be sure that the probe that it
-+ * creates does not already exist -- if the provider is unsure of the probe's
-+ * existence, it should assure its absence with dtrace_probe_lookup() before
-+ * calling dtrace_probe_create().
-+ *
-+ * 2.7.3 Return value
-+ *
-+ * dtrace_probe_create() always succeeds, and always returns the identifier
-+ * of the newly-created probe.
-+ *
-+ * 2.7.4 Caller's context
-+ *
-+ * While dtrace_probe_create() is generally expected to be called from
-+ * dtps_provide() and/or dtps_provide_module(), it may be called from other
-+ * non-DTrace contexts. Neither cpu_lock nor mod_lock may be held.
-+ *
-+ * 2.8 dtrace_id_t dtrace_probe_lookup(dtrace_provider_id_t id,
-+ * const char *mod, const char *func, const char *name)
-+ *
-+ * 2.8.1 Overview
-+ *
-+ * Looks up a probe based on provdider and one or more of module name,
-+ * function name and probe name.
-+ *
-+ * 2.8.2 Arguments and Notes
-+ *
-+ * The first argument is the provider identifier, as returned from a
-+ * successful call to dtrace_register(). The second, third, and fourth
-+ * arguments are the module name, function name, and probe name,
-+ * respectively. Any of these may be NULL; dtrace_probe_lookup() will return
-+ * the identifier of the first probe that is provided by the specified
-+ * provider and matches all of the non-NULL matching criteria.
-+ * dtrace_probe_lookup() is generally used by a provider to be check the
-+ * existence of a probe before creating it with dtrace_probe_create().
-+ *
-+ * 2.8.3 Return value
-+ *
-+ * If the probe exists, returns its identifier. If the probe does not exist,
-+ * return DTRACE_IDNONE.
-+ *
-+ * 2.8.4 Caller's context
-+ *
-+ * While dtrace_probe_lookup() is generally expected to be called from
-+ * dtps_provide() and/or dtps_provide_module(), it may also be called from
-+ * other non-DTrace contexts. Neither cpu_lock nor mod_lock may be held.
-+ *
-+ * 2.9 void *dtrace_probe_arg(dtrace_provider_id_t id, dtrace_id_t probe)
-+ *
-+ * 2.9.1 Overview
-+ *
-+ * Returns the probe argument associated with the specified probe.
-+ *
-+ * 2.9.2 Arguments and Notes
-+ *
-+ * The first argument is the provider identifier, as returned from a
-+ * successful call to dtrace_register(). The second argument is a probe
-+ * identifier, as returned from dtrace_probe_lookup() or
-+ * dtrace_probe_create(). This is useful if a probe has multiple
-+ * provider-specific components to it: the provider can create the probe
-+ * once with provider-specific state, and then add to the state by looking
-+ * up the probe based on probe identifier.
-+ *
-+ * 2.9.3 Return value
-+ *
-+ * Returns the argument associated with the specified probe. If the
-+ * specified probe does not exist, or if the specified probe is not provided
-+ * by the specified provider, NULL is returned.
-+ *
-+ * 2.9.4 Caller's context
-+ *
-+ * While dtrace_probe_arg() is generally expected to be called from
-+ * dtps_provide() and/or dtps_provide_module(), it may also be called from
-+ * other non-DTrace contexts. Neither cpu_lock nor mod_lock may be held.
-+ *
-+ * 2.10 void dtrace_probe(dtrace_id_t probe, uintptr_t arg0, uintptr_t arg1,
-+ * uintptr_t arg2, uintptr_t arg3, uintptr_t arg4)
-+ *
-+ * 2.10.1 Overview
-+ *
-+ * The epicenter of DTrace: fires the specified probes with the specified
-+ * arguments.
-+ *
-+ * 2.10.2 Arguments and Notes
-+ *
-+ * The first argument is a probe identifier as returned by
-+ * dtrace_probe_create() or dtrace_probe_lookup(). The second through sixth
-+ * arguments are the values to which the D variables "arg0" through "arg4"
-+ * will be mapped.
-+ *
-+ * dtrace_probe() should be called whenever the specified probe has fired --
-+ * however the provider defines it.
-+ *
-+ * 2.10.3 Return value
-+ *
-+ * None.
-+ *
-+ * 2.10.4 Caller's context
-+ *
-+ * dtrace_probe() may be called in virtually any context: kernel, user,
-+ * interrupt, high-level interrupt, with arbitrary adaptive locks held, with
-+ * dispatcher locks held, with interrupts disabled, etc. The only latitude
-+ * that must be afforded to DTrace is the ability to make calls within
-+ * itself (and to its in-kernel subroutines) and the ability to access
-+ * arbitrary (but mapped) memory. On some platforms, this constrains
-+ * context. For example, on UltraSPARC, dtrace_probe() cannot be called
-+ * from any context in which TL is greater than zero. dtrace_probe() may
-+ * also not be called from any routine which may be called by dtrace_probe()
-+ * -- which includes functions in the DTrace framework and some in-kernel
-+ * DTrace subroutines. All such functions "dtrace_"; providers that
-+ * instrument the kernel arbitrarily should be sure to not instrument these
-+ * routines.
-+ */
-+
-+#include <dtrace/types.h>
-+#include <linux/cred.h>
-+#include <linux/module.h>
-+#include <linux/dtrace/enabling_defines.h>
-+#include <linux/dtrace/arg_defines.h>
-+#include <dtrace/provider_defines.h>
-+#include <linux/dtrace/stability.h>
-+
-+struct dtrace_pops {
-+ void (*dtps_provide)(void *, const struct dtrace_probedesc *);
-+ void (*dtps_provide_module)(void *, struct module *);
-+ int (*dtps_enable)(void *, dtrace_id_t, void *);
-+ void (*dtps_disable)(void *, dtrace_id_t, void *);
-+ void (*dtps_suspend)(void *, dtrace_id_t, void *);
-+ void (*dtps_resume)(void *, dtrace_id_t, void *);
-+ void (*dtps_getargdesc)(void *, dtrace_id_t, void *,
-+ struct dtrace_argdesc *);
-+ uint64_t (*dtps_getargval)(void *, dtrace_id_t, void *, int, int);
-+ int (*dtps_usermode)(void *, dtrace_id_t, void *);
-+ void (*dtps_destroy)(void *, dtrace_id_t, void *);
-+ void (*dtps_destroy_module)(void *, struct module *);
-+};
-+
-+struct dtrace_helper_probedesc {
-+ char *dthpb_mod;
-+ char *dthpb_func;
-+ char *dthpb_name;
-+ uint64_t dthpb_base;
-+ uint32_t *dthpb_offs;
-+ uint32_t *dthpb_enoffs;
-+ uint32_t dthpb_noffs;
-+ uint32_t dthpb_nenoffs;
-+ uint8_t *dthpb_args;
-+ uint8_t dthpb_xargc;
-+ uint8_t dthpb_nargc;
-+ char *dthpb_xtypes;
-+ char *dthpb_ntypes;
-+};
-+
-+struct dtrace_helper_provdesc {
-+ char *dthpv_provname;
-+ struct dtrace_pattr dthpv_pattr;
-+};
-+
-+struct dtrace_mops {
-+ void (*dtms_create_probe)(void *, void *,
-+ struct dtrace_helper_probedesc *);
-+ void *(*dtms_provide_pid)(void *, struct dtrace_helper_provdesc *,
-+ pid_t);
-+ void (*dtms_remove_pid)(void *, struct dtrace_helper_provdesc *,
-+ pid_t);
-+};
-+
-+/*
-+ * DTrace Provider-to-Framework API Functions
-+ */
-+
-+struct dtrace_meta {
-+ struct dtrace_mops dtm_mops;
-+ char *dtm_name;
-+ void *dtm_arg;
-+ uint64_t dtm_count;
-+};
-+
-+struct dtrace_mprovider {
-+ char *dtmp_name;
-+ char *dtmp_pref;
-+ struct dtrace_pattr *dtmp_attr;
-+ uint32_t dtmp_priv;
-+ struct dtrace_pops *dtmp_pops;
-+ dtrace_provider_id_t dtmp_id;
-+};
-+
-+struct dtrace_pmod {
-+ struct module *mod;
-+ struct list_head list;
-+};
-+
-+extern int dtrace_register(const char *, const struct dtrace_pattr *,
-+ uint32_t, const struct cred *,
-+ const struct dtrace_pops *, void *,
-+ dtrace_provider_id_t *);
-+extern int dtrace_unregister(dtrace_provider_id_t);
-+extern void dtrace_invalidate(dtrace_provider_id_t);
-+extern int dtrace_condense(dtrace_provider_id_t);
-+extern int dtrace_attached(void);
-+
-+extern int dtrace_meta_register(const char *, const struct dtrace_mops *,
-+ void *, dtrace_meta_provider_id_t *);
-+extern int dtrace_meta_unregister(dtrace_meta_provider_id_t);
-+
-+extern dtrace_id_t dtrace_probe_create(dtrace_provider_id_t, const char *,
-+ const char *, const char *, int,
-+ void *);
-+extern void *dtrace_probe_arg(dtrace_provider_id_t, dtrace_id_t);
-+extern dtrace_id_t dtrace_probe_lookup(dtrace_provider_id_t, const char *,
-+ const char *, const char *);
-+extern void dtrace_probe(dtrace_id_t, uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t, uintptr_t);
-+
-+/*
-+ * Provider creation.
-+ */
-+#ifdef DTRACE_HAVE_PROV_EXIT
-+# define DT_PROV_EXIT(name) \
-+ extern int name##_prov_exit(void);
-+#else
-+# define DT_PROV_EXIT(name) \
-+ static int name##_prov_exit(void) \
-+ { \
-+ return (dtrace_unregister(name##_id) == 0); \
-+ }
-+#endif
-+
-+#define DT_PROVIDER_MODULE(name, priv) \
-+ dtrace_provider_id_t name##_id = DTRACE_PROVNONE; \
-+ \
-+ DT_PROV_EXIT(name) \
-+ \
-+ static int __init name##_init(void) \
-+ { \
-+ int ret = -ENOMEM; \
-+ struct dtrace_module *pdata = THIS_MODULE->pdata; \
-+ \
-+ if (pdata == NULL) \
-+ goto failed; \
-+ \
-+ ret = name##_dev_init(); \
-+ if (ret) \
-+ goto failed; \
-+ \
-+ ret = dtrace_register(__stringify(name), &name##_attr, priv, \
-+ NULL, &name##_pops, NULL, &name##_id); \
-+ if (ret) \
-+ goto failed; \
-+ \
-+ pdata->prov_exit = name##_prov_exit; \
-+ \
-+ return 0; \
-+ \
-+ failed: \
-+ return ret; \
-+ } \
-+ \
-+ static void __exit name##_exit(void) \
-+ { \
-+ name##_dev_exit(); \
-+ } \
-+ \
-+ module_init(name##_init); \
-+ module_exit(name##_exit);
-+
-+#ifdef DTRACE_HAVE_PROV_EXIT
-+# define DT_META_PROV_EXIT(name) \
-+ extern int name##_prov_exit(void);
-+#else
-+# define DT_META_PROV_EXIT(name) \
-+ static int name##_prov_exit(void) \
-+ { \
-+ return (dtrace_meta_unregister(name##_id) == 0); \
-+ }
-+#endif
-+
-+#define DT_META_PROVIDER_MODULE(name) \
-+ dtrace_meta_provider_id_t name##_id = DTRACE_METAPROVNONE; \
-+ \
-+ DT_META_PROV_EXIT(name) \
-+ \
-+ static int __init name##_init(void) \
-+ { \
-+ int ret = -ENOMEM; \
-+ struct dtrace_module *pdata = THIS_MODULE->pdata; \
-+ \
-+ if (pdata == NULL) \
-+ goto failed; \
-+ \
-+ ret = name##_dev_init(); \
-+ if (ret) \
-+ goto failed; \
-+ \
-+ ret = dtrace_meta_register(__stringify(name), &name##_mops, \
-+ NULL, &name##_id); \
-+ if (ret) \
-+ goto failed; \
-+ \
-+ pdata->prov_exit = name##_prov_exit; \
-+ \
-+ return 0; \
-+ \
-+ failed: \
-+ return ret; \
-+ } \
-+ \
-+ static void __exit name##_exit(void) \
-+ { \
-+ name##_dev_exit(); \
-+ } \
-+ \
-+ module_init(name##_init); \
-+ module_exit(name##_exit);
-+
-+#define DT_MULTI_PROVIDER_MODULE(name, plist) \
-+ static int name##_prov_exit(void) \
-+ { \
-+ int ret = 0; \
-+ struct dtrace_mprovider *prov; \
-+ \
-+ for (prov = plist; prov->dtmp_name != NULL; prov++) { \
-+ if (prov->dtmp_id != DTRACE_PROVNONE) { \
-+ ret = dtrace_unregister(prov->dtmp_id); \
-+ if (ret != 0) { \
-+ pr_warn("Failed to unregister " \
-+ "provider %s: %d", \
-+ prov->dtmp_name, ret); \
-+ break; \
-+ } \
-+ \
-+ prov->dtmp_id = DTRACE_PROVNONE; \
-+ } \
-+ } \
-+ \
-+ return (ret == 0); \
-+ } \
-+ \
-+ static int __init name##_init(void) \
-+ { \
-+ int ret = -ENOMEM; \
-+ struct dtrace_mprovider *prov; \
-+ struct dtrace_module *pdata = THIS_MODULE->pdata; \
-+ \
-+ if (pdata == NULL) \
-+ goto failed; \
-+ \
-+ ret = name##_dev_init(); \
-+ if (ret) \
-+ goto failed; \
-+ \
-+ for (prov = plist; prov->dtmp_name != NULL; prov++) { \
-+ if (dtrace_register(prov->dtmp_name, prov->dtmp_attr, \
-+ prov->dtmp_priv, NULL, \
-+ prov->dtmp_pops, prov, \
-+ &prov->dtmp_id) != 0) \
-+ pr_warn("Failed to register provider %s", \
-+ prov->dtmp_name); \
-+ } \
-+ \
-+ pdata->prov_exit = name##_prov_exit; \
-+ \
-+ return 0; \
-+ \
-+ failed: \
-+ return ret; \
-+ } \
-+ \
-+ static void __exit name##_exit(void) \
-+ { \
-+ name##_dev_exit(); \
-+ } \
-+ \
-+ module_init(name##_init); \
-+ module_exit(name##_exit);
-+
-+
-+#endif /* _DTRACE_PROVIDER_H */
-diff --git a/include/dtrace/provider_defines.h b/include/dtrace/provider_defines.h
-new file mode 100644
-index 000000000000..104514e1261b
---- /dev/null
-+++ b/include/dtrace/provider_defines.h
-@@ -0,0 +1,41 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Provider defines
-+ *
-+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _DTRACE_PROVIDER_DEFINES_H
-+#define _DTRACE_PROVIDER_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/in6.h>
-+
-+typedef uintptr_t dtrace_provider_id_t;
-+typedef uintptr_t dtrace_meta_provider_id_t;
-+typedef __be32 ipaddr_t;
-+typedef ipaddr_t *ipaddr_t_p;
-+typedef struct in6_addr in6_addr_t;
-+
-+struct dtrace_pops;
-+struct dtrace_helper_probedesc;
-+struct dtrace_helper_provdesc;
-+struct dtrace_mops;
-+struct dtrace_meta;
-+
-+#endif /* _DTRACE_PROVIDER_DEFINES_H */
-diff --git a/include/dtrace/types.h b/include/dtrace/types.h
-new file mode 100644
-index 000000000000..7f8d0d7efcc7
---- /dev/null
-+++ b/include/dtrace/types.h
-@@ -0,0 +1,131 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Kernel Types
-+ *
-+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _DTRACE_TYPES_H
-+#define _DTRACE_TYPES_H
-+
-+/*
-+ * This file contains types needed to parse the DTrace shared userspace/ kernel
-+ * headers, and a few others (it has not been gardened to remove constants used
-+ * only by the DTrace core). Userspace has its own version of these types
-+ * (mostly from <unistd.h>).
-+ *
-+ * This file is compiled both in a normal kernel environment and in a peculiar
-+ * halfway-house environment used for headers_checking of <ioctl.h>, in which
-+ * among other things, no config.h symbols are available. As a result, you
-+ * should be careful about #including kernel headers here: many will break
-+ * headers_check if added. So far, it has always been sufficient to add them to
-+ * dtrace/dtrace.h instead; if this turns out to be insufficient later (perhaps
-+ * because DTrace core files cease to #include all of <dtrace.h>), the
-+ * HEADERS_CHECK #define may prove useful to disable kernel-only portions of
-+ * this file.
-+ */
-+
-+#include <asm/bitsperlong.h>
-+#include <linux/dtrace_os.h>
-+
-+typedef unsigned char uchar_t;
-+typedef unsigned int uint_t;
-+typedef unsigned long ulong_t;
-+
-+typedef long intptr_t;
-+
-+#define UINT8_MAX (0xff)
-+#define UINT8_MIN 0
-+#define UINT16_MAX (0xffff)
-+#define UINT16_MIN 0
-+#define UINT32_MAX (0xffffffff)
-+#define UINT32_MIN 0
-+#define UINT64_MAX (~0ULL)
-+#define UINT64_MIN (0)
-+#define INT64_MAX ((long long)(~0ULL>>1))
-+#define INT64_MIN (-INT64_MAX - 1LL)
-+
-+#define NBBY (__BITS_PER_LONG / sizeof(long))
-+
-+/*
-+ * This is a bit unusual, but OpenSolaris seems to like it. Basically, the
-+ * values below are the number of time units (sec, milli, micro, nano) that
-+ * comprise 1 second. As such, it is the value of the respective multiplier.
-+ */
-+#define SEC 1
-+#define MILLISEC 1000
-+#define MICROSEC 1000000
-+#define NANOSEC 1000000000
-+
-+typedef enum {
-+ TRUE = -1,
-+ FALSE = 0
-+} boolean_t;
-+
-+
-+#define DTRACE_ACCESS_KERNEL 0x1
-+
-+#define DTRACE_CRA_PROC 0x0001
-+#define DTRACE_CRA_PROC_CONTROL 0x0002
-+#define DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER 0x0004
-+#define DTRACE_CRA_PROC_DESTRUCTIVE_CREDCHG 0x0010
-+#define DTRACE_CRA_KERNEL 0x0020
-+#define DTRACE_CRA_KERNEL_DESTRUCTIVE 0x0040
-+
-+#define DTRACE_CRA_ALL (DTRACE_CRA_PROC | \
-+ DTRACE_CRA_PROC_CONTROL | \
-+ DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER | \
-+ DTRACE_CRA_PROC_DESTRUCTIVE_CREDCHG | \
-+ DTRACE_CRA_KERNEL | \
-+ DTRACE_CRA_KERNEL_DESTRUCTIVE)
-+
-+#define DTRACE_CRV_ALLPROC 0x01
-+#define DTRACE_CRV_KERNEL 0x02
-+#define DTRACE_CRV_ALL (DTRACE_CRV_ALLPROC | DTRACE_CRV_KERNEL)
-+
-+#define DTRACE_MATCH_FAIL -1
-+#define DTRACE_MATCH_NEXT 0
-+#define DTRACE_MATCH_DONE 1
-+
-+#define DTRACE_COND_OWNER 0x01
-+#define DTRACE_COND_USERMODE 0x02
-+
-+#define P2ROUNDUP(x, a) (-(-(x) & -(a)))
-+
-+#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)
-+#define KTIME_INIT(s, ns) ((s64)(s) * NSEC_PER_SEC + (s64)(ns))
-+#else
-+# define KTIME_INIT(n, ns) { .sec = (s), .nsec = (ns) }
-+#endif
-+#define ktime_lt(t0, t1) (t0 < t1)
-+#define ktime_le(t0, t1) (t0 <= t1)
-+#define ktime_ge(t0, t1) (t0 >= t1)
-+#define ktime_gt(t0, t1) (t0 > t1)
-+#define ktime_cp(t0, t1) (t0 = t1)
-+
-+/*
-+ * Translate between kernel config options and userspace-compatible definitions.
-+ */
-+#ifdef CONFIG_64BIT
-+#define _LP64 1
-+#endif
-+#ifdef __LITTLE_ENDIAN
-+#define _LITTLE_ENDIAN 1
-+#endif
-+
-+#endif /* _DTRACE_TYPES_H */
-diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
-index bc56287a1ed1..25e7b8778b71 100644
---- a/include/linux/cpuhotplug.h
-+++ b/include/linux/cpuhotplug.h
-@@ -107,6 +107,7 @@ enum cpuhp_state {
- CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
- CPUHP_AP_ARM_MVEBU_COHERENCY,
- CPUHP_AP_MICROCODE_LOADER,
-+ CPUHP_AP_CYCLIC_STARTING,
- CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
- CPUHP_AP_PERF_X86_STARTING,
- CPUHP_AP_PERF_X86_AMD_IBS_STARTING,
-diff --git a/include/linux/cyclic.h b/include/linux/cyclic.h
-new file mode 100644
-index 000000000000..12ab85dc185b
---- /dev/null
-+++ b/include/linux/cyclic.h
-@@ -0,0 +1,49 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _CYCLIC_H_
-+#define _CYCLIC_H_
-+
-+#include <linux/ktime.h>
-+#include <linux/types.h>
-+
-+#define CY_LOW_LEVEL 0
-+#define CY_LOCK_LEVEL 1
-+#define CY_HIGH_LEVEL 2
-+#define CY_SOFT_LEVELS 2
-+#define CY_LEVELS 3
-+
-+typedef uintptr_t cyclic_id_t;
-+typedef uint16_t cyc_level_t;
-+typedef void (*cyc_func_t)(uintptr_t);
-+
-+#define CYCLIC_NONE ((cyclic_id_t)0)
-+
-+struct cyc_handler {
-+ cyc_func_t cyh_func;
-+ uintptr_t cyh_arg;
-+ cyc_level_t cyh_level;
-+};
-+
-+#define CY_INTERVAL_INF (-1)
-+
-+struct cyc_time {
-+ ktime_t cyt_when;
-+ ktime_t cyt_interval;
-+};
-+
-+struct cyc_omni_handler {
-+ void (*cyo_online)(void *, uint32_t, struct cyc_handler *,
-+ struct cyc_time *);
-+ void (*cyo_offline)(void *, uint32_t, void *);
-+ void *cyo_arg;
-+};
-+
-+extern cyclic_id_t cyclic_add(struct cyc_handler *, struct cyc_time *);
-+extern cyclic_id_t cyclic_add_omni(struct cyc_omni_handler *);
-+extern void cyclic_remove(cyclic_id_t);
-+extern void cyclic_reprogram(cyclic_id_t, ktime_t);
-+
-+#endif /* _CYCLIC_H_ */
-diff --git a/include/linux/dtrace/cpu_defines.h b/include/linux/dtrace/cpu_defines.h
-new file mode 100644
-index 000000000000..c8719378da80
---- /dev/null
-+++ b/include/linux/dtrace/cpu_defines.h
-@@ -0,0 +1,61 @@
-+/* Copyright (C) 2011-2014 Oracle, Inc. */
-+
-+#ifndef _LINUX_DTRACE_CPU_DEFINES_H_
-+#define _LINUX_DTRACE_CPU_DEFINES_H_
-+
-+#include <linux/percpu.h>
-+
-+#define CPUC_SIZE (sizeof (uint16_t) + sizeof(uint8_t) + \
-+ sizeof(uintptr_t) + sizeof(struct mutex))
-+#define CPUC_PADSIZE (192 - CPUC_SIZE)
-+
-+#define per_cpu_core(cpu) (&per_cpu(dtrace_cpu_core, (cpu)))
-+#if 0
-+# define this_cpu_core (this_cpu_ptr(&dtrace_cpu_core))
-+#else
-+# define this_cpu_core (per_cpu_core(smp_processor_id()))
-+#endif
-+
-+#define DTRACE_CPUFLAG_ISSET(flag) \
-+ (this_cpu_core->cpuc_dtrace_flags & (flag))
-+
-+#define DTRACE_CPUFLAG_SET(flag) \
-+ (this_cpu_core->cpuc_dtrace_flags |= (flag))
-+
-+#define DTRACE_CPUFLAG_CLEAR(flag) \
-+ (this_cpu_core->cpuc_dtrace_flags &= ~(flag))
-+
-+#define CPU_DTRACE_NOFAULT 0x0001
-+#define CPU_DTRACE_DROP 0x0002
-+#define CPU_DTRACE_BADADDR 0x0004
-+#define CPU_DTRACE_BADALIGN 0x0008
-+#define CPU_DTRACE_DIVZERO 0x0010
-+#define CPU_DTRACE_ILLOP 0x0020
-+#define CPU_DTRACE_NOSCRATCH 0x0040
-+#define CPU_DTRACE_KPRIV 0x0080
-+#define CPU_DTRACE_UPRIV 0x0100
-+#define CPU_DTRACE_TUPOFLOW 0x0200
-+#define CPU_DTRACE_ENTRY 0x0800
-+#define CPU_DTRACE_BADSTACK 0x1000
-+#define CPU_DTRACE_NOPF 0x2000
-+#define CPU_DTRACE_PF_TRAPPED 0x4000
-+
-+#define CPU_DTRACE_FAULT (CPU_DTRACE_BADADDR | CPU_DTRACE_BADALIGN | \
-+ CPU_DTRACE_DIVZERO | CPU_DTRACE_ILLOP | \
-+ CPU_DTRACE_NOSCRATCH | CPU_DTRACE_KPRIV | \
-+ CPU_DTRACE_UPRIV | CPU_DTRACE_TUPOFLOW | \
-+ CPU_DTRACE_BADSTACK | CPU_DTRACE_PF_TRAPPED)
-+#define CPU_DTRACE_ERROR (CPU_DTRACE_FAULT | CPU_DTRACE_DROP)
-+
-+typedef uint32_t processorid_t;
-+typedef uint32_t psetid_t;
-+typedef uint32_t chipid_t;
-+typedef uint32_t lgrp_id_t;
-+
-+struct cpu_core;
-+struct cpuinfo;
-+
-+#define per_cpu_info(cpu) (&per_cpu(dtrace_cpu_info, (cpu)))
-+#define this_cpu_info (this_cpu_ptr(&dtrace_cpu_info))
-+
-+#endif /* _LINUX_DTRACE_CPU_DEFINES_H_ */
-diff --git a/include/linux/dtrace_cpu.h b/include/linux/dtrace_cpu.h
-new file mode 100644
-index 000000000000..6b3dc7219f49
---- /dev/null
-+++ b/include/linux/dtrace_cpu.h
-@@ -0,0 +1,53 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_CPU_H_
-+#define _LINUX_DTRACE_CPU_H_
-+
-+#ifdef CONFIG_DTRACE
-+
-+#include <linux/ktime.h>
-+#include <linux/mutex.h>
-+#include <linux/spinlock.h>
-+#include <linux/dtrace_types.h>
-+#include <linux/dtrace_cpu_defines.h>
-+#include <asm/dtrace_cpuinfo.h>
-+
-+struct cpu_core {
-+ uint16_t cpuc_dtrace_flags;
-+ uint8_t cpuc_dcpc_intr_state;
-+ uint8_t cpuc_pad[CPUC_PADSIZE];
-+ uintptr_t cpuc_dtrace_illval;
-+ struct mutex cpuc_pid_lock;
-+
-+ uintptr_t cpu_dtrace_caller;
-+ struct pt_regs *cpu_dtrace_regs;
-+ ktime_t cpu_dtrace_chillmark;
-+ ktime_t cpu_dtrace_chilled;
-+ rwlock_t cpu_ft_lock;
-+ atomic64_t cpuc_sync_requests;
-+ atomic64_t cpuc_in_probe_ctx;
-+ dtrace_id_t cpuc_current_probe;
-+};
-+
-+DECLARE_PER_CPU_SHARED_ALIGNED(struct cpu_core, dtrace_cpu_core);
-+
-+struct cpuinfo {
-+ processorid_t cpu_id;
-+ psetid_t cpu_pset;
-+ chipid_t cpu_chip;
-+ lgrp_id_t cpu_lgrp;
-+ cpuinfo_arch_t *cpu_info;
-+};
-+
-+DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo, dtrace_cpu_info);
-+
-+/* ABI requirement: type names compiled into DTrace userspace. */
-+typedef struct cpuinfo cpuinfo_t;
-+
-+extern void dtrace_cpu_init(void);
-+
-+#endif /* CONFIG_DTRACE */
-+#endif /* _LINUX_DTRACE_CPU_H_ */
-diff --git a/include/linux/dtrace_cpu_defines.h b/include/linux/dtrace_cpu_defines.h
-new file mode 100644
-index 000000000000..f5866a6e95b8
---- /dev/null
-+++ b/include/linux/dtrace_cpu_defines.h
-@@ -0,0 +1,2 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+#include <linux/dtrace/cpu_defines.h>
-diff --git a/include/linux/dtrace_os.h b/include/linux/dtrace_os.h
-new file mode 100644
-index 000000000000..5bcd77e08a14
---- /dev/null
-+++ b/include/linux/dtrace_os.h
-@@ -0,0 +1,120 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_OS_H_
-+#define _LINUX_DTRACE_OS_H_
-+
-+#ifndef HEADERS_CHECK
-+
-+#ifdef CONFIG_DTRACE
-+
-+#include <linux/ktime.h>
-+#include <linux/mm.h>
-+#include <linux/notifier.h>
-+#include <linux/timekeeper_internal.h>
-+#include <asm/unistd.h>
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_task.h>
-+#include <linux/dtrace_psinfo.h>
-+
-+extern struct module *dtrace_kmod;
-+
-+extern void __init dtrace_os_init(void);
-+extern void __init dtrace_psinfo_os_init(void);
-+extern void __init dtrace_task_os_init(void);
-+
-+extern void dtrace_mod_pdata_alloc(struct module *);
-+extern void dtrace_mod_pdata_free(struct module *);
-+extern int dtrace_destroy_prov(struct module *);
-+
-+extern int dtrace_enable(void);
-+extern void dtrace_disable(void);
-+
-+extern ktime_t dtrace_gethrtime(void);
-+extern ktime_t dtrace_getwalltime(void);
-+
-+enum dtrace_vtime_state {
-+ DTRACE_VTIME_INACTIVE = 0,
-+ DTRACE_VTIME_ACTIVE
-+};
-+
-+extern enum dtrace_vtime_state dtrace_vtime_active;
-+
-+typedef void for_each_module_fn(void *, struct module *);
-+extern void dtrace_for_each_module(for_each_module_fn *fn, void *arg);
-+
-+extern void dtrace_update_time(struct timekeeper *);
-+extern ktime_t dtrace_get_walltime(void);
-+
-+extern void dtrace_vtime_enable(void);
-+extern void dtrace_vtime_disable(void);
-+extern void dtrace_vtime_switch(struct task_struct *, struct task_struct *);
-+
-+#include <asm/dtrace_util.h>
-+
-+extern int dtrace_instr_size(const asm_instr_t *);
-+
-+extern int dtrace_die_notifier(struct notifier_block *, unsigned long, void *);
-+
-+#define STACKTRACE_KERNEL 0x01
-+#define STACKTRACE_USER 0x02
-+#define STACKTRACE_TYPE 0x0f
-+
-+struct stacktrace_state {
-+ uint64_t *pcs;
-+ uint64_t *fps;
-+ int limit;
-+ int depth;
-+ int flags;
-+};
-+
-+extern void dtrace_stacktrace(struct stacktrace_state *);
-+extern void dtrace_user_stacktrace(struct stacktrace_state *);
-+extern void dtrace_handle_badaddr(struct pt_regs *);
-+extern void dtrace_mod_pdata_init(struct dtrace_module *pdata);
-+extern void dtrace_mod_pdata_cleanup(struct dtrace_module *pdata);
-+
-+/*
-+ * This is only safe to call if we know this is a userspace fault
-+ * or that the call happens after early boot.
-+ */
-+static inline int dtrace_no_pf(struct pt_regs *regs)
-+{
-+ if (unlikely(DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))) {
-+ dtrace_handle_badaddr(regs);
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+extern void (*dtrace_helpers_cleanup)(struct task_struct *);
-+extern void (*dtrace_helpers_fork)(struct task_struct *, struct task_struct *);
-+
-+#else
-+
-+/*
-+ * See arch/x86/mm/fault.c.
-+ */
-+
-+#define dtrace_no_pf(ignore) 0
-+
-+/*
-+ * See kernel/timekeeper.c
-+ */
-+#define dtrace_update_time(ignore)
-+
-+/*
-+ * See kernel/dtrace/dtrace_os.c
-+ */
-+#define dtrace_mod_pdata_alloc(ignore)
-+#define dtrace_mod_pdata_free(ignore)
-+#define dtrace_destroy_prov(ignore) 1
-+
-+#endif /* CONFIG_DTRACE */
-+
-+#endif /* !HEADERS_CHECK */
-+
-+#endif /* _LINUX_DTRACE_OS_H_ */
-diff --git a/include/linux/dtrace_psinfo.h b/include/linux/dtrace_psinfo.h
-new file mode 100644
-index 000000000000..53a9c317a8a3
---- /dev/null
-+++ b/include/linux/dtrace_psinfo.h
-@@ -0,0 +1,59 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_PSINFO_H_
-+#define _LINUX_DTRACE_PSINFO_H_
-+
-+#ifdef CONFIG_DTRACE
-+
-+#define PR_PSARGS_SZ 80
-+#define PR_ARGV_SZ 512
-+#define PR_ENVP_SZ 512
-+
-+/*
-+ * DTrace's per-process info (per-tgid).
-+ *
-+ * All threads in a process share the same structure instance.
-+ */
-+struct dtrace_psinfo {
-+ atomic_t dtps_usage;
-+ unsigned long dtps_argc;
-+ char **dtps_argv;
-+ unsigned long dtps_envc;
-+ char **dtps_envp;
-+ char dtps_psargs[PR_PSARGS_SZ];
-+};
-+
-+/*
-+ * DTrace psinfo API. Requires struct dtrace_task as its argument.
-+ */
-+
-+extern void dtrace_psinfo_alloc(struct task_struct *);
-+extern void dtrace_psinfo_free(struct dtrace_psinfo *);
-+
-+static inline void dtrace_psinfo_get(struct dtrace_psinfo *psinfo)
-+{
-+ if (likely(psinfo))
-+ atomic_inc(&(psinfo)->dtps_usage);
-+}
-+
-+static inline void dtrace_psinfo_put(struct dtrace_psinfo *psinfo)
-+{
-+ if (likely((psinfo))) {
-+ if (atomic_dec_and_test(&(psinfo)->dtps_usage))
-+ dtrace_psinfo_free(psinfo);
-+ }
-+}
-+
-+#else /* CONFIG_DTRACE */
-+
-+#define dtrace_psinfo_alloc(ignore)
-+#define dtrace_psinfo_free(ignore)
-+#define dtrace_psinfo_get(ignore)
-+#define dtrace_psinfo_put(ignore)
-+
-+#endif /* CONFIG_DTRACE */
-+
-+#endif /* _LINUX_DTRACE_PSINFO_H_ */
-diff --git a/include/linux/dtrace_task.h b/include/linux/dtrace_task.h
-new file mode 100644
-index 000000000000..ce7111223788
---- /dev/null
-+++ b/include/linux/dtrace_task.h
-@@ -0,0 +1,38 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_TASK_H_
-+#define _LINUX_DTRACE_TASK_H_
-+
-+#ifdef CONFIG_DTRACE
-+
-+#include <linux/sched.h>
-+
-+/*
-+ * Opaque handle for per-task data.
-+ */
-+struct dtrace_task;
-+
-+/*
-+ * DTrace's kernel API for per-task data manipulation.
-+ */
-+
-+extern void dtrace_task_init(struct task_struct *);
-+extern void dtrace_task_exec(struct task_struct *);
-+extern void dtrace_task_copy(struct task_struct *, struct task_struct *);
-+extern void dtrace_task_free(struct task_struct *);
-+extern void dtrace_task_dup(struct task_struct *, struct task_struct *);
-+
-+#else /* CONFIG_DTRACE */
-+
-+#define dtrace_task_init(ignore)
-+#define dtrace_task_exec(ignore)
-+#define dtrace_task_copy(ignore1, ignore2)
-+#define dtrace_task_free(ignore)
-+#define dtrace_task_dup(ignore1, ignore2)
-+
-+#endif /* CONFIG_DTRACE */
-+
-+#endif /* _LINUX_DTRACE_TASK_H_ */
-diff --git a/include/linux/dtrace_task_impl.h b/include/linux/dtrace_task_impl.h
-new file mode 100644
-index 000000000000..2f76b475c2f8
---- /dev/null
-+++ b/include/linux/dtrace_task_impl.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+#ifndef _LINUX_DTRACE_TASK_IMPL_H_
-+#define _LINUX_DTRACE_TASK_IMPL_H_
-+
-+#ifdef CONFIG_DTRACE
-+
-+#include <linux/dtrace_task.h>
-+#include <linux/dtrace_psinfo.h>
-+
-+struct dtrace_task {
-+ uint32_t dt_predcache;
-+ ktime_t dt_vtime;
-+ ktime_t dt_start;
-+ uint8_t dt_stop;
-+ uint8_t dt_sig;
-+ struct dtrace_psinfo *dt_psinfo;
-+ void *dt_helpers;
-+ uint32_t dt_probes;
-+ uint64_t dt_tp_count;
-+ void *dt_ustack;
-+};
-+
-+#endif /* CONFIG_DTRACE */
-+#endif /* _LINUX_DTRACE_TASK_IMPL_H_ */
-+
-diff --git a/include/linux/dtrace_types.h b/include/linux/dtrace_types.h
-new file mode 100644
-index 000000000000..4484dc58e188
---- /dev/null
-+++ b/include/linux/dtrace_types.h
-@@ -0,0 +1,13 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _DTRACE_TYPES_H_
-+#define _DTRACE_TYPES_H_
-+
-+typedef uint32_t dtrace_id_t;
-+
-+#define DTRACE_IDNONE 0
-+
-+#endif /* _DTRACE_TYPES_H_ */
-diff --git a/include/linux/ktime.h b/include/linux/ktime.h
-index a12b5523cc18..ba226005fd2a 100644
---- a/include/linux/ktime.h
-+++ b/include/linux/ktime.h
-@@ -156,6 +156,14 @@ static inline s64 ktime_divns(const ktime_t kt, s64 div)
- }
- #endif
-
-+/*
-+ * ktime_nz - Check whether a ktime_v variable is non-zero
-+ */
-+static inline int ktime_nz(const ktime_t kt)
-+{
-+ return kt != 0LL;
-+}
-+
- static inline s64 ktime_to_us(const ktime_t kt)
- {
- return ktime_divns(kt, NSEC_PER_USEC);
-diff --git a/include/linux/module.h b/include/linux/module.h
-index d44fe50d7c7f..44915ed85337 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -512,6 +512,9 @@ struct module {
- struct klp_modinfo *klp_info;
- #endif
-
-+#ifdef CONFIG_DTRACE
-+ void *pdata;
-+#endif
- #ifdef CONFIG_MODULE_UNLOAD
- /* What modules depend on me? */
- struct list_head source_list;
-diff --git a/include/linux/mutex.h b/include/linux/mutex.h
-index dcd185cbfe79..bb18028db361 100644
---- a/include/linux/mutex.h
-+++ b/include/linux/mutex.h
-@@ -20,6 +20,10 @@
- #include <linux/osq_lock.h>
- #include <linux/debug_locks.h>
-
-+#ifdef CONFIG_SMP
-+# include <asm/current.h>
-+#endif
-+
- struct ww_acquire_ctx;
-
- /*
-@@ -224,4 +228,16 @@ enum mutex_trylock_recursive_enum {
- extern /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
- mutex_trylock_recursive(struct mutex *lock);
-
-+#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
-+static inline int mutex_owned(struct mutex *lock)
-+{
-+ return mutex_is_locked(lock) && __mutex_owner(lock) == current;
-+}
-+#else
-+static inline int mutex_owned(struct mutex *lock)
-+{
-+ return mutex_is_locked(lock);
-+}
-+#endif
-+
- #endif /* __LINUX_MUTEX_H */
-diff --git a/include/linux/rwlock.h b/include/linux/rwlock.h
-index 3dcd617e65ae..a7e72774f17e 100644
---- a/include/linux/rwlock.h
-+++ b/include/linux/rwlock.h
-@@ -59,6 +59,13 @@ do { \
- # define do_raw_write_unlock(rwlock) do {arch_write_unlock(&(rwlock)->raw_lock); __release(lock); } while (0)
- #endif
-
-+#ifdef CONFIG_DTRACE
-+#define peek_read_can_lock(rwlock) \
-+ arch_peek_read_can_lock(&(rwlock)->raw_lock)
-+#define peek_write_can_lock(rwlock) \
-+ arch_peek_write_can_lock(&(rwlock)->raw_lock)
-+#endif /* CONFIG_DTRACE */
-+
- /*
- * Define the various rw_lock methods. Note we define these
- * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
-diff --git a/include/linux/sched.h b/include/linux/sched.h
-index 76cd21fa5501..0be45d979989 100644
---- a/include/linux/sched.h
-+++ b/include/linux/sched.h
-@@ -34,6 +34,7 @@
- #include <linux/rseq.h>
- #include <linux/seqlock.h>
- #include <linux/kcsan.h>
-+#include <linux/dtrace_task.h>
-
- /* task_struct member predeclarations (sorted alphabetically): */
- struct audit_context;
-@@ -1304,6 +1305,9 @@ struct task_struct {
- struct request_queue *throttle_queue;
- #endif
-
-+#ifdef CONFIG_DTRACE
-+ struct dtrace_task *dt_task;
-+#endif
- #ifdef CONFIG_UPROBES
- struct uprobe_task *utask;
- #endif
-diff --git a/include/linux/spinlock_up.h b/include/linux/spinlock_up.h
-index 0ac9112c1bbe..cfd00c13f2aa 100644
---- a/include/linux/spinlock_up.h
-+++ b/include/linux/spinlock_up.h
-@@ -69,4 +69,9 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
-
- #define arch_spin_is_contended(lock) (((void)(lock), 0))
-
-+#ifdef CONFIG_DTRACE
-+#define arch_peek_read_can_lock(lock) (((void)(lock), 1))
-+#define arch_peek_write_can_lock(lock) (((void)(lock), 1))
-+#endif /* CONFIG_DTRACE */
-+
- #endif /* __LINUX_SPINLOCK_UP_H */
-diff --git a/include/uapi/linux/dtrace/Kbuild b/include/uapi/linux/dtrace/Kbuild
-new file mode 100644
-index 000000000000..0cb5b941b72b
---- /dev/null
-+++ b/include/uapi/linux/dtrace/Kbuild
-@@ -0,0 +1,35 @@
-+# UAPI Header export list
-+header-y += actions_defines.h
-+header-y += actions.h
-+header-y += arg_defines.h
-+header-y += arg.h
-+header-y += buffer_defines.h
-+header-y += buffer.h
-+header-y += conf_defines.h
-+header-y += conf.h
-+header-y += cpu_defines.h
-+header-y += dif_defines.h
-+header-y += dif.h
-+header-y += difo_defines.h
-+header-y += difo.h
-+header-y += dof_defines.h
-+header-y += dof.h
-+header-y += dtrace.h
-+header-y += enabling_defines.h
-+header-y += enabling.h
-+header-y += fasttrap_defines.h
-+header-y += fasttrap.h
-+header-y += fasttrap_ioctl.h
-+header-y += faults_defines.h
-+header-y += faults.h
-+header-y += helpers_defines.h
-+header-y += helpers.h
-+header-y += ioctl.h
-+header-y += metadesc_defines.h
-+header-y += metadesc.h
-+header-y += options_defines.h
-+header-y += options.h
-+header-y += stability_defines.h
-+header-y += stability.h
-+header-y += status.h
-+header-y += universal.h
-diff --git a/include/uapi/linux/dtrace/actions.h b/include/uapi/linux/dtrace/actions.h
-new file mode 100644
-index 000000000000..9b47343271ba
---- /dev/null
-+++ b/include/uapi/linux/dtrace/actions.h
-@@ -0,0 +1,14 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ACTIONS_H
-+#define _LINUX_DTRACE_ACTIONS_H
-+
-+#include <linux/dtrace/actions_defines.h>
-+
-+#endif /* _LINUX_DTRACE_ACTIONS_H */
-diff --git a/include/uapi/linux/dtrace/actions_defines.h b/include/uapi/linux/dtrace/actions_defines.h
-new file mode 100644
-index 000000000000..4512c291f58a
---- /dev/null
-+++ b/include/uapi/linux/dtrace/actions_defines.h
-@@ -0,0 +1,181 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ACTIONS_DEFINES_H
-+#define _LINUX_DTRACE_ACTIONS_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * The upper byte determines the class of the action; the low bytes determines
-+ * the specific action within that class. The classes of actions are as
-+ * follows:
-+ *
-+ * [ no class ] <= May record process- or kernel-related data
-+ * DTRACEACT_PROC <= Only records process-related data
-+ * DTRACEACT_PROC_DESTRUCTIVE <= Potentially destructive to processes
-+ * DTRACEACT_KERNEL <= Only records kernel-related data
-+ * DTRACEACT_KERNEL_DESTRUCTIVE <= Potentially destructive to the kernel
-+ * DTRACEACT_SPECULATIVE <= Speculation-related action
-+ * DTRACEACT_AGGREGATION <= Aggregating action
-+ */
-+#define DTRACEACT_NONE 0 /* no action */
-+#define DTRACEACT_DIFEXPR 1 /* action is DIF expression */
-+#define DTRACEACT_EXIT 2 /* exit() action */
-+#define DTRACEACT_PRINTF 3 /* printf() action */
-+#define DTRACEACT_PRINTA 4 /* printa() action */
-+#define DTRACEACT_LIBACT 5 /* library-controlled action */
-+#define DTRACEACT_TRACEMEM 6 /* tracemem() action */
-+#define DTRACEACT_PCAP 7 /* pcap() action */
-+
-+#define DTRACEACT_PROC 0x0100
-+#define DTRACEACT_USTACK (DTRACEACT_PROC + 1)
-+#define DTRACEACT_JSTACK (DTRACEACT_PROC + 2)
-+#define DTRACEACT_USYM (DTRACEACT_PROC + 3)
-+#define DTRACEACT_UMOD (DTRACEACT_PROC + 4)
-+#define DTRACEACT_UADDR (DTRACEACT_PROC + 5)
-+
-+#define DTRACEACT_PROC_DESTRUCTIVE 0x0200
-+#define DTRACEACT_STOP (DTRACEACT_PROC_DESTRUCTIVE + 1)
-+#define DTRACEACT_RAISE (DTRACEACT_PROC_DESTRUCTIVE + 2)
-+#define DTRACEACT_SYSTEM (DTRACEACT_PROC_DESTRUCTIVE + 3)
-+#define DTRACEACT_FREOPEN (DTRACEACT_PROC_DESTRUCTIVE + 4)
-+
-+#define DTRACEACT_PROC_CONTROL 0x0300
-+
-+#define DTRACEACT_KERNEL 0x0400
-+#define DTRACEACT_STACK (DTRACEACT_KERNEL + 1)
-+#define DTRACEACT_SYM (DTRACEACT_KERNEL + 2)
-+#define DTRACEACT_MOD (DTRACEACT_KERNEL + 3)
-+
-+#define DTRACEACT_KERNEL_DESTRUCTIVE 0x0500
-+#define DTRACEACT_BREAKPOINT (DTRACEACT_KERNEL_DESTRUCTIVE + 1)
-+#define DTRACEACT_PANIC (DTRACEACT_KERNEL_DESTRUCTIVE + 2)
-+#define DTRACEACT_CHILL (DTRACEACT_KERNEL_DESTRUCTIVE + 3)
-+
-+#define DTRACEACT_SPECULATIVE 0x0600
-+#define DTRACEACT_SPECULATE (DTRACEACT_SPECULATIVE + 1)
-+#define DTRACEACT_COMMIT (DTRACEACT_SPECULATIVE + 2)
-+#define DTRACEACT_DISCARD (DTRACEACT_SPECULATIVE + 3)
-+
-+#define DTRACEACT_CLASS(x) ((x) & 0xff00)
-+
-+#define DTRACEACT_ISAGG(x) \
-+ (DTRACEACT_CLASS(x) == DTRACEACT_AGGREGATION)
-+
-+#define DTRACEACT_ISDESTRUCTIVE(x) \
-+ (DTRACEACT_CLASS(x) == DTRACEACT_PROC_DESTRUCTIVE || \
-+ DTRACEACT_CLASS(x) == DTRACEACT_KERNEL_DESTRUCTIVE)
-+
-+#define DTRACEACT_ISSPECULATIVE(x) \
-+ (DTRACEACT_CLASS(x) == DTRACEACT_SPECULATIVE)
-+
-+#define DTRACEACT_ISPRINTFLIKE(x) \
-+ ((x) == DTRACEACT_PRINTF || (x) == DTRACEACT_PRINTA || \
-+ (x) == DTRACEACT_SYSTEM || (x) == DTRACEACT_FREOPEN)
-+
-+/*
-+ * DTrace Aggregating Actions
-+ *
-+ * These are functions f(x) for which the following is true:
-+ *
-+ * f(f(x_0) U f(x_1) U ... U f(x_n)) = f(x_0 U x_1 U ... U x_n)
-+ *
-+ * where x_n is a set of arbitrary data. Aggregating actions are in their own
-+ * DTrace action class, DTTRACEACT_AGGREGATION. The macros provided here allow
-+ * for easier processing of the aggregation argument and data payload for a few
-+ * aggregating actions (notably: quantize(), lquantize(), and ustack()).
-+ */
-+
-+#define DTRACEACT_AGGREGATION 0x0700
-+#define DTRACEAGG_COUNT (DTRACEACT_AGGREGATION + 1)
-+#define DTRACEAGG_MIN (DTRACEACT_AGGREGATION + 2)
-+#define DTRACEAGG_MAX (DTRACEACT_AGGREGATION + 3)
-+#define DTRACEAGG_AVG (DTRACEACT_AGGREGATION + 4)
-+#define DTRACEAGG_SUM (DTRACEACT_AGGREGATION + 5)
-+#define DTRACEAGG_STDDEV (DTRACEACT_AGGREGATION + 6)
-+#define DTRACEAGG_QUANTIZE (DTRACEACT_AGGREGATION + 7)
-+#define DTRACEAGG_LQUANTIZE (DTRACEACT_AGGREGATION + 8)
-+#define DTRACEAGG_LLQUANTIZE (DTRACEACT_AGGREGATION + 9)
-+
-+#define DTRACE_QUANTIZE_NBUCKETS \
-+ (((sizeof(uint64_t) * NBBY) - 1) * 2 + 1)
-+
-+#define DTRACE_QUANTIZE_ZEROBUCKET ((sizeof(uint64_t) * NBBY) - 1)
-+
-+#define DTRACE_QUANTIZE_BUCKETVAL(buck) \
-+ (int64_t)((buck) < DTRACE_QUANTIZE_ZEROBUCKET ? \
-+ -(1LL << (DTRACE_QUANTIZE_ZEROBUCKET - 1 - (buck))) : \
-+ (buck) == DTRACE_QUANTIZE_ZEROBUCKET ? 0 : \
-+ 1LL << ((buck) - DTRACE_QUANTIZE_ZEROBUCKET - 1))
-+
-+#define DTRACE_LQUANTIZE_STEPSHIFT 48
-+#define DTRACE_LQUANTIZE_STEPMASK ((uint64_t)UINT16_MAX << 48)
-+#define DTRACE_LQUANTIZE_LEVELSHIFT 32
-+#define DTRACE_LQUANTIZE_LEVELMASK ((uint64_t)UINT16_MAX << 32)
-+#define DTRACE_LQUANTIZE_BASESHIFT 0
-+#define DTRACE_LQUANTIZE_BASEMASK UINT32_MAX
-+
-+#define DTRACE_LQUANTIZE_STEP(x) \
-+ (uint16_t)(((x) & DTRACE_LQUANTIZE_STEPMASK) >> \
-+ DTRACE_LQUANTIZE_STEPSHIFT)
-+
-+#define DTRACE_LQUANTIZE_LEVELS(x) \
-+ (uint16_t)(((x) & DTRACE_LQUANTIZE_LEVELMASK) >> \
-+ DTRACE_LQUANTIZE_LEVELSHIFT)
-+
-+#define DTRACE_LQUANTIZE_BASE(x) \
-+ (int32_t)(((x) & DTRACE_LQUANTIZE_BASEMASK) >> \
-+ DTRACE_LQUANTIZE_BASESHIFT)
-+
-+#define DTRACE_LLQUANTIZE_STEPSSHIFT 48
-+#define DTRACE_LLQUANTIZE_STEPSMASK ((uint64_t)UINT16_MAX << 48)
-+#define DTRACE_LLQUANTIZE_HMAGSHIFT 32
-+#define DTRACE_LLQUANTIZE_HMAGMASK ((uint64_t)UINT16_MAX << 32)
-+#define DTRACE_LLQUANTIZE_LMAGSHIFT 16
-+#define DTRACE_LLQUANTIZE_LMAGMASK ((uint64_t)UINT16_MAX << 16)
-+#define DTRACE_LLQUANTIZE_FACTORSHIFT 0
-+#define DTRACE_LLQUANTIZE_FACTORMASK UINT16_MAX
-+
-+#define DTRACE_LLQUANTIZE_STEPS(x) \
-+ (uint16_t)(((x) & DTRACE_LLQUANTIZE_STEPSMASK) >> \
-+ DTRACE_LLQUANTIZE_STEPSSHIFT)
-+
-+#define DTRACE_LLQUANTIZE_HMAG(x) \
-+ (uint16_t)(((x) & DTRACE_LLQUANTIZE_HMAGMASK) >> \
-+ DTRACE_LLQUANTIZE_HMAGSHIFT)
-+
-+#define DTRACE_LLQUANTIZE_LMAG(x) \
-+ (uint16_t)(((x) & DTRACE_LLQUANTIZE_LMAGMASK) >> \
-+ DTRACE_LLQUANTIZE_LMAGSHIFT)
-+
-+#define DTRACE_LLQUANTIZE_FACTOR(x) \
-+ (uint16_t)(((x) & DTRACE_LLQUANTIZE_FACTORMASK) >> \
-+ DTRACE_LLQUANTIZE_FACTORSHIFT)
-+
-+#define DTRACE_USTACK_NFRAMES(x) (uint32_t)((x) & UINT32_MAX)
-+#define DTRACE_USTACK_STRSIZE(x) (uint32_t)((x) >> 32)
-+#define DTRACE_USTACK_ARG(x, y) \
-+ ((((uint64_t)(y)) << 32) | ((x) & UINT32_MAX))
-+
-+#ifndef _LP64
-+# ifndef _LITTLE_ENDIAN
-+# define DTRACE_PTR(type, name) uint32_t name##pad; type *name
-+# else
-+# define DTRACE_PTR(type, name) type *name; uint32_t name##pad
-+# endif
-+#else
-+# define DTRACE_PTR(type, name) type *name
-+#endif
-+
-+#endif /* _LINUX_DTRACE_ACTIONS_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/arg.h b/include/uapi/linux/dtrace/arg.h
-new file mode 100644
-index 000000000000..4a9099a816e6
---- /dev/null
-+++ b/include/uapi/linux/dtrace/arg.h
-@@ -0,0 +1,42 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ARG_H
-+#define _LINUX_DTRACE_ARG_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/arg_defines.h>
-+
-+/*
-+ * Because it would waste both space and time, argument types do not reside
-+ * with the probe. In order to determine argument types for args[X]
-+ * variables, the D compiler queries for argument types on a probe-by-probe
-+ * basis. (This optimizes for the common case that arguments are either not
-+ * used or used in an untyped fashion.) Typed arguments are specified with a
-+ * string of the type name in the dtragd_native member of the argument
-+ * description structure. Typed arguments may be further translated to types
-+ * of greater stability; the provider indicates such a translated argument by
-+ * filling in the dtargd_xlate member with the string of the translated type.
-+ * Finally, the provider may indicate which argument value a given argument
-+ * maps to by setting the dtargd_mapping member -- allowing a single argument
-+ * to map to multiple args[X] variables.
-+ */
-+typedef struct dtrace_argdesc {
-+ dtrace_id_t dtargd_id;
-+ int dtargd_ndx;
-+ int dtargd_mapping;
-+ char dtargd_native[DTRACE_ARGTYPELEN];
-+ char dtargd_xlate[DTRACE_ARGTYPELEN];
-+} dtrace_argdesc_t;
-+
-+#endif /* _LINUX_DTRACE_ARG_H */
-diff --git a/include/uapi/linux/dtrace/arg_defines.h b/include/uapi/linux/dtrace/arg_defines.h
-new file mode 100644
-index 000000000000..72862cd1b8e6
---- /dev/null
-+++ b/include/uapi/linux/dtrace/arg_defines.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ARG_DEFINES_H
-+#define _LINUX_DTRACE_ARG_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_argdesc;
-+
-+#endif /* _LINUX_DTRACE_ARG_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/buffer.h b/include/uapi/linux/dtrace/buffer.h
-new file mode 100644
-index 000000000000..9bbbc4f1f14b
---- /dev/null
-+++ b/include/uapi/linux/dtrace/buffer.h
-@@ -0,0 +1,43 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_BUFFER_H
-+#define _LINUX_DTRACE_BUFFER_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/actions_defines.h>
-+#include <linux/dtrace/buffer_defines.h>
-+
-+/*
-+ * In order to get a snapshot of the principal or aggregation buffer,
-+ * user-level passes a buffer description to the kernel with the dtrace_bufdesc
-+ * structure. This describes which CPU user-level is interested in, and
-+ * where user-level wishes the kernel to snapshot the buffer to (the
-+ * dtbd_data field). The kernel uses the same structure to pass back some
-+ * information regarding the buffer: the size of data actually copied out, the
-+ * number of drops, the number of errors, and the offset of the oldest record.
-+ * If the buffer policy is a "switch" policy, taking a snapshot of the
-+ * principal buffer has the additional effect of switching the active and
-+ * inactive buffers. Taking a snapshot of the aggregation buffer _always_ has
-+ * the additional effect of switching the active and inactive buffers.
-+ */
-+typedef struct dtrace_bufdesc {
-+ uint64_t dtbd_size; /* size of buffer */
-+ uint32_t dtbd_cpu; /* CPU or DTRACE_CPUALL */
-+ uint32_t dtbd_errors; /* number of errors */
-+ uint64_t dtbd_drops; /* number of drops */
-+ DTRACE_PTR(char, dtbd_data); /* data */
-+ uint64_t dtbd_oldest; /* offset of oldest record */
-+} dtrace_bufdesc_t;
-+
-+#endif /* _LINUX_DTRACE_BUFFER_H */
-diff --git a/include/uapi/linux/dtrace/buffer_defines.h b/include/uapi/linux/dtrace/buffer_defines.h
-new file mode 100644
-index 000000000000..16c3c193618a
---- /dev/null
-+++ b/include/uapi/linux/dtrace/buffer_defines.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_BUFFER_DEFINES_H
-+#define _LINUX_DTRACE_BUFFER_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_bufdesc;
-+
-+#endif /* _LINUX_DTRACE_BUFFER_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/conf.h b/include/uapi/linux/dtrace/conf.h
-new file mode 100644
-index 000000000000..95b201958f4c
---- /dev/null
-+++ b/include/uapi/linux/dtrace/conf.h
-@@ -0,0 +1,35 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_CONF_H
-+#define _LINUX_DTRACE_CONF_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/conf_defines.h>
-+
-+/*
-+ * User-level may need to understand some elements of the kernel DTrace
-+ * configuration in order to generate correct DIF. This information is
-+ * conveyed via the dtrace_conf structure.
-+ */
-+typedef struct dtrace_conf {
-+ uint_t dtc_difversion; /* supported DIF version */
-+ uint_t dtc_difintregs; /* # of DIF integer registers */
-+ uint_t dtc_diftupregs; /* # of DIF tuple registers */
-+ uint_t dtc_ctfmodel; /* CTF data model */
-+ /* Deviation from Solaris... Used to just be 8 padding entries. */
-+ uint_t dtc_maxbufs; /* max # of buffers */
-+ uint_t dtc_pad[7]; /* reserved for future use */
-+} dtrace_conf_t;
-+
-+#endif /* _LINUX_DTRACE_CONF_H */
-diff --git a/include/uapi/linux/dtrace/conf_defines.h b/include/uapi/linux/dtrace/conf_defines.h
-new file mode 100644
-index 000000000000..5c4a1cb5d37c
---- /dev/null
-+++ b/include/uapi/linux/dtrace/conf_defines.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_CONF_DEFINES_H
-+#define _LINUX_DTRACE_CONF_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_conf;
-+
-+#endif /* _LINUX_DTRACE_CONF_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/cpu_defines.h b/include/uapi/linux/dtrace/cpu_defines.h
-new file mode 100644
-index 000000000000..a1cd3e410ccc
---- /dev/null
-+++ b/include/uapi/linux/dtrace/cpu_defines.h
-@@ -0,0 +1,17 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_CPU_DEFINES_H_
-+#define _LINUX_DTRACE_CPU_DEFINES_H_
-+
-+typedef uint32_t processorid_t;
-+typedef uint32_t psetid_t;
-+typedef uint32_t chipid_t;
-+typedef uint32_t lgrp_id_t;
-+
-+#endif /* _LINUX_DTRACE_CPU_DEFINES_H_ */
-diff --git a/include/uapi/linux/dtrace/dif.h b/include/uapi/linux/dtrace/dif.h
-new file mode 100644
-index 000000000000..92daea17a1f1
---- /dev/null
-+++ b/include/uapi/linux/dtrace/dif.h
-@@ -0,0 +1,60 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DIF_H
-+#define _LINUX_DTRACE_DIF_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/dif_defines.h>
-+
-+/*
-+ * The following definitions describe the DTrace Intermediate Format (DIF), a a
-+ * RISC-like instruction set and program encoding used to represent predicates
-+ * and actions that can be bound to DTrace probes. The constants below defining
-+ * the number of available registers are suggested minimums; the compiler should
-+ * use DTRACEIOC_CONF to dynamically obtain the number of registers provided by
-+ * the current DTrace implementation.
-+ */
-+
-+/*
-+ * A DTrace Intermediate Format Type (DIF Type) is used to represent the types
-+ * of variables, function and associative array arguments, and the return type
-+ * for each DIF object (shown below). It contains a description of the type,
-+ * its size in bytes, and a module identifier.
-+ */
-+
-+typedef struct dtrace_diftype {
-+ uint8_t dtdt_kind;
-+ uint8_t dtdt_ckind;
-+ uint8_t dtdt_flags;
-+ uint8_t dtdt_pad;
-+ uint32_t dtdt_size;
-+} dtrace_diftype_t;
-+
-+/*
-+ * A DTrace Intermediate Format variable record is used to describe each of the
-+ * variables referenced by a given DIF object. It contains an integer variable
-+ * identifier along with variable scope and properties, as shown below. The
-+ * size of this structure must be sizeof (int) aligned.
-+ */
-+
-+typedef struct dtrace_difv {
-+ uint32_t dtdv_name;
-+ uint32_t dtdv_id;
-+ uint8_t dtdv_kind;
-+ uint8_t dtdv_scope;
-+ uint16_t dtdv_flags;
-+ struct dtrace_diftype dtdv_type;
-+} dtrace_difv_t;
-+
-+#endif /* _LINUX_DTRACE_DIF_H */
-diff --git a/include/uapi/linux/dtrace/dif_defines.h b/include/uapi/linux/dtrace/dif_defines.h
-new file mode 100644
-index 000000000000..80b913f097a2
---- /dev/null
-+++ b/include/uapi/linux/dtrace/dif_defines.h
-@@ -0,0 +1,288 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DIF_DEFINES_H
-+#define _LINUX_DTRACE_DIF_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * The following definitions describe the DTrace Intermediate Format (DIF), a a
-+ * RISC-like instruction set and program encoding used to represent predicates
-+ * and actions that can be bound to DTrace probes. The constants below defining
-+ * the number of available registers are suggested minimums; the compiler should
-+ * use DTRACEIOC_CONF to dynamically obtain the number of registers provided by
-+ * the current DTrace implementation.
-+ */
-+
-+#define DIF_VERSION_1 1
-+#define DIF_VERSION_2 2
-+#define DIF_VERSION DIF_VERSION_2
-+#define DIF_DIR_NREGS 8 /* number of DIF integer registers */
-+#define DIF_DTR_NREGS 8 /* number of DIF tuple registers */
-+
-+#define DIF_OP_OR 1 /* or r1, r2, rd */
-+#define DIF_OP_XOR 2 /* xor r1, r2, rd */
-+#define DIF_OP_AND 3 /* and r1, r2, rd */
-+#define DIF_OP_SLL 4 /* sll r1, r2, rd */
-+#define DIF_OP_SRL 5 /* srl r1, r2, rd */
-+#define DIF_OP_SUB 6 /* sub r1, r2, rd */
-+#define DIF_OP_ADD 7 /* add r1, r2, rd */
-+#define DIF_OP_MUL 8 /* mul r1, r2, rd */
-+#define DIF_OP_SDIV 9 /* sdiv r1, r2, rd */
-+#define DIF_OP_UDIV 10 /* udiv r1, r2, rd */
-+#define DIF_OP_SREM 11 /* srem r1, r2, rd */
-+#define DIF_OP_UREM 12 /* urem r1, r2, rd */
-+#define DIF_OP_NOT 13 /* not r1, rd */
-+#define DIF_OP_MOV 14 /* mov r1, rd */
-+#define DIF_OP_CMP 15 /* cmp r1, r2 */
-+#define DIF_OP_TST 16 /* tst r1 */
-+#define DIF_OP_BA 17 /* ba label */
-+#define DIF_OP_BE 18 /* be label */
-+#define DIF_OP_BNE 19 /* bne label */
-+#define DIF_OP_BG 20 /* bg label */
-+#define DIF_OP_BGU 21 /* bgu label */
-+#define DIF_OP_BGE 22 /* bge label */
-+#define DIF_OP_BGEU 23 /* bgeu label */
-+#define DIF_OP_BL 24 /* bl label */
-+#define DIF_OP_BLU 25 /* blu label */
-+#define DIF_OP_BLE 26 /* ble label */
-+#define DIF_OP_BLEU 27 /* bleu label */
-+#define DIF_OP_LDSB 28 /* ldsb [r1], rd */
-+#define DIF_OP_LDSH 29 /* ldsh [r1], rd */
-+#define DIF_OP_LDSW 30 /* ldsw [r1], rd */
-+#define DIF_OP_LDUB 31 /* ldub [r1], rd */
-+#define DIF_OP_LDUH 32 /* lduh [r1], rd */
-+#define DIF_OP_LDUW 33 /* lduw [r1], rd */
-+#define DIF_OP_LDX 34 /* ldx [r1], rd */
-+#define DIF_OP_RET 35 /* ret rd */
-+#define DIF_OP_NOP 36 /* nop */
-+#define DIF_OP_SETX 37 /* setx intindex, rd */
-+#define DIF_OP_SETS 38 /* sets strindex, rd */
-+#define DIF_OP_SCMP 39 /* scmp r1, r2 */
-+#define DIF_OP_LDGA 40 /* ldga var, ri, rd */
-+#define DIF_OP_LDGS 41 /* ldgs var, rd */
-+#define DIF_OP_STGS 42 /* stgs var, rs */
-+#define DIF_OP_LDTA 43 /* ldta var, ri, rd */
-+#define DIF_OP_LDTS 44 /* ldts var, rd */
-+#define DIF_OP_STTS 45 /* stts var, rs */
-+#define DIF_OP_SRA 46 /* sra r1, r2, rd */
-+#define DIF_OP_CALL 47 /* call subr, rd */
-+#define DIF_OP_PUSHTR 48 /* pushtr type, rs, rr */
-+#define DIF_OP_PUSHTV 49 /* pushtv type, rs, rv */
-+#define DIF_OP_POPTS 50 /* popts */
-+#define DIF_OP_FLUSHTS 51 /* flushts */
-+#define DIF_OP_LDGAA 52 /* ldgaa var, rd */
-+#define DIF_OP_LDTAA 53 /* ldtaa var, rd */
-+#define DIF_OP_STGAA 54 /* stgaa var, rs */
-+#define DIF_OP_STTAA 55 /* sttaa var, rs */
-+#define DIF_OP_LDLS 56 /* ldls var, rd */
-+#define DIF_OP_STLS 57 /* stls var, rs */
-+#define DIF_OP_ALLOCS 58 /* allocs r1, rd */
-+#define DIF_OP_COPYS 59 /* copys r1, r2, rd */
-+#define DIF_OP_STB 60 /* stb r1, [rd] */
-+#define DIF_OP_STH 61 /* sth r1, [rd] */
-+#define DIF_OP_STW 62 /* stw r1, [rd] */
-+#define DIF_OP_STX 63 /* stx r1, [rd] */
-+#define DIF_OP_ULDSB 64 /* uldsb [r1], rd */
-+#define DIF_OP_ULDSH 65 /* uldsh [r1], rd */
-+#define DIF_OP_ULDSW 66 /* uldsw [r1], rd */
-+#define DIF_OP_ULDUB 67 /* uldub [r1], rd */
-+#define DIF_OP_ULDUH 68 /* ulduh [r1], rd */
-+#define DIF_OP_ULDUW 69 /* ulduw [r1], rd */
-+#define DIF_OP_ULDX 70 /* uldx [r1], rd */
-+#define DIF_OP_RLDSB 71 /* rldsb [r1], rd */
-+#define DIF_OP_RLDSH 72 /* rldsh [r1], rd */
-+#define DIF_OP_RLDSW 73 /* rldsw [r1], rd */
-+#define DIF_OP_RLDUB 74 /* rldub [r1], rd */
-+#define DIF_OP_RLDUH 75 /* rlduh [r1], rd */
-+#define DIF_OP_RLDUW 76 /* rlduw [r1], rd */
-+#define DIF_OP_RLDX 77 /* rldx [r1], rd */
-+#define DIF_OP_XLATE 78 /* xlate xlrindex, rd */
-+#define DIF_OP_XLARG 79 /* xlarg xlrindex, rd */
-+
-+#define DIF_INTOFF_MAX 0xffff /* highest integer table offset */
-+#define DIF_STROFF_MAX 0xffff /* highest string table offset */
-+#define DIF_REGISTER_MAX 0xff /* highest register number */
-+#define DIF_VARIABLE_MAX 0xffff /* highest variable identifier */
-+#define DIF_SUBROUTINE_MAX 0xffff /* highest subroutine code */
-+
-+#define DIF_VAR_ARRAY_MIN 0x0000 /* lowest numbered array variable */
-+#define DIF_VAR_ARRAY_UBASE 0x0080 /* lowest user-defined array */
-+#define DIF_VAR_ARRAY_MAX 0x00ff /* highest numbered array variable */
-+
-+#define DIF_VAR_OTHER_MIN 0x0100 /* lowest numbered scalar or assc */
-+#define DIF_VAR_OTHER_UBASE 0x0500 /* lowest user-defined scalar or assc */
-+#define DIF_VAR_OTHER_MAX 0xffff /* highest numbered scalar or assc */
-+
-+#define DIF_VAR_ARGS 0x0000
-+#define DIF_VAR_REGS 0x0001
-+#define DIF_VAR_UREGS 0x0002
-+#define DIF_VAR_CURTHREAD 0x0100
-+#define DIF_VAR_TIMESTAMP 0x0101
-+#define DIF_VAR_VTIMESTAMP 0x0102
-+#define DIF_VAR_IPL 0x0103
-+#define DIF_VAR_EPID 0x0104
-+#define DIF_VAR_ID 0x0105
-+#define DIF_VAR_ARG0 0x0106
-+#define DIF_VAR_ARG1 0x0107
-+#define DIF_VAR_ARG2 0x0108
-+#define DIF_VAR_ARG3 0x0109
-+#define DIF_VAR_ARG4 0x010a
-+#define DIF_VAR_ARG5 0x010b
-+#define DIF_VAR_ARG6 0x010c
-+#define DIF_VAR_ARG7 0x010d
-+#define DIF_VAR_ARG8 0x010e
-+#define DIF_VAR_ARG9 0x010f
-+#define DIF_VAR_STACKDEPTH 0x0110
-+#define DIF_VAR_CALLER 0x0111
-+#define DIF_VAR_PROBEPROV 0x0112
-+#define DIF_VAR_PROBEMOD 0x0113
-+#define DIF_VAR_PROBEFUNC 0x0114
-+#define DIF_VAR_PROBENAME 0x0115
-+#define DIF_VAR_PID 0x0116
-+#define DIF_VAR_TID 0x0117
-+#define DIF_VAR_EXECNAME 0x0118
-+#define DIF_VAR_ZONENAME 0x0119
-+#define DIF_VAR_WALLTIMESTAMP 0x011a
-+#define DIF_VAR_USTACKDEPTH 0x011b
-+#define DIF_VAR_UCALLER 0x011c
-+#define DIF_VAR_PPID 0x011d
-+#define DIF_VAR_UID 0x011e
-+#define DIF_VAR_GID 0x011f
-+#define DIF_VAR_ERRNO 0x0120
-+#define DIF_VAR_CURCPU 0x0121
-+
-+#define DIF_SUBR_RAND 0
-+#define DIF_SUBR_MUTEX_OWNED 1
-+#define DIF_SUBR_MUTEX_OWNER 2
-+#define DIF_SUBR_MUTEX_TYPE_ADAPTIVE 3
-+#define DIF_SUBR_MUTEX_TYPE_SPIN 4
-+#define DIF_SUBR_RW_READ_HELD 5
-+#define DIF_SUBR_RW_WRITE_HELD 6
-+#define DIF_SUBR_RW_ISWRITER 7
-+#define DIF_SUBR_COPYIN 8
-+#define DIF_SUBR_COPYINSTR 9
-+#define DIF_SUBR_SPECULATION 10
-+#define DIF_SUBR_PROGENYOF 11
-+#define DIF_SUBR_STRLEN 12
-+#define DIF_SUBR_COPYOUT 13
-+#define DIF_SUBR_COPYOUTSTR 14
-+#define DIF_SUBR_ALLOCA 15
-+#define DIF_SUBR_BCOPY 16
-+#define DIF_SUBR_COPYINTO 17
-+#define DIF_SUBR_MSGDSIZE 18
-+#define DIF_SUBR_MSGSIZE 19
-+#define DIF_SUBR_GETMAJOR 20
-+#define DIF_SUBR_GETMINOR 21
-+#define DIF_SUBR_DDI_PATHNAME 22
-+#define DIF_SUBR_STRJOIN 23
-+#define DIF_SUBR_LLTOSTR 24
-+#define DIF_SUBR_BASENAME 25
-+#define DIF_SUBR_DIRNAME 26
-+#define DIF_SUBR_CLEANPATH 27
-+#define DIF_SUBR_STRCHR 28
-+#define DIF_SUBR_STRRCHR 29
-+#define DIF_SUBR_STRSTR 30
-+#define DIF_SUBR_STRTOK 31
-+#define DIF_SUBR_SUBSTR 32
-+#define DIF_SUBR_INDEX 33
-+#define DIF_SUBR_RINDEX 34
-+#define DIF_SUBR_HTONS 35
-+#define DIF_SUBR_HTONL 36
-+#define DIF_SUBR_HTONLL 37
-+#define DIF_SUBR_NTOHS 38
-+#define DIF_SUBR_NTOHL 39
-+#define DIF_SUBR_NTOHLL 40
-+#define DIF_SUBR_INET_NTOP 41
-+#define DIF_SUBR_INET_NTOA 42
-+#define DIF_SUBR_INET_NTOA6 43
-+#define DIF_SUBR_D_PATH 44
-+#define DIF_SUBR_LINK_NTOP 45
-+
-+#define DIF_SUBR_MAX 45
-+
-+typedef uint32_t dif_instr_t;
-+
-+#define DIF_INSTR_OP(i) (((i) >> 24) & 0xff)
-+#define DIF_INSTR_R1(i) (((i) >> 16) & 0xff)
-+#define DIF_INSTR_R2(i) (((i) >> 8) & 0xff)
-+#define DIF_INSTR_RD(i) ((i) & 0xff)
-+#define DIF_INSTR_RS(i) ((i) & 0xff)
-+#define DIF_INSTR_LABEL(i) ((i) & 0xffffff)
-+#define DIF_INSTR_VAR(i) (((i) >> 8) & 0xffff)
-+#define DIF_INSTR_INTEGER(i) (((i) >> 8) & 0xffff)
-+#define DIF_INSTR_STRING(i) (((i) >> 8) & 0xffff)
-+#define DIF_INSTR_SUBR(i) (((i) >> 8) & 0xffff)
-+#define DIF_INSTR_TYPE(i) (((i) >> 16) & 0xff)
-+#define DIF_INSTR_XLREF(i) (((i) >> 8) & 0xffff)
-+#define DIF_INSTR_FMT(op, r1, r2, d) \
-+ (((op) << 24) | ((r1) << 16) | ((r2) << 8) | (d))
-+
-+#define DIF_INSTR_NOT(r1, d) (DIF_INSTR_FMT(DIF_OP_NOT, r1, 0, d))
-+#define DIF_INSTR_MOV(r1, d) (DIF_INSTR_FMT(DIF_OP_MOV, r1, 0, d))
-+#define DIF_INSTR_CMP(op, r1, r2) (DIF_INSTR_FMT(op, r1, r2, 0))
-+#define DIF_INSTR_TST(r1) (DIF_INSTR_FMT(DIF_OP_TST, r1, 0, 0))
-+#define DIF_INSTR_BRANCH(op, label) (((op) << 24) | (label))
-+#define DIF_INSTR_LOAD(op, r1, d) (DIF_INSTR_FMT(op, r1, 0, d))
-+#define DIF_INSTR_STORE(op, r1, d) (DIF_INSTR_FMT(op, r1, 0, d))
-+#define DIF_INSTR_SETX(i, d) ((DIF_OP_SETX << 24) | ((i) << 8) | (d))
-+#define DIF_INSTR_SETS(s, d) ((DIF_OP_SETS << 24) | ((s) << 8) | (d))
-+#define DIF_INSTR_RET(d) (DIF_INSTR_FMT(DIF_OP_RET, 0, 0, d))
-+#define DIF_INSTR_NOP (DIF_OP_NOP << 24)
-+#define DIF_INSTR_LDA(op, v, r, d) (DIF_INSTR_FMT(op, v, r, d))
-+#define DIF_INSTR_LDV(op, v, d) (((op) << 24) | ((v) << 8) | (d))
-+#define DIF_INSTR_STV(op, v, rs) (((op) << 24) | ((v) << 8) | (rs))
-+#define DIF_INSTR_CALL(s, d) ((DIF_OP_CALL << 24) | ((s) << 8) | (d))
-+#define DIF_INSTR_PUSHTS(op, t, r2, rs) (DIF_INSTR_FMT(op, t, r2, rs))
-+#define DIF_INSTR_POPTS (DIF_OP_POPTS << 24)
-+#define DIF_INSTR_FLUSHTS (DIF_OP_FLUSHTS << 24)
-+#define DIF_INSTR_ALLOCS(r1, d) (DIF_INSTR_FMT(DIF_OP_ALLOCS, r1, 0, d))
-+#define DIF_INSTR_COPYS(r1, r2, d) (DIF_INSTR_FMT(DIF_OP_COPYS, r1, r2, d))
-+#define DIF_INSTR_XLATE(op, r, d) (((op) << 24) | ((r) << 8) | (d))
-+
-+#define DIF_REG_R0 0
-+
-+/*
-+ * A DTrace Intermediate Format Type (DIF Type) is used to represent the types
-+ * of variables, function and associative array arguments, and the return type
-+ * for each DIF object (shown below). It contains a description of the type,
-+ * its size in bytes, and a module identifier.
-+ */
-+
-+#define DIF_TYPE_CTF 0
-+#define DIF_TYPE_STRING 1
-+
-+#define DIF_TF_BYREF 0x1
-+
-+/*
-+ * A DTrace Intermediate Format variable record is used to describe each of the
-+ * variables referenced by a given DIF object. It contains an integer variable
-+ * identifier along with variable scope and properties, as shown below. The
-+ * size of this structure must be sizeof (int) aligned.
-+ */
-+
-+#define DIFV_KIND_ARRAY 0
-+#define DIFV_KIND_SCALAR 1
-+
-+#define DIFV_SCOPE_GLOBAL 0
-+#define DIFV_SCOPE_THREAD 1
-+#define DIFV_SCOPE_LOCAL 2
-+
-+#define DIFV_F_REF 0x1
-+#define DIFV_F_MOD 0x2
-+
-+struct dtrace_diftype;
-+struct dtrace_difv;
-+
-+#endif /* _LINUX_DTRACE_DIF_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/difo.h b/include/uapi/linux/dtrace/difo.h
-new file mode 100644
-index 000000000000..6e9efd7f0a43
---- /dev/null
-+++ b/include/uapi/linux/dtrace/difo.h
-@@ -0,0 +1,57 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DIFO_H
-+#define _LINUX_DTRACE_DIFO_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/dif.h>
-+#include <linux/dtrace/dof_defines.h>
-+
-+/*
-+ * A DIFO is used to store the compiled DIF for a D expression, its return
-+ * type, and its string and variable tables. The string table is a single
-+ * buffer of character data into which sets instructions and variable
-+ * references can reference strings using a byte offset. The variable table
-+ * is an array of dtrace_difv_t structures that describe the name and type of
-+ * each variable and the id used in the DIF code. This structure is described
-+ * above in the DIF section of this header file. The DIFO is used at both
-+ * user-level (in the library) and in the kernel, but the structure is never
-+ * passed between the two: the DOF structures form the only interface. As a
-+ * result, the definition can change depending on the presence of _KERNEL.
-+ */
-+
-+typedef struct dtrace_difo {
-+ dif_instr_t *dtdo_buf; /* instruction buffer */
-+ uint64_t *dtdo_inttab; /* integer table (optional) */
-+ char *dtdo_strtab; /* string table (optional) */
-+ struct dtrace_difv *dtdo_vartab; /* variable table (optional) */
-+ uint_t dtdo_len; /* length of instruction buffer */
-+ uint_t dtdo_intlen; /* length of integer table */
-+ uint_t dtdo_strlen; /* length of string table */
-+ uint_t dtdo_varlen; /* length of variable table */
-+ struct dtrace_diftype dtdo_rtype; /* return type */
-+ uint_t dtdo_refcnt; /* owner reference count */
-+ uint_t dtdo_destructive; /* invokes destructive subroutines */
-+#ifndef _KERNEL
-+ struct dtrace_diftype orig_dtdo_rtype; /* original return type */
-+ struct dof_relodesc *dtdo_kreltab; /* kernel relocations */
-+ struct dof_relodesc *dtdo_ureltab; /* user relocations */
-+ struct dt_node **dtdo_xlmtab; /* translator references */
-+ uint_t dtdo_krelen; /* length of krelo table */
-+ uint_t dtdo_urelen; /* length of urelo table */
-+ uint_t dtdo_xlmlen; /* length of translator table */
-+#endif
-+} dtrace_difo_t;
-+
-+#endif /* _LINUX_DTRACE_DIFO_H */
-diff --git a/include/uapi/linux/dtrace/difo_defines.h b/include/uapi/linux/dtrace/difo_defines.h
-new file mode 100644
-index 000000000000..fdd25f2b7691
---- /dev/null
-+++ b/include/uapi/linux/dtrace/difo_defines.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DIFO_DEFINES_H
-+#define _LINUX_DTRACE_DIFO_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_difo;
-+
-+#endif /* _LINUX_DTRACE_DIFO_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/dof.h b/include/uapi/linux/dtrace/dof.h
-new file mode 100644
-index 000000000000..54c6ca710443
---- /dev/null
-+++ b/include/uapi/linux/dtrace/dof.h
-@@ -0,0 +1,196 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DOF_H
-+#define _LINUX_DTRACE_DOF_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/dif.h>
-+#include <linux/dtrace/dof_defines.h>
-+
-+/*
-+ * DTrace programs can be persistently encoded in the DOF format so that they
-+ * may be embedded in other programs (for example, in an ELF file) or in the
-+ * dtrace driver configuration file for use in anonymous tracing. The DOF
-+ * format is versioned and extensible so that it can be revised and so that
-+ * internal data structures can be modified or extended compatibly. All DOF
-+ * structures use fixed-size types, so the 32-bit and 64-bit representations
-+ * are identical and consumers can use either data model transparently.
-+ *
-+ * The file layout is structured as follows:
-+ *
-+ * +---------------+-------------------+----- ... ----+---- ... ------+
-+ * | dof_hdr_t | dof_sec_t[ ... ] | loadable | non-loadable |
-+ * | (file header) | (section headers) | section data | section data |
-+ * +---------------+-------------------+----- ... ----+---- ... ------+
-+ * |<------------ dof_hdr.dofh_loadsz --------------->| |
-+ * |<------------ dof_hdr.dofh_filesz ------------------------------->|
-+ *
-+ * The file header stores meta-data including a magic number, data model for
-+ * the instrumentation, data encoding, and properties of the DIF code within.
-+ * The header describes its own size and the size of the section headers. By
-+ * convention, an array of section headers follows the file header, and then
-+ * the data for all loadable sections and unloadable sections. This permits
-+ * consumer code to easily download the headers and all loadable data into the
-+ * DTrace driver in one contiguous chunk, omitting other extraneous sections.
-+ *
-+ * The section headers describe the size, offset, alignment, and section type
-+ * for each section. Sections are described using a set of #defines that tell
-+ * the consumer what kind of data is expected. Sections can contain links to
-+ * other sections by storing a dof_secidx_t, an index into the section header
-+ * array, inside of the section data structures. The section header includes
-+ * an entry size so that sections with data arrays can grow their structures.
-+ *
-+ * The DOF data itself can contain many snippets of DIF (i.e. >1 DIFOs), which
-+ * are represented themselves as a collection of related DOF sections. This
-+ * permits us to change the set of sections associated with a DIFO over time,
-+ * and also permits us to encode DIFOs that contain different sets of sections.
-+ * When a DOF section wants to refer to a DIFO, it stores the dof_secidx_t of a
-+ * section of type DOF_SECT_DIFOHDR. This section's data is then an array of
-+ * dof_secidx_t's which in turn denote the sections associated with this DIFO.
-+ *
-+ * This loose coupling of the file structure (header and sections) to the
-+ * structure of the DTrace program itself (ECB descriptions, action
-+ * descriptions, and DIFOs) permits activities such as relocation processing
-+ * to occur in a single pass without having to understand D program structure.
-+ *
-+ * Finally, strings are always stored in ELF-style string tables along with a
-+ * string table section index and string table offset. Therefore strings in
-+ * DOF are always arbitrary-length and not bound to the current implementation.
-+ */
-+
-+typedef struct dof_hdr {
-+ uint8_t dofh_ident[DOF_ID_SIZE];/* ident bytes (see defines) */
-+ uint32_t dofh_flags; /* file attribute flags (if any) */
-+ uint32_t dofh_hdrsize; /* size of file header in bytes */
-+ uint32_t dofh_secsize; /* size of section header in bytes */
-+ uint32_t dofh_secnum; /* number of section headers */
-+ uint64_t dofh_secoff; /* file offset of section headers */
-+ uint64_t dofh_loadsz; /* file size of loadable portion */
-+ uint64_t dofh_filesz; /* file size of entire DOF file */
-+ uint64_t dofh_pad; /* reserved for future use */
-+} dof_hdr_t;
-+
-+typedef struct dof_sec {
-+ uint32_t dofs_type; /* section type (see defines) */
-+ uint32_t dofs_align; /* section data memory alignment */
-+ uint32_t dofs_flags; /* section flags (if any) */
-+ uint32_t dofs_entsize; /* size of section entry (if table) */
-+ uint64_t dofs_offset; /* offset of section data within file */
-+ uint64_t dofs_size; /* size of section data in bytes */
-+} dof_sec_t;
-+
-+
-+typedef struct dof_ecbdesc {
-+ dof_secidx_t dofe_probes; /* link to DOF_SECT_PROBEDESC */
-+ dof_secidx_t dofe_pred; /* link to DOF_SECT_DIFOHDR */
-+ dof_secidx_t dofe_actions; /* link to DOF_SECT_ACTDESC */
-+ uint32_t dofe_pad; /* reserved for future use */
-+ uint64_t dofe_uarg; /* user-supplied library argument */
-+} dof_ecbdesc_t;
-+
-+typedef struct dof_probedesc {
-+ dof_secidx_t dofp_strtab; /* link to DOF_SECT_STRTAB section */
-+ dof_stridx_t dofp_provider; /* provider string */
-+ dof_stridx_t dofp_mod; /* module string */
-+ dof_stridx_t dofp_func; /* function string */
-+ dof_stridx_t dofp_name; /* name string */
-+ uint32_t dofp_id; /* probe identifier (or zero) */
-+} dof_probedesc_t;
-+
-+typedef struct dof_actdesc {
-+ dof_secidx_t dofa_difo; /* link to DOF_SECT_DIFOHDR */
-+ dof_secidx_t dofa_strtab; /* link to DOF_SECT_STRTAB section */
-+ uint32_t dofa_kind; /* action kind (DTRACEACT_* constant) */
-+ uint32_t dofa_ntuple; /* number of subsequent tuple actions */
-+ uint64_t dofa_arg; /* kind-specific argument */
-+ uint64_t dofa_uarg; /* user-supplied argument */
-+} dof_actdesc_t;
-+
-+typedef struct dof_difohdr {
-+ struct dtrace_diftype dofd_rtype; /* return type for this fragment */
-+ dof_secidx_t dofd_links[1]; /* variable length array of indices */
-+} dof_difohdr_t;
-+
-+typedef struct dof_relohdr {
-+ dof_secidx_t dofr_strtab; /* link to DOF_SECT_STRTAB for names */
-+ dof_secidx_t dofr_relsec; /* link to DOF_SECT_RELTAB for relos */
-+ dof_secidx_t dofr_tgtsec; /* link to section we are relocating */
-+} dof_relohdr_t;
-+
-+typedef struct dof_relodesc {
-+ dof_stridx_t dofr_name; /* string name of relocation symbol */
-+ uint32_t dofr_type; /* relo type (DOF_RELO_* constant) */
-+ uint64_t dofr_offset; /* byte offset for relocation */
-+ uint64_t dofr_data; /* additional type-specific data */
-+} dof_relodesc_t;
-+
-+typedef struct dof_optdesc {
-+ uint32_t dofo_option; /* option identifier */
-+ dof_secidx_t dofo_strtab; /* string table, if string option */
-+ uint64_t dofo_value; /* option value or string index */
-+} dof_optdesc_t;
-+
-+typedef struct dof_provider {
-+ dof_secidx_t dofpv_strtab; /* link to DOF_SECT_STRTAB section */
-+ dof_secidx_t dofpv_probes; /* link to DOF_SECT_PROBES section */
-+ dof_secidx_t dofpv_prargs; /* link to DOF_SECT_PRARGS section */
-+ dof_secidx_t dofpv_proffs; /* link to DOF_SECT_PROFFS section */
-+ dof_stridx_t dofpv_name; /* provider name string */
-+ dof_attr_t dofpv_provattr; /* provider attributes */
-+ dof_attr_t dofpv_modattr; /* module attributes */
-+ dof_attr_t dofpv_funcattr; /* function attributes */
-+ dof_attr_t dofpv_nameattr; /* name attributes */
-+ dof_attr_t dofpv_argsattr; /* args attributes */
-+ dof_secidx_t dofpv_prenoffs; /* link to DOF_SECT_PRENOFFS section */
-+} dof_provider_t;
-+
-+typedef struct dof_probe {
-+ uint64_t dofpr_addr; /* probe base address or offset */
-+ dof_stridx_t dofpr_func; /* probe function string */
-+ dof_stridx_t dofpr_name; /* probe name string */
-+ dof_stridx_t dofpr_nargv; /* native argument type strings */
-+ dof_stridx_t dofpr_xargv; /* translated argument type strings */
-+ uint32_t dofpr_argidx; /* index of first argument mapping */
-+ uint32_t dofpr_offidx; /* index of first offset entry */
-+ uint8_t dofpr_nargc; /* native argument count */
-+ uint8_t dofpr_xargc; /* translated argument count */
-+ uint16_t dofpr_noffs; /* number of offset entries for probe */
-+ uint32_t dofpr_enoffidx; /* index of first is-enabled offset */
-+ uint16_t dofpr_nenoffs; /* number of is-enabled offsets */
-+ uint16_t dofpr_pad1; /* reserved for future use */
-+ uint32_t dofpr_pad2; /* reserved for future use */
-+} dof_probe_t;
-+
-+typedef struct dof_xlator {
-+ dof_secidx_t dofxl_members; /* link to DOF_SECT_XLMEMBERS section */
-+ dof_secidx_t dofxl_strtab; /* link to DOF_SECT_STRTAB section */
-+ dof_stridx_t dofxl_argv; /* input parameter type strings */
-+ uint32_t dofxl_argc; /* input parameter list length */
-+ dof_stridx_t dofxl_type; /* output type string name */
-+ dof_attr_t dofxl_attr; /* output stability attributes */
-+} dof_xlator_t;
-+
-+typedef struct dof_xlmember {
-+ dof_secidx_t dofxm_difo; /* member link to DOF_SECT_DIFOHDR */
-+ dof_stridx_t dofxm_name; /* member name */
-+ struct dtrace_diftype dofxm_type; /* member type */
-+} dof_xlmember_t;
-+
-+typedef struct dof_xlref {
-+ dof_secidx_t dofxr_xlator; /* link to DOF_SECT_XLATORS section */
-+ uint32_t dofxr_member; /* index of referenced dof_xlmember */
-+ uint32_t dofxr_argn; /* index of argument for DIF_OP_XLARG */
-+} dof_xlref_t;
-+
-+#endif /* _LINUX_DTRACE_DOF_H */
-diff --git a/include/uapi/linux/dtrace/dof_defines.h b/include/uapi/linux/dtrace/dof_defines.h
-new file mode 100644
-index 000000000000..5357d5e099cc
---- /dev/null
-+++ b/include/uapi/linux/dtrace/dof_defines.h
-@@ -0,0 +1,192 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DOF_DEFINES_H
-+#define _LINUX_DTRACE_DOF_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * DTrace programs can be persistently encoded in the DOF format so that they
-+ * may be embedded in other programs (for example, in an ELF file) or in the
-+ * dtrace driver configuration file for use in anonymous tracing. The DOF
-+ * format is versioned and extensible so that it can be revised and so that
-+ * internal data structures can be modified or extended compatibly. All DOF
-+ * structures use fixed-size types, so the 32-bit and 64-bit representations
-+ * are identical and consumers can use either data model transparently.
-+ *
-+ * The file layout is structured as follows:
-+ *
-+ * +---------------+-------------------+----- ... ----+---- ... ------+
-+ * | dof_hdr_t | dof_sec_t[ ... ] | loadable | non-loadable |
-+ * | (file header) | (section headers) | section data | section data |
-+ * +---------------+-------------------+----- ... ----+---- ... ------+
-+ * |<------------ dof_hdr.dofh_loadsz --------------->| |
-+ * |<------------ dof_hdr.dofh_filesz ------------------------------->|
-+ *
-+ * The file header stores meta-data including a magic number, data model for
-+ * the instrumentation, data encoding, and properties of the DIF code within.
-+ * The header describes its own size and the size of the section headers. By
-+ * convention, an array of section headers follows the file header, and then
-+ * the data for all loadable sections and unloadable sections. This permits
-+ * consumer code to easily download the headers and all loadable data into the
-+ * DTrace driver in one contiguous chunk, omitting other extraneous sections.
-+ *
-+ * The section headers describe the size, offset, alignment, and section type
-+ * for each section. Sections are described using a set of #defines that tell
-+ * the consumer what kind of data is expected. Sections can contain links to
-+ * other sections by storing a dof_secidx_t, an index into the section header
-+ * array, inside of the section data structures. The section header includes
-+ * an entry size so that sections with data arrays can grow their structures.
-+ *
-+ * The DOF data itself can contain many snippets of DIF (i.e. >1 DIFOs), which
-+ * are represented themselves as a collection of related DOF sections. This
-+ * permits us to change the set of sections associated with a DIFO over time,
-+ * and also permits us to encode DIFOs that contain different sets of sections.
-+ * When a DOF section wants to refer to a DIFO, it stores the dof_secidx_t of a
-+ * section of type DOF_SECT_DIFOHDR. This section's data is then an array of
-+ * dof_secidx_t's which in turn denote the sections associated with this DIFO.
-+ *
-+ * This loose coupling of the file structure (header and sections) to the
-+ * structure of the DTrace program itself (ECB descriptions, action
-+ * descriptions, and DIFOs) permits activities such as relocation processing
-+ * to occur in a single pass without having to understand D program structure.
-+ *
-+ * Finally, strings are always stored in ELF-style string tables along with a
-+ * string table section index and string table offset. Therefore strings in
-+ * DOF are always arbitrary-length and not bound to the current implementation.
-+ */
-+
-+#define DOF_ID_SIZE 16 /* total size of dofh_ident[] in bytes */
-+
-+#define DOF_ID_MAG0 0
-+#define DOF_ID_MAG1 1
-+#define DOF_ID_MAG2 2
-+#define DOF_ID_MAG3 3
-+#define DOF_ID_MODEL 4
-+#define DOF_ID_ENCODING 5
-+#define DOF_ID_VERSION 6
-+#define DOF_ID_DIFVERS 7
-+#define DOF_ID_DIFIREG 8 /* DIF integer registers used by compiler */
-+#define DOF_ID_DIFTREG 9 /* DIF tuple registers used by compiler */
-+#define DOF_ID_PAD 10 /* start of padding bytes (all zeroes) */
-+
-+#define DOF_MAG_MAG0 0x7F /* DOF_ID_MAG[0-3] */
-+#define DOF_MAG_MAG1 'D'
-+#define DOF_MAG_MAG2 'O'
-+#define DOF_MAG_MAG3 'F'
-+
-+#define DOF_MAG_STRING "\177DOF"
-+#define DOF_MAG_STRLEN 4
-+
-+#define DOF_MODEL_NONE 0 /* DOF_ID_MODEL */
-+#define DOF_MODEL_ILP32 1
-+#define DOF_MODEL_LP64 2
-+
-+#ifdef _LP64
-+#define DOF_MODEL_NATIVE DOF_MODEL_LP64
-+#else
-+#define DOF_MODEL_NATIVE DOF_MODEL_ILP32
-+#endif
-+
-+#define DOF_ENCODE_NONE 0 /* DOF_ID_ENCODING */
-+#define DOF_ENCODE_LSB 1
-+#define DOF_ENCODE_MSB 2
-+
-+#ifndef _LITTLE_ENDIAN
-+#define DOF_ENCODE_NATIVE DOF_ENCODE_MSB
-+#else
-+#define DOF_ENCODE_NATIVE DOF_ENCODE_LSB
-+#endif
-+
-+#define DOF_VERSION_1 1
-+#define DOF_VERSION_2 2
-+#define DOF_VERSION DOF_VERSION_2
-+
-+#define DOF_FL_VALID 0 /* mask of all valid dofh_flags bits */
-+
-+typedef uint32_t dof_secidx_t; /* section header table index type */
-+typedef uint32_t dof_stridx_t; /* string table index type */
-+
-+#define DOF_SECIDX_NONE -1U /* null value for section indices */
-+#define DOF_STRIDX_NONE -1U /* null value for string indices */
-+
-+#define DOF_SECT_NONE 0 /* null section */
-+#define DOF_SECT_COMMENTS 1 /* compiler comments */
-+#define DOF_SECT_SOURCE 2 /* D program source code */
-+#define DOF_SECT_ECBDESC 3 /* dof_ecbdesc_t */
-+#define DOF_SECT_PROBEDESC 4 /* dof_probedesc_t */
-+#define DOF_SECT_ACTDESC 5 /* dof_actdesc_t array */
-+#define DOF_SECT_DIFOHDR 6 /* dof_difohdr_t (variable length) */
-+#define DOF_SECT_DIF 7 /* uint32_t array of byte code */
-+#define DOF_SECT_STRTAB 8 /* string table */
-+#define DOF_SECT_VARTAB 9 /* dtrace_difv_t array */
-+#define DOF_SECT_RELTAB 10 /* dof_relodesc_t array */
-+#define DOF_SECT_TYPTAB 11 /* dtrace_diftype_t array */
-+#define DOF_SECT_URELHDR 12 /* dof_relohdr_t (user relocations) */
-+#define DOF_SECT_KRELHDR 13 /* dof_relohdr_t (kernel relocations) */
-+#define DOF_SECT_OPTDESC 14 /* dof_optdesc_t array */
-+#define DOF_SECT_PROVIDER 15 /* dof_provider_t */
-+#define DOF_SECT_PROBES 16 /* dof_probe_t array */
-+#define DOF_SECT_PRARGS 17 /* uint8_t array (probe arg mappings) */
-+#define DOF_SECT_PROFFS 18 /* uint32_t array (probe arg offsets) */
-+#define DOF_SECT_INTTAB 19 /* uint64_t array */
-+#define DOF_SECT_UTSNAME 20 /* struct utsname */
-+#define DOF_SECT_XLTAB 21 /* dof_xlref_t array */
-+#define DOF_SECT_XLMEMBERS 22 /* dof_xlmember_t array */
-+#define DOF_SECT_XLIMPORT 23 /* dof_xlator_t */
-+#define DOF_SECT_XLEXPORT 24 /* dof_xlator_t */
-+#define DOF_SECT_PREXPORT 25 /* dof_secidx_t array (exported objs) */
-+#define DOF_SECT_PRENOFFS 26 /* uint32_t array (enabled offsets) */
-+
-+#define DOF_SECF_LOAD 1 /* section should be loaded */
-+
-+#define DOF_SEC_ISLOADABLE(x) \
-+ (((x) == DOF_SECT_ECBDESC) || ((x) == DOF_SECT_PROBEDESC) || \
-+ ((x) == DOF_SECT_ACTDESC) || ((x) == DOF_SECT_DIFOHDR) || \
-+ ((x) == DOF_SECT_DIF) || ((x) == DOF_SECT_STRTAB) || \
-+ ((x) == DOF_SECT_VARTAB) || ((x) == DOF_SECT_RELTAB) || \
-+ ((x) == DOF_SECT_TYPTAB) || ((x) == DOF_SECT_URELHDR) || \
-+ ((x) == DOF_SECT_KRELHDR) || ((x) == DOF_SECT_OPTDESC) || \
-+ ((x) == DOF_SECT_PROVIDER) || ((x) == DOF_SECT_PROBES) || \
-+ ((x) == DOF_SECT_PRARGS) || ((x) == DOF_SECT_PROFFS) || \
-+ ((x) == DOF_SECT_INTTAB) || ((x) == DOF_SECT_XLTAB) || \
-+ ((x) == DOF_SECT_XLMEMBERS) || ((x) == DOF_SECT_XLIMPORT) || \
-+ ((x) == DOF_SECT_XLIMPORT) || ((x) == DOF_SECT_XLEXPORT) || \
-+ ((x) == DOF_SECT_PREXPORT) || ((x) == DOF_SECT_PRENOFFS))
-+
-+#define DOF_RELO_NONE 0 /* empty relocation entry */
-+#define DOF_RELO_SETX 1 /* relocate setx value */
-+
-+typedef uint32_t dof_attr_t; /* encoded stability attributes */
-+
-+#define DOF_ATTR(n, d, c) (((n) << 24) | ((d) << 16) | ((c) << 8))
-+#define DOF_ATTR_NAME(a) (((a) >> 24) & 0xff)
-+#define DOF_ATTR_DATA(a) (((a) >> 16) & 0xff)
-+#define DOF_ATTR_CLASS(a) (((a) >> 8) & 0xff)
-+
-+struct dof_hdr;
-+struct dof_sec;
-+struct dof_ecbdesc;
-+struct dof_probedesc;
-+struct dof_actdesc;
-+struct dof_difohdr;
-+struct dof_relohdr;
-+struct dof_relodesc;
-+struct dof_optdesc;
-+struct dof_provider;
-+struct dof_xlator;
-+struct dof_xlmember;
-+struct dof_xlref;
-+
-+#endif /* _LINUX_DTRACE_DOF_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/dtrace.h b/include/uapi/linux/dtrace/dtrace.h
-new file mode 100644
-index 000000000000..0ee9d35876ef
---- /dev/null
-+++ b/include/uapi/linux/dtrace/dtrace.h
-@@ -0,0 +1,33 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_H_
-+#define _LINUX_DTRACE_H_
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/dif.h>
-+#include <linux/dtrace/actions.h>
-+#include <linux/dtrace/dof.h>
-+#include <linux/dtrace/difo.h>
-+#include <linux/dtrace/enabling.h>
-+#include <linux/dtrace/metadesc.h>
-+#include <linux/dtrace/options.h>
-+#include <linux/dtrace/buffer.h>
-+#include <linux/dtrace/status.h>
-+#include <linux/dtrace/conf.h>
-+#include <linux/dtrace/faults.h>
-+#include <linux/dtrace/arg.h>
-+#include <linux/dtrace/stability.h>
-+#include <linux/dtrace/helpers.h>
-+
-+#endif /* _LINUX_DTRACE_H_ */
-diff --git a/include/uapi/linux/dtrace/enabling.h b/include/uapi/linux/dtrace/enabling.h
-new file mode 100644
-index 000000000000..8aac2ab9ea8d
---- /dev/null
-+++ b/include/uapi/linux/dtrace/enabling.h
-@@ -0,0 +1,76 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ENABLING_H
-+#define _LINUX_DTRACE_ENABLING_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/difo_defines.h>
-+#include <linux/dtrace/enabling_defines.h>
-+
-+/*
-+ * When DTrace is tracking the description of a DTrace enabling entity (probe,
-+ * predicate, action, ECB, record, etc.), it does so in a description
-+ * structure. These structures all end in "desc", and are used at both
-+ * user-level and in the kernel -- but (with the exception of
-+ * dtrace_probedesc_t) they are never passed between them. Typically,
-+ * user-level will use the description structures when assembling an enabling.
-+ * It will then distill those description structures into a DOF object (see
-+ * above), and send it into the kernel. The kernel will again use the
-+ * description structures to create a description of the enabling as it reads
-+ * the DOF. When the description is complete, the enabling will be actually
-+ * created -- turning it into the structures that represent the enabling
-+ * instead of merely describing it. Not surprisingly, the description
-+ * structures bear a strong resemblance to the DOF structures that act as their
-+ * conduit.
-+ */
-+
-+struct dtrace_predicate;
-+
-+typedef struct dtrace_probedesc {
-+ dtrace_id_t dtpd_id; /* probe identifier */
-+ char dtpd_provider[DTRACE_PROVNAMELEN]; /* probe provider name */
-+ char dtpd_mod[DTRACE_MODNAMELEN]; /* probe module name */
-+ char dtpd_func[DTRACE_FUNCNAMELEN]; /* probe function name */
-+ char dtpd_name[DTRACE_NAMELEN]; /* probe name */
-+} dtrace_probedesc_t;
-+
-+typedef struct dtrace_repldesc {
-+ struct dtrace_probedesc dtrpd_match; /* probe descr. to match */
-+ struct dtrace_probedesc dtrpd_create; /* probe descr. to create */
-+} dtrace_repldesc_t;
-+
-+typedef struct dtrace_preddesc {
-+ struct dtrace_difo *dtpdd_difo; /* pointer to DIF object */
-+ struct dtrace_predicate *dtpdd_predicate; /* pointer to predicate */
-+} dtrace_preddesc_t;
-+
-+typedef struct dtrace_actdesc {
-+ struct dtrace_difo *dtad_difo; /* pointer to DIF object */
-+ struct dtrace_actdesc *dtad_next; /* next action */
-+ dtrace_actkind_t dtad_kind; /* kind of action */
-+ uint32_t dtad_ntuple; /* number in tuple */
-+ uint64_t dtad_arg; /* action argument */
-+ uint64_t dtad_uarg; /* user argument */
-+ int dtad_refcnt; /* reference count */
-+} dtrace_actdesc_t;
-+
-+typedef struct dtrace_ecbdesc {
-+ struct dtrace_actdesc *dted_action; /* action description(s) */
-+ struct dtrace_preddesc dted_pred; /* predicate description */
-+ struct dtrace_probedesc dted_probe; /* probe description */
-+ uint64_t dted_uarg; /* library argument */
-+ int dted_refcnt; /* reference count */
-+} dtrace_ecbdesc_t;
-+
-+#endif /* _LINUX_DTRACE_ENABLING_H */
-diff --git a/include/uapi/linux/dtrace/enabling_defines.h b/include/uapi/linux/dtrace/enabling_defines.h
-new file mode 100644
-index 000000000000..221c3efca015
---- /dev/null
-+++ b/include/uapi/linux/dtrace/enabling_defines.h
-@@ -0,0 +1,25 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ENABLING_DEFINES_H
-+#define _LINUX_DTRACE_ENABLING_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_probedesc;
-+struct dtrace_repldesc;
-+struct dtrace_preddesc;
-+struct dtrace_actdesc;
-+struct dtrace_ecbdesc;
-+
-+#endif /* _LINUX_DTRACE_ENABLING_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/fasttrap.h b/include/uapi/linux/dtrace/fasttrap.h
-new file mode 100644
-index 000000000000..4dbf1a2a35cd
---- /dev/null
-+++ b/include/uapi/linux/dtrace/fasttrap.h
-@@ -0,0 +1,56 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FASTTRAP_H
-+#define _LINUX_DTRACE_FASTTRAP_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/fasttrap_defines.h>
-+
-+typedef enum fasttrap_probe_type {
-+ DTFTP_NONE = 0,
-+ DTFTP_ENTRY,
-+ DTFTP_RETURN,
-+ DTFTP_OFFSETS,
-+ DTFTP_POST_OFFSETS,
-+ DTFTP_IS_ENABLED
-+} fasttrap_probe_type_t;
-+
-+typedef struct fasttrap_probe_spec {
-+ pid_t ftps_pid; /* task PID */
-+ enum fasttrap_probe_type ftps_type; /* probe type */
-+ char ftps_func[DTRACE_FUNCNAMELEN]; /* probe function */
-+ char ftps_mod[DTRACE_MODNAMELEN]; /* probe module */
-+ uint64_t ftps_pc; /* probe address */
-+ uint64_t ftps_size; /* function size (in bytes) */
-+ uint8_t ftps_glen; /* glob pattern length */
-+ char ftps_gstr[1]; /* glob pattern string */
-+} fasttrap_probe_spec_t;
-+
-+typedef uint8_t fasttrap_instr_t;
-+
-+typedef struct fasttrap_instr_query {
-+ uint64_t ftiq_pc;
-+ pid_t ftiq_pid;
-+ fasttrap_instr_t ftiq_instr;
-+} fasttrap_instr_query_t;
-+
-+/*
-+ * Include after the definitions, to get ioctl()s when fasttrap.h is included.
-+ * fasttrap_ioctl.h also #includes this header, to get structures when it is
-+ * included itself, as is done by headers_check.
-+ */
-+
-+#include <linux/dtrace/fasttrap_ioctl.h>
-+
-+#endif /* _LINUX_DTRACE_FASTTRAP_H */
-diff --git a/include/uapi/linux/dtrace/fasttrap_defines.h b/include/uapi/linux/dtrace/fasttrap_defines.h
-new file mode 100644
-index 000000000000..4bb07564e1c4
---- /dev/null
-+++ b/include/uapi/linux/dtrace/fasttrap_defines.h
-@@ -0,0 +1,25 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FASTTRAP_DEFINES_H
-+#define _LINUX_DTRACE_FASTTRAP_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+#ifndef __cplusplus
-+enum fasttrap_probe_type;
-+#endif
-+struct fasttrap_probe_spec;
-+struct fasttrap_instr_query;
-+
-+#endif /* _LINUX_DTRACE_FASTTRAP_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/fasttrap_ioctl.h b/include/uapi/linux/dtrace/fasttrap_ioctl.h
-new file mode 100644
-index 000000000000..b5a8b0731fb6
---- /dev/null
-+++ b/include/uapi/linux/dtrace/fasttrap_ioctl.h
-@@ -0,0 +1,19 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FASTRRAP_IOCTL_H_
-+#define _LINUX_DTRACE_FASTTRAP_IOCTL_H_
-+
-+#include <linux/ioctl.h>
-+#include <linux/dtrace/fasttrap.h>
-+
-+#define FASTTRAPIOC 0xf4
-+#define FASTTRAPIOC_MAKEPROBE _IOW(FASTTRAPIOC, 1, struct fasttrap_probe_spec)
-+#define FASTTRAPIOC_GETINSTR _IOR(FASTTRAPIOC, 2, struct fasttrap_instr_query)
-+
-+#endif /* _LINUX_DTRACE_FASTTRAP_IOCTL_H_ */
-diff --git a/include/uapi/linux/dtrace/faults.h b/include/uapi/linux/dtrace/faults.h
-new file mode 100644
-index 000000000000..afa2ae548fa6
---- /dev/null
-+++ b/include/uapi/linux/dtrace/faults.h
-@@ -0,0 +1,20 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FAULTS_H
-+#define _LINUX_DTRACE_FAULTS_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/faults_defines.h>
-+
-+#endif /* _LINUX_DTRACE_FAULTS_H */
-diff --git a/include/uapi/linux/dtrace/faults_defines.h b/include/uapi/linux/dtrace/faults_defines.h
-new file mode 100644
-index 000000000000..d225f2e847e4
---- /dev/null
-+++ b/include/uapi/linux/dtrace/faults_defines.h
-@@ -0,0 +1,39 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FAULTS_DEFINES_H
-+#define _LINUX_DTRACE_FAULTS_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * The constants below DTRACEFLT_LIBRARY indicate probe processing faults;
-+ * constants at or above DTRACEFLT_LIBRARY indicate faults in probe
-+ * postprocessing at user-level. Probe processing faults induce an ERROR
-+ * probe and are replicated in unistd.d to allow users' ERROR probes to decode
-+ * the error condition using thse symbolic labels.
-+ */
-+#define DTRACEFLT_UNKNOWN 0 /* Unknown fault */
-+#define DTRACEFLT_BADADDR 1 /* Bad address */
-+#define DTRACEFLT_BADALIGN 2 /* Bad alignment */
-+#define DTRACEFLT_ILLOP 3 /* Illegal operation */
-+#define DTRACEFLT_DIVZERO 4 /* Divide-by-zero */
-+#define DTRACEFLT_NOSCRATCH 5 /* Out of scratch space */
-+#define DTRACEFLT_KPRIV 6 /* Illegal kernel access */
-+#define DTRACEFLT_UPRIV 7 /* Illegal user access */
-+#define DTRACEFLT_TUPOFLOW 8 /* Tuple stack overflow */
-+#define DTRACEFLT_BADSTACK 9 /* Bad stack */
-+
-+#define DTRACEFLT_LIBRARY 1000 /* Library-level fault */
-+
-+#endif /* _LINUX_DTRACE_FAULTS_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/helpers.h b/include/uapi/linux/dtrace/helpers.h
-new file mode 100644
-index 000000000000..553f23994881
---- /dev/null
-+++ b/include/uapi/linux/dtrace/helpers.h
-@@ -0,0 +1,101 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_HELPERS_H
-+#define _LINUX_DTRACE_HELPERS_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/helpers_defines.h>
-+
-+/*
-+ * DTrace Helpers
-+ *
-+ * In general, DTrace establishes probes in processes and takes actions on
-+ * processes without knowing their specific user-level structures. Instead of
-+ * existing in the framework, process-specific knowledge is contained by the
-+ * enabling D program -- which can apply process-specific knowledge by making
-+ * appropriate use of DTrace primitives like copyin() and copyinstr() to
-+ * operate on user-level data. However, there may exist some specific probes
-+ * of particular semantic relevance that the application developer may wish to
-+ * explicitly export. For example, an application may wish to export a probe
-+ * at the point that it begins and ends certain well-defined transactions. In
-+ * addition to providing probes, programs may wish to offer assistance for
-+ * certain actions. For example, in highly dynamic environments (e.g., Java),
-+ * it may be difficult to obtain a stack trace in terms of meaningful symbol
-+ * names (the translation from instruction addresses to corresponding symbol
-+ * names may only be possible in situ); these environments may wish to define
-+ * a series of actions to be applied in situ to obtain a meaningful stack
-+ * trace.
-+ *
-+ * These two mechanisms -- user-level statically defined tracing and assisting
-+ * DTrace actions -- are provided via DTrace _helpers_. Helpers are specified
-+ * via DOF, but unlike enabling DOF, helper DOF may contain definitions of
-+ * providers, probes and their arguments. If a helper wishes to provide
-+ * action assistance, probe descriptions and corresponding DIF actions may be
-+ * specified in the helper DOF. For such helper actions, however, the probe
-+ * description describes the specific helper: all DTrace helpers have the
-+ * provider name "dtrace" and the module name "helper", and the name of the
-+ * helper is contained in the function name (for example, the ustack() helper
-+ * is named "ustack"). Any helper-specific name may be contained in the name
-+ * (for example, if a helper were to have a constructor, it might be named
-+ * "dtrace:helper:<helper>:init"). Helper actions are only called when the
-+ * action that they are helping is taken. Helper actions may only return DIF
-+ * expressions, and may only call the following subroutines:
-+ *
-+ * alloca() <= Allocates memory out of the consumer's scratch space
-+ * bcopy() <= Copies memory to scratch space
-+ * copyin() <= Copies memory from user-level into consumer's scratch
-+ * copyinto() <= Copies memory into a specific location in scratch
-+ * copyinstr() <= Copies a string into a specific location in scratch
-+ *
-+ * Helper actions may only access the following built-in variables:
-+ *
-+ * curthread <= Current kthread_t pointer
-+ * tid <= Current thread identifier
-+ * pid <= Current process identifier
-+ * ppid <= Parent process identifier
-+ * uid <= Current user ID
-+ * gid <= Current group ID
-+ * execname <= Current executable name
-+ * zonename <= Current zone name
-+ *
-+ * Helper actions may not manipulate or allocate dynamic variables, but they
-+ * may have clause-local and statically-allocated global variables. The
-+ * helper action variable state is specific to the helper action -- variables
-+ * used by the helper action may not be accessed outside of the helper
-+ * action, and the helper action may not access variables that like outside
-+ * of it. Helper actions may not load from kernel memory at-large; they are
-+ * restricting to loading current user state (via copyin() and variants) and
-+ * scratch space. As with probe enablings, helper actions are executed in
-+ * program order. The result of the helper action is the result of the last
-+ * executing helper expression.
-+ *
-+ * Helpers -- composed of either providers/probes or probes/actions (or both)
-+ * -- are added by opening the "helper" minor node, and issuing an ioctl(2)
-+ * (DTRACEHIOC_ADDDOF) that specifies the dof_helper_t structure. This
-+ * encapsulates the name and base address of the user-level library or
-+ * executable publishing the helpers and probes as well as the DOF that
-+ * contains the definitions of those helpers and probes.
-+ *
-+ * The DTRACEHIOC_ADD and DTRACEHIOC_REMOVE are left in place for legacy
-+ * helpers and should no longer be used. No other ioctls are valid on the
-+ * helper minor node.
-+ */
-+
-+typedef struct dof_helper {
-+ char dofhp_mod[DTRACE_MODNAMELEN]; /* executable or library name */
-+ uint64_t dofhp_addr; /* base address of object */
-+ uint64_t dofhp_dof; /* address of helper DOF */
-+} dof_helper_t;
-+
-+#endif /* _LINUX_DTRACE_HELPERS_H */
-diff --git a/include/uapi/linux/dtrace/helpers_defines.h b/include/uapi/linux/dtrace/helpers_defines.h
-new file mode 100644
-index 000000000000..8bf52f058001
---- /dev/null
-+++ b/include/uapi/linux/dtrace/helpers_defines.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_HELPERS_DEFINES_H
-+#define _LINUX_DTRACE_HELPERS_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dof_helper;
-+
-+#endif /* _LINUX_DTRACE_HELPERS_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/ioctl.h b/include/uapi/linux/dtrace/ioctl.h
-new file mode 100644
-index 000000000000..ef2476af2629
---- /dev/null
-+++ b/include/uapi/linux/dtrace/ioctl.h
-@@ -0,0 +1,47 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_IOCTL_H_
-+#define _LINUX_DTRACE_IOCTL_H_
-+
-+#include <linux/ioctl.h>
-+#include <linux/dtrace/arg.h>
-+#include <linux/dtrace/buffer.h>
-+#include <linux/dtrace/conf.h>
-+#include <linux/dtrace/dof.h>
-+#include <linux/dtrace/enabling.h>
-+#include <linux/dtrace/helpers.h>
-+#include <linux/dtrace/metadesc.h>
-+#include <linux/dtrace/stability.h>
-+#include <linux/dtrace/status.h>
-+#include <linux/dtrace/cpu_defines.h>
-+
-+#define DTRACEIOC 0xd4
-+#define DTRACEIOC_PROVIDER _IOR(DTRACEIOC, 1, struct dtrace_providerdesc)
-+#define DTRACEIOC_PROBES _IOR(DTRACEIOC, 2, struct dtrace_probedesc)
-+#define DTRACEIOC_BUFSNAP _IOR(DTRACEIOC, 4, struct dtrace_bufdesc)
-+#define DTRACEIOC_PROBEMATCH _IOR(DTRACEIOC, 5, struct dtrace_probedesc)
-+#define DTRACEIOC_ENABLE _IOW(DTRACEIOC, 6, void *)
-+#define DTRACEIOC_AGGSNAP _IOR(DTRACEIOC, 7, struct dtrace_bufdesc)
-+#define DTRACEIOC_EPROBE _IOW(DTRACEIOC, 8, struct dtrace_eprobedesc)
-+#define DTRACEIOC_PROBEARG _IOR(DTRACEIOC, 9, struct dtrace_argdesc)
-+#define DTRACEIOC_CONF _IOR(DTRACEIOC, 10, struct dtrace_conf)
-+#define DTRACEIOC_STATUS _IOR(DTRACEIOC, 11, struct dtrace_status)
-+#define DTRACEIOC_GO _IOW(DTRACEIOC, 12, processorid_t)
-+#define DTRACEIOC_STOP _IOW(DTRACEIOC, 13, processorid_t)
-+#define DTRACEIOC_AGGDESC _IOR(DTRACEIOC, 15, struct dtrace_aggdesc)
-+#define DTRACEIOC_FORMAT _IOR(DTRACEIOC, 16, struct dtrace_fmtdesc)
-+#define DTRACEIOC_DOFGET _IOR(DTRACEIOC, 17, struct dof_hdr)
-+#define DTRACEIOC_REPLICATE _IOR(DTRACEIOC, 18, void *)
-+
-+#define DTRACEHIOC 0xd8
-+#define DTRACEHIOC_ADD _IOW(DTRACEHIOC, 1, struct dof_hdr)
-+#define DTRACEHIOC_REMOVE _IOW(DTRACEHIOC, 2, int)
-+#define DTRACEHIOC_ADDDOF _IOW(DTRACEHIOC, 3, struct dof_helper)
-+
-+#endif /* _LINUX_DTRACE_IOCTL_H */
-diff --git a/include/uapi/linux/dtrace/metadesc.h b/include/uapi/linux/dtrace/metadesc.h
-new file mode 100644
-index 000000000000..a6b3d82b2c97
---- /dev/null
-+++ b/include/uapi/linux/dtrace/metadesc.h
-@@ -0,0 +1,81 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_METADESC_H
-+#define _LINUX_DTRACE_METADESC_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/actions_defines.h>
-+#include <linux/dtrace/metadesc_defines.h>
-+
-+/*
-+ * DTrace separates the trace data stream from the metadata stream. The only
-+ * metadata tokens placed in the data stream are enabled probe identifiers
-+ * (EPIDs) or (in the case of aggregations) aggregation identifiers. In order
-+ * to determine the structure of the data, DTrace consumers pass the token to
-+ * the kernel, and receive in return a corresponding description of the enabled
-+ * probe (via the dtrace_eprobedesc structure) or the aggregation (via the
-+ * dtrace_aggdesc structure). Both of these structures are expressed in terms
-+ * of record descriptions (via the dtrace_recdesc structure) that describe the
-+ * exact structure of the data. Some record descriptions may also contain a
-+ * format identifier; this additional bit of metadata can be retrieved from the
-+ * kernel, for which a format description is returned via the dtrace_fmtdesc
-+ * structure. Note that all four of these structures must be bitness-neutral
-+ * to allow for a 32-bit DTrace consumer on a 64-bit kernel.
-+ */
-+typedef struct dtrace_recdesc {
-+ dtrace_actkind_t dtrd_action; /* kind of action */
-+ uint32_t dtrd_size; /* size of record */
-+ uint32_t dtrd_offset; /* offset in ECB's data */
-+ uint16_t dtrd_alignment; /* required alignment */
-+ uint16_t dtrd_format; /* format, if any */
-+ uint64_t dtrd_arg; /* action argument */
-+ uint64_t dtrd_uarg; /* user argument */
-+} dtrace_recdesc_t;
-+
-+typedef struct dtrace_eprobedesc {
-+ dtrace_epid_t dtepd_epid; /* enabled probe ID */
-+ dtrace_id_t dtepd_probeid; /* probe ID */
-+ uint64_t dtepd_uarg; /* library argument */
-+ uint32_t dtepd_size; /* total size */
-+ int dtepd_nrecs; /* number of records */
-+ struct dtrace_recdesc dtepd_rec[1]; /* records themselves */
-+} dtrace_eprobedesc_t;
-+
-+typedef struct dtrace_aggdesc {
-+ DTRACE_PTR(char, dtagd_name); /* not filled in by kernel */
-+ dtrace_aggvarid_t dtagd_varid; /* not filled in by kernel */
-+ int dtagd_flags; /* not filled in by kernel */
-+ dtrace_aggid_t dtagd_id; /* aggregation ID */
-+ dtrace_epid_t dtagd_epid; /* enabled probe ID */
-+ uint32_t dtagd_size; /* size in bytes */
-+ int dtagd_nrecs; /* number of records */
-+ uint32_t dtagd_pad; /* explicit padding */
-+ struct dtrace_recdesc dtagd_rec[1]; /* record descriptions */
-+} dtrace_aggdesc_t;
-+
-+typedef struct dtrace_fmtdesc {
-+ DTRACE_PTR(char, dtfd_string); /* format string */
-+ int dtfd_length; /* length of format string */
-+ uint16_t dtfd_format; /* format identifier */
-+} dtrace_fmtdesc_t;
-+
-+#define DTRACE_SIZEOF_EPROBEDESC(desc) \
-+ (sizeof(struct dtrace_eprobedesc) + ((desc)->dtepd_nrecs ? \
-+ (((desc)->dtepd_nrecs - 1) * sizeof(struct dtrace_recdesc)) : 0))
-+
-+#define DTRACE_SIZEOF_AGGDESC(desc) \
-+ (sizeof(struct dtrace_aggdesc) + ((desc)->dtagd_nrecs ? \
-+ (((desc)->dtagd_nrecs - 1) * sizeof(struct dtrace_recdesc)) : 0))
-+
-+#endif /* _LINUX_DTRACE_METADESC_H */
-diff --git a/include/uapi/linux/dtrace/metadesc_defines.h b/include/uapi/linux/dtrace/metadesc_defines.h
-new file mode 100644
-index 000000000000..b27cc28822c8
---- /dev/null
-+++ b/include/uapi/linux/dtrace/metadesc_defines.h
-@@ -0,0 +1,24 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_METADESC_DEFINES_H
-+#define _LINUX_DTRACE_METADESC_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_recdesc;
-+struct dtrace_eprobedesc;
-+struct dtrace_aggdesc;
-+struct dtrace_fmtdesc;
-+
-+#endif /* _LINUX_DTRACE_METADESC_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/options.h b/include/uapi/linux/dtrace/options.h
-new file mode 100644
-index 000000000000..0a652ca2a148
---- /dev/null
-+++ b/include/uapi/linux/dtrace/options.h
-@@ -0,0 +1,20 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_OPTIONS_H
-+#define _LINUX_DTRACE_OPTIONS_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/options_defines.h>
-+
-+#endif /* _LINUX_DTRACE_OPTIONS_H */
-diff --git a/include/uapi/linux/dtrace/options_defines.h b/include/uapi/linux/dtrace/options_defines.h
-new file mode 100644
-index 000000000000..26009c84437e
---- /dev/null
-+++ b/include/uapi/linux/dtrace/options_defines.h
-@@ -0,0 +1,72 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_OPTIONS_DEFINES_H
-+#define _LINUX_DTRACE_OPTIONS_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * Run-time DTrace options are set and retrieved via DOF_SECT_OPTDESC sections
-+ * in a DOF image. The dof_optdesc structure contains an option identifier and
-+ * an option value. The valid option identifiers are found below; the mapping
-+ * between option identifiers and option identifying strings is maintained at
-+ * user-level. Note that the value of DTRACEOPT_UNSET is such that all of the
-+ * following are potentially valid option values: all positive integers, zero
-+ * and negative one. Some options (notably "bufpolicy" and "bufresize") take
-+ * predefined tokens as their values; these are defined with
-+ * DTRACEOPT_{option}_{token}.
-+ */
-+
-+#define DTRACEOPT_BUFSIZE 0 /* buffer size */
-+#define DTRACEOPT_BUFPOLICY 1 /* buffer policy */
-+#define DTRACEOPT_DYNVARSIZE 2 /* dynamic variable size */
-+#define DTRACEOPT_AGGSIZE 3 /* aggregation size */
-+#define DTRACEOPT_SPECSIZE 4 /* speculation size */
-+#define DTRACEOPT_NSPEC 5 /* number of speculations */
-+#define DTRACEOPT_STRSIZE 6 /* string size */
-+#define DTRACEOPT_CLEANRATE 7 /* dynvar cleaning rate */
-+#define DTRACEOPT_CPU 8 /* CPU to trace */
-+#define DTRACEOPT_BUFRESIZE 9 /* buffer resizing policy */
-+#define DTRACEOPT_GRABANON 10 /* grab anonymous state, if any */
-+#define DTRACEOPT_FLOWINDENT 11 /* indent function entry/return */
-+#define DTRACEOPT_QUIET 12 /* only output explicitly traced data */
-+#define DTRACEOPT_STACKFRAMES 13 /* number of stack frames */
-+#define DTRACEOPT_USTACKFRAMES 14 /* number of user stack frames */
-+#define DTRACEOPT_AGGRATE 15 /* aggregation snapshot rate */
-+#define DTRACEOPT_SWITCHRATE 16 /* buffer switching rate */
-+#define DTRACEOPT_STATUSRATE 17 /* status rate */
-+#define DTRACEOPT_DESTRUCTIVE 18 /* destructive actions allowed */
-+#define DTRACEOPT_STACKINDENT 19 /* output indent for stack traces */
-+#define DTRACEOPT_RAWBYTES 20 /* always print bytes in raw form */
-+#define DTRACEOPT_JSTACKFRAMES 21 /* number of jstack() frames */
-+#define DTRACEOPT_JSTACKSTRSIZE 22 /* size of jstack() string table */
-+#define DTRACEOPT_AGGSORTKEY 23 /* sort aggregations by key */
-+#define DTRACEOPT_AGGSORTREV 24 /* reverse-sort aggregations */
-+#define DTRACEOPT_AGGSORTPOS 25 /* agg. position to sort on */
-+#define DTRACEOPT_AGGSORTKEYPOS 26 /* agg. key position to sort on */
-+#define DTRACEOPT_QUIETRESIZE 27 /* quieten buffer-resize messages */
-+#define DTRACEOPT_NORESOLVE 28 /* prevent resolution of symbols */
-+#define DTRACEOPT_PCAPSIZE 29 /* number of bytes to be captured */
-+#define DTRACEOPT_MAX 30 /* number of options */
-+
-+#define DTRACEOPT_UNSET (dtrace_optval_t)-2 /* unset option */
-+
-+#define DTRACEOPT_BUFPOLICY_RING 0 /* ring buffer */
-+#define DTRACEOPT_BUFPOLICY_FILL 1 /* fill buffer, then stop */
-+#define DTRACEOPT_BUFPOLICY_SWITCH 2 /* switch buffers */
-+
-+#define DTRACEOPT_BUFRESIZE_AUTO 0 /* automatic resizing */
-+#define DTRACEOPT_BUFRESIZE_MANUAL 1 /* manual resizing */
-+
-+#endif /* _LINUX_DTRACE_OPTIONS_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/stability.h b/include/uapi/linux/dtrace/stability.h
-new file mode 100644
-index 000000000000..380effdab291
---- /dev/null
-+++ b/include/uapi/linux/dtrace/stability.h
-@@ -0,0 +1,52 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_STABILITY_H
-+#define _LINUX_DTRACE_STABILITY_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/stability_defines.h>
-+
-+/*
-+ * Each DTrace provider advertises the name and data stability of each of its
-+ * probe description components, as well as its architectural dependencies. The
-+ * D compiler can query the provider attributes (dtrace_pattr_t) in order to
-+ * compute the properties of an input program and report them.
-+ */
-+
-+typedef struct dtrace_ppriv {
-+ uint32_t dtpp_flags; /* privilege flags */
-+ uid_t dtpp_uid; /* user ID */
-+} dtrace_ppriv_t;
-+
-+typedef struct dtrace_attribute {
-+ dtrace_stability_t dtat_name; /* entity name stability */
-+ dtrace_stability_t dtat_data; /* entity data stability */
-+ dtrace_class_t dtat_class; /* entity data dependency */
-+} dtrace_attribute_t;
-+
-+typedef struct dtrace_pattr {
-+ struct dtrace_attribute dtpa_provider; /* provider attributes */
-+ struct dtrace_attribute dtpa_mod; /* module attributes */
-+ struct dtrace_attribute dtpa_func; /* function attributes */
-+ struct dtrace_attribute dtpa_name; /* name attributes */
-+ struct dtrace_attribute dtpa_args; /* args[] attributes */
-+} dtrace_pattr_t;
-+
-+typedef struct dtrace_providerdesc {
-+ char dtvd_name[DTRACE_PROVNAMELEN]; /* provider name */
-+ struct dtrace_pattr dtvd_attr; /* stability attributes */
-+ struct dtrace_ppriv dtvd_priv; /* privileges required */
-+} dtrace_providerdesc_t;
-+
-+#endif /* _LINUX_DTRACE_STABILITY_H */
-diff --git a/include/uapi/linux/dtrace/stability_defines.h b/include/uapi/linux/dtrace/stability_defines.h
-new file mode 100644
-index 000000000000..ca58c5c03c2b
---- /dev/null
-+++ b/include/uapi/linux/dtrace/stability_defines.h
-@@ -0,0 +1,53 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_STABILITY_DEFINES_H
-+#define _LINUX_DTRACE_STABILITY_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+typedef uint8_t dtrace_stability_t; /* stability code */
-+typedef uint8_t dtrace_class_t; /* architectural dependency class */
-+
-+#define DTRACE_STABILITY_INTERNAL 0 /* private to DTrace itself */
-+#define DTRACE_STABILITY_PRIVATE 1 /* private to Sun (see docs) */
-+#define DTRACE_STABILITY_OBSOLETE 2 /* scheduled for removal */
-+#define DTRACE_STABILITY_EXTERNAL 3 /* not controlled by Sun */
-+#define DTRACE_STABILITY_UNSTABLE 4 /* new or rapidly changing */
-+#define DTRACE_STABILITY_EVOLVING 5 /* less rapidly changing */
-+#define DTRACE_STABILITY_STABLE 6 /* mature interface from Sun */
-+#define DTRACE_STABILITY_STANDARD 7 /* industry standard */
-+#define DTRACE_STABILITY_MAX 7 /* maximum valid stability */
-+
-+#define DTRACE_CLASS_UNKNOWN 0 /* unknown architectural dependency */
-+#define DTRACE_CLASS_CPU 1 /* CPU-module-specific */
-+#define DTRACE_CLASS_PLATFORM 2 /* platform-specific (uname -i) */
-+#define DTRACE_CLASS_GROUP 3 /* hardware-group-specific (uname -m) */
-+#define DTRACE_CLASS_ISA 4 /* ISA-specific (uname -p) */
-+#define DTRACE_CLASS_COMMON 5 /* common to all systems */
-+#define DTRACE_CLASS_MAX 5 /* maximum valid class */
-+
-+#define DTRACE_PRIV_NONE 0x0000
-+#define DTRACE_PRIV_KERNEL 0x0001
-+#define DTRACE_PRIV_USER 0x0002
-+#define DTRACE_PRIV_PROC 0x0004
-+#define DTRACE_PRIV_OWNER 0x0008
-+#define DTRACE_PRIV_ALL (DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER | \
-+ DTRACE_PRIV_PROC | DTRACE_PRIV_OWNER)
-+
-+struct dtrace_ppriv;
-+struct dtrace_attribute;
-+struct dtrace_pattr;
-+struct dtrace_providerdesc;
-+
-+#endif /* _LINUX_DTRACE_STABILITY_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/status.h b/include/uapi/linux/dtrace/status.h
-new file mode 100644
-index 000000000000..dc324199f170
---- /dev/null
-+++ b/include/uapi/linux/dtrace/status.h
-@@ -0,0 +1,50 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_STATUS_H
-+#define _LINUX_DTRACE_STATUS_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * The status of DTrace is relayed via the dtrace_status structure. This
-+ * structure contains members to count drops other than the capacity drops
-+ * available via the buffer interface (see above). This consists of dynamic
-+ * drops (including capacity dynamic drops, rinsing drops and dirty drops), and
-+ * speculative drops (including capacity speculative drops, drops due to busy
-+ * speculative buffers and drops due to unavailable speculative buffers).
-+ * Additionally, the status structure contains a field to indicate the number
-+ * of "fill"-policy buffers have been filled and a boolean field to indicate
-+ * that exit() has been called. If the dtst_exiting field is non-zero, no
-+ * further data will be generated until tracing is stopped (at which time any
-+ * enablings of the END action will be processed); if user-level sees that
-+ * this field is non-zero, tracing should be stopped as soon as possible.
-+ */
-+
-+typedef struct dtrace_status {
-+ uint64_t dtst_dyndrops; /* dynamic drops */
-+ uint64_t dtst_dyndrops_rinsing; /* dyn drops due to rinsing */
-+ uint64_t dtst_dyndrops_dirty; /* dyn drops due to dirty */
-+ uint64_t dtst_specdrops; /* speculative drops */
-+ uint64_t dtst_specdrops_busy; /* spec drops due to busy */
-+ uint64_t dtst_specdrops_unavail; /* spec drops due to unavail */
-+ uint64_t dtst_errors; /* total errors */
-+ uint64_t dtst_filled; /* number of filled bufs */
-+ uint64_t dtst_stkstroverflows; /* stack string tab overflows */
-+ uint64_t dtst_dblerrors; /* errors in ERROR probes */
-+ char dtst_killed; /* non-zero if killed */
-+ char dtst_exiting; /* non-zero if exit() called */
-+ char dtst_pad[6]; /* pad out to 64-bit align */
-+} dtrace_status_t;
-+
-+#endif /* _LINUX_DTRACE_STATUS_H */
-diff --git a/include/uapi/linux/dtrace/universal.h b/include/uapi/linux/dtrace/universal.h
-new file mode 100644
-index 000000000000..5c2f3f838fef
---- /dev/null
-+++ b/include/uapi/linux/dtrace/universal.h
-@@ -0,0 +1,47 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_UNIVERSAL_H_
-+#define _LINUX_DTRACE_UNIVERSAL_H_
-+
-+#define DTRACE_CPUALL -1 /* all CPUs */
-+#define DTRACE_IDNONE 0 /* invalid probe identifier */
-+#define DTRACE_EPIDNONE 0 /* invalid enabled probe identifier */
-+#define DTRACE_AGGIDNONE 0 /* invalid aggregation identifier */
-+#define DTRACE_AGGVARIDNONE 0 /* invalid aggregation variable ID */
-+#define DTRACE_CACHEIDNONE 0 /* invalid predicate cache */
-+#define DTRACE_PROVNONE 0 /* invalid provider identifier */
-+#define DTRACE_METAPROVNONE 0 /* invalid meta-provider identifier */
-+#define DTRACE_ARGNONE -1 /* invalid argument index */
-+
-+#define DTRACE_PROVNAMELEN 64
-+#define DTRACE_MODNAMELEN 64
-+#define DTRACE_FUNCNAMELEN 128
-+#define DTRACE_NAMELEN 64
-+#define DTRACE_FULLNAMELEN (DTRACE_PROVNAMELEN + DTRACE_MODNAMELEN + \
-+ DTRACE_FUNCNAMELEN + DTRACE_NAMELEN + 4)
-+#define DTRACE_ARGTYPELEN 128
-+
-+typedef uint16_t dtrace_actkind_t; /* action kind */
-+
-+typedef uint32_t dtrace_aggid_t; /* aggregation identifier */
-+typedef uint32_t dtrace_cacheid_t; /* predicate cache identifier */
-+typedef uint32_t dtrace_epid_t; /* enabled probe identifier */
-+typedef uint32_t dtrace_optid_t; /* option identifier */
-+typedef uint32_t dtrace_specid_t; /* speculation identifier */
-+
-+typedef uint64_t dtrace_aggvarid_t; /* aggregation variable id */
-+typedef uint64_t dtrace_genid_t; /* generation identifier */
-+typedef uint64_t dtrace_optval_t; /* option value */
-+
-+#endif /* _LINUX_DTRACE_UNIVERSAL_H_ */
-diff --git a/init/Kconfig b/init/Kconfig
-index 5a86bbbf43e0..0f1b919272da 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -2052,6 +2052,8 @@ config PROFILING
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-+source "kernel/dtrace/Kconfig"
-+
- #
- # Place an empty function call at each tracepoint site. Can be
- # dynamically changed for a probe function.
-diff --git a/init/main.c b/init/main.c
-index 9d964511fe0c..f510b7af38c2 100644
---- a/init/main.c
-+++ b/init/main.c
-@@ -98,6 +98,8 @@
- #include <linux/mem_encrypt.h>
- #include <linux/kcsan.h>
- #include <linux/init_syscalls.h>
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-
- #include <asm/io.h>
- #include <asm/bugs.h>
-@@ -1057,6 +1059,10 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
- sfi_init_late();
- kcsan_init();
-
-+#ifdef CONFIG_DTRACE
-+ dtrace_os_init();
-+#endif
-+
- /* Do the rest non-__init'ed, we're now alive */
- arch_call_rest_init();
-
-@@ -1512,6 +1518,10 @@ static noinline void __init kernel_init_freeable(void)
-
- init_mm_internals();
-
-+#ifdef CONFIG_DTRACE
-+ dtrace_cpu_init();
-+#endif
-+
- rcu_init_tasks_generic();
- do_pre_smp_initcalls();
- lockup_detector_init();
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 6c9f19911be0..498cb12d89c6 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -121,6 +121,7 @@ obj-$(CONFIG_TORTURE_TEST) += torture.o
- obj-$(CONFIG_HAS_IOMEM) += iomem.o
- obj-$(CONFIG_RSEQ) += rseq.o
- obj-$(CONFIG_WATCH_QUEUE) += watch_queue.o
-+obj-$(CONFIG_DTRACE) += dtrace/
-
- obj-$(CONFIG_SYSCTL_KUNIT_TEST) += sysctl-test.o
-
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-new file mode 100644
-index 000000000000..854e4411343f
---- /dev/null
-+++ b/kernel/dtrace/Kconfig
-@@ -0,0 +1,54 @@
-+#
-+# Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+#
-+
-+menuconfig DTRACE
-+ bool "DTrace (Dynamic Tracing) Support"
-+ default y
-+ depends on ARCH_SUPPORTS_DTRACE
-+ select KALLSYMS
-+ select KALLMODSYMS
-+ select WAITFD
-+ select CTF
-+ help
-+ The DTrace dynamic tracing framework.
-+
-+if DTRACE
-+
-+config DT_CORE
-+ tristate "DTrace core"
-+ default m
-+ help
-+ The core of DTrace: needed for all providers.
-+
-+if DT_CORE
-+
-+config DT_DT_TEST
-+ tristate "DTrace Test Probe"
-+ default m
-+ help
-+ A test provider used by the testsuite.
-+
-+config DT_DEBUG
-+ bool "DTrace debugging"
-+ default m
-+ help
-+ This controls the inclusion of various piece of code that perform
-+ internal checks within the DTrace core. It also enables all the
-+ assertions within the DTrace code.
-+
-+if DT_DEBUG
-+
-+config DT_DEBUG_MUTEX
-+ bool "DTrace mutex debugging"
-+ default n
-+ help
-+ This controls the use of DTrace specific wrappers to output debug
-+ messages whenever a mutex is locked or unlocked within the DTrace
-+ code (core and providers).
-+
-+endif # DT_DEBUG
-+
-+endif # DT_CORE
-+
-+endif #DTRACE
-diff --git a/kernel/dtrace/Makefile b/kernel/dtrace/Makefile
-new file mode 100644
-index 000000000000..872785327c3d
---- /dev/null
-+++ b/kernel/dtrace/Makefile
-@@ -0,0 +1,12 @@
-+#
-+# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+#
-+
-+DT_CORE_ARCH_OBJS = $(addprefix ../../arch/$(SRCARCH)/kernel/, \
-+ dtrace_util.o)
-+
-+ifdef CONFIG_DT_CORE
-+obj-y += cyclic.o dtrace_os.o dtrace_cpu.o \
-+ dtrace_task.o dtrace_psinfo.o \
-+ $(DT_CORE_ARCH_OBJS)
-+endif
-diff --git a/kernel/dtrace/cyclic.c b/kernel/dtrace/cyclic.c
-new file mode 100644
-index 000000000000..6497ceee3782
---- /dev/null
-+++ b/kernel/dtrace/cyclic.c
-@@ -0,0 +1,526 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: cyclic.c
-+ * DESCRIPTION: Minimal cyclic implementation
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/cpu.h>
-+#include <linux/cyclic.h>
-+#include <linux/hrtimer.h>
-+#include <linux/module.h>
-+#include <linux/proc_fs.h>
-+#include <linux/seq_file.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+#include <linux/workqueue.h>
-+
-+static int omni_enabled;
-+
-+#define _CYCLIC_CPU_UNDEF (-1)
-+#define _CYCLIC_CPU_OMNI (-2)
-+#define CYCLIC_IS_OMNI(cyc) ((cyc)->cpu == _CYCLIC_CPU_OMNI)
-+
-+struct cyclic_work {
-+ struct work_struct work;
-+ struct cyclic *cyc;
-+};
-+
-+struct cyclic {
-+ struct list_head list;
-+ int cpu;
-+ union {
-+ struct {
-+ struct cyc_time when;
-+ struct cyc_handler hdlr;
-+ uint32_t pend;
-+ struct hrtimer timr;
-+ struct cyclic_work work;
-+ } cyc;
-+ struct {
-+ struct cyc_omni_handler hdlr;
-+ struct list_head cycl;
-+ } omni;
-+ };
-+};
-+
-+static LIST_HEAD(cyclics);
-+
-+static void cyclic_fire(struct work_struct *work)
-+{
-+ struct cyclic_work *cwork = (struct cyclic_work *)work;
-+ struct cyclic *cyc = cwork->cyc;
-+ uint32_t cpnd, npnd;
-+
-+ do {
-+ /*
-+ * We know that the 'pend' counter for the cyclic is non-zero.
-+ * So, we can start with calling the handler at least once.
-+ */
-+ (*cyc->cyc.hdlr.cyh_func)(cyc->cyc.hdlr.cyh_arg);
-+
-+again:
-+ /*
-+ * The 'pend' counter may be modified by cyclic_expire() while
-+ * we go through this loop. We use an atomic compare-and-set
-+ * instruction to determine whether it got changed. If so, we
-+ * retrieve the updated 'pend' value and try this again.
-+ *
-+ * Note that when the cyclic is being removed, the hrtimer will
-+ * be cancelled first, which ensures that 'pend' will no longer
-+ * be incremented. When that happens, this loop will simply
-+ * run through the remaining pending calls, and terminate.
-+ */
-+ cpnd = cyc->cyc.pend;
-+ npnd = cpnd - 1;
-+ if (cmpxchg(&cyc->cyc.pend, cpnd, npnd) != cpnd)
-+ goto again;
-+ } while (npnd > 0);
-+}
-+
-+/*
-+ * Timer expiration handler for cyclic hrtimers. Cyclic worker functions must
-+ * be able to perform a variety of tasks (including calling functions that
-+ * could sleep), and therefore they cannot be called from interrupt context.
-+ *
-+ * We schedule a workqueue to do the actual work.
-+ *
-+ * But... under heavy load it is possible that the hrtimer will expire again
-+ * before the workqueue had a chance to run. That would lead to missed events
-+ * which isn't quite acceptable. Therefore, we use a counter to record how
-+ * many times the timer has expired vs how many times the handler has been
-+ * called. The counter is incremented by this function upon hrtimer expiration
-+ * and decremented by the cyclic_fire. Note that the workqueue is responsible
-+ * for calling the handler multiple times if the counter indicates that multiple
-+ * invocation are pending.
-+ *
-+ * This function is called as hrtimer handler, and therefore runs in interrupt
-+ * context, which by definition will ensure that manipulation of the 'pend'
-+ * counter in the cyclic can be done without locking, and changes will appear
-+ * atomic to the cyclic_fire().
-+ *
-+ * Moral of the story: the handler may not get called at the absolute times as
-+ * requested, but it will be called the correct number of times.
-+ */
-+static enum hrtimer_restart cyclic_expire(struct hrtimer *timr)
-+{
-+ struct cyclic *cyc = container_of(timr, struct cyclic, cyc.timr);
-+
-+ /*
-+ * High priority cyclics call directly into their handler. This means
-+ * that the handler must satisfy all requirements for executing code in
-+ * interrupt context.
-+ */
-+ if (cyc->cyc.hdlr.cyh_level == CY_HIGH_LEVEL) {
-+ (*cyc->cyc.hdlr.cyh_func)(cyc->cyc.hdlr.cyh_arg);
-+ goto done;
-+ }
-+
-+ /*
-+ * Increment the 'pend' counter, in case the work is already set to
-+ * run. If the counter was 0 upon entry, we need to schedule the
-+ * work. If the increment wraps the counter back to 0, we admit
-+ * defeat, and reset it to its max value.
-+ */
-+ if (cyc->cyc.pend++ == 0)
-+ schedule_work_on(cyc->cpu,
-+ (struct work_struct *)&cyc->cyc.work);
-+ else if (cyc->cyc.pend == 0)
-+ cyc->cyc.pend = UINT_MAX;
-+
-+done:
-+ /*
-+ * Prepare the timer for the next expiration.
-+ */
-+ if (cyc->cyc.when.cyt_interval == CY_INTERVAL_INF)
-+ return HRTIMER_NORESTART;
-+
-+ hrtimer_forward_now(timr, cyc->cyc.when.cyt_interval);
-+
-+ return HRTIMER_RESTART;
-+}
-+
-+struct cyclic *cyclic_new(int omni)
-+{
-+ struct cyclic *cyc;
-+
-+ cyc = kmalloc(sizeof(struct cyclic), GFP_KERNEL);
-+ if (cyc == NULL)
-+ return NULL;
-+
-+ INIT_LIST_HEAD(&cyc->list);
-+
-+ if (!omni) {
-+ cyc->cpu = _CYCLIC_CPU_UNDEF;
-+ cyc->cyc.pend = 0;
-+ hrtimer_init(&cyc->cyc.timr, CLOCK_MONOTONIC,
-+ HRTIMER_MODE_REL_PINNED);
-+ cyc->cyc.timr.function = cyclic_expire;
-+ cyc->cyc.work.cyc = cyc;
-+ INIT_WORK((struct work_struct *)&cyc->cyc.work, cyclic_fire);
-+ } else {
-+ cyc->cpu = _CYCLIC_CPU_OMNI;
-+ INIT_LIST_HEAD(&cyc->omni.cycl);
-+ }
-+
-+ return cyc;
-+}
-+
-+static inline void cyclic_restart(struct cyclic *cyc)
-+{
-+ if (cyc->cyc.when.cyt_interval == CY_INTERVAL_INF)
-+ return;
-+
-+ if (cyc->cyc.when.cyt_when == 0)
-+ hrtimer_start(&cyc->cyc.timr, cyc->cyc.when.cyt_interval,
-+ HRTIMER_MODE_REL_PINNED);
-+ else
-+ hrtimer_start(&cyc->cyc.timr, cyc->cyc.when.cyt_when,
-+ HRTIMER_MODE_ABS_PINNED);
-+}
-+
-+/*
-+ * Add a new cyclic to the system.
-+ */
-+cyclic_id_t cyclic_add(struct cyc_handler *hdlr, struct cyc_time *when)
-+{
-+ struct cyclic *cyc;
-+
-+ if (hdlr == NULL || when == NULL)
-+ return CYCLIC_NONE;
-+
-+ cyc = cyclic_new(0);
-+ if (cyc == NULL)
-+ return CYCLIC_NONE;
-+
-+ list_add(&cyc->list, &cyclics);
-+ cyc->cpu = smp_processor_id();
-+ cyc->cyc.when = *when;
-+ cyc->cyc.hdlr = *hdlr;
-+
-+ cyclic_restart(cyc);
-+
-+ return (cyclic_id_t)cyc;
-+}
-+EXPORT_SYMBOL(cyclic_add);
-+
-+static void cyclic_omni_xcall(struct cyclic *cyc)
-+{
-+ cyclic_restart(cyc);
-+}
-+
-+/*
-+ * Add a new cyclic to the system.
-+ */
-+static void cyclic_add_pinned(int cpu, struct cyclic *omni,
-+ struct cyc_handler *hdlr, struct cyc_time *when)
-+{
-+ struct cyclic *cyc;
-+
-+ cyc = cyclic_new(0);
-+ if (cyc == NULL)
-+ return;
-+
-+ list_add(&cyc->list, &omni->omni.cycl);
-+ cyc->cpu = cpu;
-+ cyc->cyc.when = *when;
-+ cyc->cyc.hdlr = *hdlr;
-+
-+ smp_call_function_single(cpu, (smp_call_func_t)cyclic_omni_xcall,
-+ cyc, 1);
-+}
-+
-+/*
-+ * Start a cyclic on a specific CPU as sub-cyclic to an omni-present cyclic.
-+ */
-+static void cyclic_omni_start(struct cyclic *omni, int cpu)
-+{
-+ struct cyc_time when;
-+ struct cyc_handler hdlr;
-+
-+ omni->omni.hdlr.cyo_online(omni->omni.hdlr.cyo_arg, cpu, &hdlr, &when);
-+ cyclic_add_pinned(cpu, omni, &hdlr, &when);
-+}
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+static int cyclic_cpu_offline(unsigned int cpu)
-+{
-+ struct cyclic *cyc;
-+
-+ list_for_each_entry(cyc, &cyclics, list) {
-+ struct cyclic *c, *n;
-+
-+ if (!CYCLIC_IS_OMNI(cyc))
-+ continue;
-+
-+ list_for_each_entry_safe(c, n, &cyc->omni.cycl, list) {
-+ if (c->cpu == cpu)
-+ cyclic_remove((cyclic_id_t)c);
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int cyclic_cpu_online(unsigned int cpu)
-+{
-+ struct cyclic *cyc;
-+
-+ list_for_each_entry(cyc, &cyclics, list) {
-+ struct cyclic *c, *n;
-+
-+ if (!CYCLIC_IS_OMNI(cyc))
-+ continue;
-+
-+ list_for_each_entry_safe(c, n, &cyc->omni.cycl, list) {
-+ if (c->cpu == cpu)
-+ break;
-+ }
-+
-+ if (c->cpu == cpu)
-+ continue;
-+
-+ cyclic_omni_start(cyc, cpu);
-+ }
-+ return 0;
-+}
-+#endif
-+
-+/*
-+ * Add a new omnipresent cyclic to the system.
-+ */
-+cyclic_id_t cyclic_add_omni(struct cyc_omni_handler *omni)
-+{
-+ int cpu;
-+ struct cyclic *cyc;
-+
-+ cyc = cyclic_new(1);
-+ if (cyc == NULL)
-+ return CYCLIC_NONE;
-+
-+ list_add(&cyc->list, &cyclics);
-+ cyc->omni.hdlr = *omni;
-+
-+ for_each_online_cpu(cpu)
-+ cyclic_omni_start(cyc, cpu);
-+
-+ return (cyclic_id_t)cyc;
-+}
-+EXPORT_SYMBOL(cyclic_add_omni);
-+
-+/*
-+ * Remove a specific cyclic from the system.
-+ */
-+void cyclic_remove(cyclic_id_t id)
-+{
-+ struct cyclic *cyc = (struct cyclic *)id;
-+
-+ if (CYCLIC_IS_OMNI(cyc)) {
-+ struct cyclic *child, *n;
-+
-+ /*
-+ * If this is an omni-present cyclic, we first need to remove
-+ * all the associated per-CPU cyclics. Note that the recursive
-+ * call into cyclic_remove() for a child cyclic will remove it
-+ * from the list of per-CPU cyclics associated with the
-+ * omni-present cyclic, so we do not need to handle that here.
-+ */
-+ list_for_each_entry_safe(child, n, &cyc->omni.cycl, list)
-+ cyclic_remove((cyclic_id_t)child);
-+ } else {
-+ /*
-+ * We know that hrtimer_cancel() will wait for the timer
-+ * callback to finish if it is being executed at the time of
-+ * making this call. It is therefore guaranteed that 'pend'
-+ * will no longer get incremented.
-+ *
-+ * The call to cancel_work_sync() will wait for the workqueue
-+ * handler to finish also, and since the handler always brings
-+ * 'pend' down to zero prior to returning, it is guaranteed that
-+ * (1) all pending handler calls will be made before
-+ * cyclic_remove() returns
-+ * (2) the amount of work to do before returning is finite.
-+ */
-+ hrtimer_cancel(&cyc->cyc.timr);
-+ cancel_work_sync((struct work_struct *)&cyc->cyc.work);
-+ }
-+
-+ list_del(&cyc->list);
-+ kfree(cyc);
-+}
-+EXPORT_SYMBOL(cyclic_remove);
-+
-+struct cyclic_reprog {
-+ cyclic_id_t cycid;
-+ ktime_t delta;
-+};
-+
-+static void cyclic_reprogram_xcall(struct cyclic_reprog *creprog)
-+{
-+ cyclic_reprogram(creprog->cycid, creprog->delta);
-+}
-+
-+/*
-+ * Reprogram cyclic to fire with given delta from now.
-+ *
-+ * The underlying design makes it safe to call cyclic_reprogram from whithin a
-+ * cyclic handler without race with cyclic_remove. If called from outside of the
-+ * cyclic handler it is up to the owner to ensure to not call cyclic_reprogram
-+ * after call to cyclic_remove.
-+ *
-+ * This function cannot be called from interrupt/bottom half contexts.
-+ */
-+void cyclic_reprogram(cyclic_id_t id, ktime_t delta)
-+{
-+ struct cyclic *cyc = (struct cyclic *)id;
-+
-+ /*
-+ * For omni present cyclic we reprogram child for current CPU.
-+ */
-+ if (CYCLIC_IS_OMNI(cyc)) {
-+ struct cyclic *c, *n;
-+
-+ list_for_each_entry_safe(c, n, &cyc->omni.cycl, list) {
-+ if (c->cpu != smp_processor_id())
-+ continue;
-+
-+ hrtimer_start(&c->cyc.timr, delta,
-+ HRTIMER_MODE_ABS_PINNED);
-+
-+ break;
-+ }
-+
-+ return;
-+ }
-+
-+ /*
-+ * Regular cyclic reprogram must ensure that the timer remains bound
-+ * to the CPU it was registered on. In case we are called from
-+ * different CPU we use xcall to trigger reprogram from correct cpu.
-+ */
-+ if (cyc->cpu != smp_processor_id()) {
-+ struct cyclic_reprog creprog = {
-+ .cycid = id,
-+ .delta = delta,
-+ };
-+
-+ smp_call_function_single(cyc->cpu, (smp_call_func_t)
-+ cyclic_reprogram_xcall, &creprog, 1);
-+ } else {
-+ hrtimer_start(&cyc->cyc.timr, delta, HRTIMER_MODE_REL_PINNED);
-+ }
-+}
-+EXPORT_SYMBOL(cyclic_reprogram);
-+
-+static void *s_start(struct seq_file *seq, loff_t *pos)
-+{
-+ loff_t n = *pos;
-+ struct cyclic *cyc;
-+
-+ list_for_each_entry(cyc, &cyclics, list) {
-+ if (n == 0)
-+ return cyc;
-+
-+ n--;
-+ }
-+
-+ return NULL;
-+}
-+
-+static void *s_next(struct seq_file *seq, void *p, loff_t *pos)
-+{
-+ struct cyclic *cyc = p;
-+
-+ ++*pos;
-+
-+ cyc = list_entry(cyc->list.next, struct cyclic, list);
-+ if (&cyc->list == &cyclics)
-+ return NULL;
-+
-+ return cyc;
-+}
-+
-+static void s_stop(struct seq_file *seq, void *p)
-+{
-+}
-+
-+static int s_show(struct seq_file *seq, void *p)
-+{
-+ struct cyclic *cyc = p;
-+
-+ if (CYCLIC_IS_OMNI(cyc)) {
-+ struct cyclic *c;
-+
-+ seq_puts(seq, "Omni-present cyclic:\n");
-+ list_for_each_entry(c, &cyc->omni.cycl, list)
-+ seq_printf(seq,
-+ " CPU-%d: %c %lld ns hdlr %pB arg %llx\n",
-+ c->cpu,
-+ c->cyc.hdlr.cyh_level == CY_HIGH_LEVEL
-+ ? 'H' : 'l',
-+ c->cyc.when.cyt_interval,
-+ c->cyc.hdlr.cyh_func,
-+ (uint64_t)c->cyc.hdlr.cyh_arg);
-+ } else
-+ seq_printf(seq, "CPU-%d: %c %lld ns hdlr %pB arg %llx\n",
-+ cyc->cpu,
-+ cyc->cyc.hdlr.cyh_level == CY_HIGH_LEVEL
-+ ? 'H' : 'l',
-+ cyc->cyc.when.cyt_interval,
-+ cyc->cyc.hdlr.cyh_func,
-+ (uint64_t)cyc->cyc.hdlr.cyh_arg);
-+
-+ return 0;
-+}
-+
-+static const struct seq_operations cyclicinfo_ops = {
-+ .start = s_start,
-+ .next = s_next,
-+ .stop = s_stop,
-+ .show = s_show,
-+};
-+
-+static int cyclicinfo_open(struct inode *inode, struct file *file)
-+{
-+ return seq_open(file, &cyclicinfo_ops);
-+}
-+
-+static const struct proc_ops proc_cyclicinfo_ops = {
-+ .proc_open = cyclicinfo_open,
-+ .proc_read = seq_read,
-+ .proc_lseek = seq_lseek,
-+ .proc_release = seq_release,
-+};
-+
-+static int __init cyclic_init(void)
-+{
-+ int ret;
-+
-+ proc_create("cyclicinfo", 0400, NULL, &proc_cyclicinfo_ops);
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+ if (!omni_enabled) {
-+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_CYCLIC_STARTING,
-+ "Cyclic omni-timer starting",
-+ cyclic_cpu_online,
-+ cyclic_cpu_offline);
-+ if (ret)
-+ pr_warn_once("Cannot enable cyclic omni timer\n");
-+ else
-+ omni_enabled = 1;
-+ }
-+#endif
-+
-+ return 0;
-+}
-+module_init(cyclic_init);
-diff --git a/kernel/dtrace/dtrace_cpu.c b/kernel/dtrace/dtrace_cpu.c
-new file mode 100644
-index 000000000000..1bc6e3bb4ce0
---- /dev/null
-+++ b/kernel/dtrace/dtrace_cpu.c
-@@ -0,0 +1,61 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_cpu.c
-+ * DESCRIPTION: DTrce - per-CPU state
-+ *
-+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/module.h>
-+#include <asm/dtrace_cpuinfo.h>
-+
-+DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_core, dtrace_cpu_core);
-+EXPORT_PER_CPU_SYMBOL(dtrace_cpu_core);
-+
-+DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo, dtrace_cpu_info);
-+EXPORT_PER_CPU_SYMBOL(dtrace_cpu_info);
-+
-+void dtrace_cpu_init(void)
-+{
-+ int cpu;
-+
-+ /*
-+ * Force this type into the CTF for the sake of userspace's
-+ * ABI requirements.
-+ */
-+ cpuinfo_t *dummy __attribute__((__unused__)) = NULL;
-+
-+ for_each_present_cpu(cpu) {
-+ cpuinfo_arch_t *ci = &cpu_data(cpu);
-+ struct cpuinfo *cpui = per_cpu_info(cpu);
-+ struct cpu_core *cpuc = per_cpu_core(cpu);
-+
-+ cpui->cpu_id = cpu;
-+ cpui->cpu_pset = 0;
-+ cpui->cpu_chip = dtrace_cpuinfo_chip(ci);
-+ cpui->cpu_lgrp = 0;
-+ cpui->cpu_info = ci;
-+
-+ cpuc->cpuc_dtrace_flags = 0;
-+ cpuc->cpuc_dcpc_intr_state = 0;
-+ cpuc->cpuc_dtrace_illval = 0;
-+ mutex_init(&cpuc->cpuc_pid_lock);
-+
-+ cpuc->cpu_dtrace_regs = NULL;
-+ cpuc->cpu_dtrace_caller = 0;
-+ rwlock_init(&cpuc->cpu_ft_lock);
-+
-+ cpuc->cpuc_current_probe = DTRACE_IDNONE;
-+ }
-+}
-diff --git a/kernel/dtrace/dtrace_os.c b/kernel/dtrace/dtrace_os.c
-new file mode 100644
-index 000000000000..d023f3913323
---- /dev/null
-+++ b/kernel/dtrace/dtrace_os.c
-@@ -0,0 +1,332 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_os.c
-+ * DESCRIPTION: DTrace - OS support functions
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/binfmts.h>
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/fs.h>
-+#include <linux/hardirq.h>
-+#include <linux/interrupt.h>
-+#include <linux/kdebug.h>
-+#include <linux/module.h>
-+#include <linux/moduleloader.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/stacktrace.h>
-+#include <linux/timekeeping.h>
-+#include <linux/vmalloc.h>
-+#include <linux/kallsyms.h>
-+#include <linux/uaccess.h>
-+#include <linux/workqueue.h>
-+#include <asm/ptrace.h>
-+#include <linux/init_task.h>
-+#include <linux/sched/mm.h>
-+#include <linux/shmem_fs.h>
-+#include <linux/dtrace_task_impl.h>
-+
-+/*
-+ * OS SPECIFIC DTRACE SETUP
-+ */
-+
-+/*
-+ * DTrace pseudo module that represents vmlinux (the kernel itself).
-+ * Since we populate its sdt data members only once, it can be marked
-+ * as RO after init.
-+ */
-+struct module *dtrace_kmod __ro_after_init = NULL;
-+EXPORT_SYMBOL(dtrace_kmod);
-+
-+int dtrace_ustackdepth_max = 2048;
-+
-+struct kmem_cache *dtrace_pdata_cachep = NULL;
-+
-+void __init dtrace_os_init(void)
-+{
-+ /*
-+ * Setup for module handling.
-+ */
-+ dtrace_pdata_cachep = kmem_cache_create("dtrace_pdata_cache",
-+ sizeof(struct dtrace_module), 0,
-+ SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
-+ if (dtrace_pdata_cachep == NULL)
-+ pr_debug("Can't allocate kmem cache for pdata\n");
-+
-+ /*
-+ * We need to set up a psinfo structure for PID 0 (swapper).
-+ */
-+ dtrace_task_os_init();
-+ dtrace_psinfo_os_init();
-+ dtrace_task_init(&init_task);
-+ dtrace_psinfo_alloc(&init_task);
-+}
-+
-+/*
-+ * MODULE SUPPORT FUNCTIONS
-+ */
-+extern struct list_head *dtrace_modules;
-+
-+/*
-+ * Iterate over all loaded kernel modules. This is required until the linux
-+ * kernel receives its own module iterator.
-+ */
-+void dtrace_for_each_module(for_each_module_fn func, void *arg)
-+{
-+ struct module *mp;
-+
-+ if (func == NULL)
-+ return;
-+
-+ /* The dtrace fake module is not in the list. */
-+ func(arg, dtrace_kmod);
-+
-+ list_for_each_entry(mp, dtrace_modules, list) {
-+
-+#ifdef MODULES_VADDR
-+ if ((uintptr_t)mp < MODULES_VADDR ||
-+ (uintptr_t)mp >= MODULES_END)
-+ continue;
-+#else
-+ if ((uintptr_t)mp < VMALLOC_START ||
-+ (uintptr_t)mp >= VMALLOC_END)
-+ continue;
-+#endif
-+
-+ func(arg, mp);
-+ }
-+}
-+EXPORT_SYMBOL_GPL(dtrace_for_each_module);
-+
-+
-+void dtrace_mod_pdata_alloc(struct module *mp)
-+{
-+ struct dtrace_module *pdata;
-+
-+ pdata = kmem_cache_alloc(dtrace_pdata_cachep, GFP_KERNEL | __GFP_ZERO);
-+ if (pdata == NULL) {
-+ mp->pdata = NULL;
-+ return;
-+ }
-+
-+ dtrace_mod_pdata_init(pdata);
-+ mp->pdata = pdata;
-+}
-+
-+void dtrace_mod_pdata_free(struct module *mp)
-+{
-+ struct dtrace_module *pdata = mp->pdata;
-+
-+ if (mp->pdata == NULL)
-+ return;
-+
-+ mp->pdata = NULL;
-+ dtrace_mod_pdata_cleanup(pdata);
-+ kmem_cache_free(dtrace_pdata_cachep, pdata);
-+}
-+
-+/*
-+ * This function is called with module_mutex held.
-+ */
-+int dtrace_destroy_prov(struct module *mp)
-+{
-+ struct dtrace_module *pdata = mp->pdata;
-+
-+ if (pdata != NULL && pdata->prov_exit != NULL)
-+ return pdata->prov_exit();
-+
-+ return 1;
-+}
-+
-+/*---------------------------------------------------------------------------*\
-+(* TIME SUPPORT FUNCTIONS *)
-+\*---------------------------------------------------------------------------*/
-+enum dtrace_vtime_state dtrace_vtime_active = 0;
-+
-+/*
-+ * Until Linux kernel gains lock-free realtime clock access we are maintaining
-+ * our own version for lock-free access from within a probe context.
-+ */
-+static struct dtrace_time_fast {
-+ seqcount_latch_t dtwf_seq;
-+ ktime_t dtwf_offsreal[2];
-+} dtrace_time ____cacheline_aligned;
-+
-+/*
-+ * Callback from timekeeper code that allows dtrace to update its own time data.
-+ */
-+void dtrace_update_time(struct timekeeper *tk)
-+{
-+ raw_write_seqcount_latch(&dtrace_time.dtwf_seq);
-+ dtrace_time.dtwf_offsreal[0] = tk->offs_real;
-+ raw_write_seqcount_latch(&dtrace_time.dtwf_seq);
-+ dtrace_time.dtwf_offsreal[1] = tk->offs_real;
-+}
-+
-+/* Lock free walltime */
-+ktime_t dtrace_get_walltime(void)
-+{
-+ u64 nsec = ktime_get_mono_fast_ns();
-+ unsigned int seq;
-+ ktime_t offset;
-+
-+ do {
-+ seq = raw_read_seqcount_latch(&dtrace_time.dtwf_seq);
-+ offset = dtrace_time.dtwf_offsreal[seq & 0x1];
-+ } while (read_seqcount_latch_retry(&dtrace_time.dtwf_seq, seq));
-+
-+ return ktime_add_ns(offset, nsec);
-+}
-+EXPORT_SYMBOL(dtrace_get_walltime);
-+
-+ktime_t dtrace_gethrtime(void)
-+{
-+ return ns_to_ktime(ktime_get_raw_fast_ns());
-+}
-+EXPORT_SYMBOL(dtrace_gethrtime);
-+
-+/* Needed for lockstat probes where we cannot include ktime.h */
-+u64 dtrace_gethrtime_ns(void)
-+{
-+ return ktime_get_raw_fast_ns();
-+}
-+EXPORT_SYMBOL(dtrace_gethrtime_ns);
-+
-+void dtrace_vtime_enable(void)
-+{
-+ enum dtrace_vtime_state old, new;
-+
-+ do {
-+ old = dtrace_vtime_active;
-+ if (old == DTRACE_VTIME_ACTIVE) {
-+ pr_warn_once("DTrace virtual time already enabled");
-+ return;
-+ }
-+
-+ new = DTRACE_VTIME_ACTIVE;
-+ } while (cmpxchg(&dtrace_vtime_active, old, new) != old);
-+}
-+EXPORT_SYMBOL(dtrace_vtime_enable);
-+
-+void dtrace_vtime_disable(void)
-+{
-+ int old, new;
-+
-+ do {
-+ old = dtrace_vtime_active;
-+ if (old == DTRACE_VTIME_INACTIVE) {
-+ pr_warn_once("DTrace virtual time already disabled");
-+ return;
-+ }
-+
-+ new = DTRACE_VTIME_INACTIVE;
-+ } while (cmpxchg(&dtrace_vtime_active, old, new) != old);
-+}
-+EXPORT_SYMBOL(dtrace_vtime_disable);
-+
-+void dtrace_vtime_switch(struct task_struct *prev, struct task_struct *next)
-+{
-+ struct dtrace_task *dprev = prev->dt_task;
-+ struct dtrace_task *dnext = next->dt_task;
-+ ktime_t now = dtrace_gethrtime();
-+
-+ if (dprev != NULL && ktime_nz(dprev->dt_start)) {
-+ dprev->dt_vtime = ktime_add(dprev->dt_vtime,
-+ ktime_sub(now,
-+ dprev->dt_start));
-+ dprev->dt_start = ktime_set(0, 0);
-+ }
-+
-+ if (dnext != NULL)
-+ dnext->dt_start = now;
-+}
-+
-+void dtrace_stacktrace(struct stacktrace_state *st)
-+{
-+ int i;
-+
-+ if ((st->flags & STACKTRACE_TYPE) == STACKTRACE_USER) {
-+ dtrace_user_stacktrace(st);
-+ return;
-+ }
-+
-+ if (st->pcs == NULL) {
-+ st->depth = 0;
-+ return;
-+ }
-+
-+ st->depth = stack_trace_save((long unsigned int *) st->pcs,
-+ st->limit ? st->limit : 512, st->depth);
-+
-+ /*
-+ * For entirely unknown reasons, the save_stack_trace() implementation
-+ * on x86_64 adds a ULONG_MAX entry after the last stack trace entry.
-+ * This might be a sentinel value, but given that struct stack_trace
-+ * already contains a nr_entries counter, this seems rather pointless.
-+ * Alas, we need to add a special case for that... And to make matters
-+ * worse, it actually does this only when there is room for it (i.e.
-+ * when nr_entries < max_entries).
-+ * Since ULONG_MAX is never a valid PC, we can just check for that.
-+ */
-+#if defined(CONFIG_X86_64) || defined(CONFIG_ARM64)
-+ if (st->depth && st->pcs[st->depth - 1] == ULONG_MAX)
-+ st->depth--;
-+#endif
-+
-+ if (st->fps != NULL) {
-+ for (i = 0; i < st->limit; i++)
-+ st->fps[i] = 0;
-+ }
-+}
-+EXPORT_SYMBOL(dtrace_stacktrace);
-+
-+/*
-+ * INVALID OPCODE AND PAGE FAULT HANDLING
-+ */
-+static struct notifier_block dtrace_die = {
-+ .notifier_call = dtrace_die_notifier,
-+ .priority = 0x7fffffff
-+};
-+
-+static int dtrace_enabled;
-+
-+/*
-+ * DTrace enable/disable must be called with dtrace_lock being held. It is not
-+ * possible to check for safety here with an ASSERT as the lock itself is in the
-+ * DTrace Framework kernel module.
-+ */
-+int dtrace_enable(void)
-+{
-+ if (dtrace_enabled)
-+ return 0;
-+
-+ if (register_die_notifier(&dtrace_die) != 0)
-+ return 1;
-+
-+ dtrace_enabled = 1;
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_enable);
-+
-+void dtrace_disable(void)
-+{
-+ if (!dtrace_enabled)
-+ return;
-+
-+ unregister_die_notifier(&dtrace_die);
-+ dtrace_enabled = 0;
-+}
-+EXPORT_SYMBOL(dtrace_disable);
-diff --git a/kernel/dtrace/dtrace_psinfo.c b/kernel/dtrace/dtrace_psinfo.c
-new file mode 100644
-index 000000000000..bb5f6fc2ce63
---- /dev/null
-+++ b/kernel/dtrace/dtrace_psinfo.c
-@@ -0,0 +1,212 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_psinfo.c
-+ * DESCRIPTION: DTrace - DTrace psinfo implementation
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/binfmts.h>
-+#include <linux/dtrace_psinfo.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/mm.h>
-+#include <linux/sched.h>
-+#include <linux/sched/mm.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+
-+struct kmem_cache *dtrace_psinfo_cachep;
-+
-+/*
-+ * Free the psinfo_t structure.
-+ */
-+void dtrace_psinfo_free(struct dtrace_psinfo *psinfo)
-+{
-+ kfree(psinfo->dtps_argv);
-+ kfree(psinfo->dtps_envp);
-+ kmem_cache_free(dtrace_psinfo_cachep, psinfo);
-+}
-+
-+/*
-+ * Allocate a new dtrace_psinfo_t structure.
-+ */
-+void dtrace_psinfo_alloc(struct task_struct *tsk)
-+{
-+ struct dtrace_psinfo *psinfo;
-+ struct mm_struct *mm = NULL;
-+
-+ if (unlikely(tsk->dt_task == NULL))
-+ return;
-+
-+ if (likely(tsk->dt_task->dt_psinfo != NULL)) {
-+ struct dtrace_psinfo *tmp = tsk->dt_task->dt_psinfo;
-+ tsk->dt_task->dt_psinfo = NULL;
-+
-+ dtrace_psinfo_put(tmp);
-+ }
-+
-+ psinfo = kmem_cache_alloc(dtrace_psinfo_cachep, GFP_KERNEL);
-+ if (psinfo == NULL)
-+ goto fail;
-+
-+ mm = get_task_mm(tsk);
-+ if (mm) {
-+ size_t len = mm->arg_end - mm->arg_start;
-+ int i = 0;
-+ char *p;
-+
-+ /*
-+ * Construct the psargs string.
-+ */
-+ if (len > 0) {
-+ if (len >= PR_PSARGS_SZ)
-+ len = PR_PSARGS_SZ - 1;
-+
-+ i = access_process_vm(tsk, mm->arg_start,
-+ psinfo->dtps_psargs, len, 0);
-+
-+ if (i > 0) {
-+ if (i < len)
-+ len = i;
-+
-+ for (i = 0, --len; i < len; i++) {
-+ if (psinfo->dtps_psargs[i] == '\0')
-+ psinfo->dtps_psargs[i] = ' ';
-+ }
-+ }
-+ }
-+
-+ if (i < 0)
-+ i = 0;
-+
-+ while (i < PR_PSARGS_SZ)
-+ psinfo->dtps_psargs[i++] = 0;
-+
-+ /*
-+ * Determine the number of arguments.
-+ */
-+ psinfo->dtps_argc = 0;
-+ for (p = (char *)mm->arg_start; p < (char *)mm->arg_end;
-+ psinfo->dtps_argc++) {
-+ size_t l = strnlen_user(p, MAX_ARG_STRLEN);
-+
-+ if (!l)
-+ break;
-+
-+ p += l + 1;
-+ }
-+
-+ /*
-+ * Limit the number of stored argument pointers.
-+ */
-+ len = psinfo->dtps_argc;
-+ if (len >= PR_ARGV_SZ)
-+ len = PR_ARGV_SZ - 1;
-+
-+ psinfo->dtps_argv = kmalloc((len + 1) * sizeof(char *),
-+ GFP_KERNEL);
-+ if (psinfo->dtps_argv == NULL)
-+ goto fail;
-+
-+ /*
-+ * Now populate the array of argument strings.
-+ */
-+ for (i = 0, p = (char *)mm->arg_start; i < len; i++) {
-+ psinfo->dtps_argv[i] = p;
-+ p += strnlen_user(p, MAX_ARG_STRLEN) + 1;
-+ }
-+ psinfo->dtps_argv[len] = NULL;
-+
-+ /*
-+ * Determine the number of environment variables.
-+ */
-+ psinfo->dtps_envc = 0;
-+ for (p = (char *)mm->env_start; p < (char *)mm->env_end;
-+ psinfo->dtps_envc++) {
-+ size_t l = strnlen_user(p, MAX_ARG_STRLEN);
-+
-+ if (!l)
-+ break;
-+
-+ p += l + 1;
-+ }
-+
-+ /*
-+ * Limit the number of stored environment pointers.
-+ */
-+ len = psinfo->dtps_envc;
-+ if (len >= PR_ENVP_SZ)
-+ len = PR_ENVP_SZ - 1;
-+
-+ psinfo->dtps_envp = kmalloc((len + 1) * sizeof(char *),
-+ GFP_KERNEL);
-+ if (psinfo->dtps_envp == NULL)
-+ goto fail;
-+
-+ /*
-+ * Now populate the array of environment variable strings.
-+ */
-+ for (i = 0, p = (char *)mm->env_start; i < len; i++) {
-+ psinfo->dtps_envp[i] = p;
-+ p += strnlen_user(p, MAX_ARG_STRLEN) + 1;
-+ }
-+ psinfo->dtps_envp[len] = NULL;
-+
-+ mmput(mm);
-+ } else {
-+ size_t len = min(TASK_COMM_LEN, PR_PSARGS_SZ);
-+ int i;
-+
-+ /*
-+ * We end up here for tasks that do not have managed memory at
-+ * all, which generally means that this is a kernel thread.
-+ * If it is not, this is still safe because we know that tasks
-+ * always have the comm member populated with something (even
-+ * if it would be an empty string).
-+ */
-+ memcpy(psinfo->dtps_psargs, tsk->comm, len);
-+ for (i = len; i < PR_PSARGS_SZ; i++)
-+ psinfo->dtps_psargs[i] = 0;
-+
-+ psinfo->dtps_argc = 0;
-+ psinfo->dtps_argv = kmalloc(sizeof(char *), GFP_KERNEL);
-+ psinfo->dtps_argv[0] = NULL;
-+ psinfo->dtps_envc = 0;
-+ psinfo->dtps_envp = kmalloc(sizeof(char *), GFP_KERNEL);
-+ psinfo->dtps_envp[0] = NULL;
-+ }
-+
-+ atomic_set(&psinfo->dtps_usage, 1);
-+ tsk->dt_task->dt_psinfo = psinfo; /* new one */
-+
-+ return;
-+
-+fail:
-+ if (mm)
-+ mmput(mm);
-+
-+ if (psinfo)
-+ dtrace_psinfo_free(psinfo);
-+}
-+
-+/*
-+ * Initialize DTrace's psinfo subsystem.
-+ */
-+void __init dtrace_psinfo_os_init(void)
-+{
-+ dtrace_psinfo_cachep = kmem_cache_create("dtrace_psinfo_cache",
-+ sizeof(struct dtrace_psinfo), 0,
-+ SLAB_HWCACHE_ALIGN | SLAB_PANIC,
-+ NULL);
-+
-+}
-diff --git a/kernel/dtrace/dtrace_task.c b/kernel/dtrace/dtrace_task.c
-new file mode 100644
-index 000000000000..02bcc6b7e0a2
---- /dev/null
-+++ b/kernel/dtrace/dtrace_task.c
-@@ -0,0 +1,237 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_task.c
-+ * DESCRIPTION: DTrace - per-task data
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/sched/mm.h>
-+#include <linux/slab.h>
-+
-+struct kmem_cache *dtrace_task_cachep;
-+
-+void (*dtrace_helpers_fork)(struct task_struct *, struct task_struct *);
-+EXPORT_SYMBOL(dtrace_helpers_fork);
-+
-+/*
-+ * Reset per-task sate to default values. Modifies only part of
-+ * the state that does not persist across process forks.
-+ */
-+static void dtrace_task_reinit(struct dtrace_task *dtsk)
-+{
-+ dtsk->dt_predcache = 0;
-+ dtsk->dt_stop = 0;
-+ dtsk->dt_sig = 0;
-+
-+ dtsk->dt_helpers = NULL;
-+ dtsk->dt_probes = 0;
-+ dtsk->dt_tp_count = 0;
-+}
-+
-+/*
-+ * Allocate new per-task structure and initialize it with default
-+ * values.
-+ */
-+static struct dtrace_task *dtrace_task_alloc(void)
-+{
-+ struct dtrace_task *dtsk;
-+
-+ /* Try to allocate new task. */
-+ dtsk = kmem_cache_alloc(dtrace_task_cachep, GFP_KERNEL);
-+ if (dtsk == NULL)
-+ return NULL;
-+
-+ /* Initialize new task. */
-+ dtrace_task_reinit(dtsk);
-+
-+ dtsk->dt_vtime = ktime_set(0, 0);
-+ dtsk->dt_start = ktime_set(0, 0);
-+ dtsk->dt_psinfo = NULL;
-+ dtsk->dt_ustack = NULL;
-+
-+ return dtsk;
-+}
-+
-+/*
-+ * Cleans all attached resources to the per-task structure so it is ready to be
-+ * reused or freed.
-+ */
-+static void dtrace_task_cleanup(struct task_struct *tsk)
-+{
-+ struct dtrace_psinfo *psinfo;
-+
-+ /* Nothing to remove. */
-+ if (tsk->dt_task == NULL)
-+ return;
-+
-+ /* Release psinfo if any. */
-+ psinfo = tsk->dt_task->dt_psinfo;
-+ if (psinfo != NULL) {
-+ tsk->dt_task->dt_psinfo = NULL;
-+ dtrace_psinfo_put(psinfo);
-+ }
-+}
-+
-+/*
-+ * Kernel hooks for per-task events.
-+ */
-+
-+/*
-+ * Called when a new task has been created.
-+ *
-+ * It tries to allocate new per-task data strcture and initialize
-+ * it with default values.
-+ */
-+void dtrace_task_init(struct task_struct *tsk)
-+{
-+ struct mm_struct *mm = NULL;
-+
-+ /* Initialize new task structure */
-+ tsk->dt_task = dtrace_task_alloc();
-+ if (tsk->dt_task == NULL)
-+ return;
-+
-+ /* Try to setup initial userspace stack. */
-+ mm = get_task_mm(tsk);
-+ if (mm) {
-+ tsk->dt_task->dt_ustack = (void *)mm->start_stack;
-+ mmput(mm);
-+ }
-+}
-+
-+/*
-+ * Called when a task has been duplicated.
-+ *
-+ * When a task is duplicated this is called early to provide new instance
-+ * of per-task data. This hook is called very early after a dup has been
-+ * performed. The new task shares almost everything with its parent and
-+ * locking performed must be aligned with locking of the kernel.
-+ *
-+ * DTrace resets new task to its default values.
-+ */
-+void dtrace_task_dup(struct task_struct *src, struct task_struct *dst)
-+{
-+ struct dtrace_psinfo *psinfo;
-+ struct dtrace_task *dtsk;
-+
-+ /* Nothing to clone. */
-+ if (src->dt_task == NULL)
-+ return;
-+
-+ /* Allocate and reinitialize new task. */
-+ dtsk = dtrace_task_alloc();
-+ if (dtsk == NULL) {
-+ dst->dt_task = NULL;
-+ return;
-+ }
-+ dtrace_task_reinit(dtsk);
-+
-+ /* Share psinfo if it is available. */
-+ psinfo = src->dt_task->dt_psinfo;
-+ if (psinfo != NULL) {
-+ dtrace_psinfo_get(psinfo);
-+ dtsk->dt_psinfo = psinfo;
-+ }
-+
-+ /* Copy remaining attributes of the source task. */
-+ dtsk->dt_ustack = src->dt_task->dt_ustack;
-+ dst->dt_task = dtsk;
-+}
-+
-+/*
-+ * Called when a process has been copied.
-+ *
-+ * If the original task has helpers attached fork them too.
-+ */
-+void dtrace_task_copy(struct task_struct *tsk, struct task_struct *child)
-+{
-+ if (tsk->dt_task == NULL)
-+ return;
-+
-+ if (child->dt_task == NULL)
-+ return;
-+
-+ /* Handle helpers for this task. */
-+ if (likely(dtrace_helpers_fork == NULL))
-+ return;
-+
-+ if (tsk->dt_task->dt_helpers != NULL)
-+ (*dtrace_helpers_fork)(tsk, child);
-+}
-+
-+/*
-+ * Called when a task has performed exec.
-+ *
-+ * If DTrace's per-task structure is already allocated it is reused for
-+ * the new task. If it is not present an allocation attempt is made.
-+ */
-+void dtrace_task_exec(struct task_struct *tsk)
-+{
-+ struct mm_struct *mm = NULL;
-+
-+ /* Try to reuse existing dtrace task. */
-+ if (tsk->dt_task != NULL) {
-+ dtrace_task_cleanup(tsk);
-+ dtrace_task_reinit(tsk->dt_task);
-+
-+ /* Try to set up initial userspace stack. */
-+ mm = get_task_mm(tsk);
-+ if (mm) {
-+ tsk->dt_task->dt_ustack = (void *)mm->start_stack;
-+ mmput(mm);
-+ }
-+ } else {
-+ dtrace_task_init(tsk);
-+
-+ /* No luck, we won't be able to trace this task. */
-+ if (tsk->dt_task == NULL)
-+ return;
-+ }
-+
-+ /* Finalize init of the per-task structure. */
-+ dtrace_psinfo_alloc(tsk);
-+}
-+
-+/*
-+ * Called when a task is about to be released.
-+ *
-+ * The DTrace's per-task data are disconnected and freed.
-+ */
-+void dtrace_task_free(struct task_struct *tsk)
-+{
-+ struct dtrace_task *dtsk = tsk->dt_task;
-+
-+ /* Nothing to do. */
-+ if (dtsk == NULL)
-+ return;
-+
-+ /* Release the per-task data. */
-+ dtrace_task_cleanup(tsk);
-+ tsk->dt_task = NULL;
-+ kmem_cache_free(dtrace_task_cachep, dtsk);
-+}
-+
-+/*
-+ * Initialize DTrace's task subsystem.
-+ */
-+void __init dtrace_task_os_init(void)
-+{
-+ /* Will panic if not initialized so no need to check for errors. */
-+ dtrace_task_cachep = kmem_cache_create("dtrace_task_cache",
-+ sizeof(struct dtrace_task), 0,
-+ SLAB_HWCACHE_ALIGN | SLAB_PANIC,
-+ NULL);
-+}
-+
-diff --git a/kernel/exit.c b/kernel/exit.c
-index 5c5859a9ba75..da498c5f029c 100644
---- a/kernel/exit.c
-+++ b/kernel/exit.c
-@@ -64,6 +64,7 @@
- #include <linux/rcuwait.h>
- #include <linux/compat.h>
- #include <linux/io_uring.h>
-+#include <linux/dtrace_os.h>
-
- #include <linux/uaccess.h>
- #include <asm/unistd.h>
-@@ -795,6 +796,9 @@ void __noreturn do_exit(long code)
- tsk->exit_code = code;
- taskstats_exit(tsk, group_dead);
-
-+ /* Remove DTrace state for this task */
-+ dtrace_task_free(tsk);
-+
- exit_mm();
-
- if (group_dead)
-diff --git a/kernel/fork.c b/kernel/fork.c
-index c675fdbd3dce..0d8a2b12fd90 100644
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -96,6 +96,7 @@
- #include <linux/kasan.h>
- #include <linux/scs.h>
- #include <linux/io_uring.h>
-+#include <linux/dtrace_task_impl.h>
-
- #include <asm/pgalloc.h>
- #include <linux/uaccess.h>
-@@ -442,6 +443,7 @@ void put_task_stack(struct task_struct *tsk)
- void free_task(struct task_struct *tsk)
- {
- scs_release(tsk);
-+ dtrace_task_free(tsk);
-
- #ifndef CONFIG_THREAD_INFO_IN_TASK
- /*
-@@ -943,6 +945,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
- #ifdef CONFIG_MEMCG
- tsk->active_memcg = NULL;
- #endif
-+
-+ dtrace_task_dup(orig, tsk);
- return tsk;
-
- free_stack:
-@@ -2300,6 +2304,25 @@ static __latent_entropy struct task_struct *copy_process(
- syscall_tracepoint_update(p);
- write_unlock_irq(&tasklist_lock);
-
-+#ifdef CONFIG_DTRACE
-+ /*
-+ * We make this call fairly late into the copy_process() handling,
-+ * because we need to ensure that we can look up this task based on
-+ * its pid using find_task_by_vpid(). We also must ensure that the
-+ * tasklist_lock has been released.
-+ */
-+ dtrace_task_copy(current, p);
-+
-+ /*
-+ * If we're called with stack_start != 0, this is almost certainly a
-+ * thread being created in current. Make sure it gets its own psinfo
-+ * data, because we need to record a new bottom of stack value.
-+ */
-+ if (p->mm && args->stack)
-+ if (p->dt_task != NULL)
-+ p->dt_task->dt_ustack = (void *)args->stack;
-+#endif
-+
- proc_fork_connector(p);
- sched_post_fork(p);
- cgroup_post_fork(p, args);
-diff --git a/kernel/module.c b/kernel/module.c
-index 9e471dbedc83..f4269dabc638 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -46,6 +46,7 @@
- #include <asm/mmu_context.h>
- #include <linux/license.h>
- #include <asm/sections.h>
-+#include <linux/dtrace_os.h>
- #include <linux/tracepoint.h>
- #include <linux/ftrace.h>
- #include <linux/livepatch.h>
-@@ -90,6 +91,9 @@
- DEFINE_MUTEX(module_mutex);
- EXPORT_SYMBOL_GPL(module_mutex);
- static LIST_HEAD(modules);
-+#ifdef CONFIG_DTRACE
-+struct list_head *dtrace_modules = &modules;
-+#endif /* CONFIG_DTRACE */
-
- /* Work queue for freeing init sections in success case */
- static void do_free_init(struct work_struct *w);
-@@ -1023,6 +1027,12 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
- }
- }
-
-+ /* Try destroying DTrace provider. */
-+ if (!dtrace_destroy_prov(mod)) {
-+ ret = -EBUSY;
-+ goto out;
-+ }
-+
- /* Stop the machine so refcounts can't move and disable module. */
- ret = try_stop_module(mod, flags, &forced);
- if (ret != 0)
-@@ -2212,6 +2222,7 @@ void __weak module_arch_freeing_init(struct module *mod)
- /* Free a module, remove from lists, etc. */
- static void free_module(struct module *mod)
- {
-+ dtrace_mod_pdata_free(mod);
- trace_module_free(mod);
-
- mod_sysfs_teardown(mod);
-@@ -3943,6 +3954,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
- /* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
- ftrace_module_init(mod);
-
-+ /* Allocate DTrace per-module data. */
-+ dtrace_mod_pdata_alloc(mod);
-+
- /* Finally it's fully formed, ready to start executing. */
- err = complete_formation(mod, info);
- if (err)
-diff --git a/kernel/sched/core.c b/kernel/sched/core.c
-index 77aa0e788b9b..db893818f3ea 100644
---- a/kernel/sched/core.c
-+++ b/kernel/sched/core.c
-@@ -13,6 +13,7 @@
- #include "sched.h"
-
- #include <linux/nospec.h>
-+#include <linux/dtrace_os.h>
-
- #include <linux/kcov.h>
- #include <linux/scs.h>
-@@ -3600,6 +3601,11 @@ static struct rq *finish_task_switch(struct task_struct *prev)
-
- rq->prev_mm = NULL;
-
-+#ifdef CONFIG_DTRACE
-+ if (dtrace_vtime_active)
-+ dtrace_vtime_switch(prev, current);
-+#endif
-+
- /*
- * A task struct has one reference for the use as "current".
- * If a task dies, then it sets TASK_DEAD in tsk->state and calls
-@@ -7195,6 +7201,10 @@ void __init sched_init(void)
- #endif /* CONFIG_SMP */
- hrtick_rq_init(rq);
- atomic_set(&rq->nr_iowait, 0);
-+
-+#ifdef CONFIG_DTRACE
-+ rq->dtrace_cpu_info = per_cpu_info(i);
-+#endif
- }
-
- set_load_weight(&init_task, false);
-diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
-index c122176c627e..f917e368e4f8 100644
---- a/kernel/sched/sched.h
-+++ b/kernel/sched/sched.h
-@@ -345,6 +345,7 @@ extern bool dl_cpu_busy(unsigned int cpu);
- #ifdef CONFIG_CGROUP_SCHED
-
- #include <linux/cgroup.h>
-+#include <linux/dtrace_cpu.h>
- #include <linux/psi.h>
-
- struct cfs_rq;
-@@ -1042,6 +1043,9 @@ struct rq {
- /* Must be inspected within a rcu lock section */
- struct cpuidle_state *idle_state;
- #endif
-+#ifdef CONFIG_DTRACE
-+ struct cpuinfo *dtrace_cpu_info;
-+#endif
- };
-
- #ifdef CONFIG_FAIR_GROUP_SCHED
-diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
-index 6858a31364b6..b74807546fba 100644
---- a/kernel/time/timekeeping.c
-+++ b/kernel/time/timekeeping.c
-@@ -22,6 +22,7 @@
- #include <linux/pvclock_gtod.h>
- #include <linux/compiler.h>
- #include <linux/audit.h>
-+#include <linux/dtrace_os.h>
-
- #include "tick-internal.h"
- #include "ntp_internal.h"
-@@ -743,6 +744,7 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
- tk_update_ktime_data(tk);
-
- update_vsyscall(tk);
-+ dtrace_update_time(tk);
- update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
-
- tk->tkr_mono.base_real = tk->tkr_mono.base + tk->offs_real;
-diff --git a/scripts/coccinelle/dtrace/enum-elision.cocci b/scripts/coccinelle/dtrace/enum-elision.cocci
-new file mode 100644
-index 000000000000..77a5b33bd166
---- /dev/null
-+++ b/scripts/coccinelle/dtrace/enum-elision.cocci
-@@ -0,0 +1,29 @@
-+/// Reduce uses of typedefs of named enums to the name of the enum
-+
-+virtual patch
-+virtual context
-+virtual org
-+virtual report
-+
-+@td@
-+type T;
-+identifier E;
-+@@
-+- typedef enum E
-++ enum E
-+ { ...
-+- } T;
-++ };
-+@@
-+type td.T;
-+identifier td.E;
-+@@
-+- T
-++ enum E
-+
-+@@
-+type td.T;
-+identifier td.E;
-+@@
-+- const T
-++ const enum E
-diff --git a/scripts/coccinelle/dtrace/typedef-elision.cocci b/scripts/coccinelle/dtrace/typedef-elision.cocci
-new file mode 100644
-index 000000000000..bc4caf375b60
---- /dev/null
-+++ b/scripts/coccinelle/dtrace/typedef-elision.cocci
-@@ -0,0 +1,83 @@
-+/// Reduce uses of typedefs of named structures to the name of the structure
-+
-+virtual patch
-+virtual context
-+virtual org
-+virtual report
-+
-+@td@
-+type T;
-+identifier S;
-+@@
-+(
-+- typedef struct S
-++ struct S
-+ { ...
-+- } T;
-++ };
-+|
-+ struct S;
-+- typedef struct S T;
-+)
-+@@
-+type td.T;
-+identifier td.S;
-+@@
-+- T
-++ struct S
-+
-+@@
-+type td.T;
-+identifier td.S;
-+@@
-+- const T
-++ const struct S
-+
-+/// Now structures declared with typedefs of opaque structs, one by one
-+@@
-+typedef dtrace_ecb_t;
-+@@
-+- dtrace_ecb_t
-++ struct dtrace_ecb
-+
-+@@
-+typedef dtrace_actdesc_t;
-+@@
-+- dtrace_actdesc_t
-++ struct dtrace_actdesc
-+
-+@@
-+typedef dtrace_state_t;
-+@@
-+- dtrace_state_t
-++ struct dtrace_state
-+
-+@@
-+typedef dtrace_vstate_t;
-+@@
-+- dtrace_vstate_t
-++ struct dtrace_vstate
-+
-+@@
-+typedef dtrace_mstate_t;
-+@@
-+- dtrace_mstate_t
-++ struct dtrace_mstate
-+
-+@@
-+typedef dtrace_task_t;
-+@@
-+- dtrace_task_t
-++ struct dtrace_task
-+
-+@@
-+typedef dtrace_psinfo_t;
-+@@
-+- dtrace_psinfo_t
-++ struct dtrace_psinfo
-+
-+@@
-+typedef dt_fbt_bl_entry_t;
-+@@
-+- dt_fbt_bl_entry_t
-++ struct dt_fbt_bl_entry
-diff --git a/scripts/package/mkspec b/scripts/package/mkspec
-index e9ff22c6fb4c..cba5be72adb9 100755
---- a/scripts/package/mkspec
-+++ b/scripts/package/mkspec
-@@ -150,6 +150,7 @@ $M %exclude /lib/modules/$KERNELRELEASE/source
- %files headers
- %defattr (-, root, root)
- /usr/include
-+ %exclude /usr/include/linux/dtrace
- $S$M
- $S$M %files devel
- $S$M %defattr (-, root, root)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0005-dtrace-modular-components-and-x86-support.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0005-dtrace-modular-components-and-x86-support.patch
deleted file mode 100644
index 9513abc33965..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0005-dtrace-modular-components-and-x86-support.patch
+++ /dev/null
@@ -1,18392 +0,0 @@
-From 4b3eec83a54c9bd853648e4b256fb28a078a36aa Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 17:52:54 +0000
-Subject: [PATCH 05/19] dtrace: modular components and x86 support
-
-This implements the core DTrace module (including the entire DIF
-interpreter and support for all built-in D variables and functions) and
-one test provider, dt_test.ko. It uses the machinery added in the last
-few commits. An x86 implementation of the architecture-dependent parts
-is also added so that one platform at least can compile it.
-
-At this stage, almost no probes will exist: they are added by the
-following commits, that add providers and SDT probes.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- Makefile | 1 +
- arch/x86/dtrace/Makefile.arch | 11 +
- arch/x86/dtrace/dtrace_asm_x86_64.S | 228 ++
- arch/x86/dtrace/dtrace_isa_x86_64.c | 228 ++
- dtrace/Makefile | 19 +
- dtrace/ctf_api.h | 33 +
- dtrace/dt_test.h | 30 +
- dtrace/dt_test_dev.c | 176 +
- dtrace/dt_test_mod.c | 52 +
- dtrace/dtrace.h | 35 +
- dtrace/dtrace_actdesc.c | 91 +
- dtrace/dtrace_anon.c | 144 +
- dtrace/dtrace_buffer.c | 490 +++
- dtrace/dtrace_debug.h | 118 +
- dtrace/dtrace_dev.c | 1599 +++++++++
- dtrace/dtrace_dev.h | 35 +
- dtrace/dtrace_dif.c | 4905 +++++++++++++++++++++++++++
- dtrace/dtrace_dof.c | 2504 ++++++++++++++
- dtrace/dtrace_ecb.c | 936 +++++
- dtrace/dtrace_enable.c | 449 +++
- dtrace/dtrace_fmt.c | 104 +
- dtrace/dtrace_hash.c | 266 ++
- dtrace/dtrace_isa.c | 361 ++
- dtrace/dtrace_match.c | 364 ++
- dtrace/dtrace_mod.c | 45 +
- dtrace/dtrace_predicate.c | 80 +
- dtrace/dtrace_priv.c | 120 +
- dtrace/dtrace_probe.c | 1542 +++++++++
- dtrace/dtrace_probe_ctx.c | 659 ++++
- dtrace/dtrace_ptofapi.c | 649 ++++
- dtrace/dtrace_spec.c | 434 +++
- dtrace/dtrace_state.c | 1108 ++++++
- dtrace/dtrace_util.c | 282 ++
- 33 files changed, 18098 insertions(+)
- create mode 100644 arch/x86/dtrace/Makefile.arch
- create mode 100644 arch/x86/dtrace/dtrace_asm_x86_64.S
- create mode 100644 arch/x86/dtrace/dtrace_isa_x86_64.c
- create mode 100644 dtrace/Makefile
- create mode 100644 dtrace/ctf_api.h
- create mode 100644 dtrace/dt_test.h
- create mode 100644 dtrace/dt_test_dev.c
- create mode 100644 dtrace/dt_test_mod.c
- create mode 100644 dtrace/dtrace.h
- create mode 100644 dtrace/dtrace_actdesc.c
- create mode 100644 dtrace/dtrace_anon.c
- create mode 100644 dtrace/dtrace_buffer.c
- create mode 100644 dtrace/dtrace_debug.h
- create mode 100644 dtrace/dtrace_dev.c
- create mode 100644 dtrace/dtrace_dev.h
- create mode 100644 dtrace/dtrace_dif.c
- create mode 100644 dtrace/dtrace_dof.c
- create mode 100644 dtrace/dtrace_ecb.c
- create mode 100644 dtrace/dtrace_enable.c
- create mode 100644 dtrace/dtrace_fmt.c
- create mode 100644 dtrace/dtrace_hash.c
- create mode 100644 dtrace/dtrace_isa.c
- create mode 100644 dtrace/dtrace_match.c
- create mode 100644 dtrace/dtrace_mod.c
- create mode 100644 dtrace/dtrace_predicate.c
- create mode 100644 dtrace/dtrace_priv.c
- create mode 100644 dtrace/dtrace_probe.c
- create mode 100644 dtrace/dtrace_probe_ctx.c
- create mode 100644 dtrace/dtrace_ptofapi.c
- create mode 100644 dtrace/dtrace_spec.c
- create mode 100644 dtrace/dtrace_state.c
- create mode 100644 dtrace/dtrace_util.c
-
-diff --git a/Makefile b/Makefile
-index fb9393fa10f0..4b25be692ac1 100644
---- a/Makefile
-+++ b/Makefile
-@@ -651,6 +651,7 @@ drivers-y := drivers/ sound/
- drivers-$(CONFIG_SAMPLES) += samples/
- drivers-y += net/ virt/
- libs-y := lib/
-+dtrace-y := dtrace/
- endif # KBUILD_EXTMOD
-
- # The all: target is the default when no target is given on the
-diff --git a/arch/x86/dtrace/Makefile.arch b/arch/x86/dtrace/Makefile.arch
-new file mode 100644
-index 000000000000..ffb9ef4d1722
---- /dev/null
-+++ b/arch/x86/dtrace/Makefile.arch
-@@ -0,0 +1,11 @@
-+#
-+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
-+#
-+
-+DTARCHDIR = ../arch/x86/dtrace
-+
-+ccflags-y += -I$(srctree)/arch/x86/dtrace/include -Idtrace
-+
-+dtrace-obj += dtrace_asm_x86_64.o dtrace_isa_x86_64.o
-+
-+dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
-diff --git a/arch/x86/dtrace/dtrace_asm_x86_64.S b/arch/x86/dtrace/dtrace_asm_x86_64.S
-new file mode 100644
-index 000000000000..46d3fe1b9703
---- /dev/null
-+++ b/arch/x86/dtrace/dtrace_asm_x86_64.S
-@@ -0,0 +1,228 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - x86 specific assembly
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/linkage.h>
-+#include <asm/smap.h>
-+
-+#define CPU_DTRACE_BADADDR 0x0004 /* DTrace fault: bad address */
-+
-+#if defined(__x86_64__)
-+ SYM_CODE_START(dtrace_caller)
-+ movq $-1, %rax
-+ ret
-+ SYM_CODE_END(dtrace_caller)
-+
-+#elif defined(__i386__)
-+
-+ SYM_CODE_START(dtrace_caller)
-+ movl $-1, %eax
-+ ret
-+ SYM_CODE_END(dtrace_caller)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_FUNC_START(dtrace_copy)
-+ pushq %rbp
-+ movq %rsp, %rbp
-+
-+ ASM_STAC
-+ xchgq %rdi, %rsi # make %rsi source, %rdi dest
-+ movq %rdx, %rcx # load count
-+ repz # repeat for count ...
-+ smovb # move from %ds:rsi to %ed:rdi
-+ ASM_CLAC
-+ leave
-+ ret
-+ SYM_FUNC_END(dtrace_copy)
-+
-+#elif defined(__i386__)
-+
-+ SYM_FUNC_START(dtrace_copy)
-+ pushl %ebp
-+ movl %esp, %ebp
-+ pushl %esi
-+ pushl %edi
-+
-+ movl 8(%ebp), %esi # Load source address
-+ movl 12(%ebp), %edi # Load destination address
-+ movl 16(%ebp), %ecx # Load count
-+ repz # Repeat for count...
-+ smovb # move from %ds:si to %es:di
-+
-+ popl %edi
-+ popl %esi
-+ movl %ebp, %esp
-+ popl %ebp
-+ ret
-+ SYM_FUNC_END(dtrace_copy)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_FUNC_START(dtrace_copystr)
-+ pushq %rbp
-+ movq %rsp, %rbp
-+
-+ ASM_STAC
-+0:
-+ movb (%rdi), %al # load from source
-+ movb %al, (%rsi) # store to destination
-+ addq $1, %rdi # increment source pointer
-+ addq $1, %rsi # increment destination pointer
-+ subq $1, %rdx # decrement remaining count
-+ cmpb $0, %al
-+ je 2f
-+ testq $0xfff, %rdx # test if count is 4k-aligned
-+ jnz 1f # if not, continue with copying
-+ testq $CPU_DTRACE_BADADDR, (%rcx) # load and test dtrace flags
-+ jnz 2f
-+1:
-+ cmpq $0, %rdx
-+ jne 0b
-+2:
-+ ASM_CLAC
-+ leave
-+ ret
-+
-+ SYM_FUNC_END(dtrace_copystr)
-+
-+#elif defined(__i386__)
-+
-+ SYM_FUNC_START(dtrace_copystr)
-+
-+ pushl %ebp # Setup stack frame
-+ movl %esp, %ebp
-+ pushl %ebx # Save registers
-+
-+ movl 8(%ebp), %ebx # Load source address
-+ movl 12(%ebp), %edx # Load destination address
-+ movl 16(%ebp), %ecx # Load count
-+
-+0:
-+ movb (%ebx), %al # Load from source
-+ movb %al, (%edx) # Store to destination
-+ incl %ebx # Increment source pointer
-+ incl %edx # Increment destination pointer
-+ decl %ecx # Decrement remaining count
-+ cmpb $0, %al
-+ je 2f
-+ testl $0xfff, %ecx # Check if count is 4k-aligned
-+ jnz 1f
-+ movl 20(%ebp), %eax # load flags pointer
-+ testl $CPU_DTRACE_BADADDR, (%eax) # load and test dtrace flags
-+ jnz 2f
-+1:
-+ cmpl $0, %ecx
-+ jne 0b
-+
-+2:
-+ popl %ebx
-+ movl %ebp, %esp
-+ popl %ebp
-+ ret
-+
-+ SYM_FUNC_END(dtrace_copystr)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_CODE_START(dtrace_fuword8_nocheck)
-+ xorq %rax, %rax
-+ ASM_STAC
-+ movb (%rdi), %al
-+ ASM_CLAC
-+ ret
-+ SYM_CODE_END(dtrace_fuword8_nocheck)
-+
-+#elif defined(__i386__)
-+
-+ SYM_CODE_START(dtrace_fuword8_nocheck)
-+ movl 4(%esp), %ecx
-+ xorl %eax, %eax
-+ movzbl (%ecx), %eax
-+ ret
-+ SYM_CODE_END(dtrace_fuword8_nocheck)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_CODE_START(dtrace_fuword16_nocheck)
-+ xorq %rax, %rax
-+ ASM_STAC
-+ movw (%rdi), %ax
-+ ASM_CLAC
-+ ret
-+ SYM_CODE_END(dtrace_fuword16_nocheck)
-+
-+#elif defined(__i386__)
-+
-+ SYM_CODE_START(dtrace_fuword16_nocheck)
-+ movl 4(%esp), %ecx
-+ xorl %eax, %eax
-+ movzwl (%ecx), %eax
-+ ret
-+ SYM_CODE_END(dtrace_fuword16_nocheck)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_CODE_START(dtrace_fuword32_nocheck)
-+ xorq %rax, %rax
-+ ASM_STAC
-+ movl (%rdi), %eax
-+ ASM_CLAC
-+ ret
-+ SYM_CODE_END(dtrace_fuword32_nocheck)
-+
-+#elif defined(__i386__)
-+
-+ SYM_CODE_START(dtrace_fuword32_nocheck)
-+ movl 4(%esp), %ecx
-+ xorl %eax, %eax
-+ movl (%ecx), %eax
-+ ret
-+ SYM_CODE_END(dtrace_fuword32_nocheck)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_CODE_START(dtrace_fuword64_nocheck)
-+ ASM_STAC
-+ movq (%rdi), %rax
-+ ASM_CLAC
-+ ret
-+ SYM_CODE_END(dtrace_fuword64_nocheck)
-+
-+#elif defined(__i386__)
-+
-+ SYM_CODE_START(dtrace_fuword64_nocheck)
-+ movl 4(%esp), %ecx
-+ xorl %eax, %eax
-+ xorl %edx, %edx
-+ movl (%ecx), %eax
-+ movl 4(%ecx), %edx
-+ ret
-+ SYM_CODE_END(dtrace_fuword64_nocheck)
-+
-+#endif /* __i386__ */
-diff --git a/arch/x86/dtrace/dtrace_isa_x86_64.c b/arch/x86/dtrace/dtrace_isa_x86_64.c
-new file mode 100644
-index 000000000000..5accadc9f121
---- /dev/null
-+++ b/arch/x86/dtrace/dtrace_isa_x86_64.c
-@@ -0,0 +1,228 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_isa_x86_64.c
-+ * DESCRIPTION: DTrace - x86_64 architecture specific support functions
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <asm/unwind.h>
-+
-+#include "dtrace.h"
-+
-+/* Register indices */
-+#define REG_TRAPNO 25
-+#define REG_GS 24
-+#define REG_FS 23
-+#define REG_ES 22
-+#define REG_DS 21
-+#define REG_SS 20
-+#define REG_RSP 19
-+#define REG_RFL 18
-+#define REG_CS 17
-+#define REG_RIP 16
-+#define REG_ERR 15
-+#define REG_RDI 14
-+#define REG_RSI 13
-+#define REG_RDX 12
-+#define REG_RCX 11
-+#define REG_RAX 10
-+#define REG_R8 9
-+#define REG_R9 8
-+#define REG_R10 7
-+#define REG_R11 6
-+#define REG_RBX 5
-+#define REG_RBP 4
-+#define REG_R12 3
-+#define REG_R13 2
-+#define REG_R14 1
-+#define REG_R15 0
-+
-+extern void dtrace_copy(uintptr_t, uintptr_t, size_t);
-+extern void dtrace_copystr(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+
-+uintptr_t _userlimit = 0x00007fffffffffffLL;
-+uintptr_t kernelbase = 0xffff880000000000LL;
-+
-+static int dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
-+{
-+#ifdef FIXME
-+ ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
-+#else
-+ if (kaddr < kernelbase || kaddr + size < kaddr) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = kaddr;
-+ return 0;
-+ }
-+#endif
-+
-+ if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = uaddr;
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+void dtrace_copyin_arch(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_copycheck(uaddr, kaddr, size))
-+ dtrace_copy(uaddr, kaddr, size);
-+}
-+
-+void dtrace_copyout(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_copycheck(uaddr, kaddr, size))
-+ dtrace_copy(kaddr, uaddr, size);
-+}
-+
-+void dtrace_copyinstr_arch(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_copycheck(uaddr, kaddr, size))
-+ dtrace_copystr(uaddr, kaddr, size, flags);
-+}
-+
-+void dtrace_copyoutstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_copycheck(uaddr, kaddr, size))
-+ dtrace_copystr(kaddr, uaddr, size, flags);
-+}
-+
-+#define DTRACE_FUWORD(bits) \
-+ uint##bits##_t dtrace_fuword##bits(void *uaddr) \
-+ { \
-+ extern uint##bits##_t dtrace_fuword##bits##_nocheck(void *);\
-+ \
-+ if ((uintptr_t)uaddr > _userlimit) { \
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); \
-+ this_cpu_core->cpuc_dtrace_illval = (uintptr_t)uaddr; \
-+ return 0; \
-+ } \
-+ \
-+ return dtrace_fuword##bits##_nocheck(uaddr); \
-+ }
-+
-+DTRACE_FUWORD(8)
-+DTRACE_FUWORD(16)
-+DTRACE_FUWORD(32)
-+DTRACE_FUWORD(64)
-+
-+uint64_t dtrace_getarg(int argno, int aframes)
-+{
-+ unsigned long bp;
-+ uint64_t *st;
-+ uint64_t val;
-+ int i;
-+ struct unwind_state state;
-+
-+ if (this_cpu_core->cpu_dtrace_regs)
-+ bp = this_cpu_core->cpu_dtrace_regs->bp;
-+ else {
-+ unwind_start(&state, current, NULL, NULL);
-+ for (i = 0; !unwind_done(&state) && i < aframes;
-+ unwind_next_frame(&state)) {
-+ i++;
-+ }
-+
-+ bp = (unsigned long)state.bp;
-+ }
-+
-+ ASSERT(argno >= 5);
-+
-+ /*
-+ * The first 5 arguments (arg0 through arg4) are passed in registers
-+ * to dtrace_probe(). The remaining arguments (arg5 through arg9) are
-+ * passed on the stack.
-+ *
-+ * Stack layout:
-+ * bp[0] = pushed bp from caller
-+ * bp[1] = return address
-+ * bp[2] = 6th argument (arg5 -> argno = 5)
-+ * bp[3] = 7th argument (arg6 -> argno = 6)
-+ * ...
-+ */
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ st = (uint64_t *)bp;
-+ val = st[2 + (argno - 5)];
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return val;
-+}
-+
-+ulong_t dtrace_getreg(struct task_struct *task, uint_t reg)
-+{
-+ struct pt_regs *rp = task_pt_regs(task);
-+
-+ int regmap[] = {
-+ REG_RBX, /* 0 -> EBX */
-+ REG_RCX, /* 1 -> ECX */
-+ REG_RDX, /* 2 -> EDX */
-+ REG_RSI, /* 3 -> ESI */
-+ REG_RDI, /* 4 -> EDI */
-+ REG_RBP, /* 5 -> EBP */
-+ REG_RAX, /* 6 -> EAX */
-+ REG_DS, /* 7 -> DS */
-+ REG_ES, /* 8 -> ES */
-+ REG_FS, /* 9 -> FS */
-+ REG_GS, /* 10 -> GS */
-+ REG_TRAPNO, /* 11 -> TRAPNO */
-+ REG_RIP, /* 12 -> EIP */
-+ REG_CS, /* 13 -> CS */
-+ REG_RFL, /* 14 -> EFL */
-+ REG_RSP, /* 15 -> UESP */
-+ REG_SS, /* 16 -> SS */
-+ };
-+
-+ if (reg > REG_TRAPNO) {
-+ /*
-+ * Convert register alias index into register mapping index.
-+ */
-+ reg -= REG_GS + 1;
-+
-+ if (reg >= sizeof(regmap) / sizeof(int)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return 0;
-+ }
-+
-+ reg = regmap[reg];
-+ }
-+
-+ /*
-+ * Most common case: direct index into pt_regs structure.
-+ */
-+ if (reg <= REG_SS)
-+ return (&rp->r15)[reg];
-+
-+ switch (reg) {
-+ case REG_DS:
-+ return task->thread.ds;
-+ case REG_ES:
-+ return task->thread.es;
-+ case REG_FS:
-+ return task->thread.fsbase;
-+ case REG_GS:
-+ return task->thread.gsbase;
-+ case REG_TRAPNO:
-+ return task->thread.trap_nr;
-+ default:
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return 0;
-+ }
-+}
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-new file mode 100644
-index 000000000000..36a4b97b922c
---- /dev/null
-+++ b/dtrace/Makefile
-@@ -0,0 +1,19 @@
-+#
-+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
-+#
-+
-+obj-$(CONFIG_DT_CORE) += dtrace.o
-+obj-$(CONFIG_DT_DT_TEST) += dt_test.o
-+
-+dtrace-y := dtrace_mod.o dtrace_dev.o \
-+ dtrace_actdesc.o dtrace_anon.o \
-+ dtrace_buffer.o dtrace_dif.o dtrace_dof.o \
-+ dtrace_ecb.o dtrace_enable.o \
-+ dtrace_fmt.o dtrace_hash.o dtrace_isa.o \
-+ dtrace_match.o dtrace_priv.o \
-+ dtrace_probe.o dtrace_probe_ctx.o \
-+ dtrace_ptofapi.o dtrace_predicate.o \
-+ dtrace_spec.o dtrace_state.o dtrace_util.o
-+dt_test-y := dt_test_mod.o dt_test_dev.o
-+
-+-include arch/$(SRCARCH)/dtrace/Makefile.arch
-diff --git a/dtrace/ctf_api.h b/dtrace/ctf_api.h
-new file mode 100644
-index 000000000000..e09bafc676f4
---- /dev/null
-+++ b/dtrace/ctf_api.h
-@@ -0,0 +1,33 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Compact C Type format
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef __CTF_API_H_
-+#define __CTF_API_H_
-+
-+/*
-+ * The CTF data model is inferred to be the caller's data model or the data
-+ * model of the given object, unless ctf_setmodel() is explicitly called.
-+ */
-+#define CTF_MODEL_ILP32 1 /* object data model is ILP32 */
-+#define CTF_MODEL_LP64 2 /* object data model is LP64 */
-+#ifdef CONFIG_64BIT
-+# define CTF_MODEL_NATIVE CTF_MODEL_LP64
-+#else
-+# define CTF_MODEL_NATIVE CTF_MODEL_ILP32
-+#endif
-+
-+#endif /* __CTF_API_H_ */
-diff --git a/dtrace/dt_test.h b/dtrace/dt_test.h
-new file mode 100644
-index 000000000000..6efe4656001b
---- /dev/null
-+++ b/dtrace/dt_test.h
-@@ -0,0 +1,30 @@
-+/*
-+ * Dynamic Tracing for Linux - test provider
-+ *
-+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _DT_TEST_H_
-+#define _DT_TEST_H_
-+
-+extern void dt_test_provide(void *, const struct dtrace_probedesc *);
-+extern int dt_test_enable(void *arg, dtrace_id_t, void *);
-+extern void dt_test_disable(void *arg, dtrace_id_t, void *);
-+extern void dt_test_destroy(void *, dtrace_id_t, void *);
-+
-+extern dtrace_provider_id_t dt_test_id;
-+
-+extern int dt_test_dev_init(void);
-+extern void dt_test_dev_exit(void);
-+
-+#endif /* _DT_TEST_H_ */
-diff --git a/dtrace/dt_test_dev.c b/dtrace/dt_test_dev.c
-new file mode 100644
-index 000000000000..8e1f5bab8a12
---- /dev/null
-+++ b/dtrace/dt_test_dev.c
-@@ -0,0 +1,176 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dt_test_dev.c
-+ * DESCRIPTION: DTrace - test provider device driver
-+ *
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/types.h>
-+#include <trace/syscall.h>
-+#include <asm/unistd.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "dt_test.h"
-+
-+static dtrace_id_t pid = DTRACE_IDNONE;
-+static int enabled;
-+
-+/*
-+ * Some arrays of structures of different sizes populated with
-+ * unchanging randomly-chosen numbers, for padding tests.
-+ */
-+
-+static struct dt_test_int_char
-+{
-+ int foo;
-+ char bar;
-+} intish[2] __attribute__((used)) = { { 47204473, 48 },
-+ { 18472, 62 } };
-+
-+static struct dt_test_long_int
-+{
-+ long foo;
-+ int bar;
-+} longish[2] __attribute__((used)) = { { 43737975, 240724 },
-+ { 24924709, 526 } };
-+
-+static struct dt_test_longlong_long
-+{
-+ long long foo;
-+ long bar;
-+} longlongish[2] __attribute__((used)) = { { 4294479287, 4395957 },
-+ { 5239637, 249750 } };
-+
-+static struct dt_test_like_a_scatterlist
-+{
-+ unsigned long a;
-+ unsigned int b;
-+ unsigned int c;
-+ u64 d;
-+ unsigned int e;
-+} scatter_failure[2] __attribute__((used)) = { { .a = 1, .b = 2,
-+ .c = 3, .d = 4, .e = 5 },
-+ { .a = 6, .b = 7,
-+ .c = 8, .d = 9, .e = 10 } };
-+
-+void dt_test_provide(void *arg, const struct dtrace_probedesc *desc)
-+{
-+ dtrace_id_t probe;
-+
-+ probe = dtrace_probe_lookup(dt_test_id, "dt_test", NULL, "test");
-+ if (probe != DTRACE_IDNONE)
-+ return;
-+
-+ pid = dtrace_probe_create(dt_test_id, "dt_test", NULL, "test", 1, NULL);
-+}
-+
-+int dt_test_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ enabled = 1;
-+
-+ return 0;
-+}
-+
-+void dt_test_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ enabled = 0;
-+}
-+
-+void dt_test_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+}
-+
-+void probe_p(dtrace_id_t pid, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2,
-+ uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6,
-+ uintptr_t arg7, uintptr_t arg8, uintptr_t arg9)
-+{
-+}
-+
-+/*
-+ * Direct calling into dtrace_probe() when passing more than 5 parameters to
-+ * the probe requires a stub function. Otherwise we may not be able to get
-+ * to the value of all arguments correctly.
-+ */
-+void dt_test_probe(uintptr_t arg0, uintptr_t arg1, uintptr_t arg2,
-+ uintptr_t arg3, uintptr_t arg4, uintptr_t arg5,
-+ uintptr_t arg6, uintptr_t arg7, uintptr_t arg8,
-+ uintptr_t arg9)
-+{
-+ /*
-+ * Yes, this is not nice.
-+ * Not at all...
-+ * But we're doing it anyway...
-+ */
-+ typeof(probe_p) *probe_fn = (void *)&dtrace_probe;
-+
-+ probe_fn(pid, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-+ arg9);
-+}
-+
-+static long dt_test_ioctl(struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ if (enabled) {
-+ dt_test_probe(cmd, arg, 2ULL, 3ULL, 4ULL, 5ULL, 6ULL, 7ULL,
-+ 8ULL, 9ULL);
-+
-+ return 0;
-+ }
-+
-+ return -EAGAIN;
-+}
-+
-+static int dt_test_open(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static int dt_test_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations dt_test_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = dt_test_ioctl,
-+ .open = dt_test_open,
-+ .release = dt_test_close,
-+};
-+
-+static struct miscdevice dt_test_dev = {
-+ .minor = DT_DEV_DT_TEST_MINOR,
-+ .name = "dt_test",
-+ .nodename = "dtrace/provider/dt_test",
-+ .fops = &dt_test_fops,
-+};
-+
-+int dt_test_dev_init(void)
-+{
-+ int ret = 0;
-+
-+ ret = misc_register(&dt_test_dev);
-+ if (ret)
-+ pr_err("%s: Can't register misc device %d\n",
-+ dt_test_dev.name, dt_test_dev.minor);
-+
-+ return ret;
-+}
-+
-+void dt_test_dev_exit(void)
-+{
-+ misc_deregister(&dt_test_dev);
-+}
-diff --git a/dtrace/dt_test_mod.c b/dtrace/dt_test_mod.c
-new file mode 100644
-index 000000000000..d8af71665a37
---- /dev/null
-+++ b/dtrace/dt_test_mod.c
-@@ -0,0 +1,52 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dt_test_mod.c
-+ * DESCRIPTION: DTrace - test provider kernel module
-+ *
-+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "dt_test.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("DTrace Test Probe");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+static const struct dtrace_pattr dt_test_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pops dt_test_pops = {
-+ .dtps_provide = dt_test_provide,
-+ .dtps_provide_module = NULL,
-+ .dtps_destroy_module = NULL,
-+ .dtps_enable = dt_test_enable,
-+ .dtps_disable = dt_test_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = NULL,
-+ .dtps_getargval = NULL,
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = dt_test_destroy
-+};
-+
-+DT_PROVIDER_MODULE(dt_test, DTRACE_PRIV_USER)
-diff --git a/dtrace/dtrace.h b/dtrace/dtrace.h
-new file mode 100644
-index 000000000000..f632b910ac30
---- /dev/null
-+++ b/dtrace/dtrace.h
-@@ -0,0 +1,35 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _DTRACE_H_
-+#define _DTRACE_H_
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/sched.h>
-+#include <linux/types.h>
-+
-+#include "dtrace_debug.h"
-+
-+#include <dtrace/types.h>
-+
-+#include <linux/dtrace/dtrace.h>
-+
-+#include <dtrace/provider.h>
-+#include <dtrace/dtrace_impl.h>
-+
-+#endif /* _DTRACE_H_ */
-diff --git a/dtrace/dtrace_actdesc.c b/dtrace/dtrace_actdesc.c
-new file mode 100644
-index 000000000000..fada47a6e5eb
---- /dev/null
-+++ b/dtrace/dtrace_actdesc.c
-@@ -0,0 +1,91 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_actdesc.c
-+ * DESCRIPTION: DTrace - action implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+struct dtrace_actdesc *dtrace_actdesc_create(dtrace_actkind_t kind,
-+ uint32_t ntuple,
-+ uint64_t uarg, uint64_t arg)
-+{
-+ struct dtrace_actdesc *act;
-+
-+#ifdef FIXME
-+ ASSERT(!DTRACEACT_ISPRINTFLIKE(kind) ||
-+ (arg != 0 && (uintptr_t)arg >= KERNELBASE) ||
-+ (arg == 0 && kind == DTRACEACT_PRINTA));
-+#else
-+ ASSERT(!DTRACEACT_ISPRINTFLIKE(kind) ||
-+ (arg != 0) ||
-+ (arg == 0 && kind == DTRACEACT_PRINTA));
-+#endif
-+
-+ act = kzalloc(sizeof(struct dtrace_actdesc), GFP_KERNEL);
-+ if (act == NULL)
-+ return NULL;
-+
-+ act->dtad_kind = kind;
-+ act->dtad_ntuple = ntuple;
-+ act->dtad_uarg = uarg;
-+ act->dtad_arg = arg;
-+ act->dtad_refcnt = 1;
-+
-+ return act;
-+}
-+
-+void dtrace_actdesc_hold(struct dtrace_actdesc *act)
-+{
-+ ASSERT(act->dtad_refcnt >= 1);
-+
-+ act->dtad_refcnt++;
-+}
-+
-+void dtrace_actdesc_release(struct dtrace_actdesc *act,
-+ struct dtrace_vstate *vstate)
-+{
-+ dtrace_actkind_t kind = act->dtad_kind;
-+ struct dtrace_difo *dp;
-+
-+ ASSERT(act->dtad_refcnt >= 1);
-+
-+ if (--act->dtad_refcnt != 0)
-+ return;
-+
-+ dp = act->dtad_difo;
-+ if (dp != NULL)
-+ dtrace_difo_release(dp, vstate);
-+
-+ if (DTRACEACT_ISPRINTFLIKE(kind)) {
-+ char *str = (char *)(uintptr_t)act->dtad_arg;
-+
-+#ifdef FIXME
-+ ASSERT((str != NULL && (uintptr_t)str >= KERNELBASE) ||
-+ (str == NULL && act->dtad_kind == DTRACEACT_PRINTA));
-+#else
-+ ASSERT((str != NULL) ||
-+ (str == NULL && act->dtad_kind == DTRACEACT_PRINTA));
-+#endif
-+
-+ if (str != NULL)
-+ vfree(str);
-+ }
-+
-+ kfree(act);
-+}
-diff --git a/dtrace/dtrace_anon.c b/dtrace/dtrace_anon.c
-new file mode 100644
-index 000000000000..80d0d9c1a9fd
---- /dev/null
-+++ b/dtrace/dtrace_anon.c
-@@ -0,0 +1,144 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_anon.c
-+ * DESCRIPTION: DTrace - Anonymous state implementation
-+ *
-+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include "dtrace.h"
-+
-+struct dtrace_anon dtrace_anon;
-+
-+struct dtrace_state *dtrace_anon_grab(void)
-+{
-+ struct dtrace_state *state;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ state = dtrace_anon.dta_state;
-+ if (state == NULL) {
-+ ASSERT(dtrace_anon.dta_enabling == NULL);
-+
-+ return NULL;
-+ }
-+
-+ ASSERT(dtrace_anon.dta_enabling != NULL);
-+ ASSERT(dtrace_retained != NULL);
-+
-+ dtrace_enabling_destroy(dtrace_anon.dta_enabling);
-+ dtrace_anon.dta_enabling = NULL;
-+ dtrace_anon.dta_state = NULL;
-+
-+ return state;
-+}
-+
-+void dtrace_anon_property(void)
-+{
-+ int i, rv;
-+ struct dtrace_state *state;
-+ struct dof_hdr *dof;
-+ char c[32]; /* enough for "dof-data-" + digits */
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+ for (i = 0; ; i++) {
-+ snprintf(c, sizeof(c), "dof-data-%d", i);
-+
-+ dtrace_err_verbose = 1;
-+
-+ dof = dtrace_dof_property(c);
-+ if (dof == NULL) {
-+ dtrace_err_verbose = 0;
-+ break;
-+ }
-+
-+#ifdef FIXME
-+ /*
-+ * We want to create anonymous state, so we need to transition
-+ * the kernel debugger to indicate that DTrace is active. If
-+ * this fails (e.g. because the debugger has modified text in
-+ * some way), we won't continue with the processing.
-+ */
-+ if (kdi_dtrace_set(KDI_DTSET_DTRACE_ACTIVATE) != 0) {
-+ pr_info("kernel debugger active; "
-+ "anonymous enabling ignored.");
-+ dtrace_dof_destroy(dof);
-+ break;
-+ }
-+#endif
-+
-+ /*
-+ * If we haven't allocated an anonymous state, we'll do so now.
-+ */
-+ state = dtrace_anon.dta_state;
-+ if (state == NULL) {
-+ state = dtrace_state_create(NULL);
-+ dtrace_anon.dta_state = state;
-+
-+ if (state == NULL) {
-+ /*
-+ * This basically shouldn't happen: there is no
-+ * failure mode from dtrace_state_create().
-+ * Still, the interface allows for a failure
-+ * mode, and we want to fail as gracefully as
-+ * possible: we'll emit an error message and
-+ * cease processing anonymous state in this
-+ * case.
-+ */
-+ pr_warn("failed to create anonymous state");
-+ dtrace_dof_destroy(dof);
-+ break;
-+ }
-+ }
-+
-+ rv = dtrace_dof_slurp(dof, &state->dts_vstate, current_cred(),
-+ &dtrace_anon.dta_enabling, 0, TRUE);
-+
-+ if (rv == 0)
-+ rv = dtrace_dof_options(dof, state);
-+
-+ dtrace_err_verbose = 0;
-+ dtrace_dof_destroy(dof);
-+
-+ if (rv != 0) {
-+ /*
-+ * This is malformed DOF; chuck any anonymous state
-+ * that we created.
-+ */
-+ ASSERT(dtrace_anon.dta_enabling == NULL);
-+ dtrace_state_destroy(state);
-+ dtrace_anon.dta_state = NULL;
-+ break;
-+ }
-+
-+ ASSERT(dtrace_anon.dta_enabling != NULL);
-+ }
-+
-+ if (dtrace_anon.dta_enabling != NULL) {
-+ int rval;
-+
-+ /*
-+ * dtrace_enabling_retain() can only fail because we are
-+ * trying to retain more enablings than are allowed -- but
-+ * we only have one anonymous enabling, and we are guaranteed
-+ * to be allowed at least one retained enabling; we assert
-+ * that dtrace_enabling_retain() returns success.
-+ */
-+ rval = dtrace_enabling_retain(dtrace_anon.dta_enabling);
-+ ASSERT(rval == 0);
-+
-+ dtrace_enabling_dump(dtrace_anon.dta_enabling);
-+ }
-+}
-diff --git a/dtrace/dtrace_buffer.c b/dtrace/dtrace_buffer.c
-new file mode 100644
-index 000000000000..9e7faebc51b7
---- /dev/null
-+++ b/dtrace/dtrace_buffer.c
-@@ -0,0 +1,490 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_buffer.c
-+ * DESCRIPTION: DTrace - buffer implementation
-+ *
-+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+dtrace_optval_t dtrace_nonroot_maxsize = (16 * 1024 * 1024);
-+
-+/*
-+ * Note: called from cross call context. This function switches the two
-+ * buffers on a given CPU. The atomicity of this operation is assured by
-+ * disabling interrupts while the actual switch takes place; the disabling of
-+ * interrupts serializes the execution with any execution of dtrace_probe() on
-+ * the same CPU.
-+ */
-+void dtrace_buffer_switch(struct dtrace_buffer *buf)
-+{
-+ caddr_t tomax = buf->dtb_tomax;
-+ caddr_t xamot = buf->dtb_xamot;
-+ dtrace_icookie_t cookie;
-+
-+ ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH));
-+ ASSERT(!(buf->dtb_flags & DTRACEBUF_RING));
-+
-+ local_irq_save(cookie);
-+
-+ dt_dbg_buf("Switch (CPU %d): tomax %p (%lld) <-> xamot %p (%lld)\n",
-+ smp_processor_id(), tomax, buf->dtb_offset,
-+ xamot, buf->dtb_xamot_offset);
-+
-+ buf->dtb_tomax = xamot;
-+ buf->dtb_xamot = tomax;
-+ buf->dtb_xamot_drops = buf->dtb_drops;
-+ buf->dtb_xamot_offset = buf->dtb_offset;
-+ buf->dtb_xamot_errors = buf->dtb_errors;
-+ buf->dtb_xamot_flags = buf->dtb_flags;
-+ buf->dtb_offset = 0;
-+ buf->dtb_drops = 0;
-+ buf->dtb_errors = 0;
-+ buf->dtb_flags &= ~(DTRACEBUF_ERROR | DTRACEBUF_DROPPED);
-+
-+ local_irq_restore(cookie);
-+}
-+
-+/*
-+ * Note: called from cross call context. This function activates a buffer
-+ * on a CPU. As with dtrace_buffer_switch(), the atomicity of the operation
-+ * is guaranteed by the disabling of interrupts.
-+ */
-+void dtrace_buffer_activate(struct dtrace_state *state)
-+{
-+ struct dtrace_buffer *buf;
-+ dtrace_icookie_t cookie;
-+
-+ local_irq_save(cookie);
-+
-+ buf = &state->dts_buffer[smp_processor_id()];
-+
-+ if (buf->dtb_tomax != NULL)
-+ /*
-+ * We might like to assert that the buffer is marked inactive,
-+ * but this isn't necessarily true: the buffer for the CPU
-+ * that processes the BEGIN probe has its buffer activated
-+ * manually. In this case, we take the (harmless) action
-+ * re-clearing the bit INACTIVE bit.
-+ */
-+ buf->dtb_flags &= ~DTRACEBUF_INACTIVE;
-+
-+ local_irq_restore(cookie);
-+}
-+
-+int dtrace_buffer_alloc(struct dtrace_buffer *bufs, size_t size, int flags,
-+ processorid_t cpuid)
-+{
-+ processorid_t cpu;
-+ struct dtrace_buffer *buf;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+#ifdef FIXME
-+ if (size > dtrace_nonroot_maxsize &&
-+ !PRIV_POLICY_CHOICE(current_cred(), PRIV_ALL, FALSE))
-+ return -EFBIG;
-+#endif
-+
-+ for_each_online_cpu(cpu) {
-+ if (cpuid != DTRACE_CPUALL && cpuid != cpu)
-+ continue;
-+
-+ buf = &bufs[cpu];
-+
-+ /*
-+ * If there is already a buffer allocated for this CPU, it
-+ * is only possible that this is a DR event. In this case,
-+ * the buffer size must match our specified size.
-+ */
-+ if (buf->dtb_tomax != NULL) {
-+ ASSERT(buf->dtb_size == size);
-+ continue;
-+ }
-+
-+ ASSERT(buf->dtb_xamot == NULL);
-+
-+ buf->dtb_tomax = dtrace_vzalloc_try(size);
-+ if (buf->dtb_tomax == NULL)
-+ goto err;
-+
-+ buf->dtb_size = size;
-+ buf->dtb_flags = flags;
-+ buf->dtb_offset = 0;
-+ buf->dtb_drops = 0;
-+
-+ if (flags & DTRACEBUF_NOSWITCH)
-+ continue;
-+
-+ buf->dtb_xamot = dtrace_vzalloc_try(size);
-+ if (buf->dtb_xamot == NULL)
-+ goto err;
-+ }
-+
-+ return 0;
-+
-+err:
-+ for_each_online_cpu(cpu) {
-+ if (cpuid != DTRACE_CPUALL && cpuid != cpu)
-+ continue;
-+
-+ buf = &bufs[cpu];
-+
-+ if (buf->dtb_xamot != NULL) {
-+ ASSERT(buf->dtb_tomax != NULL);
-+ ASSERT(buf->dtb_size == size);
-+ vfree(buf->dtb_xamot);
-+ }
-+
-+ if (buf->dtb_tomax != NULL) {
-+ ASSERT(buf->dtb_size == size);
-+ vfree(buf->dtb_tomax);
-+ }
-+
-+ buf->dtb_tomax = NULL;
-+ buf->dtb_xamot = NULL;
-+ buf->dtb_size = 0;
-+ }
-+
-+ return -ENOMEM;
-+}
-+void dtrace_buffer_drop(struct dtrace_buffer *buf)
-+{
-+ buf->dtb_drops++;
-+}
-+
-+intptr_t dtrace_buffer_reserve(struct dtrace_buffer *buf, size_t needed,
-+ size_t align, struct dtrace_state *state,
-+ struct dtrace_mstate *mstate)
-+{
-+ intptr_t offs = buf->dtb_offset, soffs;
-+ intptr_t woffs;
-+ caddr_t tomax;
-+ size_t total;
-+
-+ if (buf->dtb_flags & DTRACEBUF_INACTIVE)
-+ return -1;
-+
-+ tomax = buf->dtb_tomax;
-+ if (tomax == NULL) {
-+ dtrace_buffer_drop(buf);
-+ return -1;
-+ }
-+
-+ if (!(buf->dtb_flags & (DTRACEBUF_RING | DTRACEBUF_FILL))) {
-+ while (offs & (align - 1)) {
-+ /*
-+ * Assert that our alignment is off by a number which
-+ * is itself sizeof (uint32_t) aligned.
-+ */
-+ ASSERT(!((align - (offs & (align - 1))) &
-+ (sizeof(uint32_t) - 1)));
-+ DTRACE_STORE(uint32_t, tomax, offs, DTRACE_EPIDNONE);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- EPIDNONE "
-+ "(from %s::%d)\n",
-+ buf, offs, offs + sizeof(uint32_t) - 1,
-+ __func__, __LINE__);
-+ offs += sizeof(uint32_t);
-+ }
-+
-+ soffs = offs + needed;
-+ if (soffs > buf->dtb_size) {
-+ dtrace_buffer_drop(buf);
-+ return -1;
-+ }
-+
-+ if (mstate == NULL) {
-+ dt_dbg_buf(" Reserve: %p[%ld .. %ld]\n",
-+ buf, offs, offs + needed - 1);
-+ return offs;
-+ }
-+
-+ mstate->dtms_scratch_base = (uintptr_t)tomax + soffs;
-+ mstate->dtms_scratch_size = buf->dtb_size - soffs;
-+ mstate->dtms_scratch_ptr = mstate->dtms_scratch_base;
-+
-+ dt_dbg_buf(" Reserve: %p[%ld .. %ld]\n",
-+ buf, offs, offs + needed - 1);
-+ return offs;
-+ }
-+
-+ if (buf->dtb_flags & DTRACEBUF_FILL) {
-+ if (state->dts_activity != DTRACE_ACTIVITY_COOLDOWN &&
-+ (buf->dtb_flags & DTRACEBUF_FULL))
-+ return -1;
-+
-+ goto out;
-+ }
-+
-+ total = needed + (offs & (align - 1));
-+
-+ /*
-+ * For a ring buffer, life is quite a bit more complicated. Before
-+ * we can store any padding, we need to adjust our wrapping offset.
-+ * (If we've never before wrapped or we're not about to, no adjustment
-+ * is required.)
-+ */
-+ if ((buf->dtb_flags & DTRACEBUF_WRAPPED) ||
-+ offs + total > buf->dtb_size) {
-+ woffs = buf->dtb_xamot_offset;
-+
-+ if (offs + total > buf->dtb_size) {
-+ /*
-+ * We can't fit in the end of the buffer. First, a
-+ * sanity check that we can fit in the buffer at all.
-+ */
-+ if (total > buf->dtb_size) {
-+ dtrace_buffer_drop(buf);
-+ return -1;
-+ }
-+
-+ /*
-+ * We're going to be storing at the top of the buffer,
-+ * so now we need to deal with the wrapped offset. We
-+ * only reset our wrapped offset to 0 if it is
-+ * currently greater than the current offset. If it
-+ * is less than the current offset, it is because a
-+ * previous allocation induced a wrap -- but the
-+ * allocation didn't subsequently take the space due
-+ * to an error or false predicate evaluation. In this
-+ * case, we'll just leave the wrapped offset alone: if
-+ * the wrapped offset hasn't been advanced far enough
-+ * for this allocation, it will be adjusted in the
-+ * lower loop.
-+ */
-+ if (buf->dtb_flags & DTRACEBUF_WRAPPED) {
-+ if (woffs >= offs)
-+ woffs = 0;
-+ } else
-+ woffs = 0;
-+
-+ /*
-+ * Now we know that we're going to be storing to the
-+ * top of the buffer and that there is room for us
-+ * there. We need to clear the buffer from the current
-+ * offset to the end (there may be old gunk there).
-+ */
-+ while (offs < buf->dtb_size)
-+ tomax[offs++] = 0;
-+
-+ /*
-+ * We need to set our offset to zero. And because we
-+ * are wrapping, we need to set the bit indicating as
-+ * much. We can also adjust our needed space back
-+ * down to the space required by the ECB -- we know
-+ * that the top of the buffer is aligned.
-+ */
-+ offs = 0;
-+ total = needed;
-+ buf->dtb_flags |= DTRACEBUF_WRAPPED;
-+ } else {
-+ /*
-+ * There is room for us in the buffer, so we simply
-+ * need to check the wrapped offset.
-+ */
-+ if (woffs < offs) {
-+ /*
-+ * The wrapped offset is less than the offset.
-+ * This can happen if we allocated buffer space
-+ * that induced a wrap, but then we didn't
-+ * subsequently take the space due to an error
-+ * or false predicate evaluation. This is
-+ * okay; we know that _this_ allocation isn't
-+ * going to induce a wrap. We still can't
-+ * reset the wrapped offset to be zero,
-+ * however: the space may have been trashed in
-+ * the previous failed probe attempt. But at
-+ * least the wrapped offset doesn't need to
-+ * be adjusted at all...
-+ */
-+ goto out;
-+ }
-+ }
-+
-+ while (offs + total > woffs) {
-+ dtrace_epid_t epid = *(uint32_t *)(tomax + woffs);
-+ size_t size;
-+
-+ if (epid == DTRACE_EPIDNONE)
-+ size = sizeof(uint32_t);
-+ else {
-+ ASSERT(epid <= state->dts_necbs);
-+ ASSERT(state->dts_ecbs[epid - 1] != NULL);
-+
-+ size = state->dts_ecbs[epid - 1]->dte_size;
-+ }
-+
-+ ASSERT(woffs + size <= buf->dtb_size);
-+ ASSERT(size != 0);
-+
-+ if (woffs + size == buf->dtb_size) {
-+ /*
-+ * We've reached the end of the buffer; we want
-+ * to set the wrapped offset to 0 and break
-+ * out. However, if the offs is 0, then we're
-+ * in a strange edge-condition: the amount of
-+ * space that we want to reserve plus the size
-+ * of the record that we're overwriting is
-+ * space but subsequently don't consume it (due
-+ * to a failed predicate or error) the wrapped
-+ * offset will be 0 -- yet the EPID at offset 0
-+ * will not be committed. This situation is
-+ * relatively easy to deal with: if we're in
-+ * this case, the buffer is indistinguishable
-+ * from one that hasn't wrapped; we need only
-+ * finish the job by clearing the wrapped bit,
-+ * explicitly setting the offset to be 0, and
-+ * zero'ing out the old data in the buffer.
-+ */
-+ if (offs == 0) {
-+ buf->dtb_flags &= ~DTRACEBUF_WRAPPED;
-+ buf->dtb_offset = 0;
-+ woffs = total;
-+
-+ while (woffs < buf->dtb_size)
-+ tomax[woffs++] = 0;
-+ }
-+
-+ woffs = 0;
-+ break;
-+ }
-+
-+ woffs += size;
-+ }
-+
-+ /*
-+ * We have a wrapped offset. It may be that the wrapped offset
-+ * has become zero -- that's okay.
-+ */
-+ buf->dtb_xamot_offset = woffs;
-+ }
-+
-+out:
-+ /*
-+ * Now we can plow the buffer with any necessary padding.
-+ */
-+ while (offs & (align - 1)) {
-+ /*
-+ * Assert that our alignment is off by a number which
-+ * is itself sizeof(uint32_t) aligned.
-+ */
-+ ASSERT(!((align - (offs & (align - 1))) &
-+ (sizeof(uint32_t) - 1)));
-+ DTRACE_STORE(uint32_t, tomax, offs, DTRACE_EPIDNONE);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- EPIDNONE "
-+ "(from %s::%d)\n",
-+ buf, offs, offs + sizeof(uint32_t) - 1,
-+ __func__, __LINE__);
-+ offs += sizeof(uint32_t);
-+ }
-+
-+ if (buf->dtb_flags & DTRACEBUF_FILL) {
-+ if (offs + needed > buf->dtb_size - state->dts_reserve) {
-+ buf->dtb_flags |= DTRACEBUF_FULL;
-+ return -1;
-+ }
-+ }
-+
-+ if (mstate == NULL) {
-+ dt_dbg_buf(" Reserve: %p[%ld .. %ld]\n",
-+ buf, offs, offs + needed - 1);
-+ return offs;
-+ }
-+
-+ /*
-+ * For ring buffers and fill buffers, the scratch space is always
-+ * the inactive buffer.
-+ */
-+ mstate->dtms_scratch_base = (uintptr_t)buf->dtb_xamot;
-+ mstate->dtms_scratch_size = buf->dtb_size;
-+ mstate->dtms_scratch_ptr = mstate->dtms_scratch_base;
-+
-+ dt_dbg_buf(" Reserve: %p[%ld .. %ld]\n",
-+ buf, offs, offs + needed - 1);
-+ return offs;
-+}
-+
-+void dtrace_buffer_polish(struct dtrace_buffer *buf)
-+{
-+ ASSERT(buf->dtb_flags & DTRACEBUF_RING);
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (!(buf->dtb_flags & DTRACEBUF_WRAPPED))
-+ return;
-+
-+ /*
-+ * We need to polish the ring buffer. There are three cases:
-+ *
-+ * - The first (and presumably most common) is that there is no gap
-+ * between the buffer offset and the wrapped offset. In this case,
-+ * there is nothing in the buffer that isn't valid data; we can
-+ * mark the buffer as polished and return.
-+ *
-+ * - The second (less common than the first but still more common
-+ * than the third) is that there is a gap between the buffer offset
-+ * and the wrapped offset, and the wrapped offset is larger than the
-+ * buffer offset. This can happen because of an alignment issue, or
-+ * can happen because of a call to dtrace_buffer_reserve() that
-+ * didn't subsequently consume the buffer space. In this case,
-+ * we need to zero the data from the buffer offset to the wrapped
-+ * offset.
-+ *
-+ * - The third (and least common) is that there is a gap between the
-+ * buffer offset and the wrapped offset, but the wrapped offset is
-+ * _less_ than the buffer offset. This can only happen because a
-+ * call to dtrace_buffer_reserve() induced a wrap, but the space
-+ * was not subsequently consumed. In this case, we need to zero the
-+ * space from the offset to the end of the buffer _and_ from the
-+ * top of the buffer to the wrapped offset.
-+ */
-+ if (buf->dtb_offset < buf->dtb_xamot_offset)
-+ memset(buf->dtb_tomax + buf->dtb_offset, 0,
-+ buf->dtb_xamot_offset - buf->dtb_offset);
-+
-+ if (buf->dtb_offset > buf->dtb_xamot_offset) {
-+ memset(buf->dtb_tomax + buf->dtb_offset, 0,
-+ buf->dtb_size - buf->dtb_offset);
-+ memset(buf->dtb_tomax, 0, buf->dtb_xamot_offset);
-+ }
-+}
-+
-+void dtrace_buffer_free(struct dtrace_buffer *bufs)
-+{
-+ int cpu;
-+
-+ for_each_online_cpu(cpu) {
-+ struct dtrace_buffer *buf = &bufs[cpu];
-+
-+ if (buf->dtb_tomax == NULL) {
-+ ASSERT(buf->dtb_xamot == NULL);
-+ ASSERT(buf->dtb_size == 0);
-+
-+ continue;
-+ }
-+
-+ if (buf->dtb_xamot != NULL) {
-+ ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH));
-+
-+ vfree(buf->dtb_xamot);
-+ buf->dtb_xamot = NULL;
-+ }
-+
-+ vfree(buf->dtb_tomax);
-+ buf->dtb_size = 0;
-+ buf->dtb_tomax = NULL;
-+ }
-+}
-diff --git a/dtrace/dtrace_debug.h b/dtrace/dtrace_debug.h
-new file mode 100644
-index 000000000000..a55fd1a0436f
---- /dev/null
-+++ b/dtrace/dtrace_debug.h
-@@ -0,0 +1,118 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _DTRACE_DEBUG_H_
-+#define _DTRACE_DEBUG_H_
-+
-+#ifdef CONFIG_DT_DEBUG
-+
-+/*
-+ * Enable all output and use dynamic debug when supported.
-+ */
-+# ifdef CONFIG_DYNAMIC_DEBUG
-+
-+# define DT_DBG_AGG
-+# define DT_DBG_BUF
-+# define DT_DBG_DIF
-+# define DT_DBG_DOF
-+# define DT_DBG_ENABLE
-+# define DT_DBG_IOCTL
-+# define DT_DBG_PROBE
-+# define DT_DBG_PROVIDER
-+
-+# define dt_dbg_print(fmt, ...) pr_debug(fmt, ## __VA_ARGS__)
-+
-+# else /* CONFIG_DYNAMIC_DEBUG */
-+
-+# undef DT_DBG_AGG
-+# undef DT_DBG_BUF
-+# undef DT_DBG_DIF
-+# undef DT_DBG_DOF
-+# undef DT_DBG_ENABLE
-+# undef DT_DBG_IOCTL
-+# undef DT_DBG_PROBE
-+# undef DT_DBG_PROVIDER
-+
-+# define dt_dbg_print(fmt, ...) pr_info(fmt, ## __VA_ARGS__)
-+
-+# endif /* CONFIG_DYNAMIC_DEBUG */
-+
-+#else /* CONFIG_DT_DEBUG */
-+
-+# undef DT_DBG_AGG
-+# undef DT_DBG_BUF
-+# undef DT_DBG_DIF
-+# undef DT_DBG_DOF
-+# undef DT_DBG_ENABLE
-+# undef DT_DBG_IOCTL
-+# undef DT_DBG_PROBE
-+# undef DT_DBG_PROVIDER
-+
-+#endif /* CONFIG_DT_DEBUG */
-+
-+/*
-+ * Here are the actual actions for the various debug cases.
-+ */
-+#ifdef DT_DBG_AGG
-+# define dt_dbg_agg(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_agg(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_BUF
-+# define dt_dbg_buf(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_buf(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_DIF
-+# define dt_dbg_dif(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_dif(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_DOF
-+# define dt_dbg_dof(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_dof(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_ENABLE
-+# define dt_dbg_enable(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_enable(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_IOCTL
-+# define dt_dbg_ioctl(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_ioctl(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_PROBE
-+# define dt_dbg_probe(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_probe(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_PROVIDER
-+# define dt_dbg_prov(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_prov(fmt, ...)
-+#endif
-+
-+#endif /* _DTRACE_DEBUG_H_ */
-diff --git a/dtrace/dtrace_dev.c b/dtrace/dtrace_dev.c
-new file mode 100644
-index 000000000000..0e52c936b9e0
---- /dev/null
-+++ b/dtrace/dtrace_dev.c
-@@ -0,0 +1,1599 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_dev.c
-+ * DESCRIPTION: DTrace - Framework device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/delay.h>
-+#include <dtrace/types.h>
-+#include <linux/dtrace/ioctl.h>
-+#include <linux/fs.h>
-+#include <linux/jiffies.h>
-+#include <linux/kernel.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <linux/uaccess.h>
-+
-+#include "ctf_api.h"
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+
-+extern char *dtrace_helptrace_buffer;
-+extern int dtrace_helptrace_bufsize;
-+extern int dtrace_helptrace_enabled;
-+
-+int dtrace_opens;
-+int dtrace_err_verbose;
-+
-+struct dtrace_pops dtrace_provider_ops = {
-+ (void (*)(void *, const struct dtrace_probedesc *))dtrace_nullop,
-+ (void (*)(void *, struct module *))dtrace_nullop,
-+ (int (*)(void *, dtrace_id_t, void *))dtrace_enable_nullop,
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
-+ NULL,
-+ NULL,
-+ NULL,
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
-+ (void (*)(void *, struct module *))dtrace_nullop,
-+};
-+
-+static size_t dtrace_retain_max = 1024;
-+
-+struct dtrace_toxrange *dtrace_toxrange;
-+int dtrace_toxranges;
-+static int dtrace_toxranges_max;
-+
-+struct kmem_cache *dtrace_state_cachep;
-+
-+struct user_namespace *init_user_namespace;
-+
-+static struct dtrace_pattr dtrace_provider_attr = {
-+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
-+};
-+
-+DEFINE_MUTEX(dtrace_lock);
-+
-+void dtrace_nullop(void)
-+{
-+}
-+
-+int dtrace_enable_nullop(void)
-+{
-+ return 0;
-+}
-+
-+
-+#ifdef CONFIG_DT_DEBUG
-+static void dtrace_ioctl_sizes(void)
-+{
-+#define DBG_PRINT(x) dt_dbg_ioctl("Size of %s: %lx\n", #x, sizeof(x))
-+ DBG_PRINT(struct dtrace_providerdesc);
-+ DBG_PRINT(struct dtrace_probedesc);
-+ DBG_PRINT(struct dtrace_bufdesc);
-+ DBG_PRINT(struct dtrace_eprobedesc);
-+ DBG_PRINT(struct dtrace_argdesc);
-+ DBG_PRINT(struct dtrace_conf);
-+ DBG_PRINT(struct dtrace_status);
-+ DBG_PRINT(processorid_t);
-+ DBG_PRINT(struct dtrace_aggdesc);
-+ DBG_PRINT(struct dtrace_fmtdesc);
-+ DBG_PRINT(struct dof_hdr);
-+#undef DBG_PRINT
-+}
-+
-+#endif
-+
-+static int dtrace_open(struct inode *inode, struct file *file)
-+{
-+ struct dtrace_state *state;
-+ uint32_t priv;
-+ kuid_t uid;
-+
-+ dtrace_cred2priv(file->f_cred, &priv, &uid);
-+ if (priv == DTRACE_PRIV_NONE)
-+ return -EACCES;
-+
-+#ifdef CONFIG_DT_DEBUG
-+ dtrace_ioctl_sizes();
-+#endif
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ dtrace_probe_provide(NULL, NULL);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ /*
-+ * Do not let a consumer continue if it is not possible to enable
-+ * DTrace.
-+ */
-+ if (dtrace_enable() != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+ return -EBUSY;
-+ }
-+
-+ dtrace_opens++;
-+ dtrace_membar_producer();
-+
-+ state = dtrace_state_create(file);
-+ mutex_unlock(&cpu_lock);
-+
-+ if (state == NULL) {
-+ if (--dtrace_opens == 0 && dtrace_anon.dta_enabling == NULL)
-+ dtrace_disable();
-+ mutex_unlock(&dtrace_lock);
-+
-+ return -EAGAIN;
-+ }
-+
-+ file->private_data = state;
-+ mutex_unlock(&dtrace_lock);
-+
-+ return 0;
-+}
-+
-+static long dtrace_ioctl(struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ struct dtrace_state *state;
-+ int rval;
-+ void __user *argp = (void __user *)arg;
-+
-+ state = (struct dtrace_state *) file->private_data;
-+ if (state->dts_anon) {
-+ ASSERT(dtrace_anon.dta_state == NULL);
-+ state = state->dts_anon;
-+ }
-+
-+ switch (cmd) {
-+ case DTRACEIOC_PROVIDER: {
-+ struct dtrace_providerdesc pvd;
-+ struct dtrace_provider *pvp;
-+
-+ dt_dbg_ioctl("IOCTL PROVIDER (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&pvd, argp, sizeof(pvd)) != 0)
-+ return -EFAULT;
-+
-+ pvd.dtvd_name[DTRACE_PROVNAMELEN - 1] = '\0';
-+ mutex_lock(&dtrace_provider_lock);
-+
-+ for (pvp = dtrace_provider; pvp != NULL; pvp = pvp->dtpv_next) {
-+ if (strcmp(pvp->dtpv_name, pvd.dtvd_name) == 0)
-+ break;
-+ }
-+
-+ mutex_unlock(&dtrace_provider_lock);
-+
-+ dt_dbg_ioctl(" Provider '%s' %sfound\n",
-+ pvd.dtvd_name, pvp ? "" : "not ");
-+ if (pvp == NULL)
-+ return -ESRCH;
-+
-+ memcpy(&pvd.dtvd_priv, &pvp->dtpv_priv,
-+ sizeof(struct dtrace_ppriv));
-+ memcpy(&pvd.dtvd_attr, &pvp->dtpv_attr,
-+ sizeof(struct dtrace_pattr));
-+
-+ if (copy_to_user(argp, &pvd, sizeof(pvd)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_EPROBE: {
-+ struct dtrace_eprobedesc epdesc;
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_action *act;
-+ void *buf;
-+ size_t size;
-+ uint8_t *dest;
-+ int nrecs;
-+
-+ dt_dbg_ioctl("IOCTL EPROBE (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&epdesc, argp, sizeof(epdesc)) != 0)
-+ return -EFAULT;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ ecb = dtrace_epid2ecb(state, epdesc.dtepd_epid);
-+ if (ecb == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+
-+ if (ecb->dte_probe == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+
-+ epdesc.dtepd_probeid = ecb->dte_probe->dtpr_id;
-+ epdesc.dtepd_uarg = ecb->dte_uarg;
-+ epdesc.dtepd_size = ecb->dte_size;
-+
-+ nrecs = epdesc.dtepd_nrecs;
-+ epdesc.dtepd_nrecs = 0;
-+ for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
-+ if (DTRACEACT_ISAGG(act->dta_kind) || act->dta_intuple)
-+ continue;
-+
-+ epdesc.dtepd_nrecs++;
-+ }
-+
-+ /*
-+ * Now that we have the size, we need to allocate a temporary
-+ * buffer in which to store the complete description. We need
-+ * the temporary buffer to be able to drop dtrace_lock()
-+ * across the copy_to_user(), below.
-+ */
-+ size = sizeof(struct dtrace_eprobedesc) +
-+ (epdesc.dtepd_nrecs * sizeof(struct dtrace_recdesc));
-+
-+ buf = vmalloc(size);
-+ if (buf == NULL)
-+ return -ENOMEM;
-+
-+ dest = buf;
-+ memcpy(dest, &epdesc, sizeof(epdesc));
-+ dest += offsetof(struct dtrace_eprobedesc, dtepd_rec[0]);
-+
-+ for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
-+ if (DTRACEACT_ISAGG(act->dta_kind) || act->dta_intuple)
-+ continue;
-+
-+ if (nrecs-- == 0)
-+ break;
-+
-+ memcpy(dest, &act->dta_rec,
-+ sizeof(struct dtrace_recdesc));
-+ dest += sizeof(struct dtrace_recdesc);
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (copy_to_user(argp, buf,
-+ (uintptr_t)(dest - (uint8_t *)buf)) != 0) {
-+ vfree(buf);
-+ return -EFAULT;
-+ }
-+
-+ vfree(buf);
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_AGGDESC: {
-+ struct dtrace_aggdesc aggdesc;
-+ struct dtrace_action *act;
-+ struct dtrace_aggregation *agg;
-+ int nrecs;
-+ uint32_t offs;
-+ struct dtrace_recdesc *lrec;
-+ void *buf;
-+ size_t size;
-+ uint8_t *dest;
-+
-+ dt_dbg_ioctl("IOCTL AGGDESC (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&aggdesc, argp, sizeof(aggdesc)) != 0)
-+ return -EFAULT;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ agg = dtrace_aggid2agg(state, aggdesc.dtagd_id);
-+ if (agg == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+
-+ aggdesc.dtagd_epid = agg->dtag_ecb->dte_epid;
-+
-+ nrecs = aggdesc.dtagd_nrecs;
-+ aggdesc.dtagd_nrecs = 0;
-+
-+ offs = agg->dtag_base;
-+ lrec = &agg->dtag_action.dta_rec;
-+ aggdesc.dtagd_size = lrec->dtrd_offset + lrec->dtrd_size -
-+ offs;
-+
-+ for (act = agg->dtag_first; ; act = act->dta_next) {
-+ ASSERT(act->dta_intuple ||
-+ DTRACEACT_ISAGG(act->dta_kind));
-+
-+ /*
-+ * If this action has a record size of zero, it
-+ * denotes an argument to the aggregating action.
-+ * Because the presence of this record doesn't (or
-+ * shouldn't) affect the way the data is interpreted,
-+ * we don't copy it out to save user-level the
-+ * confusion of dealing with a zero-length record.
-+ */
-+ if (act->dta_rec.dtrd_size == 0) {
-+ ASSERT(agg->dtag_hasarg);
-+ continue;
-+ }
-+
-+ aggdesc.dtagd_nrecs++;
-+
-+ if (act == &agg->dtag_action)
-+ break;
-+ }
-+
-+ /*
-+ * Now that we have the size, we need to allocate a temporary
-+ * buffer in which to store the complete description. We need
-+ * the temporary buffer to be able to drop dtrace_lock()
-+ * across the copyout(), below.
-+ */
-+ size = sizeof(struct dtrace_aggdesc) +
-+ (aggdesc.dtagd_nrecs * sizeof(struct dtrace_recdesc));
-+
-+ buf = vmalloc(size);
-+ if (buf == NULL)
-+ return -ENOMEM;
-+
-+ dest = buf;
-+ memcpy(dest, &aggdesc, sizeof(aggdesc));
-+ dest += offsetof(struct dtrace_aggdesc, dtagd_rec[0]);
-+
-+ for (act = agg->dtag_first; ; act = act->dta_next) {
-+ struct dtrace_recdesc rec = act->dta_rec;
-+
-+ /*
-+ * See the comment in the above loop for why we pass
-+ * over zero-length records.
-+ */
-+ if (rec.dtrd_size == 0) {
-+ ASSERT(agg->dtag_hasarg);
-+ continue;
-+ }
-+
-+ if (nrecs-- == 0)
-+ break;
-+
-+ rec.dtrd_offset -= offs;
-+ memcpy(dest, &rec, sizeof(rec));
-+ dest += sizeof(struct dtrace_recdesc);
-+
-+ if (act == &agg->dtag_action)
-+ break;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (copy_to_user(argp, buf,
-+ (uintptr_t)(dest - (uint8_t *)buf)) != 0) {
-+ vfree(buf);
-+ return -EFAULT;
-+ }
-+
-+ vfree(buf);
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_ENABLE: {
-+ struct dof_hdr *dof;
-+ struct dtrace_enabling *enab = NULL;
-+ struct dtrace_vstate *vstate;
-+ int err = 0;
-+ int rv;
-+
-+ dt_dbg_ioctl("IOCTL ENABLE (cmd %#x), argp %p\n", cmd, argp);
-+
-+ rv = 0;
-+
-+ /*
-+ * If a NULL argument has been passed, we take this as our
-+ * cue to reevaluate our enablings.
-+ */
-+ if (argp == NULL) {
-+ dtrace_enabling_matchall();
-+
-+ return 0;
-+ }
-+
-+ dof = dtrace_dof_copyin(argp, &rval);
-+ if (dof == NULL)
-+ return rval;
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&dtrace_lock);
-+ vstate = &state->dts_vstate;
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+ dtrace_dof_destroy(dof);
-+ return -EBUSY;
-+ }
-+
-+ if (dtrace_dof_slurp(dof, vstate, file->f_cred, &enab, 0,
-+ TRUE) != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+ dtrace_dof_destroy(dof);
-+ return -EINVAL;
-+ }
-+
-+ rval = dtrace_dof_options(dof, state);
-+ if (rval != 0) {
-+ dtrace_enabling_destroy(enab);
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+ dtrace_dof_destroy(dof);
-+ return rval;
-+ }
-+
-+ err = dtrace_enabling_match(enab, &rv);
-+ if (err == 0)
-+ err = dtrace_enabling_retain(enab);
-+ else
-+ dtrace_enabling_destroy(enab);
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+ dtrace_dof_destroy(dof);
-+
-+ return err == 0 ? rv : err;
-+ }
-+
-+ case DTRACEIOC_REPLICATE: {
-+ struct dtrace_repldesc desc;
-+ struct dtrace_probedesc *match = &desc.dtrpd_match;
-+ struct dtrace_probedesc *create = &desc.dtrpd_create;
-+ int err;
-+
-+ dt_dbg_ioctl("IOCTL REPLICATE (cmd %#x), argp %p\n",
-+ cmd, argp);
-+
-+ if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ match->dtpd_provider[DTRACE_PROVNAMELEN - 1] = '\0';
-+ match->dtpd_mod[DTRACE_MODNAMELEN - 1] = '\0';
-+ match->dtpd_func[DTRACE_FUNCNAMELEN - 1] = '\0';
-+ match->dtpd_name[DTRACE_NAMELEN - 1] = '\0';
-+
-+ create->dtpd_provider[DTRACE_PROVNAMELEN - 1] = '\0';
-+ create->dtpd_mod[DTRACE_MODNAMELEN - 1] = '\0';
-+ create->dtpd_func[DTRACE_FUNCNAMELEN - 1] = '\0';
-+ create->dtpd_name[DTRACE_NAMELEN - 1] = '\0';
-+
-+ mutex_lock(&dtrace_lock);
-+ err = dtrace_enabling_replicate(state, match, create);
-+ mutex_unlock(&dtrace_lock);
-+
-+ return err;
-+ }
-+
-+ case DTRACEIOC_PROBEMATCH:
-+ case DTRACEIOC_PROBES: {
-+ int id;
-+ struct dtrace_probe *probe = NULL;
-+ struct dtrace_probedesc desc;
-+ struct dtrace_probekey pkey;
-+ uint32_t priv;
-+ kuid_t uid;
-+
-+ dt_dbg_ioctl("IOCTL %s (cmd %#x), argp %p\n",
-+ cmd == DTRACEIOC_PROBES ? "PROBES"
-+ : "PROBEMATCH",
-+ cmd, argp);
-+
-+ if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ desc.dtpd_provider[DTRACE_PROVNAMELEN - 1] = '\0';
-+ desc.dtpd_mod[DTRACE_MODNAMELEN - 1] = '\0';
-+ desc.dtpd_func[DTRACE_FUNCNAMELEN - 1] = '\0';
-+ desc.dtpd_name[DTRACE_NAMELEN - 1] = '\0';
-+ dt_dbg_ioctl(" Probe ID %d %s:%s:%s:%s\n",
-+ desc.dtpd_id, desc.dtpd_provider, desc.dtpd_mod,
-+ desc.dtpd_func, desc.dtpd_name);
-+
-+ /*
-+ * Before we attempt to match this probe, we want to give
-+ * all providers the opportunity to provide it.
-+ */
-+ if (desc.dtpd_id == DTRACE_IDNONE) {
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ dtrace_probe_provide(&desc, NULL);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+ }
-+
-+ if (cmd == DTRACEIOC_PROBEMATCH) {
-+ dtrace_probekey(&desc, &pkey);
-+ pkey.dtpk_id = DTRACE_IDNONE;
-+ }
-+
-+ dtrace_cred2priv(file->f_cred, &priv, &uid);
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ id = desc.dtpd_id;
-+ if (cmd == DTRACEIOC_PROBEMATCH) {
-+ int m = 0;
-+
-+ while ((probe = dtrace_probe_get_next(&id))
-+ != NULL) {
-+ m = dtrace_match_probe(probe, &pkey, priv, uid);
-+ if (m)
-+ break;
-+
-+ id++;
-+ }
-+
-+ if (m < 0) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+ } else {
-+ while ((probe = dtrace_probe_get_next(&id))
-+ != NULL) {
-+ if (dtrace_match_priv(probe, priv, uid))
-+ break;
-+
-+ id++;
-+ }
-+ }
-+
-+ if (probe == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ return -ESRCH;
-+ }
-+
-+ dtrace_probe_description(probe, &desc);
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (copy_to_user(argp, &desc, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_PROBEARG: {
-+ struct dtrace_argdesc desc;
-+ struct dtrace_probe *probe;
-+ struct dtrace_provider *prov;
-+
-+ dt_dbg_ioctl("IOCTL PROBEARG (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ if (desc.dtargd_id == DTRACE_IDNONE)
-+ return -EINVAL;
-+
-+ if (desc.dtargd_ndx == DTRACE_ARGNONE)
-+ return -EINVAL;
-+
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ probe = dtrace_probe_lookup_id(desc.dtargd_id);
-+ if (probe == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ return -EINVAL;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ prov = probe->dtpr_provider;
-+
-+ if (prov->dtpv_pops.dtps_getargdesc == NULL) {
-+ /*
-+ * There isn't any typed information for this probe.
-+ * Set the argument number to DTRACE_ARGNONE.
-+ */
-+ desc.dtargd_ndx = DTRACE_ARGNONE;
-+ } else {
-+ desc.dtargd_native[0] = '\0';
-+ desc.dtargd_xlate[0] = '\0';
-+ desc.dtargd_mapping = desc.dtargd_ndx;
-+
-+ prov->dtpv_pops.dtps_getargdesc(
-+ prov->dtpv_arg, probe->dtpr_id,
-+ probe->dtpr_arg, &desc);
-+ }
-+
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ if (copy_to_user(argp, &desc, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_GO: {
-+ processorid_t cpuid;
-+
-+ dt_dbg_ioctl("IOCTL GO (cmd %#x), argp %p\n", cmd, argp);
-+
-+ rval = dtrace_state_go(state, &cpuid);
-+
-+ if (rval != 0)
-+ return rval;
-+
-+ if (copy_to_user(argp, &cpuid, sizeof(cpuid)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_STOP: {
-+ processorid_t cpuid;
-+
-+ dt_dbg_ioctl("IOCTL STOP (cmd %#x), argp %p\n", cmd, argp);
-+
-+ mutex_lock(&dtrace_lock);
-+ rval = dtrace_state_stop(state, &cpuid);
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (rval != 0)
-+ return rval;
-+
-+ if (copy_to_user(argp, &cpuid, sizeof(cpuid)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_DOFGET: {
-+ struct dof_hdr hdr, *dof;
-+ uint64_t len;
-+
-+ dt_dbg_ioctl("IOCTL DOFGET (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&hdr, argp, sizeof(hdr)) != 0)
-+ return -EFAULT;
-+
-+ mutex_lock(&dtrace_lock);
-+ dof = dtrace_dof_create(state);
-+ mutex_unlock(&dtrace_lock);
-+ if (dof == NULL)
-+ return -ENOMEM;
-+
-+ len = min(hdr.dofh_loadsz, dof->dofh_loadsz);
-+ rval = copy_to_user(argp, dof, len);
-+ dtrace_dof_destroy(dof);
-+
-+ return rval == 0 ? 0 : -EFAULT;
-+ }
-+
-+ case DTRACEIOC_AGGSNAP:
-+ case DTRACEIOC_BUFSNAP: {
-+ struct dtrace_bufdesc desc;
-+ caddr_t cached;
-+ struct dtrace_buffer *buf;
-+
-+ dt_dbg_ioctl("IOCTL %s (cmd %#x), argp %p\n",
-+ cmd == DTRACEIOC_AGGSNAP ? "AGGSNAP"
-+ : "BUFSNAP",
-+ cmd, argp);
-+
-+ if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ if (desc.dtbd_cpu < 0 || desc.dtbd_cpu >= NR_CPUS)
-+ return -EINVAL;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ if (cmd == DTRACEIOC_BUFSNAP)
-+ buf = &state->dts_buffer[desc.dtbd_cpu];
-+ else
-+ buf = &state->dts_aggbuffer[desc.dtbd_cpu];
-+
-+ if (buf->dtb_flags & (DTRACEBUF_RING | DTRACEBUF_FILL)) {
-+ size_t sz = buf->dtb_offset;
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_STOPPED) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EBUSY;
-+ }
-+
-+ /*
-+ * If this buffer has already been consumed, we're
-+ * going to indicate that there's nothing left here
-+ * to consume.
-+ */
-+ if (buf->dtb_flags & DTRACEBUF_CONSUMED) {
-+ mutex_unlock(&dtrace_lock);
-+
-+ desc.dtbd_size = 0;
-+ desc.dtbd_drops = 0;
-+ desc.dtbd_errors = 0;
-+ desc.dtbd_oldest = 0;
-+ sz = sizeof(desc);
-+
-+ if (copy_to_user(argp, &desc, sz) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ /*
-+ * If this is a ring buffer that has wrapped, we want
-+ * to copy the whole thing out.
-+ */
-+ if (buf->dtb_flags & DTRACEBUF_WRAPPED) {
-+ dtrace_buffer_polish(buf);
-+ sz = buf->dtb_size;
-+ }
-+
-+ if (copy_to_user(desc.dtbd_data, buf->dtb_tomax,
-+ sz) != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EFAULT;
-+ }
-+
-+ desc.dtbd_size = sz;
-+ desc.dtbd_drops = buf->dtb_drops;
-+ desc.dtbd_errors = buf->dtb_errors;
-+ desc.dtbd_oldest = buf->dtb_xamot_offset;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (copy_to_user(argp, &desc, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ buf->dtb_flags |= DTRACEBUF_CONSUMED;
-+
-+ return 0;
-+ }
-+
-+ if (buf->dtb_tomax == NULL) {
-+ ASSERT(buf->dtb_xamot == NULL);
-+ mutex_unlock(&dtrace_lock);
-+ return -ENOENT;
-+ }
-+
-+ cached = buf->dtb_tomax;
-+
-+ dtrace_xcall(desc.dtbd_cpu,
-+ (dtrace_xcall_t)dtrace_buffer_switch, buf);
-+
-+ state->dts_errors += buf->dtb_xamot_errors;
-+
-+ /*
-+ * If the buffers did not actually switch, then the cross call
-+ * did not take place -- presumably because the given CPU is
-+ * not in the ready set. If this is the case, we'll return
-+ * ENOENT.
-+ */
-+ if (buf->dtb_tomax == cached) {
-+ ASSERT(buf->dtb_xamot != cached);
-+ mutex_unlock(&dtrace_lock);
-+ return -ENOENT;
-+ }
-+
-+ ASSERT(cached == buf->dtb_xamot);
-+
-+ /*
-+ * We have our snapshot; now copy it out.
-+ */
-+ if (copy_to_user(desc.dtbd_data, buf->dtb_xamot,
-+ buf->dtb_xamot_offset) != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EFAULT;
-+ }
-+
-+ desc.dtbd_size = buf->dtb_xamot_offset;
-+ desc.dtbd_drops = buf->dtb_xamot_drops;
-+ desc.dtbd_errors = buf->dtb_xamot_errors;
-+ desc.dtbd_oldest = 0;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ /*
-+ * Finally, copy out the buffer description.
-+ */
-+ if (copy_to_user(argp, &desc, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_CONF: {
-+ struct dtrace_conf conf;
-+
-+ dt_dbg_ioctl("IOCTL CONF (cmd %#x), argp %p\n", cmd, argp);
-+
-+ memset(&conf, 0, sizeof(conf));
-+ conf.dtc_difversion = DIF_VERSION;
-+ conf.dtc_difintregs = DIF_DIR_NREGS;
-+ conf.dtc_diftupregs = DIF_DTR_NREGS;
-+ conf.dtc_ctfmodel = CTF_MODEL_NATIVE;
-+ conf.dtc_maxbufs = nr_cpu_ids;
-+
-+ if (copy_to_user(argp, &conf, sizeof(conf)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_STATUS: {
-+ struct dtrace_status stat;
-+ struct dtrace_dstate *dstate;
-+ int i, j;
-+ uint64_t nerrs;
-+
-+ dt_dbg_ioctl("IOCTL STATUS (cmd %#x), argp %p\n", cmd, argp);
-+
-+ /*
-+ * See the comment in dtrace_state_deadman() for the reason
-+ * for setting dts_laststatus to UINT64_MAX before setting
-+ * it to the correct value.
-+ */
-+ state->dts_laststatus = ns_to_ktime(UINT64_MAX);
-+ dtrace_membar_producer();
-+ state->dts_laststatus = dtrace_gethrtime();
-+
-+ memset(&stat, 0, sizeof(stat));
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ if (state->dts_activity == DTRACE_ACTIVITY_INACTIVE) {
-+ mutex_unlock(&dtrace_lock);
-+ return -ENOENT;
-+ }
-+
-+ if (state->dts_activity == DTRACE_ACTIVITY_DRAINING)
-+ stat.dtst_exiting = 1;
-+
-+ nerrs = state->dts_errors;
-+ dstate = &state->dts_vstate.dtvs_dynvars;
-+
-+ for (i = 0; i < NR_CPUS; i++) {
-+ struct dtrace_dstate_percpu *dcpu;
-+
-+ dcpu = &dstate->dtds_percpu[i];
-+ stat.dtst_dyndrops += dcpu->dtdsc_drops;
-+ stat.dtst_dyndrops_dirty += dcpu->dtdsc_dirty_drops;
-+ stat.dtst_dyndrops_rinsing += dcpu->dtdsc_rinsing_drops;
-+
-+ if (state->dts_buffer[i].dtb_flags & DTRACEBUF_FULL)
-+ stat.dtst_filled++;
-+
-+ nerrs += state->dts_buffer[i].dtb_errors;
-+
-+ for (j = 0; j < state->dts_nspeculations; j++) {
-+ struct dtrace_speculation *spec;
-+ struct dtrace_buffer *buf;
-+
-+ spec = &state->dts_speculations[j];
-+ buf = &spec->dtsp_buffer[i];
-+ stat.dtst_specdrops += buf->dtb_xamot_drops;
-+ }
-+ }
-+
-+ stat.dtst_specdrops_busy = state->dts_speculations_busy;
-+ stat.dtst_specdrops_unavail = state->dts_speculations_unavail;
-+ stat.dtst_stkstroverflows = state->dts_stkstroverflows;
-+ stat.dtst_dblerrors = state->dts_dblerrors;
-+ stat.dtst_killed = (state->dts_activity ==
-+ DTRACE_ACTIVITY_KILLED);
-+ stat.dtst_errors = nerrs;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (copy_to_user(argp, &stat, sizeof(stat)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_FORMAT: {
-+ struct dtrace_fmtdesc fmt;
-+ char *str;
-+ int len;
-+
-+ dt_dbg_ioctl("IOCTL FORMAT (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&fmt, argp, sizeof(fmt)) != 0)
-+ return -EFAULT;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ if (fmt.dtfd_format == 0 ||
-+ fmt.dtfd_format > state->dts_nformats) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * Format strings are allocated contiguously and they are
-+ * never freed; if a format index is less than the number
-+ * of formats, we can assert that the format map is non-NULL
-+ * and that the format for the specified index is non-NULL.
-+ */
-+ ASSERT(state->dts_formats != NULL);
-+ str = state->dts_formats[fmt.dtfd_format - 1];
-+ ASSERT(str != NULL);
-+
-+ len = strlen(str) + 1;
-+
-+ if (len > fmt.dtfd_length) {
-+ fmt.dtfd_length = len;
-+
-+ if (copy_to_user(argp, &fmt, sizeof(fmt)) != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+ } else {
-+ if (copy_to_user(fmt.dtfd_string, str, len) != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ return 0;
-+ }
-+
-+ default:
-+ dt_dbg_ioctl("IOCTL ??? (cmd %#x), argp %p\n",
-+ cmd, argp);
-+ break;
-+ }
-+
-+ return -ENOTTY;
-+}
-+
-+static int dtrace_close(struct inode *inode, struct file *file)
-+{
-+ struct dtrace_state *state = file->private_data;
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ /*
-+ * If there is anonymous state, destroy that first.
-+ */
-+ if (state->dts_anon) {
-+ ASSERT(dtrace_anon.dta_state == NULL);
-+ dtrace_state_destroy(state->dts_anon);
-+ }
-+
-+ dtrace_state_destroy(state);
-+ ASSERT(dtrace_opens > 0);
-+
-+ if (--dtrace_opens == 0 && dtrace_anon.dta_enabling == NULL)
-+ dtrace_disable();
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+
-+ return 0;
-+}
-+
-+static int dtrace_helper_open(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static long dtrace_helper_ioctl(struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ int rval;
-+ struct dof_helper help, *dhp = NULL;
-+ void __user *argp = (void __user *)arg;
-+
-+ switch (cmd) {
-+ case DTRACEHIOC_ADDDOF:
-+ dt_dbg_ioctl("Helper IOCTL ADDDOF (cmd %#x), argp %p\n",
-+ cmd, argp);
-+
-+ if (copy_from_user(&help, argp, sizeof(help)) != 0) {
-+ dtrace_dof_error(NULL, "failed to copy DOF helper");
-+ return -EFAULT;
-+ }
-+
-+ dhp = &help;
-+ argp = (void __user *)help.dofhp_dof;
-+
-+ /* fallthrough */
-+
-+ case DTRACEHIOC_ADD: {
-+ struct dof_hdr *dof = dtrace_dof_copyin(argp, &rval);
-+
-+ if (dof == NULL)
-+ return rval;
-+
-+ if (cmd == DTRACEHIOC_ADD)
-+ dt_dbg_ioctl("Helper IOCTL ADD (cmd %#x), argp %p\n",
-+ cmd, argp);
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ /*
-+ * The dtrace_helper_slurp() routine takes responsibility for
-+ * the dof -- it may free it now, or it may save it and free it
-+ * later.
-+ */
-+ rval = dtrace_helper_slurp(dof, dhp);
-+ if (rval == -1)
-+ rval = -EINVAL;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ dt_dbg_ioctl("Helper IOCTL %s returning %d\n",
-+ cmd == DTRACEHIOC_ADD ? "ADD"
-+ : "ADDDOF",
-+ rval);
-+
-+ return rval;
-+ }
-+
-+ case DTRACEHIOC_REMOVE:
-+ dt_dbg_ioctl("Helper IOCTL REMOVE (cmd %#x), argp %p\n",
-+ cmd, argp);
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ rval = dtrace_helper_destroygen((uintptr_t)argp);
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ dt_dbg_ioctl("Helper IOCTL REMOVE returning %d\n", rval);
-+
-+ return rval;
-+ default:
-+ dt_dbg_ioctl("Helper IOCTL ??? (cmd %#x), argp %p\n",
-+ cmd, argp);
-+ break;
-+ }
-+
-+ return -ENOTTY;
-+}
-+
-+static int dtrace_helper_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations dtrace_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = dtrace_ioctl,
-+ .open = dtrace_open,
-+ .release = dtrace_close,
-+};
-+
-+static const struct file_operations helper_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = dtrace_helper_ioctl,
-+ .compat_ioctl = dtrace_helper_ioctl,
-+ .open = dtrace_helper_open,
-+ .release = dtrace_helper_close,
-+};
-+
-+static struct miscdevice dtrace_dev = {
-+ .minor = DT_DEV_DTRACE_MINOR,
-+ .name = "dtrace",
-+ .nodename = "dtrace/dtrace",
-+ .fops = &dtrace_fops,
-+};
-+
-+static struct miscdevice helper_dev = {
-+ .minor = DT_DEV_HELPER_MINOR,
-+ .name = "helper",
-+ .nodename = "dtrace/helper",
-+ .fops = &helper_fops,
-+};
-+
-+static void dtrace_module_loaded(struct module *mp)
-+{
-+ struct dtrace_provider *prv;
-+
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+
-+ /*
-+ * Give all providers a chance to register probes for this module.
-+ */
-+ for (prv = dtrace_provider; prv != NULL; prv = prv->dtpv_next)
-+ prv->dtpv_pops.dtps_provide_module(prv->dtpv_arg, mp);
-+
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ /*
-+ * If we have any retained enablings, we need to match against them.
-+ */
-+ mutex_lock(&dtrace_lock);
-+
-+ if (dtrace_retained == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ return;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+ dtrace_enabling_matchall();
-+}
-+
-+static void dtrace_module_unloaded(struct module *mp)
-+{
-+ struct dtrace_probe template, *probe, *first, *next;
-+ struct dtrace_provider *prv;
-+
-+ template.dtpr_mod = mp->name;
-+
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (dtrace_bymod == NULL) {
-+ /*
-+ * The DTrace module is loaded (obviously) but not attached;
-+ * we don't have any work to do.
-+ */
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+ return;
-+ }
-+
-+ for (probe = first = dtrace_hash_lookup(dtrace_bymod, &template);
-+ probe != NULL; probe = probe->dtpr_nextmod) {
-+ if (probe->dtpr_ecb != NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ /*
-+ * This shouldn't _actually_ be possible -- we're
-+ * unloading a module that has an enabled probe in it.
-+ * (It's normally up to the provider to make sure that
-+ * this can't happen.) However, because dtps_enable()
-+ * doesn't have a failure mode, there can be an
-+ * enable/unload race. Upshot: we don't want to
-+ * assert, but we're not going to disable the
-+ * probe, either.
-+ */
-+ if (dtrace_err_verbose) {
-+ pr_warn("unloaded module '%s' "
-+ "had enabled probes", mp->name);
-+ }
-+
-+ return;
-+ }
-+ }
-+
-+ probe = first;
-+
-+ for (first = NULL; probe != NULL; probe = next) {
-+ dtrace_probe_remove_id(probe->dtpr_id);
-+
-+ next = probe->dtpr_nextmod;
-+ dtrace_hash_remove(dtrace_bymod, probe);
-+ dtrace_hash_remove(dtrace_byfunc, probe);
-+ dtrace_hash_remove(dtrace_byname, probe);
-+
-+ if (first == NULL) {
-+ first = probe;
-+ probe->dtpr_nextmod = NULL;
-+ } else {
-+ probe->dtpr_nextmod = first;
-+ first = probe;
-+ }
-+ }
-+
-+ /*
-+ * We've removed all of the module's probes from the hash chains and
-+ * from the probe array. Now issue a dtrace_sync() to be sure that
-+ * everyone has cleared out from any probe array processing.
-+ */
-+ dtrace_sync();
-+
-+ for (probe = first; probe != NULL; probe = first) {
-+ first = probe->dtpr_nextmod;
-+ prv = probe->dtpr_provider;
-+ prv->dtpv_pops.dtps_destroy(prv->dtpv_arg, probe->dtpr_id,
-+ probe->dtpr_arg);
-+ kfree(probe->dtpr_mod);
-+ kfree(probe->dtpr_func);
-+ kfree(probe->dtpr_name);
-+ kfree(probe);
-+ }
-+
-+ /*
-+ * Notify providers to cleanup per-module data for this module.
-+ */
-+ for (prv = dtrace_provider; prv != NULL; prv = prv->dtpv_next)
-+ if (prv->dtpv_pops.dtps_destroy_module != NULL)
-+ prv->dtpv_pops.dtps_destroy_module(prv->dtpv_arg, mp);
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+}
-+
-+/*
-+ * Register a toxic range.
-+ */
-+static void dtrace_toxrange_add(uintptr_t base, uintptr_t limit)
-+{
-+ if (dtrace_toxranges >= dtrace_toxranges_max) {
-+ int osize, nsize;
-+ struct dtrace_toxrange *range;
-+
-+ osize = dtrace_toxranges_max * sizeof(struct dtrace_toxrange);
-+
-+ if (osize == 0) {
-+ ASSERT(dtrace_toxrange == NULL);
-+ ASSERT(dtrace_toxranges_max == 0);
-+
-+ dtrace_toxranges_max = 1;
-+ } else
-+ dtrace_toxranges_max <<= 1;
-+
-+ nsize = dtrace_toxranges_max * sizeof(struct dtrace_toxrange);
-+ range = vzalloc(nsize);
-+ if (range == NULL) {
-+ pr_warn("Failed to add toxic range: out of memory\n");
-+ return;
-+ }
-+
-+ if (dtrace_toxrange != NULL) {
-+ ASSERT(osize != 0);
-+
-+ memcpy(range, dtrace_toxrange, osize);
-+ vfree(dtrace_toxrange);
-+ }
-+
-+ dtrace_toxrange = range;
-+ }
-+
-+ ASSERT(dtrace_toxrange[dtrace_toxranges].dtt_base == (uintptr_t)NULL);
-+ ASSERT(dtrace_toxrange[dtrace_toxranges].dtt_limit == (uintptr_t)NULL);
-+
-+ dtrace_toxrange[dtrace_toxranges].dtt_base = base;
-+ dtrace_toxrange[dtrace_toxranges].dtt_limit = limit;
-+ dtrace_toxranges++;
-+}
-+
-+/*
-+ * Check if an address falls within a toxic region.
-+ */
-+int dtrace_istoxic(uintptr_t kaddr, size_t size)
-+{
-+ uintptr_t taddr, tsize;
-+ int i;
-+
-+ for (i = 0; i < dtrace_toxranges; i++) {
-+ taddr = dtrace_toxrange[i].dtt_base;
-+ tsize = dtrace_toxrange[i].dtt_limit - taddr;
-+
-+ if (kaddr - taddr < tsize) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = kaddr;
-+ return 1;
-+ }
-+
-+ if (taddr - kaddr < size) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = kaddr;
-+ return 1;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int dtrace_mod_notifier(struct notifier_block *nb, unsigned long val,
-+ void *args)
-+{
-+ struct module *mp = args;
-+
-+ if (!mp)
-+ return NOTIFY_DONE;
-+
-+ switch (val) {
-+ case MODULE_STATE_LIVE:
-+ dtrace_module_loaded(mp);
-+ break;
-+
-+ case MODULE_STATE_GOING:
-+ dtrace_module_unloaded(mp);
-+ break;
-+ }
-+
-+ return NOTIFY_DONE;
-+}
-+
-+static struct notifier_block dtrace_modmgmt = {
-+ .notifier_call = dtrace_mod_notifier,
-+};
-+
-+/*
-+ * Initialize the DTrace core.
-+ *
-+ * Equivalent to: dtrace_attach()
-+ */
-+int dtrace_dev_init(void)
-+{
-+ dtrace_provider_id_t id;
-+ int rc = 0;
-+ struct cred *cred;
-+
-+ /*
-+ * Register the device for the DTrace core.
-+ */
-+ rc = misc_register(&dtrace_dev);
-+ if (rc) {
-+ pr_err("%s: Can't register misc device %d\n",
-+ dtrace_dev.name, dtrace_dev.minor);
-+
-+ return rc;
-+ }
-+
-+ /*
-+ * Register the device for the DTrace helper.
-+ */
-+ rc = misc_register(&helper_dev);
-+ if (rc) {
-+ pr_err("%s: Can't register misc device %d\n",
-+ helper_dev.name, helper_dev.minor);
-+
-+ misc_deregister(&dtrace_dev);
-+ return rc;
-+ }
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ rc = dtrace_probe_init();
-+ if (rc) {
-+ pr_err("Failed to initialize DTrace core\n");
-+
-+ goto errout;
-+ }
-+
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+ dtrace_helpers_cleanup = dtrace_helpers_destroy;
-+ dtrace_helpers_fork = dtrace_helpers_duplicate;
-+#endif
-+#ifdef FIXME
-+ dtrace_cpu_init = dtrace_cpu_setup_initial;
-+ dtrace_cpustart_init = dtrace_suspend;
-+ dtrace_cpustart_fini = dtrace_resume;
-+ dtrace_debugger_init = dtrace_suspend;
-+ dtrace_debugger_fini = dtrace_resume;
-+
-+ register_cpu_setup_func((cpu_setup_func_t *)dtrace_cpu_setup, NULL);
-+#endif
-+
-+#ifdef FIXME
-+ dtrace_taskq = taskq_create("dtrace_taskq", 1, maxclsyspri, 1, INT_MAX,
-+ 0);
-+#endif
-+
-+ dtrace_state_cachep = kmem_cache_create("dtrace_state_cache",
-+ sizeof(struct dtrace_dstate_percpu) * NR_CPUS,
-+ 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
-+
-+ /* From now on the failures are results of failed allocations. */
-+ rc = -ENOMEM;
-+
-+ /*
-+ * Create the probe hashtables.
-+ */
-+ dtrace_bymod = dtrace_hash_create(
-+ offsetof(struct dtrace_probe, dtpr_mod),
-+ offsetof(struct dtrace_probe, dtpr_nextmod),
-+ offsetof(struct dtrace_probe, dtpr_prevmod));
-+ if (dtrace_bymod == NULL)
-+ goto errout;
-+
-+ dtrace_byfunc = dtrace_hash_create(
-+ offsetof(struct dtrace_probe, dtpr_func),
-+ offsetof(struct dtrace_probe, dtpr_nextfunc),
-+ offsetof(struct dtrace_probe, dtpr_prevfunc));
-+ if (dtrace_byfunc == NULL)
-+ goto errout;
-+
-+ dtrace_byname = dtrace_hash_create(
-+ offsetof(struct dtrace_probe, dtpr_name),
-+ offsetof(struct dtrace_probe, dtpr_nextname),
-+ offsetof(struct dtrace_probe, dtpr_prevname));
-+ if (dtrace_byname == NULL)
-+ goto errout;
-+
-+ /*
-+ * Initialize cred.
-+ */
-+ cred = prepare_kernel_cred(NULL);
-+ if (cred == NULL)
-+ goto errout;
-+
-+ init_user_namespace = cred->user_ns;
-+ put_cred(cred);
-+
-+ /*
-+ * Ensure that the X configuration parameter has a legal value.
-+ */
-+ if (dtrace_retain_max < 1) {
-+ pr_warn("Illegal value (%lu) for dtrace_retain_max; "
-+ "setting to 1", (unsigned long)dtrace_retain_max);
-+
-+ dtrace_retain_max = 1;
-+ }
-+
-+ /*
-+ * Discover our toxic ranges.
-+ */
-+ dtrace_toxic_ranges(dtrace_toxrange_add);
-+
-+ /*
-+ * Register ourselves as a provider.
-+ */
-+ dtrace_register("dtrace", &dtrace_provider_attr, DTRACE_PRIV_NONE, 0,
-+ &dtrace_provider_ops, NULL, &id);
-+
-+ ASSERT(dtrace_provider != NULL);
-+ ASSERT((dtrace_provider_id_t)dtrace_provider == id);
-+
-+ /*
-+ * Create BEGIN, END, and ERROR probes.
-+ */
-+ dtrace_probeid_begin = dtrace_probe_create(
-+ (dtrace_provider_id_t)dtrace_provider, NULL,
-+ NULL, "BEGIN", 0, NULL);
-+ if (dtrace_probeid_begin == DTRACE_IDNONE)
-+ goto errout;
-+
-+ dtrace_probeid_end = dtrace_probe_create(
-+ (dtrace_provider_id_t)dtrace_provider, NULL,
-+ NULL, "END", 0, NULL);
-+ if (dtrace_probeid_end == DTRACE_IDNONE)
-+ goto errout;
-+
-+ dtrace_probeid_error = dtrace_probe_create(
-+ (dtrace_provider_id_t)dtrace_provider, NULL,
-+ NULL, "ERROR", 1, NULL);
-+ if (dtrace_probeid_error == DTRACE_IDNONE)
-+ goto errout;
-+
-+ dtrace_anon_property();
-+
-+ /*
-+ * If DTrace helper tracing is enabled, we need to allocate a trace
-+ * buffer.
-+ */
-+ if (dtrace_helptrace_enabled) {
-+ ASSERT(dtrace_helptrace_buffer == NULL);
-+
-+ dtrace_helptrace_buffer = vzalloc(dtrace_helptrace_bufsize);
-+
-+ if (dtrace_helptrace_buffer == NULL) {
-+ pr_warn("Cannot allocate helptrace buffer; "
-+ "disabling dtrace_helptrace\n");
-+ dtrace_helptrace_enabled = 0;
-+ }
-+ }
-+
-+#ifdef FIXME
-+ /*
-+ * There is usually code here to handle the case where there already
-+ * are providers when we get to this code. On Linux, that does not
-+ * seem to be possible since the DTrace core module (this code) is
-+ * loaded as a dependency for each provider, and thus this
-+ * initialization code is executed prior to the initialization code of
-+ * the first provider causing the core to be loaded.
-+ */
-+#endif
-+
-+ if (register_module_notifier(&dtrace_modmgmt))
-+ goto errout;
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+ mutex_unlock(&cpu_lock);
-+
-+ return 0;
-+
-+errout:
-+ if (dtrace_provider != NULL)
-+ (void) dtrace_unregister((dtrace_provider_id_t)dtrace_provider);
-+
-+ dtrace_hash_destroy(dtrace_bymod);
-+ dtrace_hash_destroy(dtrace_byfunc);
-+ dtrace_hash_destroy(dtrace_byname);
-+
-+ misc_deregister(&helper_dev);
-+ misc_deregister(&dtrace_dev);
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+ mutex_unlock(&cpu_lock);
-+
-+ return rc;
-+}
-+
-+void dtrace_dev_exit(void)
-+{
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ dtrace_unregister((dtrace_provider_id_t)dtrace_provider);
-+ dtrace_provider = NULL;
-+
-+ dtrace_probe_exit();
-+
-+ unregister_module_notifier(&dtrace_modmgmt);
-+
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+ dtrace_helpers_cleanup = NULL;
-+ dtrace_helpers_fork = NULL;
-+#endif
-+#ifdef FIXME
-+ dtrace_cpu_init = NULL;
-+ dtrace_cpustart_init = NULL;
-+ dtrace_cpustart_fini = NULL;
-+ dtrace_debugger_init = NULL;
-+ dtrace_debugger_fini = NULL;
-+
-+ unregister_cpu_setup_func((cpu_setup_func_t *)dtrace_cpu_setup, NULL);
-+#endif
-+
-+ mutex_unlock(&cpu_lock);
-+
-+ dtrace_hash_destroy(dtrace_bymod);
-+ dtrace_hash_destroy(dtrace_byfunc);
-+ dtrace_hash_destroy(dtrace_byname);
-+ dtrace_bymod = NULL;
-+ dtrace_byfunc = NULL;
-+ dtrace_byname = NULL;
-+
-+ /*
-+ * If DTrace helper tracing is enabled, we need to free the trace
-+ * buffer.
-+ */
-+ if (dtrace_helptrace_enabled || dtrace_helptrace_buffer)
-+ vfree(dtrace_helptrace_buffer);
-+
-+ kmem_cache_destroy(dtrace_state_cachep);
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ misc_deregister(&helper_dev);
-+ misc_deregister(&dtrace_dev);
-+}
-diff --git a/dtrace/dtrace_dev.h b/dtrace/dtrace_dev.h
-new file mode 100644
-index 000000000000..11ae2deb17a1
---- /dev/null
-+++ b/dtrace/dtrace_dev.h
-@@ -0,0 +1,35 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _DTRACE_DEV_H_
-+#define _DTRACE_DEV_H_
-+
-+#define DT_DEV_DTRACE_MINOR (16)
-+#define DT_DEV_HELPER_MINOR (DT_DEV_DTRACE_MINOR + 1)
-+#define DT_DEV_PROFILE_MINOR (DT_DEV_HELPER_MINOR + 1)
-+#define DT_DEV_SYSTRACE_MINOR (DT_DEV_PROFILE_MINOR + 1)
-+#define DT_DEV_FBT_MINOR (DT_DEV_SYSTRACE_MINOR + 1)
-+#define DT_DEV_SDT_MINOR (DT_DEV_FBT_MINOR + 1)
-+#define DT_DEV_FASTTRAP_MINOR (DT_DEV_SDT_MINOR + 1)
-+#define DT_DEV_LOCKSTAT_MINOR (DT_DEV_FASTTRAP_MINOR + 1)
-+#define DT_DEV_DT_TEST_MINOR (DT_DEV_LOCKSTAT_MINOR + 1)
-+#define DT_DEV_DT_PERF_MINOR (DT_DEV_DT_TEST_MINOR + 1)
-+
-+extern int dtrace_dev_init(void);
-+extern void dtrace_dev_exit(void);
-+
-+#endif /* _DTRACE_DEV_H_ */
-diff --git a/dtrace/dtrace_dif.c b/dtrace/dtrace_dif.c
-new file mode 100644
-index 000000000000..ae7f01b4ed9b
---- /dev/null
-+++ b/dtrace/dtrace_dif.c
-@@ -0,0 +1,4905 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_dif.c
-+ * DESCRIPTION: DTrace - DIF object implementation
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/fdtable.h>
-+#include <linux/hardirq.h>
-+#include <linux/if_arp.h>
-+#include <linux/if_ether.h>
-+#include <linux/if_infiniband.h>
-+#include <linux/in6.h>
-+#include <linux/inet.h>
-+#include <linux/kdev_t.h>
-+#include <linux/slab.h>
-+#include <linux/socket.h>
-+#include <linux/vmalloc.h>
-+#include <net/ipv6.h>
-+#include <asm/byteorder.h>
-+
-+#include <linux/mount.h>
-+
-+#include "dtrace.h"
-+
-+size_t dtrace_global_maxsize = 16 * 1024;
-+
-+/*
-+ * This externally visible variable (accessible through the backtick (`)
-+ * syntax is provided as a source of well-known, zero-filled memory. Some
-+ * translators use this in their implementation.
-+ */
-+const char dtrace_zero[256] = { 0, };
-+
-+uint64_t dtrace_vtime_references;
-+
-+static const char hexdigits[] = "0123456789abcdef";
-+
-+static int dtrace_difo_err(uint_t pc, const char *format, ...)
-+{
-+ char buf[256];
-+
-+ if (dtrace_err_verbose) {
-+ va_list alist;
-+ size_t len = strlen(format);
-+
-+ pr_err("dtrace DIF object error: [%u]: ", pc);
-+
-+ if (len >= 256 - sizeof(KERN_ERR)) {
-+ pr_err("<invalid format string>");
-+ return 1;
-+ }
-+
-+ memcpy(buf, KERN_ERR, sizeof(KERN_ERR));
-+ memcpy(buf + sizeof(KERN_ERR), format, len);
-+
-+ va_start(alist, format);
-+ vprintk(buf, alist);
-+ va_end(alist);
-+ }
-+
-+ return 1;
-+}
-+
-+/*
-+ * Validate a DTrace DIF object by checking the IR instructions. The following
-+ * rules are currently enforced by dtrace_difo_validate():
-+ *
-+ * 1. Each instruction must have a valid opcode
-+ * 2. Each register, string, variable, or subroutine reference must be valid
-+ * 3. No instruction can modify register %r0 (must be zero)
-+ * 4. All instruction reserved bits must be set to zero
-+ * 5. The last instruction must be a "ret" instruction
-+ * 6. All branch targets must reference a valid instruction _after_ the branch
-+ */
-+int dtrace_difo_validate(struct dtrace_difo *dp, struct dtrace_vstate *vstate,
-+ uint_t nregs, const struct cred *cr)
-+{
-+ int err = 0, i;
-+ int (*efunc)(uint_t pc, const char *, ...) = dtrace_difo_err;
-+ int kcheckload = 0;
-+ uint_t pc;
-+
-+ kcheckload = cr == NULL ||
-+ (vstate->dtvs_state->dts_cred.dcr_visible &
-+ DTRACE_CRV_KERNEL) == 0;
-+
-+ dp->dtdo_destructive = 0;
-+
-+ for (pc = 0; pc < dp->dtdo_len && err == 0; pc++) {
-+ dif_instr_t instr = dp->dtdo_buf[pc];
-+ uint_t r1 = DIF_INSTR_R1(instr);
-+ uint_t r2 = DIF_INSTR_R2(instr);
-+ uint_t rd = DIF_INSTR_RD(instr);
-+ uint_t rs = DIF_INSTR_RS(instr);
-+ uint_t label = DIF_INSTR_LABEL(instr);
-+ uint_t v = DIF_INSTR_VAR(instr);
-+ uint_t subr = DIF_INSTR_SUBR(instr);
-+ uint_t diftype = DIF_INSTR_TYPE(instr);
-+ uint_t op = DIF_INSTR_OP(instr);
-+
-+ switch (op) {
-+ case DIF_OP_OR:
-+ case DIF_OP_XOR:
-+ case DIF_OP_AND:
-+ case DIF_OP_SLL:
-+ case DIF_OP_SRL:
-+ case DIF_OP_SRA:
-+ case DIF_OP_SUB:
-+ case DIF_OP_ADD:
-+ case DIF_OP_MUL:
-+ case DIF_OP_SDIV:
-+ case DIF_OP_UDIV:
-+ case DIF_OP_SREM:
-+ case DIF_OP_UREM:
-+ case DIF_OP_COPYS:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r2);
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_NOT:
-+ case DIF_OP_MOV:
-+ case DIF_OP_ALLOCS:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_LDSB:
-+ case DIF_OP_LDSH:
-+ case DIF_OP_LDSW:
-+ case DIF_OP_LDUB:
-+ case DIF_OP_LDUH:
-+ case DIF_OP_LDUW:
-+ case DIF_OP_LDX:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ if (kcheckload)
-+ dp->dtdo_buf[pc] = DIF_INSTR_LOAD(
-+ op + DIF_OP_RLDSB -
-+ DIF_OP_LDSB,
-+ r1, rd);
-+ break;
-+ case DIF_OP_RLDSB:
-+ case DIF_OP_RLDSH:
-+ case DIF_OP_RLDSW:
-+ case DIF_OP_RLDUB:
-+ case DIF_OP_RLDUH:
-+ case DIF_OP_RLDUW:
-+ case DIF_OP_RLDX:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_ULDSB:
-+ case DIF_OP_ULDSH:
-+ case DIF_OP_ULDSW:
-+ case DIF_OP_ULDUB:
-+ case DIF_OP_ULDUH:
-+ case DIF_OP_ULDUW:
-+ case DIF_OP_ULDX:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_STB:
-+ case DIF_OP_STH:
-+ case DIF_OP_STW:
-+ case DIF_OP_STX:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to 0 address\n");
-+ break;
-+ case DIF_OP_CMP:
-+ case DIF_OP_SCMP:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r2);
-+ if (rd != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ break;
-+ case DIF_OP_TST:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0 || rd != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ break;
-+ case DIF_OP_BA:
-+ case DIF_OP_BE:
-+ case DIF_OP_BNE:
-+ case DIF_OP_BG:
-+ case DIF_OP_BGU:
-+ case DIF_OP_BGE:
-+ case DIF_OP_BGEU:
-+ case DIF_OP_BL:
-+ case DIF_OP_BLU:
-+ case DIF_OP_BLE:
-+ case DIF_OP_BLEU:
-+ if (label >= dp->dtdo_len)
-+ err += efunc(pc, "invalid branch target %u\n",
-+ label);
-+ if (label <= pc)
-+ err += efunc(pc, "backward branch to %u\n",
-+ label);
-+ break;
-+ case DIF_OP_RET:
-+ if (r1 != 0 || r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ break;
-+ case DIF_OP_NOP:
-+ case DIF_OP_POPTS:
-+ case DIF_OP_FLUSHTS:
-+ if (r1 != 0 || r2 != 0 || rd != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ break;
-+ case DIF_OP_SETX:
-+ if (DIF_INSTR_INTEGER(instr) >= dp->dtdo_intlen)
-+ err += efunc(pc, "invalid integer ref %u\n",
-+ DIF_INSTR_INTEGER(instr));
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_SETS:
-+ if (DIF_INSTR_STRING(instr) >= dp->dtdo_strlen)
-+ err += efunc(pc, "invalid string ref %u\n",
-+ DIF_INSTR_STRING(instr));
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_LDGA:
-+ case DIF_OP_LDTA:
-+ if (r1 > DIF_VAR_ARRAY_MAX)
-+ err += efunc(pc, "invalid array %u\n", r1);
-+ if (r2 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r2);
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_LDGS:
-+ case DIF_OP_LDTS:
-+ case DIF_OP_LDLS:
-+ case DIF_OP_LDGAA:
-+ case DIF_OP_LDTAA:
-+ if (v < DIF_VAR_OTHER_MIN || v > DIF_VAR_OTHER_MAX)
-+ err += efunc(pc, "invalid variable %u\n", v);
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_STGS:
-+ case DIF_OP_STTS:
-+ case DIF_OP_STLS:
-+ case DIF_OP_STGAA:
-+ case DIF_OP_STTAA:
-+ if (v < DIF_VAR_OTHER_UBASE || v > DIF_VAR_OTHER_MAX)
-+ err += efunc(pc, "invalid variable %u\n", v);
-+ if (rs >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ break;
-+ case DIF_OP_CALL:
-+ if (subr > DIF_SUBR_MAX)
-+ err += efunc(pc, "invalid subr %u\n", subr);
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+
-+ if (subr == DIF_SUBR_COPYOUT ||
-+ subr == DIF_SUBR_COPYOUTSTR)
-+ dp->dtdo_destructive = 1;
-+ break;
-+ case DIF_OP_PUSHTR:
-+ if (diftype != DIF_TYPE_STRING && diftype != DIF_TYPE_CTF)
-+ err += efunc(pc, "invalid ref type %u\n",
-+ diftype);
-+ if (r2 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r2);
-+ if (rs >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rs);
-+ break;
-+ case DIF_OP_PUSHTV:
-+ if (diftype != DIF_TYPE_CTF)
-+ err += efunc(pc, "invalid val type %u\n",
-+ diftype);
-+ if (r2 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r2);
-+ if (rs >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rs);
-+ break;
-+ default:
-+ err += efunc(pc, "invalid opcode %u\n",
-+ DIF_INSTR_OP(instr));
-+ }
-+ }
-+
-+ if (dp->dtdo_len != 0 &&
-+ DIF_INSTR_OP(dp->dtdo_buf[dp->dtdo_len - 1]) != DIF_OP_RET) {
-+ err += efunc(dp->dtdo_len - 1,
-+ "expected 'ret' as last DIF instruction\n");
-+ }
-+
-+ if (!(dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF)) {
-+ /*
-+ * If we're not returning by reference, the size must be either
-+ * 0 or the size of one of the base types.
-+ */
-+ switch (dp->dtdo_rtype.dtdt_size) {
-+ case 0:
-+ case sizeof(uint8_t):
-+ case sizeof(uint16_t):
-+ case sizeof(uint32_t):
-+ case sizeof(uint64_t):
-+ break;
-+
-+ default:
-+ err += efunc(dp->dtdo_len - 1, "bad return size\n");
-+ }
-+ }
-+
-+ for (i = 0; i < dp->dtdo_varlen && err == 0; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i],
-+ *existing = NULL;
-+ struct dtrace_diftype *vt, *et;
-+ uint_t id, ndx;
-+
-+ if (v->dtdv_scope != DIFV_SCOPE_GLOBAL &&
-+ v->dtdv_scope != DIFV_SCOPE_THREAD &&
-+ v->dtdv_scope != DIFV_SCOPE_LOCAL) {
-+ err += efunc(i, "unrecognized variable scope %d\n",
-+ v->dtdv_scope);
-+ break;
-+ }
-+
-+ if (v->dtdv_kind != DIFV_KIND_ARRAY &&
-+ v->dtdv_kind != DIFV_KIND_SCALAR) {
-+ err += efunc(i, "unrecognized variable type %d\n",
-+ v->dtdv_kind);
-+ break;
-+ }
-+
-+ id = v->dtdv_id;
-+ if (id > DIF_VARIABLE_MAX) {
-+ err += efunc(i, "%d exceeds variable id limit\n", id);
-+ break;
-+ }
-+
-+ if (id < DIF_VAR_OTHER_UBASE)
-+ continue;
-+
-+ /*
-+ * For user-defined variables, we need to check that this
-+ * definition is identical to any previous definition that we
-+ * encountered.
-+ */
-+ ndx = id - DIF_VAR_OTHER_UBASE;
-+
-+ switch (v->dtdv_scope) {
-+ case DIFV_SCOPE_GLOBAL:
-+ if (ndx < vstate->dtvs_nglobals) {
-+ struct dtrace_statvar *svar;
-+
-+ svar = vstate->dtvs_globals[ndx];
-+ if (svar != NULL)
-+ existing = &svar->dtsv_var;
-+ }
-+
-+ break;
-+
-+ case DIFV_SCOPE_THREAD:
-+ if (ndx < vstate->dtvs_ntlocals)
-+ existing = &vstate->dtvs_tlocals[ndx];
-+ break;
-+
-+ case DIFV_SCOPE_LOCAL:
-+ if (ndx < vstate->dtvs_nlocals) {
-+ struct dtrace_statvar *svar;
-+
-+ svar = vstate->dtvs_locals[ndx];
-+ if (svar != NULL)
-+ existing = &svar->dtsv_var;
-+ }
-+
-+ break;
-+ }
-+
-+ vt = &v->dtdv_type;
-+
-+ if (vt->dtdt_flags & DIF_TF_BYREF) {
-+ if (vt->dtdt_size == 0) {
-+ err += efunc(i, "zero-sized variable\n");
-+ break;
-+ }
-+
-+ if (v->dtdv_scope == DIFV_SCOPE_GLOBAL &&
-+ vt->dtdt_size > dtrace_global_maxsize) {
-+ err += efunc(i, "oversized by-ref global\n");
-+ break;
-+ }
-+ }
-+
-+ if (existing == NULL || existing->dtdv_id == 0)
-+ continue;
-+
-+ ASSERT(existing->dtdv_id == v->dtdv_id);
-+ ASSERT(existing->dtdv_scope == v->dtdv_scope);
-+
-+ if (existing->dtdv_kind != v->dtdv_kind)
-+ err += efunc(i, "%d changed variable kind\n", id);
-+
-+ et = &existing->dtdv_type;
-+
-+ if (vt->dtdt_flags != et->dtdt_flags) {
-+ err += efunc(i, "%d changed variable type flags\n", id);
-+ break;
-+ }
-+
-+ if (vt->dtdt_size != 0 && vt->dtdt_size != et->dtdt_size) {
-+ err += efunc(i, "%d changed variable type size\n", id);
-+ break;
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+/*
-+ * Validate a DTrace DIF object that it is to be used as a helper. Helpers
-+ * are much more constrained than normal DIFOs. Specifically, they may
-+ * not:
-+ *
-+ * 1. Make calls to subroutines other than copyin(), copyinstr() or
-+ * miscellaneous string routines
-+ * 2. Access DTrace variables other than the args[] array, and the
-+ * curthread, pid, ppid, tid, execname, zonename, uid and gid variables.
-+ * 3. Have thread-local variables.
-+ * 4. Have dynamic variables.
-+ */
-+int dtrace_difo_validate_helper(struct dtrace_difo *dp)
-+{
-+ int (*efunc)(uint_t pc, const char *, ...) = dtrace_difo_err;
-+ int err = 0;
-+ uint_t pc;
-+
-+ for (pc = 0; pc < dp->dtdo_len; pc++) {
-+ dif_instr_t instr = dp->dtdo_buf[pc];
-+ uint_t v = DIF_INSTR_VAR(instr);
-+ uint_t subr = DIF_INSTR_SUBR(instr);
-+ uint_t op = DIF_INSTR_OP(instr);
-+
-+ switch (op) {
-+ case DIF_OP_OR:
-+ case DIF_OP_XOR:
-+ case DIF_OP_AND:
-+ case DIF_OP_SLL:
-+ case DIF_OP_SRL:
-+ case DIF_OP_SRA:
-+ case DIF_OP_SUB:
-+ case DIF_OP_ADD:
-+ case DIF_OP_MUL:
-+ case DIF_OP_SDIV:
-+ case DIF_OP_UDIV:
-+ case DIF_OP_SREM:
-+ case DIF_OP_UREM:
-+ case DIF_OP_COPYS:
-+ case DIF_OP_NOT:
-+ case DIF_OP_MOV:
-+ case DIF_OP_RLDSB:
-+ case DIF_OP_RLDSH:
-+ case DIF_OP_RLDSW:
-+ case DIF_OP_RLDUB:
-+ case DIF_OP_RLDUH:
-+ case DIF_OP_RLDUW:
-+ case DIF_OP_RLDX:
-+ case DIF_OP_ULDSB:
-+ case DIF_OP_ULDSH:
-+ case DIF_OP_ULDSW:
-+ case DIF_OP_ULDUB:
-+ case DIF_OP_ULDUH:
-+ case DIF_OP_ULDUW:
-+ case DIF_OP_ULDX:
-+ case DIF_OP_STB:
-+ case DIF_OP_STH:
-+ case DIF_OP_STW:
-+ case DIF_OP_STX:
-+ case DIF_OP_ALLOCS:
-+ case DIF_OP_CMP:
-+ case DIF_OP_SCMP:
-+ case DIF_OP_TST:
-+ case DIF_OP_BA:
-+ case DIF_OP_BE:
-+ case DIF_OP_BNE:
-+ case DIF_OP_BG:
-+ case DIF_OP_BGU:
-+ case DIF_OP_BGE:
-+ case DIF_OP_BGEU:
-+ case DIF_OP_BL:
-+ case DIF_OP_BLU:
-+ case DIF_OP_BLE:
-+ case DIF_OP_BLEU:
-+ case DIF_OP_RET:
-+ case DIF_OP_NOP:
-+ case DIF_OP_POPTS:
-+ case DIF_OP_FLUSHTS:
-+ case DIF_OP_SETX:
-+ case DIF_OP_SETS:
-+ case DIF_OP_LDGA:
-+ case DIF_OP_LDLS:
-+ case DIF_OP_STGS:
-+ case DIF_OP_STLS:
-+ case DIF_OP_PUSHTR:
-+ case DIF_OP_PUSHTV:
-+ break;
-+
-+ case DIF_OP_LDGS:
-+ if (v >= DIF_VAR_OTHER_UBASE)
-+ break;
-+
-+ if (v >= DIF_VAR_ARG0 && v <= DIF_VAR_ARG9)
-+ break;
-+
-+ if (v == DIF_VAR_CURTHREAD || v == DIF_VAR_PID ||
-+ v == DIF_VAR_PPID || v == DIF_VAR_TID ||
-+ v == DIF_VAR_EXECNAME || v == DIF_VAR_ZONENAME ||
-+ v == DIF_VAR_UID || v == DIF_VAR_GID)
-+ break;
-+
-+ err += efunc(pc, "illegal variable %u\n", v);
-+ break;
-+
-+ case DIF_OP_LDTA:
-+ case DIF_OP_LDGAA:
-+ case DIF_OP_LDTAA:
-+ err += efunc(pc, "illegal dynamic variable load\n");
-+ break;
-+
-+ case DIF_OP_STTS:
-+ case DIF_OP_STGAA:
-+ case DIF_OP_STTAA:
-+ err += efunc(pc, "illegal dynamic variable store\n");
-+ break;
-+
-+ case DIF_OP_CALL:
-+ if (subr == DIF_SUBR_ALLOCA ||
-+ subr == DIF_SUBR_BCOPY ||
-+ subr == DIF_SUBR_COPYIN ||
-+ subr == DIF_SUBR_COPYINTO ||
-+ subr == DIF_SUBR_COPYINSTR ||
-+ subr == DIF_SUBR_INDEX ||
-+ subr == DIF_SUBR_INET_NTOA ||
-+ subr == DIF_SUBR_INET_NTOA6 ||
-+ subr == DIF_SUBR_INET_NTOP ||
-+ subr == DIF_SUBR_LINK_NTOP ||
-+ subr == DIF_SUBR_LLTOSTR ||
-+ subr == DIF_SUBR_RINDEX ||
-+ subr == DIF_SUBR_STRCHR ||
-+ subr == DIF_SUBR_STRJOIN ||
-+ subr == DIF_SUBR_STRRCHR ||
-+ subr == DIF_SUBR_STRSTR ||
-+ subr == DIF_SUBR_HTONS ||
-+ subr == DIF_SUBR_HTONL ||
-+ subr == DIF_SUBR_HTONLL ||
-+ subr == DIF_SUBR_NTOHS ||
-+ subr == DIF_SUBR_NTOHL ||
-+ subr == DIF_SUBR_NTOHLL)
-+ break;
-+
-+ err += efunc(pc, "invalid subr %u\n", subr);
-+ break;
-+
-+ default:
-+ err += efunc(pc, "invalid opcode %u\n",
-+ DIF_INSTR_OP(instr));
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+/*
-+ * Returns 1 if the expression in the DIF object can be cached on a per-thread
-+ * basis; 0 if not.
-+ */
-+int dtrace_difo_cacheable(struct dtrace_difo *dp)
-+{
-+ int i;
-+
-+ if (dp == NULL)
-+ return 0;
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+
-+ if (v->dtdv_scope != DIFV_SCOPE_GLOBAL)
-+ continue;
-+
-+ switch (v->dtdv_id) {
-+ case DIF_VAR_CURTHREAD:
-+ case DIF_VAR_PID:
-+ case DIF_VAR_TID:
-+ case DIF_VAR_EXECNAME:
-+ case DIF_VAR_ZONENAME:
-+ break;
-+
-+ default:
-+ return 0;
-+ }
-+ }
-+
-+ /*
-+ * This DIF object may be cacheable. Now we need to look for any
-+ * array loading instructions, any memory loading instructions, or
-+ * any stores to thread-local variables.
-+ */
-+ for (i = 0; i < dp->dtdo_len; i++) {
-+ uint_t op = DIF_INSTR_OP(dp->dtdo_buf[i]);
-+
-+ if ((op >= DIF_OP_LDSB && op <= DIF_OP_LDX) ||
-+ (op >= DIF_OP_ULDSB && op <= DIF_OP_ULDX) ||
-+ (op >= DIF_OP_RLDSB && op <= DIF_OP_RLDX) ||
-+ op == DIF_OP_LDGA || op == DIF_OP_STTS)
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+/*
-+ * This routine calculates the dynamic variable chunksize for a given DIF
-+ * object. The calculation is not fool-proof, and can probably be tricked by
-+ * malicious DIF -- but it works for all compiler-generated DIF. Because this
-+ * calculation is likely imperfect, dtrace_dynvar() is able to gracefully fail
-+ * if a dynamic variable size exceeds the chunksize.
-+ */
-+static void dtrace_difo_chunksize(struct dtrace_difo *dp,
-+ struct dtrace_vstate *vstate)
-+{
-+ uint64_t sval = 0;
-+ struct dtrace_key tupregs[DIF_DTR_NREGS + 2]; /* + thread + id */
-+ const dif_instr_t *text = dp->dtdo_buf;
-+ uint_t pc, srd = 0;
-+ uint_t ttop = 0;
-+ size_t size, ksize;
-+ uint_t id, i;
-+
-+ for (pc = 0; pc < dp->dtdo_len; pc++) {
-+ dif_instr_t instr = text[pc];
-+ uint_t op = DIF_INSTR_OP(instr);
-+ uint_t rd = DIF_INSTR_RD(instr);
-+ uint_t r1 = DIF_INSTR_R1(instr);
-+ uint_t nkeys = 0;
-+ uchar_t scope;
-+ struct dtrace_key *key = tupregs;
-+
-+ switch (op) {
-+ case DIF_OP_SETX:
-+ sval = dp->dtdo_inttab[DIF_INSTR_INTEGER(instr)];
-+ srd = rd;
-+ continue;
-+
-+ case DIF_OP_STTS:
-+ key = &tupregs[DIF_DTR_NREGS];
-+ key[0].dttk_size = 0;
-+ key[1].dttk_size = 0;
-+ nkeys = 2;
-+ scope = DIFV_SCOPE_THREAD;
-+ break;
-+
-+ case DIF_OP_STGAA:
-+ case DIF_OP_STTAA:
-+ nkeys = ttop;
-+
-+ if (DIF_INSTR_OP(instr) == DIF_OP_STTAA)
-+ key[nkeys++].dttk_size = 0;
-+
-+ key[nkeys++].dttk_size = 0;
-+
-+ if (op == DIF_OP_STTAA)
-+ scope = DIFV_SCOPE_THREAD;
-+ else
-+ scope = DIFV_SCOPE_GLOBAL;
-+
-+ break;
-+
-+ case DIF_OP_PUSHTR:
-+ if (ttop == DIF_DTR_NREGS)
-+ return;
-+
-+ /*
-+ * If the register for the size of the "pushtr" is %r0
-+ * (or the value is 0) and the type is a string, we'll
-+ * use the system-wide default string size.
-+ */
-+ if ((srd == 0 || sval == 0) && r1 == DIF_TYPE_STRING)
-+ tupregs[ttop++].dttk_size =
-+ dtrace_strsize_default;
-+ else {
-+ if (srd == 0)
-+ return;
-+
-+ tupregs[ttop++].dttk_size = sval;
-+ }
-+
-+ break;
-+
-+ case DIF_OP_PUSHTV:
-+ if (ttop == DIF_DTR_NREGS)
-+ return;
-+
-+ tupregs[ttop++].dttk_size = 0;
-+ break;
-+
-+ case DIF_OP_FLUSHTS:
-+ ttop = 0;
-+ break;
-+
-+ case DIF_OP_POPTS:
-+ if (ttop != 0)
-+ ttop--;
-+ break;
-+ }
-+
-+ sval = 0;
-+ srd = 0;
-+
-+ if (nkeys == 0)
-+ continue;
-+
-+ /*
-+ * We have a dynamic variable allocation; calculate its size.
-+ */
-+ for (ksize = 0, i = 0; i < nkeys; i++)
-+ ksize += P2ROUNDUP(key[i].dttk_size, sizeof(uint64_t));
-+
-+ size = sizeof(struct dtrace_dynvar);
-+ size += sizeof(struct dtrace_key) * (nkeys - 1);
-+ size += ksize;
-+
-+ /*
-+ * Now we need to determine the size of the stored data.
-+ */
-+ id = DIF_INSTR_VAR(instr);
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+
-+ if (v->dtdv_id == id && v->dtdv_scope == scope) {
-+ size += v->dtdv_type.dtdt_size;
-+ break;
-+ }
-+ }
-+
-+ if (i == dp->dtdo_varlen)
-+ return;
-+
-+ /*
-+ * We have the size. If this is larger than the chunk size
-+ * for our dynamic variable state, reset the chunk size.
-+ */
-+ size = P2ROUNDUP(size, sizeof(uint64_t));
-+
-+ if (size > vstate->dtvs_dynvars.dtds_chunksize)
-+ vstate->dtvs_dynvars.dtds_chunksize = size;
-+ }
-+}
-+
-+void dtrace_difo_hold(struct dtrace_difo *dp)
-+{
-+ int i;
-+
-+ dp->dtdo_refcnt++;
-+ ASSERT(dp->dtdo_refcnt != 0);
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+
-+ if (v->dtdv_id != DIF_VAR_VTIMESTAMP)
-+ continue;
-+
-+ if (dtrace_vtime_references++ == 0)
-+ dtrace_vtime_enable();
-+ }
-+}
-+
-+void dtrace_difo_init(struct dtrace_difo *dp, struct dtrace_vstate *vstate)
-+{
-+ int i, oldsvars, osz, nsz, otlocals, ntlocals;
-+ uint_t id;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dp->dtdo_buf != NULL && dp->dtdo_len != 0);
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+ struct dtrace_statvar *svar, ***svarp;
-+ size_t dsize = 0;
-+ uint8_t scope = v->dtdv_scope;
-+ int *np;
-+
-+ id = v->dtdv_id;
-+ if (id < DIF_VAR_OTHER_UBASE)
-+ continue;
-+
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ switch (scope) {
-+ case DIFV_SCOPE_THREAD:
-+ while (id >= (otlocals = vstate->dtvs_ntlocals)) {
-+ struct dtrace_difv *tlocals;
-+
-+ ntlocals = otlocals << 1;
-+ if (ntlocals == 0)
-+ ntlocals = 1;
-+
-+ osz = otlocals * sizeof(struct dtrace_difv);
-+ nsz = ntlocals * sizeof(struct dtrace_difv);
-+
-+ tlocals = vzalloc(nsz);
-+
-+ if (osz != 0) {
-+ memcpy(tlocals, vstate->dtvs_tlocals,
-+ osz);
-+ vfree(vstate->dtvs_tlocals);
-+ }
-+
-+ vstate->dtvs_tlocals = tlocals;
-+ vstate->dtvs_ntlocals = ntlocals;
-+ }
-+
-+ vstate->dtvs_tlocals[id] = *v;
-+ continue;
-+
-+ case DIFV_SCOPE_LOCAL:
-+ np = &vstate->dtvs_nlocals;
-+ svarp = &vstate->dtvs_locals;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF)
-+ dsize = NR_CPUS *
-+ (v->dtdv_type.dtdt_size +
-+ sizeof(uint64_t));
-+ else
-+ dsize = NR_CPUS * sizeof(uint64_t);
-+
-+ break;
-+
-+ case DIFV_SCOPE_GLOBAL:
-+ np = &vstate->dtvs_nglobals;
-+ svarp = &vstate->dtvs_globals;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF)
-+ dsize = v->dtdv_type.dtdt_size +
-+ sizeof(uint64_t);
-+
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ continue; /* not reached */
-+ }
-+
-+ while (id >= (oldsvars = *np)) {
-+ struct dtrace_statvar **statics;
-+ int newsvars, oldsize, newsize;
-+
-+ newsvars = oldsvars << 1;
-+ if (newsvars == 0)
-+ newsvars = 1;
-+
-+ oldsize = oldsvars * sizeof(struct dtrace_statvar *);
-+ newsize = newsvars * sizeof(struct dtrace_statvar *);
-+
-+ statics = vzalloc(newsize);
-+
-+ if (oldsize != 0) {
-+ memcpy(statics, *svarp, oldsize);
-+ vfree(*svarp);
-+ }
-+
-+ *svarp = statics;
-+ *np = newsvars;
-+ }
-+
-+ svar = (*svarp)[id];
-+ if (svar == NULL) {
-+ svar = kzalloc(sizeof(struct dtrace_statvar),
-+ GFP_KERNEL);
-+ svar->dtsv_var = *v;
-+
-+ svar->dtsv_size = dsize;
-+ if (svar->dtsv_size != 0) {
-+ svar->dtsv_data =
-+ (uint64_t)(uintptr_t)vzalloc(dsize);
-+ }
-+
-+ (*svarp)[id] = svar;
-+ }
-+
-+ svar->dtsv_refcnt++;
-+ }
-+
-+ dtrace_difo_chunksize(dp, vstate);
-+ dtrace_difo_hold(dp);
-+}
-+
-+struct dtrace_difo *dtrace_difo_duplicate(struct dtrace_difo *dp,
-+ struct dtrace_vstate *vstate)
-+{
-+ struct dtrace_difo *new;
-+ size_t sz;
-+
-+ ASSERT(dp->dtdo_buf != NULL);
-+ ASSERT(dp->dtdo_refcnt != 0);
-+
-+ new = kzalloc(sizeof(struct dtrace_difo), GFP_KERNEL);
-+
-+ ASSERT(dp->dtdo_buf != NULL);
-+ sz = dp->dtdo_len * sizeof(dif_instr_t);
-+ new->dtdo_buf = vmalloc(sz);
-+ memcpy(new->dtdo_buf, dp->dtdo_buf, sz);
-+ new->dtdo_len = dp->dtdo_len;
-+
-+ if (dp->dtdo_strtab != NULL) {
-+ ASSERT(dp->dtdo_strlen != 0);
-+ new->dtdo_strtab = vmalloc(dp->dtdo_strlen);
-+ memcpy(new->dtdo_strtab, dp->dtdo_strtab, dp->dtdo_strlen);
-+ new->dtdo_strlen = dp->dtdo_strlen;
-+ }
-+
-+ if (dp->dtdo_inttab != NULL) {
-+ ASSERT(dp->dtdo_intlen != 0);
-+ sz = dp->dtdo_intlen * sizeof(uint64_t);
-+ new->dtdo_inttab = vmalloc(sz);
-+ memcpy(new->dtdo_inttab, dp->dtdo_inttab, sz);
-+ new->dtdo_intlen = dp->dtdo_intlen;
-+ }
-+
-+ if (dp->dtdo_vartab != NULL) {
-+ ASSERT(dp->dtdo_varlen != 0);
-+ sz = dp->dtdo_varlen * sizeof(struct dtrace_difv);
-+ new->dtdo_vartab = vmalloc(sz);
-+ memcpy(new->dtdo_vartab, dp->dtdo_vartab, sz);
-+ new->dtdo_varlen = dp->dtdo_varlen;
-+ }
-+
-+ dtrace_difo_init(new, vstate);
-+
-+ return new;
-+}
-+
-+void dtrace_difo_destroy(struct dtrace_difo *dp, struct dtrace_vstate *vstate)
-+{
-+ int i;
-+
-+ ASSERT(dp->dtdo_refcnt == 0);
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+ struct dtrace_statvar *svar, **svarp;
-+ uint_t id;
-+ uint8_t scope = v->dtdv_scope;
-+ int *np;
-+
-+ switch (scope) {
-+ case DIFV_SCOPE_THREAD:
-+ continue;
-+
-+ case DIFV_SCOPE_LOCAL:
-+ np = &vstate->dtvs_nlocals;
-+ svarp = vstate->dtvs_locals;
-+ break;
-+
-+ case DIFV_SCOPE_GLOBAL:
-+ np = &vstate->dtvs_nglobals;
-+ svarp = vstate->dtvs_globals;
-+ break;
-+
-+ default:
-+ BUG();
-+ }
-+
-+ id = v->dtdv_id;
-+ if (id < DIF_VAR_OTHER_UBASE)
-+ continue;
-+
-+ id -= DIF_VAR_OTHER_UBASE;
-+ ASSERT(id < *np);
-+
-+ svar = svarp[id];
-+ ASSERT(svar != NULL);
-+ ASSERT(svar->dtsv_refcnt > 0);
-+
-+ if (--svar->dtsv_refcnt > 0)
-+ continue;
-+
-+ if (svar->dtsv_size != 0) {
-+ ASSERT((void *)(uintptr_t)svar->dtsv_data != NULL);
-+ vfree((void *)(uintptr_t)svar->dtsv_data);
-+ }
-+
-+ kfree(svar);
-+ svarp[id] = NULL;
-+ }
-+
-+ vfree(dp->dtdo_buf);
-+ vfree(dp->dtdo_inttab);
-+ vfree(dp->dtdo_strtab);
-+ vfree(dp->dtdo_vartab);
-+ kfree(dp);
-+}
-+
-+void dtrace_difo_release(struct dtrace_difo *dp, struct dtrace_vstate *vstate)
-+{
-+ int i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dp->dtdo_refcnt != 0);
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+
-+ if (v->dtdv_id != DIF_VAR_VTIMESTAMP)
-+ continue;
-+
-+ ASSERT(dtrace_vtime_references > 0);
-+
-+ if (--dtrace_vtime_references == 0)
-+ dtrace_vtime_disable();
-+ }
-+
-+ if (--dp->dtdo_refcnt == 0)
-+ dtrace_difo_destroy(dp, vstate);
-+}
-+
-+/*
-+ * The key for a thread-local variable consists of the lower 60 bits of the
-+ * task pid, prefixed by a 4 bits indicating whether a hard_irq is active.
-+ * This accounts for a case where some older drivers re-enable interrupts
-+ * and can nest in hard irq context.
-+ *
-+ * All per-cpu idle threads share same pid 0. In this special case we replace
-+ * the pid with cpu id (an idle thread is bound to a single cpu). If pid is
-+ * not 0 then a NR_CPUS is added. This assures that the thread key for idle
-+ * thread never conflicts with regular pids in range 0..NR_CPUS.
-+ *
-+ * We add DIF_VARIABLE_MAX to the pid to assure that the thread key is never
-+ * equal to a variable identifier. This is necessary (but not sufficient) to
-+ * assure that global associative arrays never collide with thread-local
-+ * variables. To guarantee that they cannot collide, we must also define the
-+ * order for keying dynamic variables. That order is:
-+ *
-+ * [ key0 ] ... [ keyn ] [ variable-key ] [ tls-key ]
-+ *
-+ * Because the variable-key and the tls-key are in orthogonal spaces, there is
-+ * no way for a global variable key signature to match a thread-local key
-+ * signature.
-+ */
-+#define DTRACE_TLS_THRKEY(where) \
-+ { \
-+ uint_t intr = hardirq_count() >> HARDIRQ_SHIFT; \
-+ uint_t cpu = (current->flags & PF_IDLE) ? \
-+ smp_processor_id() : NR_CPUS; \
-+ \
-+ (where) = ((current->pid + cpu + DIF_VARIABLE_MAX) & \
-+ (((uint64_t)1 << 60) - 1)) | \
-+ ((uint64_t)intr << 60); \
-+ }
-+
-+#ifndef FIXME
-+# define DTRACE_ALIGNCHECK(addr, size, flags)
-+#endif
-+
-+/*
-+ * Test whether a range of memory starting at testaddr of size testsz falls
-+ * within the range of memory described by addr, sz. We take care to avoid
-+ * problems with overflow and underflow of the unsigned quantities, and
-+ * disallow all negative sizes. Ranges of size 0 are allowed.
-+ */
-+#define DTRACE_INRANGE(testaddr, testsz, baseaddr, basesz) \
-+ ((testaddr) - (baseaddr) < (basesz) && \
-+ (testaddr) + (testsz) - (baseaddr) <= (basesz) && \
-+ (testaddr) + (testsz) >= (testaddr))
-+
-+#define DTRACE_LOADFUNC(bits) \
-+ uint##bits##_t dtrace_load##bits(uintptr_t addr) \
-+ { \
-+ size_t size = bits / NBBY; \
-+ uint##bits##_t rval; \
-+ int i; \
-+ volatile uint16_t *flags = (volatile uint16_t *) \
-+ &this_cpu_core->cpuc_dtrace_flags; \
-+ \
-+ /* \
-+ * Deviation from the OpenSolaris code... Protect \
-+ * against dereferencing the NULL pointer since that \
-+ * really causes us a lot of grief (crash). \
-+ */ \
-+ if (addr == 0) { \
-+ *flags |= CPU_DTRACE_BADADDR; \
-+ this_cpu_core->cpuc_dtrace_illval = addr; \
-+ return 0; \
-+ } \
-+ \
-+ DTRACE_ALIGNCHECK(addr, size, flags); \
-+ \
-+ for (i = 0; i < dtrace_toxranges; i++) { \
-+ if (addr >= dtrace_toxrange[i].dtt_limit) \
-+ continue; \
-+ \
-+ if (addr + size <= dtrace_toxrange[i].dtt_base) \
-+ continue; \
-+ \
-+ /* \
-+ * This address falls within a toxic region. \
-+ */ \
-+ *flags |= CPU_DTRACE_BADADDR; \
-+ this_cpu_core->cpuc_dtrace_illval = addr; \
-+ return 0; \
-+ } \
-+ \
-+ *flags |= CPU_DTRACE_NOFAULT; \
-+ rval = *((volatile uint##bits##_t *)addr); \
-+ *flags &= ~CPU_DTRACE_NOFAULT; \
-+ \
-+ return !(*flags & CPU_DTRACE_FAULT) ? rval : 0; \
-+ }
-+
-+/*
-+ * Use the DTRACE_LOADFUNC macro to define functions for each of loading a
-+ * uint8_t, a uint16_t, a uint32_t and a uint64_t.
-+ */
-+DTRACE_LOADFUNC(8)
-+DTRACE_LOADFUNC(16)
-+DTRACE_LOADFUNC(32)
-+DTRACE_LOADFUNC(64)
-+
-+#define DT_BSWAP_8(x) ((x) & 0xff)
-+#define DT_BSWAP_16(x) ((DT_BSWAP_8(x) << 8) | DT_BSWAP_8((x) >> 8))
-+#define DT_BSWAP_32(x) ((DT_BSWAP_16(x) << 16) | DT_BSWAP_16((x) >> 16))
-+#define DT_BSWAP_64(x) ((DT_BSWAP_32(x) << 32) | DT_BSWAP_32((x) >> 32))
-+
-+static int dtrace_inscratch(uintptr_t dest, size_t size,
-+ struct dtrace_mstate *mstate)
-+{
-+ if (dest < mstate->dtms_scratch_base)
-+ return 0;
-+
-+ if (dest + size < dest)
-+ return 0;
-+
-+ if (dest + size > mstate->dtms_scratch_ptr)
-+ return 0;
-+
-+ return 1;
-+}
-+
-+static int dtrace_canstore_statvar(uint64_t addr, size_t sz,
-+ struct dtrace_statvar **svars, int nsvars)
-+{
-+ int i;
-+
-+ for (i = 0; i < nsvars; i++) {
-+ struct dtrace_statvar *svar = svars[i];
-+
-+ if (svar == NULL || svar->dtsv_size == 0)
-+ continue;
-+
-+ if (DTRACE_INRANGE(addr, sz, svar->dtsv_data, svar->dtsv_size))
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Check to see if the address is within a memory region to which a store may
-+ * be issued. This includes the DTrace scratch areas, and any DTrace variable
-+ * region. The caller of dtrace_canstore() is responsible for performing any
-+ * alignment checks that are needed before stores are actually executed.
-+ */
-+static int dtrace_canstore(uint64_t addr, size_t sz,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate)
-+{
-+ /*
-+ * First, check to see if the address is in scratch space...
-+ */
-+ if (DTRACE_INRANGE(addr, sz, mstate->dtms_scratch_base,
-+ mstate->dtms_scratch_size))
-+ return 1;
-+
-+ /*
-+ * Now check to see if it's a dynamic variable. This check will pick
-+ * up both thread-local variables and any global dynamically-allocated
-+ * variables.
-+ */
-+ if (DTRACE_INRANGE(addr, sz, (uintptr_t)vstate->dtvs_dynvars.dtds_base,
-+ vstate->dtvs_dynvars.dtds_size)) {
-+ struct dtrace_dstate *dstate = &vstate->dtvs_dynvars;
-+ uintptr_t base = (uintptr_t)dstate->dtds_base +
-+ (dstate->dtds_hashsize *
-+ sizeof(struct dtrace_dynhash));
-+ uintptr_t chunkoffs;
-+ uint64_t num;
-+
-+ /*
-+ * Before we assume that we can store here, we need to make
-+ * sure that it isn't in our metadata -- storing to our
-+ * dynamic variable metadata would corrupt our state. For
-+ * the range to not include any dynamic variable metadata,
-+ * it must:
-+ *
-+ * (1) Start above the hash table that is at the base of
-+ * the dynamic variable space
-+ *
-+ * (2) Have a starting chunk offset that is beyond the
-+ * dtrace_dynvar_t that is at the base of every chunk
-+ *
-+ * (3) Not span a chunk boundary
-+ */
-+ if (addr < base)
-+ return 0;
-+
-+ num = addr - base;
-+ chunkoffs = do_div(num, dstate->dtds_chunksize);
-+
-+ if (chunkoffs < sizeof(struct dtrace_dynvar))
-+ return 0;
-+
-+ if (chunkoffs + sz > dstate->dtds_chunksize)
-+ return 0;
-+
-+ return 1;
-+ }
-+
-+ /*
-+ * Finally, check the static local and global variables. These checks
-+ * take the longest, so we perform them last.
-+ */
-+ if (dtrace_canstore_statvar(addr, sz, vstate->dtvs_locals,
-+ vstate->dtvs_nlocals))
-+ return 1;
-+
-+ if (dtrace_canstore_statvar(addr, sz, vstate->dtvs_globals,
-+ vstate->dtvs_nglobals))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Convenience routine to check to see if the address is within a memory
-+ * region in which a load may be issued given the user's privilege level;
-+ * if not, it sets the appropriate error flags and loads 'addr' into the
-+ * illegal value slot.
-+ *
-+ * DTrace subroutines (DIF_SUBR_*) should use this helper to implement
-+ * appropriate memory access protection.
-+ */
-+int
-+dtrace_canload(uintptr_t addr, size_t sz, struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate)
-+{
-+ volatile uintptr_t *illval = &this_cpu_core->cpuc_dtrace_illval;
-+
-+ /*
-+ * If we hold the privilege to read from kernel memory, then
-+ * everything is readable.
-+ */
-+ if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0)
-+ return 1;
-+
-+ /*
-+ * You can obviously read that which you can store.
-+ */
-+ if (dtrace_canstore(addr, sz, mstate, vstate))
-+ return 1;
-+
-+ /*
-+ * We're allowed to read from our own string table.
-+ */
-+ if (DTRACE_INRANGE(addr, sz, (uintptr_t)mstate->dtms_difo->dtdo_strtab,
-+ mstate->dtms_difo->dtdo_strlen))
-+ return 1;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
-+ *illval = addr;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Convenience routine to check to see if a given string is within a memory
-+ * region in which a load may be issued given the user's privilege level;
-+ * this exists so that we don't need to issue unnecessary dtrace_strlen()
-+ * calls in the event that the user has all privileges.
-+ */
-+static int
-+dtrace_strcanload(uint64_t addr, size_t sz, struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate)
-+{
-+ size_t strsz;
-+
-+ /*
-+ * If we hold the privilege to read from kernel memory, then
-+ * everything is readable.
-+ */
-+ if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0)
-+ return 1;
-+
-+ strsz = 1 + dtrace_strlen((char *)(uintptr_t)addr, sz);
-+ if (dtrace_canload(addr, strsz, mstate, vstate))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Convenience routine to check to see if a given variable is within a memory
-+ * region in which a load may be issued given the user's privilege level.
-+ */
-+int dtrace_vcanload(void *src, struct dtrace_diftype *diftype,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate)
-+{
-+ size_t sz;
-+
-+ ASSERT(diftype->dtdt_flags & DIF_TF_BYREF);
-+
-+ /*
-+ * If we hold the privilege to read from kernel memory, then
-+ * everything is readable.
-+ */
-+ if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0)
-+ return 1;
-+
-+ if (diftype->dtdt_kind == DIF_TYPE_STRING)
-+ sz = dtrace_strlen(
-+ src,
-+ vstate->dtvs_state->dts_options[DTRACEOPT_STRSIZE]
-+ ) + 1;
-+ else
-+ sz = diftype->dtdt_size;
-+
-+ return dtrace_canload((uintptr_t)src, sz, mstate, vstate);
-+}
-+
-+/*
-+ * Copy src to dst using safe memory accesses. The src is assumed to be unsafe
-+ * memory specified by the DIF program. The dst is assumed to be safe memory
-+ * that we can store to directly because it is managed by DTrace. As with
-+ * standard bcopy, overlapping copies are handled properly.
-+ */
-+static void dtrace_bcopy(const void *src, void *dst, size_t len)
-+{
-+ if (len != 0) {
-+ uint8_t *s1 = dst;
-+ const uint8_t *s2 = src;
-+
-+ if (s1 <= s2) {
-+ do {
-+ *s1++ = dtrace_load8((uintptr_t)s2++);
-+ } while (--len != 0);
-+ } else {
-+ s2 += len;
-+ s1 += len;
-+
-+ do {
-+ *--s1 = dtrace_load8((uintptr_t)--s2);
-+ } while (--len != 0);
-+ }
-+ }
-+}
-+
-+/*
-+ * Copy src to dst using safe memory accesses, up to either the specified
-+ * length, or the point that a nul byte is encountered. The src is assumed to
-+ * be unsafe memory specified by the DIF program. The dst is assumed to be
-+ * safe memory that we can store to directly because it is managed by DTrace.
-+ * Unlike dtrace_bcopy(), overlapping regions are not handled.
-+ */
-+static void dtrace_strcpy(const void *src, void *dst, size_t len)
-+{
-+ if (len != 0) {
-+ uint8_t *s1 = dst, c;
-+ const uint8_t *s2 = src;
-+
-+ do {
-+ *s1++ = c = dtrace_load8((uintptr_t)s2++);
-+ } while (--len != 0 && c != '\0');
-+ }
-+}
-+/*
-+ * Copy src to dst, deriving the size and type from the specified (BYREF)
-+ * variable type. The src is assumed to be unsafe memory specified by the DIF
-+ * program. The dst is assumed to be DTrace variable memory that is of the
-+ * specified type; we assume that we can store to directly.
-+ */
-+static void dtrace_vcopy(void *src, void *dst, struct dtrace_diftype *diftype)
-+{
-+ ASSERT(diftype->dtdt_flags & DIF_TF_BYREF);
-+
-+ if (diftype->dtdt_kind == DIF_TYPE_STRING)
-+ dtrace_strcpy(src, dst, diftype->dtdt_size);
-+ else
-+ dtrace_bcopy(src, dst, diftype->dtdt_size);
-+}
-+
-+/*
-+ * Compare s1 to s2 using safe memory accesses. The s1 data is assumed to be
-+ * unsafe memory specified by the DIF program. The s2 data is assumed to be
-+ * safe memory that we can access directly because it is managed by DTrace.
-+ */
-+static int dtrace_bcmp(const void *s1, const void *s2, size_t len)
-+{
-+ volatile uint16_t *flags;
-+
-+ flags = (volatile uint16_t *)&this_cpu_core->cpuc_dtrace_flags;
-+
-+ if (s1 == s2)
-+ return 0;
-+
-+ if (s1 == NULL || s2 == NULL)
-+ return 1;
-+
-+ if (s1 != s2 && len != 0) {
-+ const uint8_t *ps1 = s1;
-+ const uint8_t *ps2 = s2;
-+
-+ do {
-+ if (dtrace_load8((uintptr_t)ps1++) != *ps2++)
-+ return 1;
-+ } while (--len != 0 && !(*flags & CPU_DTRACE_FAULT));
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Zero the specified region using a simple byte-by-byte loop. Note that this
-+ * is for safe DTrace-managed memory only.
-+ */
-+void dtrace_bzero(void *dst, size_t len)
-+{
-+ uchar_t *cp;
-+
-+ for (cp = dst; len != 0; len--)
-+ *cp++ = 0;
-+}
-+
-+#define DTRACE_DYNHASH_FREE 0
-+#define DTRACE_DYNHASH_SINK 1
-+#define DTRACE_DYNHASH_VALID 2
-+
-+/*
-+ * Depending on the value of the op parameter, this function looks-up,
-+ * allocates or deallocates an arbitrarily-keyed dynamic variable. If an
-+ * allocation is requested, this function will return a pointer to a
-+ * dtrace_dynvar_t corresponding to the allocated variable -- or NULL if no
-+ * variable can be allocated. If NULL is returned, the appropriate counter
-+ * will be incremented.
-+ */
-+static struct dtrace_dynvar *dtrace_dynvar(struct dtrace_dstate *dstate,
-+ uint_t nkeys,
-+ struct dtrace_key *key,
-+ size_t dsize,
-+ enum dtrace_dynvar_op op,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate)
-+{
-+ uint64_t hashval = DTRACE_DYNHASH_VALID;
-+ struct dtrace_dynhash *hash = dstate->dtds_hash;
-+ struct dtrace_dynvar *free, *new_free, *next, *dvar, *start,
-+ *prev = NULL;
-+ processorid_t me = smp_processor_id(), cpu = me;
-+ struct dtrace_dstate_percpu *dcpu = &dstate->dtds_percpu[me];
-+ size_t bucket, ksize;
-+ size_t chunksize = dstate->dtds_chunksize;
-+ uintptr_t kdata, lock;
-+ enum dtrace_dstate_state nstate;
-+ uint_t i;
-+
-+ ASSERT(nkeys != 0);
-+
-+ /*
-+ * Hash the key. As with aggregations, we use Jenkins' "One-at-a-time"
-+ * algorithm. For the by-value portions, we perform the algorithm in
-+ * 16-bit chunks (as opposed to 8-bit chunks). This speeds things up a
-+ * bit, and seems to have only a minute effect on distribution. For
-+ * the by-reference data, we perform "One-at-a-time" iterating (safely)
-+ * over each referenced byte. It's painful to do this, but it's much
-+ * better than pathological hash distribution. The efficacy of the
-+ * hashing algorithm (and a comparison with other algorithms) may be
-+ * found by running the ::dtrace_dynstat MDB dcmd.
-+ */
-+ for (i = 0; i < nkeys; i++) {
-+ if (key[i].dttk_size == 0) {
-+ uint64_t val = key[i].dttk_value;
-+
-+ hashval += (val >> 48) & 0xffff;
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+
-+ hashval += (val >> 32) & 0xffff;
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+
-+ hashval += (val >> 16) & 0xffff;
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+
-+ hashval += val & 0xffff;
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+ } else {
-+ /*
-+ * This is incredibly painful, but it beats the hell
-+ * out of the alternative.
-+ */
-+ uint64_t j, size = key[i].dttk_size;
-+ uintptr_t base = (uintptr_t)key[i].dttk_value;
-+
-+ if (!dtrace_canload(base, size, mstate, vstate))
-+ break;
-+
-+ for (j = 0; j < size; j++) {
-+ hashval += dtrace_load8(base + j);
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+ }
-+ }
-+ }
-+
-+ if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
-+ return NULL;
-+
-+ hashval += (hashval << 3);
-+ hashval ^= (hashval >> 11);
-+ hashval += (hashval << 15);
-+
-+ /*
-+ * There is a remote chance (ideally, 1 in 2^31) that our hashval
-+ * comes out to be one of our two sentinel hash values. If this
-+ * actually happens, we set the hashval to be a value known to be a
-+ * non-sentinel value.
-+ */
-+ if (hashval == DTRACE_DYNHASH_FREE || hashval == DTRACE_DYNHASH_SINK)
-+ hashval = DTRACE_DYNHASH_VALID;
-+
-+ /*
-+ * Yes, it's painful to do a divide here. If the cycle count becomes
-+ * important here, tricks can be pulled to reduce it. (However, it's
-+ * critical that hash collisions be kept to an absolute minimum;
-+ * they're much more painful than a divide.) It's better to have a
-+ * solution that generates few collisions and still keeps things
-+ * relatively simple.
-+ *
-+ * Linux cannot do a straight 64-bit divide without gcc requiring
-+ * linking in code that the kernel doesn't link, so we need to use an
-+ * alternative.
-+ *
-+ * bucket = hashval % dstate->dtds_hashsize;
-+ */
-+ {
-+ uint64_t num;
-+
-+ num = hashval;
-+ bucket = do_div(num, dstate->dtds_hashsize);
-+ }
-+
-+ if (op == DTRACE_DYNVAR_DEALLOC) {
-+ volatile uintptr_t *lockp = &hash[bucket].dtdh_lock;
-+
-+ for (;;) {
-+ while ((lock = *lockp) & 1)
-+ continue;
-+
-+ if (cmpxchg(lockp, lock, (lock + 1)) == lock)
-+ break;
-+ }
-+
-+ dtrace_membar_producer();
-+ }
-+
-+top:
-+ prev = NULL;
-+ lock = hash[bucket].dtdh_lock;
-+
-+ dtrace_membar_consumer();
-+
-+ start = hash[bucket].dtdh_chain;
-+ ASSERT(start != NULL && (start->dtdv_hashval == DTRACE_DYNHASH_SINK ||
-+ start->dtdv_hashval != DTRACE_DYNHASH_FREE ||
-+ op != DTRACE_DYNVAR_DEALLOC));
-+
-+ for (dvar = start; dvar != NULL; dvar = dvar->dtdv_next) {
-+ struct dtrace_tuple *dtuple = &dvar->dtdv_tuple;
-+ struct dtrace_key *dkey = &dtuple->dtt_key[0];
-+
-+ if (dvar->dtdv_hashval != hashval) {
-+ if (dvar->dtdv_hashval == DTRACE_DYNHASH_SINK) {
-+ /*
-+ * We've reached the sink, and therefore the
-+ * end of the hash chain; we can kick out of
-+ * the loop knowing that we have seen a valid
-+ * snapshot of state.
-+ */
-+ ASSERT(dvar->dtdv_next == NULL);
-+ ASSERT(dvar == &dtrace_dynhash_sink);
-+ break;
-+ }
-+
-+ if (dvar->dtdv_hashval == DTRACE_DYNHASH_FREE) {
-+ /*
-+ * We've gone off the rails: somewhere along
-+ * the line, one of the members of this hash
-+ * chain was deleted. Note that we could also
-+ * detect this by simply letting this loop run
-+ * to completion, as we would eventually hit
-+ * the end of the dirty list. However, we
-+ * want to avoid running the length of the
-+ * dirty list unnecessarily (it might be quite
-+ * long), so we catch this as early as
-+ * possible by detecting the hash marker. In
-+ * this case, we simply set dvar to NULL and
-+ * break; the conditional after the loop will
-+ * send us back to top.
-+ */
-+ dvar = NULL;
-+ break;
-+ }
-+
-+ goto next;
-+ }
-+
-+ if (dtuple->dtt_nkeys != nkeys)
-+ goto next;
-+
-+ for (i = 0; i < nkeys; i++, dkey++) {
-+ if (dkey->dttk_size != key[i].dttk_size)
-+ goto next; /* size or type mismatch */
-+
-+ if (dkey->dttk_size != 0) {
-+ if (dtrace_bcmp(
-+ (void *)(uintptr_t)key[i].dttk_value,
-+ (void *)(uintptr_t)dkey->dttk_value,
-+ dkey->dttk_size))
-+ goto next;
-+ } else {
-+ if (dkey->dttk_value != key[i].dttk_value)
-+ goto next;
-+ }
-+ }
-+
-+ if (op != DTRACE_DYNVAR_DEALLOC)
-+ return dvar;
-+
-+ ASSERT(dvar->dtdv_next == NULL ||
-+ dvar->dtdv_next->dtdv_hashval != DTRACE_DYNHASH_FREE);
-+
-+ if (prev != NULL) {
-+ ASSERT(hash[bucket].dtdh_chain != dvar);
-+ ASSERT(start != dvar);
-+ ASSERT(prev->dtdv_next == dvar);
-+ prev->dtdv_next = dvar->dtdv_next;
-+ } else {
-+ if (cmpxchg(&hash[bucket].dtdh_chain, start,
-+ dvar->dtdv_next) != start) {
-+ /*
-+ * We have failed to atomically swing the
-+ * hash table head pointer, presumably because
-+ * of a conflicting allocation on another CPU.
-+ * We need to reread the hash chain and try
-+ * again.
-+ */
-+ goto top;
-+ }
-+ }
-+
-+ dtrace_membar_producer();
-+
-+ /*
-+ * Now set the hash value to indicate that it's free.
-+ */
-+ ASSERT(hash[bucket].dtdh_chain != dvar);
-+ dvar->dtdv_hashval = DTRACE_DYNHASH_FREE;
-+
-+ dtrace_membar_producer();
-+
-+ /*
-+ * Set the next pointer to point at the dirty list, and
-+ * atomically swing the dirty pointer to the newly freed dvar.
-+ */
-+ do {
-+ next = dcpu->dtdsc_dirty;
-+ dvar->dtdv_next = next;
-+ } while (cmpxchg(&dcpu->dtdsc_dirty, next, dvar) != next);
-+
-+ /*
-+ * Finally, unlock this hash bucket.
-+ */
-+ ASSERT(hash[bucket].dtdh_lock == lock);
-+ ASSERT(lock & 1);
-+ hash[bucket].dtdh_lock++;
-+
-+ return NULL;
-+next:
-+ prev = dvar;
-+ continue;
-+ }
-+
-+ if (dvar == NULL) {
-+ /*
-+ * If dvar is NULL, it is because we went off the rails:
-+ * one of the elements that we traversed in the hash chain
-+ * was deleted while we were traversing it. In this case,
-+ * we assert that we aren't doing a dealloc (deallocs lock
-+ * the hash bucket to prevent themselves from racing with
-+ * one another), and retry the hash chain traversal.
-+ */
-+ ASSERT(op != DTRACE_DYNVAR_DEALLOC);
-+ goto top;
-+ }
-+
-+ if (op != DTRACE_DYNVAR_ALLOC) {
-+ /*
-+ * If we are not to allocate a new variable, we want to
-+ * return NULL now. Before we return, check that the value
-+ * of the lock word hasn't changed. If it has, we may have
-+ * seen an inconsistent snapshot.
-+ */
-+ if (op == DTRACE_DYNVAR_NOALLOC) {
-+ if (hash[bucket].dtdh_lock != lock)
-+ goto top;
-+ } else {
-+ ASSERT(op == DTRACE_DYNVAR_DEALLOC);
-+ ASSERT(hash[bucket].dtdh_lock == lock);
-+ ASSERT(lock & 1);
-+ hash[bucket].dtdh_lock++;
-+ }
-+
-+ return NULL;
-+ }
-+
-+ /*
-+ * We need to allocate a new dynamic variable. The size we need is the
-+ * size of dtrace_dynvar plus the size of nkeys dtrace_key_t's plus the
-+ * size of any auxiliary key data (rounded up to 8-byte alignment) plus
-+ * the size of any referred-to data (dsize). We then round the final
-+ * size up to the chunksize for allocation.
-+ */
-+ for (ksize = 0, i = 0; i < nkeys; i++)
-+ ksize += P2ROUNDUP(key[i].dttk_size, sizeof(uint64_t));
-+
-+ /*
-+ * This should be pretty much impossible, but could happen if, say,
-+ * strange DIF specified the tuple. Ideally, this should be an
-+ * assertion and not an error condition -- but that requires that the
-+ * chunksize calculation in dtrace_difo_chunksize() be absolutely
-+ * bullet-proof. (That is, it must not be able to be fooled by
-+ * malicious DIF.) Given the lack of backwards branches in DIF,
-+ * solving this would presumably not amount to solving the Halting
-+ * Problem -- but it still seems awfully hard.
-+ */
-+ if (sizeof(struct dtrace_dynvar) +
-+ sizeof(struct dtrace_key) * (nkeys - 1) +
-+ ksize + dsize > chunksize) {
-+ dcpu->dtdsc_drops++;
-+ return NULL;
-+ }
-+
-+ nstate = DTRACE_DSTATE_EMPTY;
-+
-+ do {
-+retry:
-+ free = dcpu->dtdsc_free;
-+
-+ if (free == NULL) {
-+ struct dtrace_dynvar *clean = dcpu->dtdsc_clean;
-+ void *rval;
-+
-+ if (clean == NULL) {
-+ /*
-+ * We're out of dynamic variable space on
-+ * this CPU. Unless we have tried all CPUs,
-+ * we'll try to allocate from a different
-+ * CPU.
-+ */
-+ switch (dstate->dtds_state) {
-+ case DTRACE_DSTATE_CLEAN: {
-+ enum dtrace_dstate_state *sp =
-+ (enum dtrace_dstate_state *)
-+ &dstate->dtds_state;
-+
-+ if (++cpu >= NR_CPUS)
-+ cpu = 0;
-+
-+ if (dcpu->dtdsc_dirty != NULL &&
-+ nstate == DTRACE_DSTATE_EMPTY)
-+ nstate = DTRACE_DSTATE_DIRTY;
-+
-+ if (dcpu->dtdsc_rinsing != NULL)
-+ nstate = DTRACE_DSTATE_RINSING;
-+
-+ dcpu = &dstate->dtds_percpu[cpu];
-+
-+ if (cpu != me)
-+ goto retry;
-+
-+ cmpxchg(sp, DTRACE_DSTATE_CLEAN,
-+ nstate);
-+
-+ /*
-+ * To increment the correct bean
-+ * counter, take another lap.
-+ */
-+ goto retry;
-+ }
-+
-+ case DTRACE_DSTATE_DIRTY:
-+ dcpu->dtdsc_dirty_drops++;
-+ break;
-+
-+ case DTRACE_DSTATE_RINSING:
-+ dcpu->dtdsc_rinsing_drops++;
-+ break;
-+
-+ case DTRACE_DSTATE_EMPTY:
-+ dcpu->dtdsc_drops++;
-+ break;
-+ }
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_DROP);
-+ return NULL;
-+ }
-+
-+ /*
-+ * The clean list appears to be non-empty. We want to
-+ * move the clean list to the free list; we start by
-+ * moving the clean pointer aside.
-+ */
-+ if (cmpxchg(&dcpu->dtdsc_clean, clean, NULL) != clean)
-+ /*
-+ * We are in one of two situations:
-+ *
-+ * (a) The clean list was switched to the
-+ * free list by another CPU.
-+ *
-+ * (b) The clean list was added to by the
-+ * cleansing cyclic.
-+ *
-+ * In either of these situations, we can
-+ * just reattempt the free list allocation.
-+ */
-+ goto retry;
-+
-+ ASSERT(clean->dtdv_hashval == DTRACE_DYNHASH_FREE);
-+
-+ /*
-+ * Now we'll move the clean list to the free list.
-+ * It's impossible for this to fail: the only way
-+ * the free list can be updated is through this
-+ * code path, and only one CPU can own the clean list.
-+ * Thus, it would only be possible for this to fail if
-+ * this code were racing with dtrace_dynvar_clean().
-+ * (That is, if dtrace_dynvar_clean() updated the clean
-+ * list, and we ended up racing to update the free
-+ * list.) This race is prevented by the dtrace_sync()
-+ * in dtrace_dynvar_clean() -- which flushes the
-+ * owners of the clean lists out before resetting
-+ * the clean lists.
-+ */
-+ rval = cmpxchg(&dcpu->dtdsc_free, NULL, clean);
-+ ASSERT(rval == NULL);
-+
-+ goto retry;
-+ }
-+
-+ dvar = free;
-+ new_free = dvar->dtdv_next;
-+ } while (cmpxchg(&dcpu->dtdsc_free, free, new_free) != free);
-+
-+ /*
-+ * We have now allocated a new chunk. We copy the tuple keys into the
-+ * tuple array and copy any referenced key data into the data space
-+ * following the tuple array. As we do this, we relocate dttk_value
-+ * in the final tuple to point to the key data address in the chunk.
-+ */
-+ kdata = (uintptr_t)&dvar->dtdv_tuple.dtt_key[nkeys];
-+ dvar->dtdv_data = (void *)(kdata + ksize);
-+ dvar->dtdv_tuple.dtt_nkeys = nkeys;
-+
-+ for (i = 0; i < nkeys; i++) {
-+ struct dtrace_key *dkey = &dvar->dtdv_tuple.dtt_key[i];
-+ size_t kesize = key[i].dttk_size;
-+
-+ if (kesize != 0) {
-+ dtrace_bcopy(
-+ (const void *)(uintptr_t)key[i].dttk_value,
-+ (void *)kdata, kesize);
-+ dkey->dttk_value = kdata;
-+ kdata += P2ROUNDUP(kesize, sizeof(uint64_t));
-+ } else
-+ dkey->dttk_value = key[i].dttk_value;
-+
-+ dkey->dttk_size = kesize;
-+ }
-+
-+ ASSERT(dvar->dtdv_hashval == DTRACE_DYNHASH_FREE);
-+ dvar->dtdv_hashval = hashval;
-+ dvar->dtdv_next = start;
-+
-+ if (cmpxchg(&hash[bucket].dtdh_chain, start, dvar) == start)
-+ return dvar;
-+
-+ /*
-+ * The cas has failed. Either another CPU is adding an element to
-+ * this hash chain, or another CPU is deleting an element from this
-+ * hash chain. The simplest way to deal with both of these cases
-+ * (though not necessarily the most efficient) is to free our
-+ * allocated block and tail-call ourselves. Note that the free is
-+ * to the dirty list and _not_ to the free list. This is to prevent
-+ * races with allocators, above.
-+ */
-+ dvar->dtdv_hashval = DTRACE_DYNHASH_FREE;
-+
-+ dtrace_membar_producer();
-+
-+ do {
-+ free = dcpu->dtdsc_dirty;
-+ dvar->dtdv_next = free;
-+ } while (cmpxchg(&dcpu->dtdsc_dirty, free, dvar) != free);
-+
-+ return dtrace_dynvar(dstate, nkeys, key, dsize, op, mstate, vstate);
-+}
-+
-+/*
-+ * Return a string. In the event that the user lacks the privilege to access
-+ * arbitrary kernel memory, we copy the string out to scratch memory so that we
-+ * don't fail access checking.
-+ *
-+ * dtrace_dif_variable() uses this routine as a helper for various
-+ * builtin values such as 'execname' and 'probefunc.'
-+ */
-+static uintptr_t dtrace_dif_varstr(uintptr_t addr, struct dtrace_state *state,
-+ struct dtrace_mstate *mstate)
-+{
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ uintptr_t ret;
-+ size_t strsz;
-+
-+ /*
-+ * The easy case: this probe is allowed to read all of memory, so
-+ * we can just return this as a vanilla pointer.
-+ */
-+ if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0)
-+ return addr;
-+
-+ /*
-+ * This is the tougher case: we copy the string in question from
-+ * kernel memory into scratch memory and return it that way: this
-+ * ensures that we won't trip up when access checking tests the
-+ * BYREF return value.
-+ */
-+ strsz = dtrace_strlen((char *)addr, size) + 1;
-+
-+ if (mstate->dtms_scratch_ptr + strsz >
-+ mstate->dtms_scratch_base + mstate->dtms_scratch_size) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ return (uintptr_t)NULL;
-+ }
-+
-+ dtrace_strcpy((const void *)addr, (void *)mstate->dtms_scratch_ptr,
-+ strsz);
-+ ret = mstate->dtms_scratch_ptr;
-+ mstate->dtms_scratch_ptr += strsz;
-+
-+ return ret;
-+}
-+
-+/*
-+ * This function implements the DIF emulator's variable lookups. The emulator
-+ * passes a reserved variable identifier and optional built-in array index.
-+ *
-+ * This function is annotated to be always inlined in dtrace_dif_emulate()
-+ * because (1) that is the only place where it is called from, and (2) it has
-+ * come to our attention that some GCC versions inline it automatically while
-+ * others do not and that messes up the number of frames to skip (aframes).
-+ */
-+static __always_inline uint64_t dtrace_dif_variable(struct dtrace_mstate *mstate,
-+ struct dtrace_state *state,
-+ uint64_t v, uint64_t ndx)
-+{
-+ /*
-+ * If we're accessing one of the uncached arguments, we'll turn this
-+ * into a reference in the args array.
-+ */
-+ if (v >= DIF_VAR_ARG0 && v <= DIF_VAR_ARG9) {
-+ ndx = v - DIF_VAR_ARG0;
-+ v = DIF_VAR_ARGS;
-+ }
-+
-+ switch (v) {
-+ case DIF_VAR_ARGS:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_ARGS);
-+
-+ if (ndx >= DTRACE_MSTATE_ARGS_MAX) {
-+ int aframes =
-+ mstate->dtms_probe->dtpr_aframes + 1;
-+ struct dtrace_provider *pv;
-+ uint64_t val;
-+
-+ pv = mstate->dtms_probe->dtpr_provider;
-+ if (pv->dtpv_pops.dtps_getargval != NULL)
-+ val = pv->dtpv_pops.dtps_getargval(
-+ pv->dtpv_arg,
-+ mstate->dtms_probe->dtpr_id,
-+ mstate->dtms_probe->dtpr_arg,
-+ ndx, aframes);
-+ else
-+ val = dtrace_getarg(ndx, aframes);
-+
-+ /*
-+ * This is regrettably required to keep the compiler
-+ * from tail-optimizing the call to dtrace_getarg().
-+ * The condition always evaluates to true, but the
-+ * compiler has no way of figuring that out a priori.
-+ * (None of this would be necessary if the compiler
-+ * could be relied upon to _always_ tail-optimize
-+ * the call to dtrace_getarg() -- but it can't.)
-+ */
-+ if (mstate->dtms_probe != NULL)
-+ return val;
-+
-+ ASSERT(0);
-+ }
-+
-+ return mstate->dtms_arg[ndx];
-+
-+ case DIF_VAR_UREGS: {
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ return dtrace_getreg(current, ndx);
-+ }
-+
-+ case DIF_VAR_CURTHREAD:
-+ if (!dtrace_priv_kernel(state))
-+ return 0;
-+
-+ return (uint64_t)(uintptr_t)current;
-+
-+ case DIF_VAR_TIMESTAMP:
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_TIMESTAMP)) {
-+ mstate->dtms_timestamp = dtrace_gethrtime();
-+ mstate->dtms_present |= DTRACE_MSTATE_TIMESTAMP;
-+ }
-+
-+ return ktime_to_ns(mstate->dtms_timestamp);
-+
-+ case DIF_VAR_WALLTIMESTAMP:
-+ return ktime_to_ns(dtrace_get_walltime());
-+
-+ case DIF_VAR_VTIMESTAMP:
-+ ASSERT(dtrace_vtime_references != 0);
-+
-+ if (current->dt_task != NULL)
-+ return ktime_to_ns(current->dt_task->dt_vtime);
-+
-+ /*
-+ * This is not ideal but without any data available
-+ * there is no reasonable default value for vtimestamp
-+ * variable.
-+ */
-+ return ktime_to_ns(0);
-+
-+ case DIF_VAR_IPL:
-+ if (!dtrace_priv_kernel(state))
-+ return 0;
-+
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_IPL)) {
-+ mstate->dtms_ipl = dtrace_getipl();
-+ mstate->dtms_present |= DTRACE_MSTATE_IPL;
-+ }
-+
-+ return mstate->dtms_ipl;
-+
-+ case DIF_VAR_EPID:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_EPID);
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_EPID);
-+
-+ return mstate->dtms_epid;
-+
-+ case DIF_VAR_ID:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+ return mstate->dtms_probe->dtpr_id;
-+
-+ case DIF_VAR_STACKDEPTH:
-+ if (!dtrace_priv_kernel(state))
-+ return 0;
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_STACKDEPTH)) {
-+ int aframes = mstate->dtms_probe->dtpr_aframes + 2;
-+
-+ mstate->dtms_stackdepth = dtrace_getstackdepth(
-+ mstate, aframes);
-+ mstate->dtms_present |= DTRACE_MSTATE_STACKDEPTH;
-+ }
-+
-+ return mstate->dtms_stackdepth;
-+
-+ case DIF_VAR_USTACKDEPTH:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_USTACKDEPTH)) {
-+ /*
-+ * See comment in DIF_VAR_PID.
-+ */
-+ if (DTRACE_ANCHORED(mstate->dtms_probe) &&
-+ in_interrupt())
-+ mstate->dtms_ustackdepth = 0;
-+ else
-+ mstate->dtms_ustackdepth =
-+ dtrace_getustackdepth();
-+
-+ mstate->dtms_present |= DTRACE_MSTATE_USTACKDEPTH;
-+ }
-+
-+ return mstate->dtms_ustackdepth;
-+
-+ case DIF_VAR_CALLER:
-+ if (!dtrace_priv_kernel(state))
-+ return 0;
-+
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_CALLER)) {
-+ int aframes = mstate->dtms_probe->dtpr_aframes + 1;
-+
-+ if (!DTRACE_ANCHORED(mstate->dtms_probe)) {
-+ /*
-+ * If this is an unanchored probe, we are
-+ * required to go through the slow path:
-+ * dtrace_caller() only guarantees correct
-+ * results for anchored probes.
-+ */
-+ uint64_t caller[2];
-+
-+ dtrace_getpcstack(caller, 2, aframes,
-+ (uint32_t *)(uintptr_t)
-+ mstate->dtms_arg[0]);
-+ mstate->dtms_caller = caller[1];
-+ } else if ((mstate->dtms_caller =
-+ dtrace_caller(aframes, 0)) == -1) {
-+ /*
-+ * We have failed to do this the quick way;
-+ * we must resort to the slower approach of
-+ * calling dtrace_getpcstack().
-+ */
-+ uint64_t caller;
-+
-+ dtrace_getpcstack(&caller, 1, aframes, NULL);
-+ mstate->dtms_caller = caller;
-+ }
-+
-+ mstate->dtms_present |= DTRACE_MSTATE_CALLER;
-+ }
-+
-+ return mstate->dtms_caller;
-+
-+ case DIF_VAR_UCALLER:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_UCALLER)) {
-+ uint64_t ustack[4];
-+
-+ /*
-+ * dtrace_getupcstack() fills in the first uint64_t with
-+ * the current PID, and the second uint64_t with the
-+ * current TGID. The third uint64_t will be the
-+ * program counter at user-level. The fourth uint64_t
-+ * will contain the caller, which is what we're after.
-+ */
-+ ustack[3] = 0;
-+ dtrace_getupcstack(ustack, 4);
-+
-+ mstate->dtms_ucaller = ustack[3];
-+ mstate->dtms_present |= DTRACE_MSTATE_UCALLER;
-+ }
-+
-+ return mstate->dtms_ucaller;
-+
-+ case DIF_VAR_PROBEPROV:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+
-+ return dtrace_dif_varstr(
-+ (uintptr_t)mstate->dtms_probe->dtpr_provider->dtpv_name,
-+ state, mstate);
-+
-+ case DIF_VAR_PROBEMOD:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+ return dtrace_dif_varstr(
-+ (uintptr_t)mstate->dtms_probe->dtpr_mod, state,
-+ mstate);
-+
-+ case DIF_VAR_PROBEFUNC:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+
-+ return dtrace_dif_varstr(
-+ (uintptr_t)mstate->dtms_probe->dtpr_func, state,
-+ mstate);
-+
-+ case DIF_VAR_PROBENAME:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+
-+ return dtrace_dif_varstr(
-+ (uintptr_t)mstate->dtms_probe->dtpr_name, state,
-+ mstate);
-+
-+ case DIF_VAR_PID:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * It is always safe to dereference current, it always points
-+ * to a valid task_struct.
-+ */
-+ return (uint64_t)current->tgid;
-+
-+ case DIF_VAR_PPID:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * It is always safe to dereference current, it always points
-+ * to a valid task_struct.
-+ *
-+ * Additionally, it is safe to dereference one's parent, since
-+ * it is never NULL after process birth.
-+ */
-+ return (uint64_t)current->real_parent->tgid;
-+
-+ case DIF_VAR_TID:
-+ return (uint64_t)current->pid;
-+
-+ case DIF_VAR_EXECNAME:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * It is always safe to dereference current, it always points
-+ * to a valid task_struct.
-+ */
-+ return dtrace_dif_varstr((uintptr_t)current->comm, state,
-+ mstate);
-+
-+ case DIF_VAR_ZONENAME:
-+ return 0;
-+
-+ case DIF_VAR_UID:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * It is always safe to dereference current, it always points
-+ * to a valid task_struct.
-+ *
-+ * Additionally, it is safe to dereference one's own process
-+ * credential, since this is never NULL after process birth.
-+ */
-+ return (uint64_t)from_kuid(current_user_ns(),
-+ current_real_cred()->uid);
-+
-+ case DIF_VAR_GID:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * It is always safe to dereference current, it always points
-+ * to a valid task_struct.
-+ *
-+ * Additionally, it is safe to dereference one's own process
-+ * credential, since this is never NULL after process birth.
-+ */
-+ return (uint64_t)from_kgid(current_user_ns(),
-+ current_real_cred()->gid);
-+
-+ case DIF_VAR_ERRNO: {
-+ int64_t arg0;
-+
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * We need to do some magic here to get the correct semantics
-+ * for the 'errno' variable. It can only have a non-zero value
-+ * when executing a system call, and for Linux, only after the
-+ * actual system call implementation has completed, indicating
-+ * in its return value either an error code (-2048 < errno < 0)
-+ * or a valid result. So, the only time we can expect a valid
-+ * value in errno is during the processing of any return probe
-+ * in the syscall provider. In all other cases, it should have
-+ * the value 0.
-+ *
-+ * So, we only look at probes that match: syscall:::return
-+ */
-+ if (strncmp(mstate->dtms_probe->dtpr_provider->dtpv_name,
-+ "syscall", 7) != 0)
-+ return 0;
-+ if (strncmp(mstate->dtms_probe->dtpr_name, "return", 6) != 0)
-+ return 0;
-+
-+ /*
-+ * Error number is present if arg0 lies between 0 and -2048,
-+ * exclusive.
-+ */
-+ arg0 = (int64_t)mstate->dtms_arg[ndx];
-+ if (arg0 < 0 && arg0 > -2048)
-+ return (uint64_t)-arg0;
-+
-+ return 0;
-+ }
-+
-+ case DIF_VAR_CURCPU:
-+ return (uint64_t)(uintptr_t)this_cpu_info;
-+
-+ default:
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return 0;
-+ }
-+}
-+
-+#define DTRACE_V4MAPPED_OFFSET (sizeof(uint32_t) * 3)
-+
-+/*
-+ * Emulate the execution of DTrace ID subroutines invoked by the call opcode.
-+ * Notice that we don't bother validating the proper number of arguments or
-+ * their types in the tuple stack. This isn't needed because all argument
-+ * interpretation is safe because of our load safety -- the worst that can
-+ * happen is that a bogus program can obtain bogus results.
-+ */
-+static void dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
-+ struct dtrace_key *tupregs, int nargs,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_state *state)
-+{
-+ volatile uint16_t *flags = &this_cpu_core->cpuc_dtrace_flags;
-+ volatile uintptr_t *illval = &this_cpu_core->cpuc_dtrace_illval;
-+ struct dtrace_vstate *vstate = &state->dts_vstate;
-+ struct mutex mtx;
-+
-+ union {
-+ rwlock_t ri;
-+ uintptr_t rw;
-+ } r;
-+
-+ dt_dbg_dif(" Subroutine %d\n", subr);
-+
-+ switch (subr) {
-+ case DIF_SUBR_RAND:
-+ regs[rd] = ktime_to_ns(dtrace_gethrtime()) * 2416 + 374441;
-+ regs[rd] = do_div(regs[rd], 1771875);
-+ break;
-+
-+ case DIF_SUBR_MUTEX_OWNED:
-+ if (!dtrace_canload(tupregs[0].dttk_value,
-+ sizeof(struct mutex), mstate, vstate))
-+ break;
-+
-+ dtrace_bcopy((const void *)(uintptr_t)tupregs[0].dttk_value,
-+ &mtx, sizeof(struct mutex));
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+ regs[rd] = mutex_owned(&mtx);
-+ break;
-+
-+ case DIF_SUBR_MUTEX_OWNER:
-+ regs[rd] = 0;
-+ if (!dtrace_canload(tupregs[0].dttk_value,
-+ sizeof(struct mutex), mstate, vstate))
-+ break;
-+
-+ dtrace_bcopy((const void *)(uintptr_t)tupregs[0].dttk_value,
-+ &mtx, sizeof(struct mutex));
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+#ifdef CONFIG_SMP
-+ regs[rd] = (uintptr_t)__mutex_owner(&mtx);
-+#else
-+ regs[rd] = 0;
-+#endif
-+ break;
-+
-+ case DIF_SUBR_MUTEX_TYPE_ADAPTIVE:
-+ if (!dtrace_canload(tupregs[0].dttk_value,
-+ sizeof(struct mutex), mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * On Linux, all mutexes are adaptive.
-+ */
-+ regs[rd] = 1;
-+ break;
-+
-+ case DIF_SUBR_MUTEX_TYPE_SPIN:
-+ if (!dtrace_canload(tupregs[0].dttk_value,
-+ sizeof(struct mutex), mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * On Linux, all mutexes are adaptive.
-+ */
-+ regs[rd] = 0;
-+ break;
-+
-+ case DIF_SUBR_RW_READ_HELD: {
-+ if (!dtrace_canload(tupregs[0].dttk_value, sizeof(rwlock_t),
-+ mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ r.rw = dtrace_loadptr(tupregs[0].dttk_value);
-+ regs[rd] = !peek_write_can_lock(&r.ri) &&
-+ peek_read_can_lock(&r.ri);
-+ break;
-+ }
-+
-+ case DIF_SUBR_RW_WRITE_HELD:
-+ if (!dtrace_canload(tupregs[0].dttk_value, sizeof(rwlock_t),
-+ mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ r.rw = dtrace_loadptr(tupregs[0].dttk_value);
-+ regs[rd] = !peek_write_can_lock(&r.ri);
-+ break;
-+
-+ case DIF_SUBR_RW_ISWRITER:
-+ if (!dtrace_canload(tupregs[0].dttk_value, sizeof(rwlock_t),
-+ mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ r.rw = dtrace_loadptr(tupregs[0].dttk_value);
-+ /*
-+ * On Linux there is no way to determine whether someone is
-+ * trying to acquire a write lock.
-+ */
-+ regs[rd] = !peek_write_can_lock(&r.ri);
-+ break;
-+
-+ case DIF_SUBR_BCOPY: {
-+ /*
-+ * We need to be sure that the destination is in the scratch
-+ * region -- no other region is allowed.
-+ */
-+ uintptr_t src = tupregs[0].dttk_value;
-+ uintptr_t dest = tupregs[1].dttk_value;
-+ size_t size = tupregs[2].dttk_value;
-+
-+ if (!dtrace_inscratch(dest, size, mstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ if (!dtrace_canload(src, size, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ dtrace_bcopy((void *)src, (void *)dest, size);
-+ break;
-+ }
-+
-+ case DIF_SUBR_ALLOCA:
-+ case DIF_SUBR_COPYIN: {
-+ uintptr_t dest = P2ROUNDUP(mstate->dtms_scratch_ptr, 8);
-+ uint64_t size;
-+ size_t scratch_size;
-+
-+ size = tupregs[subr == DIF_SUBR_ALLOCA ? 0 : 1].dttk_value;
-+ scratch_size = (dest - mstate->dtms_scratch_ptr) + size;
-+
-+ /*
-+ * This action doesn't require any credential checks since
-+ * probes will not activate in user contexts to which the
-+ * enabling user does not have permissions.
-+ */
-+
-+ /*
-+ * Rounding up the user allocation size could have overflowed
-+ * a large, bogus allocation (like -1ULL) to 0.
-+ */
-+ if (scratch_size < size ||
-+ !DTRACE_INSCRATCH(mstate, scratch_size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (subr == DIF_SUBR_COPYIN) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_copyin(tupregs[0].dttk_value, dest, size, flags);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+ }
-+
-+ mstate->dtms_scratch_ptr += scratch_size;
-+ regs[rd] = dest;
-+ break;
-+ }
-+
-+ case DIF_SUBR_COPYINTO: {
-+ uint64_t size = tupregs[1].dttk_value;
-+ uintptr_t dest = tupregs[2].dttk_value;
-+
-+ /*
-+ * This action doesn't require any credential checks since
-+ * probes will not activate in user contexts to which the
-+ * enabling user does not have permissions.
-+ */
-+ if (!dtrace_inscratch(dest, size, mstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_copyin(tupregs[0].dttk_value, dest, size, flags);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+ break;
-+ }
-+
-+ case DIF_SUBR_COPYINSTR: {
-+ uintptr_t dest = mstate->dtms_scratch_ptr;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+
-+ if (nargs > 1 && tupregs[1].dttk_value < size)
-+ size = tupregs[1].dttk_value + 1;
-+
-+ /*
-+ * This action doesn't require any credential checks since
-+ * probes will not activate in user contexts to which the
-+ * enabling user does not have permissions.
-+ */
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_copyinstr(tupregs[0].dttk_value, dest, size, flags);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ ((char *)dest)[size - 1] = '\0';
-+ mstate->dtms_scratch_ptr += size;
-+ regs[rd] = dest;
-+ break;
-+ }
-+
-+#if 0 /* FIXME */
-+ case DIF_SUBR_MSGSIZE:
-+ case DIF_SUBR_MSGDSIZE: {
-+ uintptr_t baddr = tupregs[0].dttk_value, daddr;
-+ uintptr_t wptr, rptr;
-+ size_t count = 0;
-+ int cont = 0;
-+
-+ while (baddr != NULL && !(*flags & CPU_DTRACE_FAULT)) {
-+
-+ if (!dtrace_canload(baddr, sizeof(mblk_t), mstate,
-+ vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ wptr = dtrace_loadptr(baddr +
-+ offsetof(mblk_t, b_wptr));
-+
-+ rptr = dtrace_loadptr(baddr +
-+ offsetof(mblk_t, b_rptr));
-+
-+ if (wptr < rptr) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = tupregs[0].dttk_value;
-+ break;
-+ }
-+
-+ daddr = dtrace_loadptr(baddr +
-+ offsetof(mblk_t, b_datap));
-+
-+ baddr = dtrace_loadptr(baddr +
-+ offsetof(mblk_t, b_cont));
-+
-+ /*
-+ * We want to prevent against denial-of-service here,
-+ * so we're only going to search the list for
-+ * dtrace_msgdsize_max mblks.
-+ */
-+ if (cont++ > dtrace_msgdsize_max) {
-+ *flags |= CPU_DTRACE_ILLOP;
-+ break;
-+ }
-+
-+ if (subr == DIF_SUBR_MSGDSIZE) {
-+ if (dtrace_load8(daddr +
-+ offsetof(dblk_t, db_type)) != M_DATA)
-+ continue;
-+ }
-+
-+ count += wptr - rptr;
-+ }
-+
-+ if (!(*flags & CPU_DTRACE_FAULT))
-+ regs[rd] = count;
-+
-+ break;
-+ }
-+#endif
-+
-+ case DIF_SUBR_PROGENYOF: {
-+ pid_t pid = tupregs[0].dttk_value;
-+ struct task_struct *p;
-+ int rval = 0;
-+
-+ for (p = current; p != NULL; p = p->real_parent) {
-+ if (p->pid == pid) {
-+ rval = 1;
-+ break;
-+ }
-+
-+ if (p == p->real_parent)
-+ break;
-+ }
-+
-+ regs[rd] = rval;
-+ break;
-+ }
-+
-+ case DIF_SUBR_SPECULATION:
-+ regs[rd] = dtrace_speculation(state);
-+ break;
-+
-+ case DIF_SUBR_COPYOUT: {
-+ uintptr_t kaddr = tupregs[0].dttk_value;
-+ uintptr_t uaddr = tupregs[1].dttk_value;
-+ uint64_t size = tupregs[2].dttk_value;
-+
-+ if (!dtrace_destructive_disallow &&
-+ dtrace_priv_proc_control(state) &&
-+ !dtrace_istoxic(kaddr, size) &&
-+ dtrace_canload(kaddr, size, mstate, vstate)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_copyout(kaddr, uaddr, size, flags);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+ }
-+ break;
-+ }
-+
-+ case DIF_SUBR_COPYOUTSTR: {
-+ uintptr_t kaddr = tupregs[0].dttk_value;
-+ uintptr_t uaddr = tupregs[1].dttk_value;
-+ uint64_t size = tupregs[2].dttk_value;
-+
-+ if (!dtrace_destructive_disallow &&
-+ dtrace_priv_proc_control(state) &&
-+ !dtrace_istoxic(kaddr, size) &&
-+ dtrace_strcanload(kaddr, size, mstate, vstate)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_copyoutstr(kaddr, uaddr, size, flags);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+ }
-+ break;
-+ }
-+
-+ case DIF_SUBR_STRLEN: {
-+ size_t sz;
-+ uintptr_t addr = (uintptr_t)tupregs[0].dttk_value;
-+
-+ sz = dtrace_strlen((char *)addr,
-+ state->dts_options[DTRACEOPT_STRSIZE]);
-+
-+ if (!dtrace_canload(addr, sz + 1, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ regs[rd] = sz;
-+
-+ break;
-+ }
-+
-+ case DIF_SUBR_STRCHR:
-+ case DIF_SUBR_STRRCHR: {
-+ /*
-+ * We're going to iterate over the string looking for the
-+ * specified character. We will iterate until we have reached
-+ * the string length or we have found the character. If this
-+ * is DIF_SUBR_STRRCHR, we will look for the last occurrence
-+ * of the specified character instead of the first.
-+ */
-+ uintptr_t saddr = tupregs[0].dttk_value;
-+ uintptr_t addr = tupregs[0].dttk_value;
-+ uintptr_t limit = addr +
-+ state->dts_options[DTRACEOPT_STRSIZE];
-+ char c, target = (char)tupregs[1].dttk_value;
-+
-+ for (regs[rd] = 0; addr < limit; addr++) {
-+ c = dtrace_load8(addr);
-+ if (c == target) {
-+ regs[rd] = addr;
-+
-+ if (subr == DIF_SUBR_STRCHR)
-+ break;
-+ }
-+
-+ if (c == '\0')
-+ break;
-+ }
-+
-+ if (!dtrace_canload(saddr, addr - saddr, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ break;
-+ }
-+
-+ case DIF_SUBR_STRSTR:
-+ case DIF_SUBR_INDEX:
-+ case DIF_SUBR_RINDEX: {
-+ /*
-+ * We're going to iterate over the string looking for the
-+ * specified string. We will iterate until we have reached
-+ * the string length or we have found the string. (Yes, this
-+ * is done in the most naive way possible -- but considering
-+ * that the string we're searching for is likely to be
-+ * relatively short, the complexity of Rabin-Karp or similar
-+ * hardly seems merited.)
-+ */
-+ char *addr = (char *)(uintptr_t)
-+ tupregs[0].dttk_value;
-+ char *substr = (char *)(uintptr_t)
-+ tupregs[1].dttk_value;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ size_t len = dtrace_strlen(addr, size);
-+ size_t sublen = dtrace_strlen(substr, size);
-+ char *limit = addr + len, *orig = addr;
-+ int notfound = subr == DIF_SUBR_STRSTR ? 0 : -1;
-+ int inc = 1;
-+
-+ regs[rd] = notfound;
-+
-+ if (!dtrace_canload((uintptr_t)addr, len + 1, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!dtrace_canload((uintptr_t)substr, sublen + 1, mstate,
-+ vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * strstr() and index()/rindex() have similar semantics if
-+ * both strings are the empty string: strstr() returns a
-+ * pointer to the (empty) string, and index() and rindex()
-+ * both return index 0 (regardless of any position argument).
-+ */
-+ if (sublen == 0 && len == 0) {
-+ if (subr == DIF_SUBR_STRSTR)
-+ regs[rd] = (uintptr_t)addr;
-+ else
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (subr != DIF_SUBR_STRSTR) {
-+ if (subr == DIF_SUBR_RINDEX) {
-+ limit = orig - 1;
-+ addr += len;
-+ inc = -1;
-+ }
-+
-+ /*
-+ * Both index() and rindex() take an optional position
-+ * argument that denotes the starting position.
-+ */
-+ if (nargs == 3) {
-+ int64_t pos = (int64_t)tupregs[2].dttk_value;
-+
-+ /*
-+ * If the position argument to index() is
-+ * negative, Perl implicitly clamps it at
-+ * zero. This semantic is a little surprising
-+ * given the special meaning of negative
-+ * positions to similar Perl functions like
-+ * substr(), but it appears to reflect a
-+ * notion that index() can start from a
-+ * negative index and increment its way up to
-+ * the string. Given this notion, Perl's
-+ * rindex() is at least self-consistent in
-+ * that it implicitly clamps positions greater
-+ * than the string length to be the string
-+ * length. Where Perl completely loses
-+ * coherence, however, is when the specified
-+ * substring is the empty string (""). In
-+ * this case, even if the position is
-+ * negative, rindex() returns 0 -- and even if
-+ * the position is greater than the length,
-+ * index() returns the string length. These
-+ * semantics violate the notion that index()
-+ * should never return a value less than the
-+ * specified position and that rindex() should
-+ * never return a value greater than the
-+ * specified position. (One assumes that
-+ * these semantics are artifacts of Perl's
-+ * implementation and not the results of
-+ * deliberate design -- it beggars belief that
-+ * even Larry Wall could desire such oddness.)
-+ * While in the abstract one would wish for
-+ * consistent position semantics across
-+ * substr(), index() and rindex() -- or at the
-+ * very least self-consistent position
-+ * semantics for index() and rindex() -- we
-+ * instead opt to keep with the extant Perl
-+ * semantics, in all their broken glory. (Do
-+ * we have more desire to maintain Perl's
-+ * semantics than Perl does? Probably.)
-+ */
-+ if (subr == DIF_SUBR_RINDEX) {
-+ if (pos < 0) {
-+ if (sublen == 0)
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (pos > len)
-+ pos = len;
-+ } else {
-+ if (pos < 0)
-+ pos = 0;
-+
-+ if (pos >= len) {
-+ if (sublen == 0)
-+ regs[rd] = len;
-+ break;
-+ }
-+ }
-+
-+ addr = orig + pos;
-+ }
-+ }
-+
-+ for (regs[rd] = notfound; addr != limit; addr += inc) {
-+ if (dtrace_strncmp(addr, substr, sublen) == 0) {
-+ if (subr != DIF_SUBR_STRSTR) {
-+ /*
-+ * As D index() and rindex() are
-+ * modeled on Perl (and not on awk),
-+ * we return a zero-based (and not a
-+ * one-based) index. (For you Perl
-+ * weenies: no, we're not going to add
-+ * $[ -- and shouldn't you be at a con
-+ * or something?)
-+ */
-+ regs[rd] = (uintptr_t)(addr - orig);
-+ break;
-+ }
-+
-+ ASSERT(subr == DIF_SUBR_STRSTR);
-+ regs[rd] = (uintptr_t)addr;
-+ break;
-+ }
-+ }
-+
-+ break;
-+ }
-+
-+ case DIF_SUBR_STRTOK: {
-+ uintptr_t addr = tupregs[0].dttk_value;
-+ uintptr_t tokaddr = tupregs[1].dttk_value;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ uintptr_t limit, toklimit = tokaddr + size;
-+ uint8_t c = 0, tokmap[32]; /* 256 / 8 */
-+ char *dest = (char *)mstate->dtms_scratch_ptr;
-+ int i;
-+
-+ /*
-+ * Check both the token buffer and (later) the input buffer,
-+ * since both could be non-scratch addresses.
-+ */
-+ if (!dtrace_strcanload(tokaddr, size, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (addr == (uintptr_t)NULL) {
-+ /*
-+ * If the address specified is NULL, we use our saved
-+ * strtok pointer from the mstate. Note that this
-+ * means that the saved strtok pointer is _only_
-+ * valid within multiple enablings of the same probe --
-+ * it behaves like an implicit clause-local variable.
-+ */
-+ addr = mstate->dtms_strtok;
-+ } else {
-+ /*
-+ * If the user-specified address is non-NULL we must
-+ * access check it. This is the only time we have
-+ * a chance to do so, since this address may reside
-+ * in the string table of this clause-- future calls
-+ * (when we fetch addr from mstate->dtms_strtok)
-+ * would fail this access check.
-+ */
-+ if (!dtrace_strcanload(addr, size, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+ }
-+
-+ /*
-+ * First, zero the token map, and then process the token
-+ * string -- setting a bit in the map for every character
-+ * found in the token string.
-+ */
-+ for (i = 0; i < sizeof(tokmap); i++)
-+ tokmap[i] = 0;
-+
-+ for (; tokaddr < toklimit; tokaddr++) {
-+ c = dtrace_load8(tokaddr);
-+ if (c == '\0')
-+ break;
-+
-+ ASSERT((c >> 3) < sizeof(tokmap));
-+ tokmap[c >> 3] |= (1 << (c & 0x7));
-+ }
-+
-+ for (limit = addr + size; addr < limit; addr++) {
-+ /*
-+ * We're looking for a character that is _not_ contained
-+ * in the token string.
-+ */
-+ c = dtrace_load8(addr);
-+ if (c == '\0')
-+ break;
-+
-+ if (!(tokmap[c >> 3] & (1 << (c & 0x7))))
-+ break;
-+ }
-+
-+ if (c == '\0') {
-+ /*
-+ * We reached the end of the string without finding
-+ * any character that was not in the token string.
-+ * We return NULL in this case, and we set the saved
-+ * address to NULL as well.
-+ */
-+ regs[rd] = 0;
-+ mstate->dtms_strtok = (uintptr_t)NULL;
-+ break;
-+ }
-+
-+ /*
-+ * From here on, we're copying into the destination string.
-+ */
-+ for (i = 0; addr < limit && i < size - 1; addr++) {
-+ c = dtrace_load8(addr);
-+ if (c == '\0')
-+ break;
-+
-+ if (tokmap[c >> 3] & (1 << (c & 0x7)))
-+ break;
-+
-+ ASSERT(i < size);
-+ dest[i++] = c;
-+ }
-+
-+ ASSERT(i < size);
-+ dest[i] = '\0';
-+ regs[rd] = (uintptr_t)dest;
-+ mstate->dtms_scratch_ptr += size;
-+ mstate->dtms_strtok = addr;
-+ break;
-+ }
-+
-+ case DIF_SUBR_SUBSTR: {
-+ uintptr_t s = tupregs[0].dttk_value;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ char *d = (char *)mstate->dtms_scratch_ptr;
-+ int64_t index = (int64_t)tupregs[1].dttk_value;
-+ int64_t remaining = (int64_t)tupregs[2].dttk_value;
-+ size_t len = dtrace_strlen((char *)s, size);
-+ int64_t i = 0;
-+
-+ if (!dtrace_canload(s, len + 1, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (nargs <= 2)
-+ remaining = (int64_t)size;
-+
-+ if (index < 0) {
-+ index += len;
-+
-+ if (index < 0 && index + remaining > 0) {
-+ remaining += index;
-+ index = 0;
-+ }
-+ }
-+
-+ if (index >= len || index < 0)
-+ remaining = 0;
-+ else if (remaining < 0)
-+ remaining += len - index;
-+ else if (index + remaining > size)
-+ remaining = size - index;
-+
-+ for (i = 0; i < remaining; i++) {
-+ d[i] = dtrace_load8(s + index + i);
-+ if (d[i] == '\0')
-+ break;
-+ }
-+
-+ d[i] = '\0';
-+
-+ mstate->dtms_scratch_ptr += size;
-+ regs[rd] = (uintptr_t)d;
-+ break;
-+ }
-+
-+ case DIF_SUBR_GETMAJOR:
-+ regs[rd] = MAJOR(tupregs[0].dttk_value);
-+ break;
-+
-+ case DIF_SUBR_GETMINOR:
-+ regs[rd] = MINOR(tupregs[0].dttk_value);
-+ break;
-+
-+#if 0 /* FIXME */
-+ case DIF_SUBR_DDI_PATHNAME: {
-+ /*
-+ * This one is a galactic mess. We are going to roughly
-+ * emulate ddi_pathname(), but it's made more complicated
-+ * by the fact that we (a) want to include the minor name and
-+ * (b) must proceed iteratively instead of recursively.
-+ */
-+ uintptr_t dest = mstate->dtms_scratch_ptr;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ char *start = (char *)dest, *end = start + size - 1;
-+ uintptr_t daddr = tupregs[0].dttk_value;
-+ int64_t minor = (int64_t)tupregs[1].dttk_value;
-+ char *s;
-+ int i, len, depth = 0;
-+
-+ /*
-+ * Due to all the pointer jumping we do and context we must
-+ * rely upon, we just mandate that the user must have kernel
-+ * read privileges to use this routine.
-+ */
-+ if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) == 0) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = daddr;
-+ regs[rd] = 0;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ *end = '\0';
-+
-+ /*
-+ * We want to have a name for the minor. In order to do this,
-+ * we need to walk the minor list from the devinfo. We want
-+ * to be sure that we don't infinitely walk a circular list,
-+ * so we check for circularity by sending a scout pointer
-+ * ahead two elements for every element that we iterate over;
-+ * if the list is circular, these will ultimately point to the
-+ * same element. You may recognize this little trick as the
-+ * answer to a stupid interview question -- one that always
-+ * seems to be asked by those who had to have it laboriously
-+ * explained to them, and who can't even concisely describe
-+ * the conditions under which one would be forced to resort to
-+ * this technique. Needless to say, those conditions are
-+ * found here -- and probably only here. Is this the only use
-+ * of this infamous trick in shipping, production code? If it
-+ * isn't, it probably should be...
-+ */
-+ if (minor != -1) {
-+ uintptr_t maddr = dtrace_loadptr(daddr +
-+ offsetof(struct dev_info, devi_minor));
-+
-+ uintptr_t next = offsetof(struct ddi_minor_data, next);
-+ uintptr_t name = offsetof(struct ddi_minor_data,
-+ d_minor) + offsetof(struct ddi_minor, name);
-+ uintptr_t dev = offsetof(struct ddi_minor_data,
-+ d_minor) + offsetof(struct ddi_minor, dev);
-+ uintptr_t scout;
-+
-+ if (maddr != NULL)
-+ scout = dtrace_loadptr(maddr + next);
-+
-+ while (maddr != NULL && !(*flags & CPU_DTRACE_FAULT)) {
-+ uint64_t m;
-+#ifdef _LP64
-+ m = dtrace_load64(maddr + dev) & MAXMIN64;
-+#else
-+ m = dtrace_load32(maddr + dev) & MAXMIN;
-+#endif
-+ if (m != minor) {
-+ maddr = dtrace_loadptr(maddr + next);
-+
-+ if (scout == NULL)
-+ continue;
-+
-+ scout = dtrace_loadptr(scout + next);
-+
-+ if (scout == NULL)
-+ continue;
-+
-+ scout = dtrace_loadptr(scout + next);
-+
-+ if (scout == NULL)
-+ continue;
-+
-+ if (scout == maddr) {
-+ *flags |= CPU_DTRACE_ILLOP;
-+ break;
-+ }
-+
-+ continue;
-+ }
-+
-+ /*
-+ * We have the minor data. Now we need to
-+ * copy the minor's name into the end of the
-+ * pathname.
-+ */
-+ s = (char *)dtrace_loadptr(maddr + name);
-+ len = dtrace_strlen(s, size);
-+
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+ if (len != 0) {
-+ end -= len + 1;
-+ if (end < start)
-+ break;
-+
-+ *end = ':';
-+ }
-+
-+ for (i = 1; i <= len; i++)
-+ end[i] = dtrace_load8((uintptr_t)s++);
-+ break;
-+ }
-+ }
-+
-+ while (daddr != NULL && !(*flags & CPU_DTRACE_FAULT)) {
-+ ddi_node_state_t devi_state;
-+
-+ devi_state = dtrace_load32(daddr +
-+ offsetof(struct dev_info, devi_node_state));
-+
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+ if (devi_state >= DS_INITIALIZED) {
-+ s = (char *)dtrace_loadptr(daddr +
-+ offsetof(struct dev_info, devi_addr));
-+ len = dtrace_strlen(s, size);
-+
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+ if (len != 0) {
-+ end -= len + 1;
-+ if (end < start)
-+ break;
-+
-+ *end = '@';
-+ }
-+
-+ for (i = 1; i <= len; i++)
-+ end[i] = dtrace_load8((uintptr_t)s++);
-+ }
-+
-+ /*
-+ * Now for the node name...
-+ */
-+ s = (char *)dtrace_loadptr(daddr +
-+ offsetof(struct dev_info, devi_node_name));
-+
-+ daddr = dtrace_loadptr(daddr +
-+ offsetof(struct dev_info, devi_parent));
-+
-+ /*
-+ * If our parent is NULL (that is, if we're the root
-+ * node), we're going to use the special path
-+ * "devices".
-+ */
-+ if (daddr == NULL)
-+ s = "devices";
-+
-+ len = dtrace_strlen(s, size);
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+ end -= len + 1;
-+ if (end < start)
-+ break;
-+
-+ for (i = 1; i <= len; i++)
-+ end[i] = dtrace_load8((uintptr_t)s++);
-+ *end = '/';
-+
-+ if (depth++ > dtrace_devdepth_max) {
-+ *flags |= CPU_DTRACE_ILLOP;
-+ break;
-+ }
-+ }
-+
-+ if (end < start)
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+
-+ if (daddr == NULL) {
-+ regs[rd] = (uintptr_t)end;
-+ mstate->dtms_scratch_ptr += size;
-+ }
-+
-+ break;
-+ }
-+#endif
-+
-+ case DIF_SUBR_STRJOIN: {
-+ char *d = (char *)mstate->dtms_scratch_ptr;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ uintptr_t s1 = tupregs[0].dttk_value;
-+ uintptr_t s2 = tupregs[1].dttk_value;
-+ int i = 0;
-+
-+ if (!dtrace_strcanload(s1, size, mstate, vstate) ||
-+ !dtrace_strcanload(s2, size, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ for (;;) {
-+ if (i >= size) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ d[i] = dtrace_load8(s1++);
-+ if ((d[i++]) == '\0') {
-+ i--;
-+ break;
-+ }
-+ }
-+
-+ for (;;) {
-+ if (i >= size) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ d[i] = dtrace_load8(s2++);
-+ if ((d[i++]) == '\0')
-+ break;
-+ }
-+
-+ if (i < size) {
-+ mstate->dtms_scratch_ptr += i;
-+ regs[rd] = (uintptr_t)d;
-+ }
-+
-+ break;
-+ }
-+
-+ case DIF_SUBR_LLTOSTR: {
-+ int64_t i = (int64_t)tupregs[0].dttk_value;
-+ int64_t val = i < 0 ? i * -1 : i;
-+ uint64_t size = 22; /* room for 2^64 in dec */
-+ char *end = (char *)mstate->dtms_scratch_ptr + size
-+ - 1;
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * GCC on Linux introduces calls to functions that are not
-+ * linked into the kernel image, so we need to use the do_div()
-+ * function instead. It modifies the first argument in place
-+ * (replaces it with the quotient), and returns the remainder.
-+ *
-+ * Was:
-+ * for (*end-- = '\0'; val; val /= 10)
-+ * *end-- = '0' + (val % 10);
-+ */
-+ for (*end-- = '\0'; val; )
-+ *end-- = '0' + do_div(val, 10);
-+
-+ if (i == 0)
-+ *end-- = '0';
-+
-+ if (i < 0)
-+ *end-- = '-';
-+
-+ regs[rd] = (uintptr_t)end + 1;
-+ mstate->dtms_scratch_ptr += size;
-+ break;
-+ }
-+
-+ case DIF_SUBR_HTONS:
-+ case DIF_SUBR_NTOHS:
-+#ifdef __BIG_ENDIAN
-+ regs[rd] = (uint16_t)tupregs[0].dttk_value;
-+#else
-+ regs[rd] = DT_BSWAP_16((uint16_t)tupregs[0].dttk_value);
-+#endif
-+ break;
-+
-+
-+ case DIF_SUBR_HTONL:
-+ case DIF_SUBR_NTOHL:
-+#ifdef __BIG_ENDIAN
-+ regs[rd] = (uint32_t)tupregs[0].dttk_value;
-+#else
-+ regs[rd] = DT_BSWAP_32((uint32_t)tupregs[0].dttk_value);
-+#endif
-+ break;
-+
-+
-+ case DIF_SUBR_HTONLL:
-+ case DIF_SUBR_NTOHLL:
-+#ifdef __BIG_ENDIAN
-+ regs[rd] = (uint64_t)tupregs[0].dttk_value;
-+#else
-+ regs[rd] = DT_BSWAP_64((uint64_t)tupregs[0].dttk_value);
-+#endif
-+ break;
-+
-+
-+ case DIF_SUBR_DIRNAME:
-+ case DIF_SUBR_BASENAME: {
-+ char *dest = (char *)mstate->dtms_scratch_ptr;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ uintptr_t src = tupregs[0].dttk_value;
-+ int i, j, len = dtrace_strlen((char *)src, size);
-+ int lastbase = -1, firstbase = -1, lastdir = -1;
-+ int start, end;
-+
-+ if (!dtrace_canload(src, len + 1, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * The basename and dirname for a zero-length string is
-+ * defined to be "."
-+ */
-+ if (len == 0) {
-+ len = 1;
-+ src = (uintptr_t)".";
-+ }
-+
-+ /*
-+ * Start from the back of the string, moving back toward the
-+ * front until we see a character that isn't a slash. That
-+ * character is the last character in the basename.
-+ */
-+ for (i = len - 1; i >= 0; i--) {
-+ if (dtrace_load8(src + i) != '/')
-+ break;
-+ }
-+
-+ if (i >= 0)
-+ lastbase = i;
-+
-+ /*
-+ * Starting from the last character in the basename, move
-+ * towards the front until we find a slash. The character
-+ * that we processed immediately before that is the first
-+ * character in the basename.
-+ */
-+ for (; i >= 0; i--) {
-+ if (dtrace_load8(src + i) == '/')
-+ break;
-+ }
-+
-+ if (i >= 0)
-+ firstbase = i + 1;
-+
-+ /*
-+ * Now keep going until we find a non-slash character. That
-+ * character is the last character in the dirname.
-+ */
-+ for (; i >= 0; i--) {
-+ if (dtrace_load8(src + i) != '/')
-+ break;
-+ }
-+
-+ if (i >= 0)
-+ lastdir = i;
-+
-+ ASSERT(!(lastbase == -1 && firstbase != -1));
-+ ASSERT(!(firstbase == -1 && lastdir != -1));
-+
-+ if (lastbase == -1) {
-+ /*
-+ * We didn't find a non-slash character. We know that
-+ * the length is non-zero, so the whole string must be
-+ * slashes. In either the dirname or the basename
-+ * case, we return '/'.
-+ */
-+ ASSERT(firstbase == -1);
-+ firstbase = lastbase = lastdir = 0;
-+ }
-+
-+ if (firstbase == -1) {
-+ /*
-+ * The entire string consists only of a basename
-+ * component. If we're looking for dirname, we need
-+ * to change our string to be just "."; if we're
-+ * looking for a basename, we'll just set the first
-+ * character of the basename to be 0.
-+ */
-+ if (subr == DIF_SUBR_DIRNAME) {
-+ ASSERT(lastdir == -1);
-+ src = (uintptr_t)".";
-+ lastdir = 0;
-+ } else {
-+ firstbase = 0;
-+ }
-+ }
-+
-+ if (subr == DIF_SUBR_DIRNAME) {
-+ if (lastdir == -1) {
-+ /*
-+ * We know that we have a slash in the name --
-+ * or lastdir would be set to 0, above. And
-+ * because lastdir is -1, we know that this
-+ * slash must be the first character. (That
-+ * is, the full string must be of the form
-+ * "/basename".) In this case, the last
-+ * character of the directory name is 0.
-+ */
-+ lastdir = 0;
-+ }
-+
-+ start = 0;
-+ end = lastdir;
-+ } else {
-+ ASSERT(subr == DIF_SUBR_BASENAME);
-+ ASSERT(firstbase != -1 && lastbase != -1);
-+ start = firstbase;
-+ end = lastbase;
-+ }
-+
-+ for (i = start, j = 0; i <= end && j < size - 1; i++, j++)
-+ dest[j] = dtrace_load8(src + i);
-+
-+ dest[j] = '\0';
-+ regs[rd] = (uintptr_t)dest;
-+ mstate->dtms_scratch_ptr += size;
-+ break;
-+ }
-+
-+ case DIF_SUBR_CLEANPATH: {
-+ char *dest = (char *)mstate->dtms_scratch_ptr, c;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ uintptr_t src = tupregs[0].dttk_value;
-+ int i = 0, j = 0;
-+
-+ if (!dtrace_strcanload(src, size, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * Move forward, loading each character.
-+ */
-+ do {
-+ c = dtrace_load8(src + i++);
-+next:
-+ if (j + 5 >= size) /* 5 = strlen("/..c\0") */
-+ break;
-+
-+ if (c != '/') {
-+ dest[j++] = c;
-+ continue;
-+ }
-+
-+ c = dtrace_load8(src + i++);
-+
-+ if (c == '/') {
-+ /*
-+ * We have two slashes -- we can just advance
-+ * to the next character.
-+ */
-+ goto next;
-+ }
-+
-+ if (c != '.') {
-+ /*
-+ * This is not "." and it's not ".." -- we can
-+ * just store the "/" and this character and
-+ * drive on.
-+ */
-+ dest[j++] = '/';
-+ dest[j++] = c;
-+ continue;
-+ }
-+
-+ c = dtrace_load8(src + i++);
-+
-+ if (c == '/') {
-+ /*
-+ * This is a "/./" component. We're not going
-+ * to store anything in the destination buffer;
-+ * we're just going to go to the next component.
-+ */
-+ goto next;
-+ }
-+
-+ if (c != '.') {
-+ /*
-+ * This is not ".." -- we can just store the
-+ * "/." and this character and continue
-+ * processing.
-+ */
-+ dest[j++] = '/';
-+ dest[j++] = '.';
-+ dest[j++] = c;
-+ continue;
-+ }
-+
-+ c = dtrace_load8(src + i++);
-+
-+ if (c != '/' && c != '\0') {
-+ /*
-+ * This is not ".." -- it's "..[mumble]".
-+ * We'll store the "/.." and this character
-+ * and continue processing.
-+ */
-+ dest[j++] = '/';
-+ dest[j++] = '.';
-+ dest[j++] = '.';
-+ dest[j++] = c;
-+ continue;
-+ }
-+
-+ /*
-+ * This is "/../" or "/..\0". We need to back up
-+ * our destination pointer until we find a "/".
-+ */
-+ i--;
-+ while (j != 0 && dest[--j] != '/')
-+ continue;
-+
-+ if (c == '\0')
-+ dest[++j] = '/';
-+ } while (c != '\0');
-+
-+ dest[j] = '\0';
-+ regs[rd] = (uintptr_t)dest;
-+ mstate->dtms_scratch_ptr += size;
-+ break;
-+ }
-+
-+ case DIF_SUBR_LINK_NTOP: {
-+ struct dtrace_hwtype_alen {
-+ int dhwa_hwtype;
-+ size_t dhwa_hwalen;
-+ } hwinfo[] = {
-+ { ARPHRD_ETHER, ETH_ALEN },
-+ { ARPHRD_INFINIBAND, INFINIBAND_ALEN },
-+ { -1, 0 }
-+ };
-+/*
-+ * Captures the maximum hardware address length among all the supported
-+ * hardware types. Please update this macro when adding a new hardware type.
-+ */
-+#define DTRACE_MAX_HWTYPE_ALEN (ETH_ALEN > INFINIBAND_ALEN ? \
-+ ETH_ALEN : INFINIBAND_ALEN)
-+ uintptr_t src = tupregs[1].dttk_value;
-+ int hwtype = tupregs[0].dttk_value;
-+ uint8_t hwaddr[DTRACE_MAX_HWTYPE_ALEN];
-+ char *base;
-+ size_t size, len;
-+ int i;
-+
-+ for (i = 0; hwinfo[i].dhwa_hwtype != -1; i++) {
-+ if (hwtype == hwinfo[i].dhwa_hwtype)
-+ break;
-+ }
-+ if (hwinfo[i].dhwa_hwtype == -1) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ regs[rd] = 0;
-+ break;
-+ }
-+ len = hwinfo[i].dhwa_hwalen;
-+
-+ /*
-+ * Safely load the hardware address.
-+ */
-+ if (!dtrace_canload(src, len, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+ dtrace_bcopy((void *)src, hwaddr, len);
-+
-+ /*
-+ * Check if a hardware address string will fit in scratch.
-+ * For every byte we need 3 characters (including ':').
-+ */
-+ size = len * 3;
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+ base = (char *)mstate->dtms_scratch_ptr;
-+
-+ /*
-+ * Build the Hardware address string by working through the
-+ * address from the beginning. Given a hardware address
-+ * {0xa0, 0xaa, 0xff, 0xc, 0, 1, 2} of length 6, it will build
-+ * a0:aa:ff:0c:00:01:02.
-+ */
-+ for (i = 0; i < len; i++) {
-+ if (hwaddr[i] < 16) {
-+ *base++ = '0';
-+ *base++ = hexdigits[hwaddr[i]];
-+ } else {
-+ *base++ = hexdigits[hwaddr[i] / 16];
-+ *base++ = hexdigits[hwaddr[i] % 16];
-+ }
-+
-+ if (i < len - 1)
-+ *base++ = ':';
-+ }
-+ *base++ = '\0';
-+ regs[rd] = mstate->dtms_scratch_ptr;
-+ mstate->dtms_scratch_ptr += size;
-+#undef DTRACE_MAX_HWTYPE_ALEN
-+ break;
-+ }
-+
-+ case DIF_SUBR_INET_NTOA:
-+ case DIF_SUBR_INET_NTOA6:
-+ case DIF_SUBR_INET_NTOP: {
-+ uintptr_t src;
-+ size_t size;
-+ int af, argi, i;
-+ char *base, *end;
-+
-+ if (subr == DIF_SUBR_INET_NTOP) {
-+ af = (int)tupregs[0].dttk_value;
-+ argi = 1;
-+ } else {
-+ af = subr == DIF_SUBR_INET_NTOA ? AF_INET : AF_INET6;
-+ argi = 0;
-+ }
-+
-+ src = tupregs[argi].dttk_value;
-+ if (af == AF_INET) {
-+ ipaddr_t ip4;
-+ ipaddr_t_p ptr4;
-+ uint8_t *ptr8, val;
-+
-+ /*
-+ * Safely load the IPv4 address.
-+ */
-+ if (!dtrace_canload(src, 4, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+ ip4 = dtrace_load32(src);
-+
-+ /*
-+ * Check an IPv4 string will fit in scratch.
-+ */
-+ size = INET_ADDRSTRLEN;
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+ base = (char *)mstate->dtms_scratch_ptr;
-+ end = (char *)mstate->dtms_scratch_ptr + size - 1;
-+
-+ /*
-+ * Stringify as a dotted decimal quad.
-+ */
-+ *end-- = '\0';
-+ ptr4 = &ip4;
-+ ptr8 = (uint8_t *)ptr4;
-+ for (i = 3; i >= 0; i--) {
-+ val = ptr8[i];
-+
-+ if (val == 0) {
-+ *end-- = '0';
-+ } else {
-+ for (; val; val /= 10)
-+ *end-- = '0' + (val % 10);
-+ }
-+
-+ if (i > 0)
-+ *end-- = '.';
-+ }
-+ ASSERT(end + 1 >= base);
-+#if IS_ENABLED(CONFIG_IPV6)
-+ } else if (af == AF_INET6) {
-+ in6_addr_t ip6;
-+ int firstzero, tryzero, numzero, v6end;
-+ uint16_t val;
-+
-+ /*
-+ * Stringify using RFC 1884 convention 2 - 16 bit
-+ * hexadecimal values with a zero-run compression.
-+ * Lower case hexadecimal digits are used.
-+ * eg, fe80::214:4fff:fe0b:76c8.
-+ * The IPv4 embedded form is returned for inet_ntop,
-+ * just the IPv4 string is returned for inet_ntoa6.
-+ */
-+
-+ /*
-+ * Safely load the IPv6 address.
-+ */
-+ if (!dtrace_canload(src, sizeof(in6_addr_t), mstate,
-+ vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+ dtrace_bcopy((void *)src, (void *)(uintptr_t)&ip6,
-+ sizeof(in6_addr_t));
-+
-+ /*
-+ * Check an IPv6 string will fit in scratch.
-+ */
-+ size = INET6_ADDRSTRLEN;
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+ base = (char *)mstate->dtms_scratch_ptr;
-+ end = (char *)mstate->dtms_scratch_ptr + size - 1;
-+ *end-- = '\0';
-+
-+ /*
-+ * Find the longest run of 16 bit zero values
-+ * for the single allowed zero compression - "::".
-+ */
-+ firstzero = -1;
-+ tryzero = -1;
-+ numzero = 1;
-+ for (i = 0; i < sizeof(in6_addr_t); i++) {
-+ if (ip6.s6_addr[i] == 0 &&
-+ tryzero == -1 && i % 2 == 0) {
-+ tryzero = i;
-+ continue;
-+ }
-+
-+ if (tryzero != -1 &&
-+ (ip6.s6_addr[i] != 0 ||
-+ i == sizeof(in6_addr_t) - 1)) {
-+
-+ if (i - tryzero <= numzero) {
-+ tryzero = -1;
-+ continue;
-+ }
-+
-+ firstzero = tryzero;
-+ numzero = i - i % 2 - tryzero;
-+ tryzero = -1;
-+
-+ if (ip6.s6_addr[i] == 0 &&
-+ i == sizeof(in6_addr_t) - 1)
-+ numzero += 2;
-+ }
-+ }
-+ ASSERT(firstzero + numzero <= sizeof(in6_addr_t));
-+
-+ /*
-+ * Check for an IPv4 embedded address.
-+ */
-+ v6end = sizeof(in6_addr_t) - 2;
-+ if (ipv6_addr_type(&ip6) &
-+ (IPV6_ADDR_COMPATv4 | IPV6_ADDR_MAPPED)) {
-+ for (i = sizeof(in6_addr_t) - 1;
-+ i >= DTRACE_V4MAPPED_OFFSET; i--) {
-+ ASSERT(end >= base);
-+
-+ val = ip6.s6_addr[i];
-+
-+ if (val == 0) {
-+ *end-- = '0';
-+ } else {
-+ for (; val; val /= 10)
-+ *end-- = '0' + val % 10;
-+ }
-+
-+ if (i > DTRACE_V4MAPPED_OFFSET)
-+ *end-- = '.';
-+ }
-+
-+ if (subr == DIF_SUBR_INET_NTOA6)
-+ goto inetout;
-+
-+ /*
-+ * Set v6end to skip the IPv4 address that
-+ * we have already stringified.
-+ */
-+ v6end = 10;
-+ }
-+
-+ /*
-+ * Build the IPv6 string by working through the
-+ * address in reverse.
-+ */
-+ for (i = v6end; i >= 0; i -= 2) {
-+ ASSERT(end >= base);
-+
-+ if (i == firstzero + numzero - 2) {
-+ *end-- = ':';
-+ *end-- = ':';
-+ i -= numzero - 2;
-+ continue;
-+ }
-+
-+ if (i < 14 && i != firstzero - 2)
-+ *end-- = ':';
-+
-+ val = (ip6.s6_addr[i] << 8) +
-+ ip6.s6_addr[i + 1];
-+
-+ if (val == 0) {
-+ *end-- = '0';
-+ } else {
-+ for (; val; val /= 16)
-+ *end-- = hexdigits[val % 16];
-+ }
-+ }
-+ ASSERT(end + 1 >= base);
-+#endif
-+ } else {
-+ /*
-+ * The user didn't use AH_INET or AH_INET6.
-+ */
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+#if IS_ENABLED(CONFIG_IPV6)
-+inetout:
-+#endif
-+ regs[rd] = (uintptr_t)end + 1;
-+ mstate->dtms_scratch_ptr += size;
-+ break;
-+ }
-+
-+ case DIF_SUBR_D_PATH: {
-+ struct path *path = (struct path *)tupregs[0].dttk_value;
-+ char *dest = (char *)mstate->dtms_scratch_ptr;
-+ char *ptr;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ unsigned int fd;
-+ struct files_struct
-+ *files = current->files;
-+ struct fdtable *fdt;
-+
-+ if (!dtrace_canload((uintptr_t)path, sizeof(struct path),
-+ mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (spin_is_locked(&files->file_lock) ||
-+ !spin_trylock(&files->file_lock)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ fdt = files->fdt;
-+
-+ /*
-+ * We (currently) limit the d_path() subroutine to paths that
-+ * relate to open files in the current task.
-+ */
-+ for (fd = 0; fd < fdt->max_fds; fd++) {
-+ if (fdt->fd[fd] && &fdt->fd[fd]->f_path == path)
-+ break;
-+ }
-+
-+ spin_unlock(&files->file_lock);
-+
-+ if (fd >= fdt->max_fds) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = (uintptr_t)path;
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ ptr = d_path(path, dest, size);
-+ if (ptr < 0) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ regs[rd] = (uintptr_t)ptr;
-+ mstate->dtms_scratch_ptr += size;
-+ break;
-+ }
-+
-+ }
-+}
-+
-+/*
-+ * Emulate the execution of DTrace IR instructions specified by the given DIF
-+ * object. This function is deliberately void fo assertions as all of the
-+ * necessary checks are handled by a call to dtrace_difo_validate().
-+ */
-+uint64_t dtrace_dif_emulate(struct dtrace_difo *difo,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate,
-+ struct dtrace_state *state)
-+{
-+ const dif_instr_t *text = difo->dtdo_buf;
-+ const uint_t textlen = difo->dtdo_len;
-+ const char *strtab = difo->dtdo_strtab;
-+ const uint64_t *inttab = difo->dtdo_inttab;
-+
-+ uint64_t rval = 0;
-+ struct dtrace_statvar *svar;
-+ struct dtrace_dstate *dstate = &vstate->dtvs_dynvars;
-+ struct dtrace_difv *v;
-+ volatile uint16_t *flags = &this_cpu_core->cpuc_dtrace_flags;
-+ volatile uintptr_t *illval = &this_cpu_core->cpuc_dtrace_illval;
-+
-+ struct dtrace_key tupregs[DIF_DTR_NREGS + 2];
-+ /* +2 for thread and id */
-+ uint64_t regs[DIF_DIR_NREGS];
-+ uint64_t *tmp;
-+
-+ uint8_t cc_n = 0, cc_z = 0, cc_v = 0, cc_c = 0;
-+ int64_t cc_r;
-+ uint_t pc = 0, id, opc = 0;
-+ uint8_t ttop = 0;
-+ dif_instr_t instr;
-+ uint_t r1, r2, rd;
-+
-+ dt_dbg_dif(" DIF %p emulation (text %p, %d instructions)...\n",
-+ difo, text, textlen);
-+
-+ /*
-+ * We stash the current DIF object into the machine state: we need it
-+ * for subsequent access checking.
-+ */
-+ mstate->dtms_difo = difo;
-+
-+ regs[DIF_REG_R0] = 0; /* %r0 is fixed at zero */
-+
-+ while (pc < textlen && !(*flags & CPU_DTRACE_FAULT)) {
-+ opc = pc;
-+
-+ instr = text[pc++];
-+ r1 = DIF_INSTR_R1(instr);
-+ r2 = DIF_INSTR_R2(instr);
-+ rd = DIF_INSTR_RD(instr);
-+
-+ dt_dbg_dif(" Executing opcode %02x (%02x, %02x, %02x)\n",
-+ DIF_INSTR_OP(instr), r1, r2, rd);
-+
-+ switch (DIF_INSTR_OP(instr)) {
-+ case DIF_OP_OR:
-+ regs[rd] = regs[r1] | regs[r2];
-+ break;
-+ case DIF_OP_XOR:
-+ regs[rd] = regs[r1] ^ regs[r2];
-+ break;
-+ case DIF_OP_AND:
-+ regs[rd] = regs[r1] & regs[r2];
-+ break;
-+ case DIF_OP_SLL:
-+ regs[rd] = regs[r1] << regs[r2];
-+ break;
-+ case DIF_OP_SRL:
-+ regs[rd] = regs[r1] >> regs[r2];
-+ break;
-+ case DIF_OP_SUB:
-+ regs[rd] = regs[r1] - regs[r2];
-+ break;
-+ case DIF_OP_ADD:
-+ regs[rd] = regs[r1] + regs[r2];
-+ break;
-+ case DIF_OP_MUL:
-+ regs[rd] = regs[r1] * regs[r2];
-+ break;
-+ case DIF_OP_SDIV:
-+ if (regs[r2] == 0) {
-+ regs[rd] = 0;
-+ *flags |= CPU_DTRACE_DIVZERO;
-+ } else {
-+ int neg = 0;
-+
-+ /*
-+ * We cannot simply do a 64-bit division, since
-+ * gcc translates it into a call to a function
-+ * that is not linked into the kernel.
-+ *
-+ * regs[rd] = (int64_t)regs[r1] /
-+ * (int64_t)regs[r2];
-+ */
-+ if ((int64_t)regs[r1] < 0) {
-+ neg = !neg;
-+ regs[r1] = -(int64_t)regs[r1];
-+ }
-+ if ((int64_t)regs[r2] < 0) {
-+ neg = !neg;
-+ regs[r2] = -(int64_t)regs[r2];
-+ }
-+ regs[rd] = regs[r1];
-+ do_div(regs[rd], regs[r2]);
-+
-+ if (neg)
-+ regs[rd] = -(int64_t)regs[rd];
-+ }
-+ break;
-+
-+ case DIF_OP_UDIV:
-+ if (regs[r2] == 0) {
-+ regs[rd] = 0;
-+ *flags |= CPU_DTRACE_DIVZERO;
-+ } else {
-+ /*
-+ * We cannot simply do a 64-bit division, since
-+ * gcc translates it into a call to a function
-+ * that is not linked into the kernel.
-+ *
-+ * regs[rd] = regs[r1] / regs[r2];
-+ */
-+ regs[rd] = regs[r1];
-+ do_div(regs[rd], regs[r2]);
-+ }
-+ break;
-+
-+ case DIF_OP_SREM:
-+ if (regs[r2] == 0) {
-+ regs[rd] = 0;
-+ *flags |= CPU_DTRACE_DIVZERO;
-+ } else {
-+ int neg = 0;
-+
-+ /*
-+ * We cannot simply do a 64-bit division, since
-+ * gcc translates it into a call to a function
-+ * that is not linked into the kernel.
-+ *
-+ * regs[rd] = (int64_t)regs[r1] %
-+ * (int64_t)regs[r2];
-+ */
-+ if ((int64_t)regs[r1] < 0) {
-+ neg = !neg;
-+ regs[r1] = -(int64_t)regs[r1];
-+ }
-+ if ((int64_t)regs[r2] < 0) {
-+ neg = !neg;
-+ regs[r2] = -(int64_t)regs[r2];
-+ }
-+ regs[rd] = regs[r1];
-+ regs[rd] = do_div(regs[rd], regs[r2]);
-+
-+ if (neg)
-+ regs[rd] = -(int64_t)regs[rd];
-+ }
-+ break;
-+
-+ case DIF_OP_UREM:
-+ if (regs[r2] == 0) {
-+ regs[rd] = 0;
-+ *flags |= CPU_DTRACE_DIVZERO;
-+ } else {
-+ /*
-+ * We cannot simply do a 64-bit division, since
-+ * gcc translates it into a call to a function
-+ * that is not linked into the kernel.
-+ *
-+ * regs[rd] = regs[r1] % regs[r2];
-+ */
-+ regs[rd] = regs[r1];
-+ regs[rd] = do_div(regs[rd], regs[r2]);
-+ }
-+ break;
-+
-+ case DIF_OP_NOT:
-+ regs[rd] = ~regs[r1];
-+ break;
-+ case DIF_OP_MOV:
-+ regs[rd] = regs[r1];
-+ break;
-+ case DIF_OP_CMP:
-+ cc_r = regs[r1] - regs[r2];
-+ cc_n = cc_r < 0;
-+ cc_z = cc_r == 0;
-+ cc_v = 0;
-+ cc_c = regs[r1] < regs[r2];
-+ break;
-+ case DIF_OP_TST:
-+ cc_n = cc_v = cc_c = 0;
-+ cc_z = regs[r1] == 0;
-+ break;
-+ case DIF_OP_BA:
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BE:
-+ if (cc_z)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BNE:
-+ if (cc_z == 0)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BG:
-+ if ((cc_z | (cc_n ^ cc_v)) == 0)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BGU:
-+ if ((cc_c | cc_z) == 0)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BGE:
-+ if ((cc_n ^ cc_v) == 0)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BGEU:
-+ if (cc_c == 0)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BL:
-+ if (cc_n ^ cc_v)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BLU:
-+ if (cc_c)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BLE:
-+ if (cc_z | (cc_n ^ cc_v))
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BLEU:
-+ if (cc_c | cc_z)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_RLDSB:
-+#ifdef FIXME_OPENSOLARIS_BUG
-+ if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
-+#else
-+ if (!dtrace_canload(regs[r1], 1, mstate, vstate)) {
-+#endif
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDSB:
-+ regs[rd] = (int8_t)dtrace_load8(regs[r1]);
-+ break;
-+ case DIF_OP_RLDSH:
-+ if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDSH:
-+ regs[rd] = (int16_t)dtrace_load16(regs[r1]);
-+ break;
-+ case DIF_OP_RLDSW:
-+ if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDSW:
-+ regs[rd] = (int32_t)dtrace_load32(regs[r1]);
-+ break;
-+ case DIF_OP_RLDUB:
-+ if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDUB:
-+ regs[rd] = dtrace_load8(regs[r1]);
-+ break;
-+ case DIF_OP_RLDUH:
-+ if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDUH:
-+ regs[rd] = dtrace_load16(regs[r1]);
-+ break;
-+ case DIF_OP_RLDUW:
-+ if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDUW:
-+ regs[rd] = dtrace_load32(regs[r1]);
-+ break;
-+ case DIF_OP_RLDX:
-+ if (!dtrace_canstore(regs[r1], 8, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDX:
-+ regs[rd] = dtrace_load64(regs[r1]);
-+ break;
-+ case DIF_OP_ULDSB:
-+ regs[rd] = (int8_t)dtrace_fuword8(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDSH:
-+ regs[rd] = (int16_t)dtrace_fuword16(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDSW:
-+ regs[rd] = (int32_t)dtrace_fuword32(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDUB:
-+ regs[rd] = dtrace_fuword8((void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDUH:
-+ regs[rd] = dtrace_fuword16(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDUW:
-+ regs[rd] = dtrace_fuword32(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDX:
-+ regs[rd] = dtrace_fuword64(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_RET:
-+ rval = regs[rd];
-+ pc = textlen;
-+ break;
-+ case DIF_OP_NOP:
-+ break;
-+ case DIF_OP_SETX:
-+ regs[rd] = inttab[DIF_INSTR_INTEGER(instr)];
-+ break;
-+ case DIF_OP_SETS:
-+ regs[rd] = (uint64_t)(uintptr_t)
-+ (strtab + DIF_INSTR_STRING(instr));
-+ break;
-+ case DIF_OP_SCMP: {
-+ size_t sz = state->dts_options[
-+ DTRACEOPT_STRSIZE];
-+ uintptr_t s1 = regs[r1];
-+ uintptr_t s2 = regs[r2];
-+
-+ if (s1 != (uintptr_t)NULL &&
-+ !dtrace_strcanload(s1, sz, mstate, vstate))
-+ break;
-+ if (s2 != (uintptr_t)NULL &&
-+ !dtrace_strcanload(s2, sz, mstate, vstate))
-+ break;
-+
-+ cc_r = dtrace_strncmp((char *)s1, (char *)s2, sz);
-+
-+ cc_n = cc_r < 0;
-+ cc_z = cc_r == 0;
-+ cc_v = cc_c = 0;
-+ break;
-+ }
-+ case DIF_OP_LDGA:
-+ regs[rd] = dtrace_dif_variable(mstate, state, r1,
-+ regs[r2]);
-+ break;
-+ case DIF_OP_LDGS:
-+ id = DIF_INSTR_VAR(instr);
-+
-+ if (id >= DIF_VAR_OTHER_UBASE) {
-+ uintptr_t a;
-+
-+ id -= DIF_VAR_OTHER_UBASE;
-+ svar = vstate->dtvs_globals[id];
-+ ASSERT(svar != NULL);
-+ v = &svar->dtsv_var;
-+
-+ if (!(v->dtdv_type.dtdt_flags & DIF_TF_BYREF)) {
-+ regs[rd] = svar->dtsv_data;
-+ break;
-+ }
-+
-+ a = (uintptr_t)svar->dtsv_data;
-+
-+ /*
-+ * If the 0th byte is set to UINT8_MAX then
-+ * this is to be treated as a reference to a
-+ * NULL variable.
-+ */
-+ if (*(uint8_t *)a == UINT8_MAX)
-+ regs[rd] = 0;
-+ else
-+ regs[rd] = a + sizeof(uint64_t);
-+
-+ break;
-+ }
-+
-+ regs[rd] = dtrace_dif_variable(mstate, state, id, 0);
-+ break;
-+
-+ case DIF_OP_STGS:
-+ id = DIF_INSTR_VAR(instr);
-+
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ svar = vstate->dtvs_globals[id];
-+ ASSERT(svar != NULL);
-+ v = &svar->dtsv_var;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) {
-+ uintptr_t a = (uintptr_t)svar->dtsv_data;
-+
-+ ASSERT(a != 0);
-+ ASSERT(svar->dtsv_size != 0);
-+
-+ if (regs[rd] == 0) {
-+ *(uint8_t *)a = UINT8_MAX;
-+ break;
-+ } else {
-+ *(uint8_t *)a = 0;
-+ a += sizeof(uint64_t);
-+ }
-+
-+ if (!dtrace_vcanload(
-+ (void *)(uintptr_t)regs[rd],
-+ &v->dtdv_type, mstate, vstate))
-+ break;
-+
-+ dtrace_vcopy((void *)(uintptr_t)regs[rd],
-+ (void *)a, &v->dtdv_type);
-+ break;
-+ }
-+
-+ svar->dtsv_data = regs[rd];
-+ break;
-+
-+ case DIF_OP_LDTA:
-+ /*
-+ * There are no DTrace built-in thread-local arrays at
-+ * present. This opcode is saved for future work.
-+ */
-+ *flags |= CPU_DTRACE_ILLOP;
-+ regs[rd] = 0;
-+ break;
-+
-+ case DIF_OP_LDLS:
-+ id = DIF_INSTR_VAR(instr);
-+
-+ if (id < DIF_VAR_OTHER_UBASE) {
-+ /*
-+ * For now, this has no meaning.
-+ */
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ ASSERT(id < vstate->dtvs_nlocals);
-+ ASSERT(vstate->dtvs_locals != NULL);
-+
-+ svar = vstate->dtvs_locals[id];
-+ ASSERT(svar != NULL);
-+ v = &svar->dtsv_var;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) {
-+ uintptr_t a = (uintptr_t)svar->dtsv_data;
-+ size_t sz = v->dtdv_type.dtdt_size;
-+
-+ sz += sizeof(uint64_t);
-+ ASSERT(svar->dtsv_size == NR_CPUS * sz);
-+ a += smp_processor_id() * sz;
-+
-+ if (*(uint8_t *)a == UINT8_MAX) {
-+ /*
-+ * If the 0th byte is set to UINT8_MAX
-+ * then this is to be treated as a
-+ * reference to a NULL variable.
-+ */
-+ regs[rd] = 0;
-+ } else
-+ regs[rd] = a + sizeof(uint64_t);
-+
-+ break;
-+ }
-+
-+ ASSERT(svar->dtsv_size == NR_CPUS * sizeof(uint64_t));
-+ tmp = (uint64_t *)(uintptr_t)svar->dtsv_data;
-+ regs[rd] = tmp[smp_processor_id()];
-+ break;
-+
-+ case DIF_OP_STLS:
-+ id = DIF_INSTR_VAR(instr);
-+
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+ ASSERT(id < vstate->dtvs_nlocals);
-+
-+ ASSERT(vstate->dtvs_locals != NULL);
-+ svar = vstate->dtvs_locals[id];
-+ ASSERT(svar != NULL);
-+ v = &svar->dtsv_var;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) {
-+ uintptr_t a = (uintptr_t)svar->dtsv_data;
-+ size_t sz = v->dtdv_type.dtdt_size;
-+
-+ sz += sizeof(uint64_t);
-+ ASSERT(svar->dtsv_size == NR_CPUS * sz);
-+ a += smp_processor_id() * sz;
-+
-+ if (regs[rd] == 0) {
-+ *(uint8_t *)a = UINT8_MAX;
-+ break;
-+ } else {
-+ *(uint8_t *)a = 0;
-+ a += sizeof(uint64_t);
-+ }
-+
-+ if (!dtrace_vcanload(
-+ (void *)(uintptr_t)regs[rd],
-+ &v->dtdv_type, mstate, vstate))
-+ break;
-+
-+ dtrace_vcopy((void *)(uintptr_t)regs[rd],
-+ (void *)a, &v->dtdv_type);
-+ break;
-+ }
-+
-+ ASSERT(svar->dtsv_size == NR_CPUS * sizeof(uint64_t));
-+ tmp = (uint64_t *)(uintptr_t)svar->dtsv_data;
-+ tmp[smp_processor_id()] = regs[rd];
-+ break;
-+
-+ case DIF_OP_LDTS: {
-+ struct dtrace_dynvar *dvar;
-+ struct dtrace_key *key;
-+
-+ id = DIF_INSTR_VAR(instr);
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+ v = &vstate->dtvs_tlocals[id];
-+
-+ key = &tupregs[DIF_DTR_NREGS];
-+ key[0].dttk_value = (uint64_t)id;
-+ key[0].dttk_size = 0;
-+ DTRACE_TLS_THRKEY(key[1].dttk_value);
-+ key[1].dttk_size = 0;
-+
-+ dvar = dtrace_dynvar(dstate, 2, key, sizeof(uint64_t),
-+ DTRACE_DYNVAR_NOALLOC, mstate,
-+ vstate);
-+
-+ if (dvar == NULL) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF)
-+ regs[rd] = (uint64_t)(uintptr_t)dvar->dtdv_data;
-+ else
-+ regs[rd] = *((uint64_t *)dvar->dtdv_data);
-+
-+ break;
-+ }
-+
-+ case DIF_OP_STTS: {
-+ struct dtrace_dynvar *dvar;
-+ struct dtrace_key *key;
-+
-+ id = DIF_INSTR_VAR(instr);
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ key = &tupregs[DIF_DTR_NREGS];
-+ key[0].dttk_value = (uint64_t)id;
-+ key[0].dttk_size = 0;
-+ DTRACE_TLS_THRKEY(key[1].dttk_value);
-+ key[1].dttk_size = 0;
-+ v = &vstate->dtvs_tlocals[id];
-+
-+ dvar = dtrace_dynvar(dstate, 2, key,
-+ v->dtdv_type.dtdt_size > sizeof(uint64_t)
-+ ? v->dtdv_type.dtdt_size
-+ : sizeof(uint64_t),
-+ regs[rd]
-+ ? DTRACE_DYNVAR_ALLOC
-+ : DTRACE_DYNVAR_DEALLOC,
-+ mstate, vstate);
-+
-+ /*
-+ * Given that we're storing to thread-local data,
-+ * we need to flush our predicate cache.
-+ */
-+ if (current->dt_task != NULL)
-+ current->dt_task->dt_predcache = 0;
-+
-+ if (dvar == NULL)
-+ break;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) {
-+ if (!dtrace_vcanload(
-+ (void *)(uintptr_t)regs[rd],
-+ &v->dtdv_type, mstate, vstate))
-+ break;
-+
-+ dtrace_vcopy((void *)(uintptr_t)regs[rd],
-+ dvar->dtdv_data, &v->dtdv_type);
-+ } else
-+ *((uint64_t *)dvar->dtdv_data) = regs[rd];
-+
-+ break;
-+ }
-+
-+ case DIF_OP_SRA:
-+ regs[rd] = (int64_t)regs[r1] >> regs[r2];
-+ break;
-+
-+ case DIF_OP_CALL:
-+ dtrace_dif_subr(DIF_INSTR_SUBR(instr), rd, regs,
-+ tupregs, ttop, mstate, state);
-+ break;
-+
-+ case DIF_OP_PUSHTR:
-+ if (ttop == DIF_DTR_NREGS) {
-+ *flags |= CPU_DTRACE_TUPOFLOW;
-+ break;
-+ }
-+
-+ if (r1 == DIF_TYPE_STRING)
-+ /*
-+ * If this is a string type and the size is 0,
-+ * we'll use the system-wide default string
-+ * size. Note that we are _not_ looking at
-+ * the value of the DTRACEOPT_STRSIZE option;
-+ * had this been set, we would expect to have
-+ * a non-zero size value in the "pushtr".
-+ */
-+ tupregs[ttop].dttk_size =
-+ dtrace_strlen(
-+ (char *)(uintptr_t)regs[rd],
-+ regs[r2]
-+ ? regs[r2]
-+ : dtrace_strsize_default
-+ ) + 1;
-+ else
-+ tupregs[ttop].dttk_size = regs[r2];
-+
-+ tupregs[ttop++].dttk_value = regs[rd];
-+ break;
-+
-+ case DIF_OP_PUSHTV:
-+ if (ttop == DIF_DTR_NREGS) {
-+ *flags |= CPU_DTRACE_TUPOFLOW;
-+ break;
-+ }
-+
-+ tupregs[ttop].dttk_value = regs[rd];
-+ tupregs[ttop++].dttk_size = 0;
-+ break;
-+
-+ case DIF_OP_POPTS:
-+ if (ttop != 0)
-+ ttop--;
-+ break;
-+
-+ case DIF_OP_FLUSHTS:
-+ ttop = 0;
-+ break;
-+
-+ case DIF_OP_LDGAA:
-+ case DIF_OP_LDTAA: {
-+ struct dtrace_dynvar *dvar;
-+ struct dtrace_key *key = tupregs;
-+ uint_t nkeys = ttop;
-+
-+ id = DIF_INSTR_VAR(instr);
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ key[nkeys].dttk_value = (uint64_t)id;
-+ key[nkeys++].dttk_size = 0;
-+
-+ if (DIF_INSTR_OP(instr) == DIF_OP_LDTAA) {
-+ DTRACE_TLS_THRKEY(key[nkeys].dttk_value);
-+ key[nkeys++].dttk_size = 0;
-+ v = &vstate->dtvs_tlocals[id];
-+ } else
-+ v = &vstate->dtvs_globals[id]->dtsv_var;
-+
-+ dvar = dtrace_dynvar(dstate, nkeys, key,
-+ v->dtdv_type.dtdt_size > sizeof(uint64_t) ?
-+ v->dtdv_type.dtdt_size : sizeof(uint64_t),
-+ DTRACE_DYNVAR_NOALLOC, mstate, vstate);
-+
-+ if (dvar == NULL) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF)
-+ regs[rd] = (uint64_t)(uintptr_t)dvar->dtdv_data;
-+ else
-+ regs[rd] = *((uint64_t *)dvar->dtdv_data);
-+
-+ break;
-+ }
-+
-+ case DIF_OP_STGAA:
-+ case DIF_OP_STTAA: {
-+ struct dtrace_dynvar *dvar;
-+ struct dtrace_key *key = tupregs;
-+ uint_t nkeys = ttop;
-+
-+ id = DIF_INSTR_VAR(instr);
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ key[nkeys].dttk_value = (uint64_t)id;
-+ key[nkeys++].dttk_size = 0;
-+
-+ if (DIF_INSTR_OP(instr) == DIF_OP_STTAA) {
-+ DTRACE_TLS_THRKEY(key[nkeys].dttk_value);
-+ key[nkeys++].dttk_size = 0;
-+ v = &vstate->dtvs_tlocals[id];
-+ } else
-+ v = &vstate->dtvs_globals[id]->dtsv_var;
-+
-+ dvar = dtrace_dynvar(dstate, nkeys, key,
-+ v->dtdv_type.dtdt_size > sizeof(uint64_t)
-+ ? v->dtdv_type.dtdt_size
-+ : sizeof(uint64_t),
-+ regs[rd] ? DTRACE_DYNVAR_ALLOC
-+ : DTRACE_DYNVAR_DEALLOC,
-+ mstate, vstate);
-+
-+ if (dvar == NULL)
-+ break;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) {
-+ if (!dtrace_vcanload(
-+ (void *)(uintptr_t)regs[rd],
-+ &v->dtdv_type, mstate, vstate))
-+ break;
-+
-+ dtrace_vcopy((void *)(uintptr_t)regs[rd],
-+ dvar->dtdv_data, &v->dtdv_type);
-+ } else
-+ *((uint64_t *)dvar->dtdv_data) = regs[rd];
-+
-+ break;
-+ }
-+
-+ case DIF_OP_ALLOCS: {
-+ uintptr_t ptr =
-+ P2ROUNDUP(mstate->dtms_scratch_ptr, 8);
-+ size_t size = ptr - mstate->dtms_scratch_ptr +
-+ regs[r1];
-+
-+ /*
-+ * Rounding up the user allocation size could have
-+ * overflowed large, bogus allocations (like -1ULL) to
-+ * 0.
-+ */
-+ if (size < regs[r1] ||
-+ !DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ dtrace_bzero((void *) mstate->dtms_scratch_ptr, size);
-+ mstate->dtms_scratch_ptr += size;
-+ regs[rd] = ptr;
-+ break;
-+ }
-+
-+ case DIF_OP_COPYS:
-+ if (!dtrace_canstore(regs[rd], regs[r2], mstate,
-+ vstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ if (!dtrace_canload(regs[r1], regs[r2], mstate, vstate))
-+ break;
-+
-+ dtrace_bcopy((void *)(uintptr_t)regs[r1],
-+ (void *)(uintptr_t)regs[rd],
-+ (size_t)regs[r2]);
-+ break;
-+
-+ case DIF_OP_STB:
-+ if (!dtrace_canstore(regs[rd], 1, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ *((uint8_t *)(uintptr_t)regs[rd]) = (uint8_t)regs[r1];
-+ break;
-+
-+ case DIF_OP_STH:
-+ if (!dtrace_canstore(regs[rd], 2, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ if (regs[rd] & 1) {
-+ *flags |= CPU_DTRACE_BADALIGN;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ *((uint16_t *)(uintptr_t)regs[rd]) = (uint16_t)regs[r1];
-+ break;
-+
-+ case DIF_OP_STW:
-+ if (!dtrace_canstore(regs[rd], 4, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ if (regs[rd] & 3) {
-+ *flags |= CPU_DTRACE_BADALIGN;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ *((uint32_t *)(uintptr_t)regs[rd]) = (uint32_t)regs[r1];
-+ break;
-+
-+ case DIF_OP_STX:
-+ if (!dtrace_canstore(regs[rd], 8, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ if (regs[rd] & 7) {
-+ *flags |= CPU_DTRACE_BADALIGN;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ *((uint64_t *)(uintptr_t)regs[rd]) = regs[r1];
-+ break;
-+ }
-+ }
-+
-+
-+ if (!(*flags & CPU_DTRACE_FAULT)) {
-+ dt_dbg_dif(" DIF %p completed, rval = %llx (flags %x)\n",
-+ difo, rval, *flags);
-+ return rval;
-+ }
-+
-+ dt_dbg_dif(" DIF %p emulation failed (flags %x)\n", difo, *flags);
-+
-+ mstate->dtms_fltoffs = opc * sizeof(dif_instr_t);
-+ mstate->dtms_present |= DTRACE_MSTATE_FLTOFFS;
-+
-+ return 0;
-+}
-diff --git a/dtrace/dtrace_dof.c b/dtrace/dtrace_dof.c
-new file mode 100644
-index 000000000000..85ff9b21a205
---- /dev/null
-+++ b/dtrace/dtrace_dof.c
-@@ -0,0 +1,2504 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_dof.c
-+ * DESCRIPTION: DTrace - DOF implementation
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+#include <linux/vmalloc.h>
-+#include <linux/uaccess.h>
-+
-+#include "dtrace.h"
-+
-+size_t dtrace_difo_maxsize = 256 * 1024;
-+dtrace_optval_t dtrace_dof_maxsize = 256 * 1024;
-+size_t dtrace_actions_max = 16 * 1024;
-+dtrace_optval_t dtrace_helper_actions_max = 32;
-+dtrace_optval_t dtrace_helper_providers_max = 32;
-+
-+static int dtrace_helpers;
-+
-+static uint32_t dtrace_helptrace_next;
-+static uint32_t dtrace_helptrace_nlocals;
-+
-+#ifdef CONFIG_DT_DEBUG
-+int dtrace_helptrace_enabled = 1;
-+#else
-+int dtrace_helptrace_enabled = 0;
-+#endif
-+int dtrace_helptrace_bufsize = 512 * 1024;
-+char *dtrace_helptrace_buffer;
-+
-+void dtrace_dof_error(struct dof_hdr *dof, const char *str)
-+{
-+ if (dtrace_err_verbose)
-+ pr_warn("failed to process DOF: %s", str);
-+ else
-+ dt_dbg_dof("Failed to process DOF: %s\n", str);
-+
-+#ifdef DTRACE_ERRDEBUG
-+ dtrace_errdebug(str);
-+#endif
-+}
-+
-+/*
-+ * Create DOF out of a currently enabled state. Right now, we only create
-+ * DOF containing the run-time options -- but this could be expanded to create
-+ * complete DOF representing the enabled state.
-+ */
-+struct dof_hdr *dtrace_dof_create(struct dtrace_state *state)
-+{
-+ struct dof_hdr *dof;
-+ struct dof_sec *sec;
-+ struct dof_optdesc *opt;
-+
-+ int i, len = sizeof(struct dof_hdr) +
-+ roundup(sizeof(struct dof_sec),
-+ sizeof(uint64_t)) +
-+ sizeof(struct dof_optdesc) * DTRACEOPT_MAX;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ dof = vmalloc(len);
-+ if (dof == NULL)
-+ return NULL;
-+
-+ dof->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0;
-+ dof->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1;
-+ dof->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2;
-+ dof->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3;
-+
-+ dof->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_NATIVE;
-+ dof->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE;
-+ dof->dofh_ident[DOF_ID_VERSION] = DOF_VERSION;
-+ dof->dofh_ident[DOF_ID_DIFVERS] = DIF_VERSION;
-+ dof->dofh_ident[DOF_ID_DIFIREG] = DIF_DIR_NREGS;
-+ dof->dofh_ident[DOF_ID_DIFTREG] = DIF_DTR_NREGS;
-+
-+ dof->dofh_flags = 0;
-+ dof->dofh_hdrsize = sizeof(struct dof_hdr);
-+ dof->dofh_secsize = sizeof(struct dof_sec);
-+ dof->dofh_secnum = 1; /* only DOF_SECT_OPTDESC */
-+ dof->dofh_secoff = sizeof(struct dof_hdr);
-+ dof->dofh_loadsz = len;
-+ dof->dofh_filesz = len;
-+ dof->dofh_pad = 0;
-+
-+ /*
-+ * Fill in the option section header...
-+ */
-+ sec = (struct dof_sec *)((uintptr_t)dof + sizeof(struct dof_hdr));
-+ sec->dofs_type = DOF_SECT_OPTDESC;
-+ sec->dofs_align = sizeof(uint64_t);
-+ sec->dofs_flags = DOF_SECF_LOAD;
-+ sec->dofs_entsize = sizeof(struct dof_optdesc);
-+
-+ opt = (struct dof_optdesc *)((uintptr_t)sec +
-+ roundup(sizeof(struct dof_sec),
-+ sizeof(uint64_t)));
-+
-+ sec->dofs_offset = (uintptr_t)opt - (uintptr_t)dof;
-+ sec->dofs_size = sizeof(struct dof_optdesc) * DTRACEOPT_MAX;
-+
-+ for (i = 0; i < DTRACEOPT_MAX; i++) {
-+ opt[i].dofo_option = i;
-+ opt[i].dofo_strtab = DOF_SECIDX_NONE;
-+ opt[i].dofo_value = state->dts_options[i];
-+ }
-+
-+ return dof;
-+}
-+
-+struct dof_hdr *dtrace_dof_copyin(void __user *argp, int *errp)
-+{
-+ struct dof_hdr hdr, *dof;
-+
-+ ASSERT(!MUTEX_HELD(&dtrace_lock));
-+
-+ /*
-+ * First, we're going to copyin() the sizeof(dof_hdr_t).
-+ */
-+ if (copy_from_user(&hdr, argp, sizeof(hdr)) != 0) {
-+ dtrace_dof_error(NULL, "failed to copyin DOF header");
-+ *errp = -EFAULT;
-+ return NULL;
-+ }
-+
-+ /*
-+ * Now we'll allocate the entire DOF and copy it in -- provided
-+ * that the length isn't outrageous.
-+ */
-+ if (hdr.dofh_loadsz >= dtrace_dof_maxsize) {
-+ dtrace_dof_error(&hdr, "load size exceeds maximum");
-+ *errp = -E2BIG;
-+ return NULL;
-+ }
-+
-+ if (hdr.dofh_loadsz < sizeof(hdr)) {
-+ dtrace_dof_error(&hdr, "invalid load size");
-+ *errp = -EINVAL;
-+ return NULL;
-+ }
-+
-+ dof = vmalloc(hdr.dofh_loadsz);
-+ if (dof == NULL) {
-+ *errp = -ENOMEM;
-+ return NULL;
-+ }
-+
-+ if (copy_from_user(dof, argp, hdr.dofh_loadsz) != 0 ||
-+ dof->dofh_loadsz != hdr.dofh_loadsz) {
-+ vfree(dof);
-+ *errp = -EFAULT;
-+ return NULL;
-+ }
-+
-+ return dof;
-+}
-+
-+struct dof_hdr *dtrace_dof_property(const char *name)
-+{
-+ uchar_t *buf;
-+ uint64_t loadsz;
-+ unsigned int len, i;
-+ struct dof_hdr *dof;
-+
-+ /*
-+ * Unfortunately, array of values in .conf files are always (and
-+ * only) interpreted to be integer arrays. We must read our DOF
-+ * as an integer array, and then squeeze it into a byte array.
-+ */
-+#ifdef FIXME
-+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dtrace_devi, 0,
-+ (char *)name, (int **)&buf, &len) !=
-+ DDI_PROP_SUCCESS)
-+ return NULL;
-+#else
-+ return NULL;
-+#endif
-+
-+ for (i = 0; i < len; i++)
-+ buf[i] = (uchar_t)(((int *)buf)[i]);
-+
-+ if (len < sizeof(struct dof_hdr)) {
-+#ifdef FIXME
-+ ddi_prop_free(buf);
-+#endif
-+ dtrace_dof_error(NULL, "truncated header");
-+ return NULL;
-+ }
-+
-+ loadsz = ((struct dof_hdr *)buf)->dofh_loadsz;
-+ if (len < loadsz) {
-+#ifdef FIXME
-+ ddi_prop_free(buf);
-+#endif
-+ dtrace_dof_error(NULL, "truncated DOF");
-+ return NULL;
-+ }
-+
-+ if (loadsz >= dtrace_dof_maxsize) {
-+#ifdef FIXME
-+ ddi_prop_free(buf);
-+#endif
-+ dtrace_dof_error(NULL, "oversized DOF");
-+ return NULL;
-+ }
-+
-+ dof = vmalloc(loadsz);
-+ if (dof == NULL) {
-+ dtrace_dof_error(NULL, "out-of-memory");
-+ return NULL;
-+ }
-+ memcpy(dof, buf, loadsz);
-+#ifdef FIXME
-+ ddi_prop_free(buf);
-+#endif
-+
-+ return dof;
-+}
-+
-+void dtrace_dof_destroy(struct dof_hdr *dof)
-+{
-+ vfree(dof);
-+}
-+
-+/*
-+ * Return the dof_sec_t pointer corresponding to a given section index. If the
-+ * index is not valid, dtrace_dof_error() is called and NULL is returned. If
-+ * a type other than DOF_SECT_NONE is specified, the header is checked against
-+ * this type and NULL is returned if the types do not match.
-+ */
-+static struct dof_sec *dtrace_dof_sect(struct dof_hdr *dof, uint32_t doftype,
-+ dof_secidx_t i)
-+{
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(uintptr_t) ((uintptr_t)dof +
-+ dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (i >= dof->dofh_secnum) {
-+ dtrace_dof_error(dof, "referenced section index is invalid");
-+ return NULL;
-+ }
-+
-+ if (!(sec->dofs_flags & DOF_SECF_LOAD)) {
-+ dtrace_dof_error(dof, "referenced section is not loadable");
-+ return NULL;
-+ }
-+
-+ if (doftype != DOF_SECT_NONE && doftype != sec->dofs_type) {
-+ dtrace_dof_error(dof, "referenced section is the wrong type");
-+ return NULL;
-+ }
-+
-+ return sec;
-+}
-+
-+static struct dtrace_probedesc *dtrace_dof_probedesc(struct dof_hdr *dof,
-+ struct dof_sec *sec,
-+ struct dtrace_probedesc *desc)
-+{
-+ struct dof_probedesc *probe;
-+ struct dof_sec *strtab;
-+ uintptr_t daddr = (uintptr_t)dof;
-+ uintptr_t str;
-+ size_t size;
-+
-+ if (sec->dofs_type != DOF_SECT_PROBEDESC) {
-+ dtrace_dof_error(dof, "invalid probe section");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_align != sizeof(dof_secidx_t)) {
-+ dtrace_dof_error(dof, "bad alignment in probe description");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_offset + sizeof(struct dof_probedesc) >
-+ dof->dofh_loadsz) {
-+ dtrace_dof_error(dof, "truncated probe description");
-+ return NULL;
-+ }
-+
-+ probe = (struct dof_probedesc *)(uintptr_t)(daddr + sec->dofs_offset);
-+ strtab = dtrace_dof_sect(dof, DOF_SECT_STRTAB, probe->dofp_strtab);
-+
-+ if (strtab == NULL)
-+ return NULL;
-+
-+ str = daddr + strtab->dofs_offset;
-+ size = strtab->dofs_size;
-+
-+ if (probe->dofp_provider >= strtab->dofs_size) {
-+ dtrace_dof_error(dof, "corrupt probe provider");
-+ return NULL;
-+ }
-+
-+ strncpy(desc->dtpd_provider, (char *)(str + probe->dofp_provider),
-+ min((size_t)DTRACE_PROVNAMELEN - 1,
-+ size - probe->dofp_provider));
-+
-+ if (probe->dofp_mod >= strtab->dofs_size) {
-+ dtrace_dof_error(dof, "corrupt probe module");
-+ return NULL;
-+ }
-+
-+ strncpy(desc->dtpd_mod, (char *)(str + probe->dofp_mod),
-+ min((size_t)DTRACE_MODNAMELEN - 1, size - probe->dofp_mod));
-+
-+ if (probe->dofp_func >= strtab->dofs_size) {
-+ dtrace_dof_error(dof, "corrupt probe function");
-+ return NULL;
-+ }
-+
-+ strncpy(desc->dtpd_func, (char *)(str + probe->dofp_func),
-+ min((size_t)DTRACE_FUNCNAMELEN - 1, size - probe->dofp_func));
-+
-+ if (probe->dofp_name >= strtab->dofs_size) {
-+ dtrace_dof_error(dof, "corrupt probe name");
-+ return NULL;
-+ }
-+
-+ strncpy(desc->dtpd_name, (char *)(str + probe->dofp_name),
-+ min((size_t)DTRACE_NAMELEN - 1, size - probe->dofp_name));
-+
-+ dt_dbg_dof(" ECB Probe %s:%s:%s:%s\n",
-+ desc->dtpd_provider, desc->dtpd_mod, desc->dtpd_func,
-+ desc->dtpd_name);
-+
-+ return desc;
-+}
-+
-+static struct dtrace_difo *dtrace_dof_difo(struct dof_hdr *dof,
-+ struct dof_sec *sec,
-+ struct dtrace_vstate *vstate,
-+ const struct cred *cr)
-+{
-+ struct dtrace_difo *dp;
-+ size_t ttl = 0;
-+ struct dof_difohdr *dofd;
-+ uintptr_t daddr = (uintptr_t)dof;
-+ size_t max = dtrace_difo_maxsize;
-+ int i, l, n;
-+
-+ static const struct {
-+ int section;
-+ int bufoffs;
-+ int lenoffs;
-+ int entsize;
-+ int align;
-+ const char *msg;
-+ } difo[] = {
-+ {
-+ DOF_SECT_DIF,
-+ offsetof(struct dtrace_difo, dtdo_buf),
-+ offsetof(struct dtrace_difo, dtdo_len),
-+ sizeof(dif_instr_t),
-+ sizeof(dif_instr_t),
-+ "multiple DIF sections"
-+ },
-+ {
-+ DOF_SECT_INTTAB,
-+ offsetof(struct dtrace_difo, dtdo_inttab),
-+ offsetof(struct dtrace_difo, dtdo_intlen),
-+ sizeof(uint64_t),
-+ sizeof(uint64_t),
-+ "multiple integer tables"
-+ },
-+ {
-+ DOF_SECT_STRTAB,
-+ offsetof(struct dtrace_difo, dtdo_strtab),
-+ offsetof(struct dtrace_difo, dtdo_strlen),
-+ 0,
-+ sizeof(char),
-+ "multiple string tables"
-+ },
-+ {
-+ DOF_SECT_VARTAB,
-+ offsetof(struct dtrace_difo, dtdo_vartab),
-+ offsetof(struct dtrace_difo, dtdo_varlen),
-+ sizeof(struct dtrace_difv),
-+ sizeof(uint_t),
-+ "multiple variable tables"
-+ },
-+ {
-+ DOF_SECT_NONE,
-+ 0,
-+ 0,
-+ 0,
-+ 0,
-+ NULL
-+ }
-+ };
-+
-+ if (sec->dofs_type != DOF_SECT_DIFOHDR) {
-+ dtrace_dof_error(dof, "invalid DIFO header section");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_align != sizeof(dof_secidx_t)) {
-+ dtrace_dof_error(dof, "bad alignment in DIFO header");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_size < sizeof(struct dof_difohdr) ||
-+ sec->dofs_size % sizeof(dof_secidx_t)) {
-+ dtrace_dof_error(dof, "bad size in DIFO header");
-+ return NULL;
-+ }
-+
-+ dofd = (struct dof_difohdr *)(uintptr_t)(daddr + sec->dofs_offset);
-+ n = (sec->dofs_size - sizeof(*dofd)) / sizeof(dof_secidx_t) + 1;
-+
-+ dp = kzalloc(sizeof(struct dtrace_difo), GFP_KERNEL);
-+ if (dp == NULL) {
-+ dtrace_dof_error(dof, "out-of-memory");
-+ return NULL;
-+ }
-+ dp->dtdo_rtype = dofd->dofd_rtype;
-+
-+ for (l = 0; l < n; l++) {
-+ struct dof_sec *subsec;
-+ void **bufp;
-+ uint32_t *lenp;
-+
-+ subsec = dtrace_dof_sect(dof, DOF_SECT_NONE,
-+ dofd->dofd_links[l]);
-+ if (subsec == NULL)
-+ goto err; /* invalid section link */
-+
-+ if (ttl + subsec->dofs_size > max) {
-+ dtrace_dof_error(dof, "exceeds maximum size");
-+ goto err;
-+ }
-+
-+ ttl += subsec->dofs_size;
-+
-+ for (i = 0; difo[i].section != DOF_SECT_NONE; i++) {
-+ if (subsec->dofs_type != difo[i].section)
-+ continue;
-+
-+ if (!(subsec->dofs_flags & DOF_SECF_LOAD)) {
-+ dtrace_dof_error(dof, "section not loaded");
-+ goto err;
-+ }
-+
-+ if (subsec->dofs_align != difo[i].align) {
-+ dtrace_dof_error(dof, "bad alignment");
-+ goto err;
-+ }
-+
-+ bufp = (void **)((uintptr_t)dp + difo[i].bufoffs);
-+ lenp = (uint32_t *)((uintptr_t)dp + difo[i].lenoffs);
-+
-+ if (*bufp != NULL) {
-+ dtrace_dof_error(dof, difo[i].msg);
-+ goto err;
-+ }
-+
-+ if (difo[i].entsize != subsec->dofs_entsize) {
-+ dtrace_dof_error(dof, "entry size mismatch");
-+ goto err;
-+ }
-+
-+ if (subsec->dofs_entsize != 0) {
-+ uint64_t n = subsec->dofs_size;
-+
-+ if (do_div(n, subsec->dofs_entsize) != 0) {
-+ dtrace_dof_error(dof,
-+ "corrupt entry size");
-+ goto err;
-+ }
-+ }
-+
-+ *lenp = subsec->dofs_size;
-+ *bufp = vmalloc(subsec->dofs_size);
-+ if (*bufp == NULL) {
-+ dtrace_dof_error(dof, "out-of-memory");
-+ goto err;
-+ }
-+ memcpy(*bufp,
-+ (char *)(uintptr_t)(daddr + subsec->dofs_offset),
-+ subsec->dofs_size);
-+
-+ if (subsec->dofs_entsize != 0)
-+ *lenp /= subsec->dofs_entsize;
-+
-+ break;
-+ }
-+
-+ /*
-+ * If we encounter a loadable DIFO sub-section that is not
-+ * known to us, assume this is a broken program and fail.
-+ */
-+ if (difo[i].section == DOF_SECT_NONE &&
-+ (subsec->dofs_flags & DOF_SECF_LOAD)) {
-+ dtrace_dof_error(dof, "unrecognized DIFO subsection");
-+ goto err;
-+ }
-+ }
-+
-+ if (dp->dtdo_buf == NULL) {
-+ /*
-+ * We can't have a DIF object without DIF text.
-+ */
-+ dtrace_dof_error(dof, "missing DIF text");
-+ goto err;
-+ }
-+
-+ /*
-+ * Before we validate the DIF object, run through the variable table
-+ * looking for the strings -- if any of their size are under, we'll set
-+ * their size to be the system-wide default string size. Note that
-+ * this should _not_ happen if the "strsize" option has been set --
-+ * in this case, the compiler should have set the size to reflect the
-+ * setting of the option.
-+ */
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+ struct dtrace_diftype *t = &v->dtdv_type;
-+
-+ if (v->dtdv_id < DIF_VAR_OTHER_UBASE)
-+ continue;
-+
-+ if (t->dtdt_kind == DIF_TYPE_STRING && t->dtdt_size == 0)
-+ t->dtdt_size = dtrace_strsize_default;
-+ }
-+
-+ if (dtrace_difo_validate(dp, vstate, DIF_DIR_NREGS, cr) != 0)
-+ goto err;
-+
-+ dtrace_difo_init(dp, vstate);
-+ return dp;
-+
-+err:
-+ if (dp->dtdo_buf != NULL)
-+ vfree(dp->dtdo_buf);
-+ if (dp->dtdo_inttab != NULL)
-+ vfree(dp->dtdo_inttab);
-+ if (dp->dtdo_strtab != NULL)
-+ vfree(dp->dtdo_strtab);
-+ if (dp->dtdo_vartab != NULL)
-+ vfree(dp->dtdo_vartab);
-+
-+ kfree(dp);
-+
-+ return NULL;
-+}
-+
-+static struct dtrace_predicate *dtrace_dof_predicate(struct dof_hdr *dof,
-+ struct dof_sec *sec,
-+ struct dtrace_vstate *vstate,
-+ const struct cred *cr)
-+{
-+ struct dtrace_difo *dp;
-+
-+ if ((dp = dtrace_dof_difo(dof, sec, vstate, cr)) == NULL)
-+ return NULL;
-+
-+ return dtrace_predicate_create(dp);
-+}
-+
-+static struct dtrace_actdesc *dtrace_dof_actdesc(struct dof_hdr *dof,
-+ struct dof_sec *sec,
-+ struct dtrace_vstate *vstate,
-+ const struct cred *cr)
-+{
-+ struct dtrace_actdesc *act, *first = NULL, *last = NULL, *next;
-+ struct dof_actdesc *desc;
-+ struct dof_sec *difosec;
-+ size_t offs;
-+ uintptr_t daddr = (uintptr_t)dof;
-+ uint64_t arg;
-+ dtrace_actkind_t kind;
-+
-+ if (sec->dofs_type != DOF_SECT_ACTDESC) {
-+ dtrace_dof_error(dof, "invalid action section");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_offset + sizeof(struct dof_actdesc) > dof->dofh_loadsz) {
-+ dtrace_dof_error(dof, "truncated action description");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_align != sizeof(uint64_t)) {
-+ dtrace_dof_error(dof, "bad alignment in action description");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_size < sec->dofs_entsize) {
-+ dtrace_dof_error(dof, "section entry size exceeds total size");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_entsize != sizeof(struct dof_actdesc)) {
-+ dtrace_dof_error(dof, "bad entry size in action description");
-+ return NULL;
-+ }
-+
-+ /*
-+ * Was: sec->dofs_size / sec->dofs_entsize > dtrace_actions_max
-+ * but it is safer to simply avoid the division (it requires use of
-+ * a macro in Linux to cover 64-bit division in a 32-bit kernel.
-+ */
-+ if (sec->dofs_size > sec->dofs_entsize * dtrace_actions_max) {
-+ dtrace_dof_error(dof, "actions exceed dtrace_actions_max");
-+ return NULL;
-+ }
-+
-+ for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) {
-+ desc = (struct dof_actdesc *)(daddr +
-+ (uintptr_t)sec->dofs_offset + offs);
-+ kind = (dtrace_actkind_t)desc->dofa_kind;
-+
-+ if (DTRACEACT_ISPRINTFLIKE(kind) &&
-+ (kind != DTRACEACT_PRINTA ||
-+ desc->dofa_strtab != DOF_SECIDX_NONE)) {
-+ struct dof_sec *strtab;
-+ char *str, *fmt;
-+ uint64_t i;
-+
-+ /*
-+ * The printf()-like actions must have a format string.
-+ */
-+ strtab = dtrace_dof_sect(dof, DOF_SECT_STRTAB,
-+ desc->dofa_strtab);
-+ if (strtab == NULL)
-+ goto err;
-+
-+ str = (char *)((uintptr_t)dof +
-+ (uintptr_t)strtab->dofs_offset);
-+
-+ for (i = desc->dofa_arg; i < strtab->dofs_size; i++) {
-+ if (str[i] == '\0')
-+ break;
-+ }
-+
-+ if (i >= strtab->dofs_size) {
-+ dtrace_dof_error(dof, "bogus format string");
-+ goto err;
-+ }
-+
-+ if (i == desc->dofa_arg) {
-+ dtrace_dof_error(dof, "empty format string");
-+ goto err;
-+ }
-+
-+ i -= desc->dofa_arg;
-+ fmt = vmalloc(i + 1);
-+ if (fmt == NULL) {
-+ dtrace_dof_error(dof, "out-of-memory");
-+ goto err;
-+ }
-+ memcpy(fmt, &str[desc->dofa_arg], i + 1);
-+ arg = (uint64_t)(uintptr_t)fmt;
-+ } else {
-+ if (kind == DTRACEACT_PRINTA) {
-+ ASSERT(desc->dofa_strtab == DOF_SECIDX_NONE);
-+ arg = 0;
-+ } else
-+ arg = desc->dofa_arg;
-+ }
-+
-+ act = dtrace_actdesc_create(kind, desc->dofa_ntuple,
-+ desc->dofa_uarg, arg);
-+ if (act == NULL)
-+ goto err;
-+
-+ if (last != NULL)
-+ last->dtad_next = act;
-+ else
-+ first = act;
-+
-+ last = act;
-+
-+ if (desc->dofa_difo == DOF_SECIDX_NONE)
-+ continue;
-+
-+ difosec = dtrace_dof_sect(dof, DOF_SECT_DIFOHDR,
-+ desc->dofa_difo);
-+ if (difosec == NULL)
-+ goto err;
-+
-+ act->dtad_difo = dtrace_dof_difo(dof, difosec, vstate, cr);
-+
-+ if (act->dtad_difo == NULL)
-+ goto err;
-+ }
-+
-+ ASSERT(first != NULL);
-+ return first;
-+
-+err:
-+ for (act = first; act != NULL; act = next) {
-+ next = act->dtad_next;
-+ dtrace_actdesc_release(act, vstate);
-+ }
-+
-+ return NULL;
-+}
-+
-+static struct dtrace_ecbdesc *dtrace_dof_ecbdesc(struct dof_hdr *dof,
-+ struct dof_sec *sec,
-+ struct dtrace_vstate *vstate,
-+ const struct cred *cr)
-+{
-+ struct dtrace_ecbdesc *ep;
-+ struct dof_ecbdesc *ecb;
-+ struct dtrace_probedesc *desc;
-+ struct dtrace_predicate *pred = NULL;
-+
-+ if (sec->dofs_size < sizeof(struct dof_ecbdesc)) {
-+ dtrace_dof_error(dof, "truncated ECB description");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_align != sizeof(uint64_t)) {
-+ dtrace_dof_error(dof, "bad alignment in ECB description");
-+ return NULL;
-+ }
-+
-+ ecb = (struct dof_ecbdesc *)
-+ ((uintptr_t)dof + (uintptr_t)sec->dofs_offset);
-+ sec = dtrace_dof_sect(dof, DOF_SECT_PROBEDESC, ecb->dofe_probes);
-+
-+ if (sec == NULL)
-+ return NULL;
-+
-+ ep = kzalloc(sizeof(struct dtrace_ecbdesc), GFP_KERNEL);
-+ if (ep == NULL)
-+ return NULL;
-+ ep->dted_uarg = ecb->dofe_uarg;
-+ desc = &ep->dted_probe;
-+
-+ if (dtrace_dof_probedesc(dof, sec, desc) == NULL)
-+ goto err;
-+
-+ if (ecb->dofe_pred != DOF_SECIDX_NONE) {
-+ sec = dtrace_dof_sect(dof, DOF_SECT_DIFOHDR, ecb->dofe_pred);
-+ if (sec == NULL)
-+ goto err;
-+
-+ pred = dtrace_dof_predicate(dof, sec, vstate, cr);
-+ if (pred == NULL)
-+ goto err;
-+
-+ ep->dted_pred.dtpdd_predicate = pred;
-+ }
-+
-+ if (ecb->dofe_actions != DOF_SECIDX_NONE) {
-+ sec = dtrace_dof_sect(dof, DOF_SECT_ACTDESC, ecb->dofe_actions);
-+ if (sec == NULL)
-+ goto err;
-+
-+ ep->dted_action = dtrace_dof_actdesc(dof, sec, vstate, cr);
-+
-+ if (ep->dted_action == NULL)
-+ goto err;
-+ }
-+
-+ return ep;
-+
-+err:
-+ if (pred != NULL)
-+ dtrace_predicate_release(pred, vstate);
-+ kfree(ep);
-+ return NULL;
-+}
-+
-+/*
-+ * Apply the relocations from the specified 'sec' (a DOF_SECT_URELHDR) to the
-+ * specified DOF. At present, this amounts to simply adding 'ubase' to the
-+ * site of any user SETX relocations to account for load object base address.
-+ * In the future, if we need other relocations, this function can be extended.
-+ */
-+static int dtrace_dof_relocate(struct dof_hdr *dof, struct dof_sec *sec,
-+ uint64_t ubase)
-+{
-+ uintptr_t daddr = (uintptr_t)dof;
-+ struct dof_relohdr *dofr;
-+ struct dof_sec *ss, *rs, *ts;
-+ struct dof_relodesc *r;
-+ uint_t i, n;
-+
-+ dofr = (struct dof_relohdr *)(uintptr_t) (daddr + sec->dofs_offset);
-+
-+ if (sec->dofs_size < sizeof(struct dof_relohdr) ||
-+ sec->dofs_align != sizeof(dof_secidx_t)) {
-+ dtrace_dof_error(dof, "invalid relocation header");
-+ return -1;
-+ }
-+
-+ ss = dtrace_dof_sect(dof, DOF_SECT_STRTAB, dofr->dofr_strtab);
-+ rs = dtrace_dof_sect(dof, DOF_SECT_RELTAB, dofr->dofr_relsec);
-+ ts = dtrace_dof_sect(dof, DOF_SECT_NONE, dofr->dofr_tgtsec);
-+
-+ if (ss == NULL || rs == NULL || ts == NULL)
-+ return -1; /* dtrace_dof_error() has been called already */
-+
-+ if (rs->dofs_entsize < sizeof(struct dof_relodesc) ||
-+ rs->dofs_align != sizeof(uint64_t)) {
-+ dtrace_dof_error(dof, "invalid relocation section");
-+ return -1;
-+ }
-+
-+ r = (struct dof_relodesc *)(uintptr_t)(daddr + rs->dofs_offset);
-+ /*
-+ * Was: n = rs->dofs_size / rs->dofs_entsize;
-+ * but on Linux we need to use a macro for the division to handle the
-+ * possible case of 64-bit division on a 32-bit kernel.
-+ */
-+ n = rs->dofs_size;
-+ do_div(n, rs->dofs_entsize);
-+
-+ for (i = 0; i < n; i++) {
-+ uintptr_t taddr = daddr + ts->dofs_offset + r->dofr_offset;
-+
-+ switch (r->dofr_type) {
-+ case DOF_RELO_NONE:
-+ break;
-+ case DOF_RELO_SETX:
-+ if (r->dofr_offset >= ts->dofs_size ||
-+ r->dofr_offset + sizeof(uint64_t) >
-+ ts->dofs_size) {
-+ dtrace_dof_error(dof, "bad relocation offset");
-+ return -1;
-+ }
-+
-+ if (!IS_ALIGNED(taddr, sizeof(uint64_t))) {
-+ dtrace_dof_error(dof, "misaligned setx relo");
-+ return -1;
-+ }
-+
-+ /*
-+ * This is a bit ugly but it is necessary for arm64,
-+ * where the linking of shared libraries retains the
-+ * relocation records for the .SUNW_dof section. In
-+ * that case, the runtime loader already performed the
-+ * relocation, so we do not have to do anything here.
-+ *
-+ * We check for this situation by comparing the target
-+ * address against the base address (ubase). If it is
-+ * larger, we assume the relocation already took place.
-+ */
-+ if (*(uint64_t *)taddr > ubase)
-+ dt_dbg_dof(" Relocation by runtime " \
-+ "loader: 0x%llx (base 0x%llx)\n",
-+ *(uint64_t *)taddr, ubase);
-+ else {
-+ dt_dbg_dof(" Relocate 0x%llx + 0x%llx " \
-+ "= 0x%llx\n",
-+ *(uint64_t *)taddr, ubase,
-+ *(uint64_t *)taddr + ubase);
-+
-+ *(uint64_t *)taddr += ubase;
-+ }
-+
-+ break;
-+ default:
-+ dtrace_dof_error(dof, "invalid relocation type");
-+ return -1;
-+ }
-+
-+ r = (struct dof_relodesc *)((uintptr_t)r + rs->dofs_entsize);
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * The dof_hdr_t passed to dtrace_dof_slurp() should be a partially validated
-+ * header: it should be at the front of a memory region that is at least
-+ * sizeof(dof_hdr_t) in size -- and then at least dof_hdr.dofh_loadsz in
-+ * size. It need not be validated in any other way.
-+ */
-+int dtrace_dof_slurp(struct dof_hdr *dof, struct dtrace_vstate *vstate,
-+ const struct cred *cr, struct dtrace_enabling **enabp,
-+ uint64_t ubase, int noprobes)
-+{
-+ uint64_t len = dof->dofh_loadsz, seclen;
-+ uintptr_t daddr = (uintptr_t)dof;
-+ struct dtrace_ecbdesc *ep;
-+ struct dtrace_enabling *enab;
-+ uint_t i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dof->dofh_loadsz >= sizeof(struct dof_hdr));
-+
-+ dt_dbg_dof(" DOF 0x%p Slurping...\n", dof);
-+
-+ dt_dbg_dof(" DOF 0x%p Validating...\n", dof);
-+
-+ /*
-+ * Check the DOF header identification bytes. In addition to checking
-+ * valid settings, we also verify that unused bits/bytes are zeroed so
-+ * we can use them later without fear of regressing existing binaries.
-+ */
-+ if (memcmp(&dof->dofh_ident[DOF_ID_MAG0], DOF_MAG_STRING,
-+ DOF_MAG_STRLEN) != 0) {
-+ dtrace_dof_error(dof, "DOF magic string mismatch");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_MODEL] != DOF_MODEL_ILP32 &&
-+ dof->dofh_ident[DOF_ID_MODEL] != DOF_MODEL_LP64) {
-+ dtrace_dof_error(dof, "DOF has invalid data model");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_ENCODING] != DOF_ENCODE_NATIVE) {
-+ dtrace_dof_error(dof, "DOF encoding mismatch");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 &&
-+ dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_2) {
-+ dtrace_dof_error(dof, "DOF version mismatch");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_DIFVERS] != DIF_VERSION_2) {
-+ dtrace_dof_error(dof, "DOF uses unsupported instruction set");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_DIFIREG] > DIF_DIR_NREGS) {
-+ dtrace_dof_error(dof, "DOF uses too many integer registers");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_DIFTREG] > DIF_DTR_NREGS) {
-+ dtrace_dof_error(dof, "DOF uses too many tuple registers");
-+ return -1;
-+ }
-+
-+ for (i = DOF_ID_PAD; i < DOF_ID_SIZE; i++) {
-+ if (dof->dofh_ident[i] != 0) {
-+ dtrace_dof_error(dof, "DOF has invalid ident byte set");
-+ return -1;
-+ }
-+ }
-+
-+ if (dof->dofh_flags & ~DOF_FL_VALID) {
-+ dtrace_dof_error(dof, "DOF has invalid flag bits set");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_secsize == 0) {
-+ dtrace_dof_error(dof, "zero section header size");
-+ return -1;
-+ }
-+
-+ /*
-+ * Check that the section headers don't exceed the amount of DOF
-+ * data. Note that we cast the section size and number of sections
-+ * to uint64_t's to prevent possible overflow in the multiplication.
-+ */
-+ seclen = (uint64_t)dof->dofh_secnum * (uint64_t)dof->dofh_secsize;
-+
-+ if (dof->dofh_secoff > len || seclen > len ||
-+ dof->dofh_secoff + seclen > len) {
-+ dtrace_dof_error(dof, "truncated section headers");
-+ return -1;
-+ }
-+
-+ if (!IS_ALIGNED(dof->dofh_secoff, sizeof(uint64_t))) {
-+ dtrace_dof_error(dof, "misaligned section headers");
-+ return -1;
-+ }
-+
-+ if (!IS_ALIGNED(dof->dofh_secsize, sizeof(uint64_t))) {
-+ dtrace_dof_error(dof, "misaligned section size");
-+ return -1;
-+ }
-+
-+ /*
-+ * Take an initial pass through the section headers to be sure that
-+ * the headers don't have stray offsets. If the 'noprobes' flag is
-+ * set, do not permit sections relating to providers, probes, or args.
-+ */
-+ dt_dbg_dof(" DOF 0x%p Checking section offsets...\n", dof);
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(daddr + (uintptr_t)dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (noprobes) {
-+ switch (sec->dofs_type) {
-+ case DOF_SECT_PROVIDER:
-+ case DOF_SECT_PROBES:
-+ case DOF_SECT_PRARGS:
-+ case DOF_SECT_PROFFS:
-+ dtrace_dof_error(
-+ dof, "illegal sections for enabling");
-+ return -1;
-+ }
-+ }
-+
-+ if (DOF_SEC_ISLOADABLE(sec->dofs_type) &&
-+ !(sec->dofs_flags & DOF_SECF_LOAD)) {
-+ dtrace_dof_error(
-+ dof, "loadable section with load flag unset");
-+ return -1;
-+ }
-+
-+ /*
-+ * Just ignore non-loadable sections.
-+ */
-+ if (!(sec->dofs_flags & DOF_SECF_LOAD))
-+ continue;
-+
-+ if (sec->dofs_align & (sec->dofs_align - 1)) {
-+ dtrace_dof_error(dof, "bad section alignment");
-+ return -1;
-+ }
-+
-+ if (sec->dofs_offset & (sec->dofs_align - 1)) {
-+ dtrace_dof_error(dof, "misaligned section");
-+ return -1;
-+ }
-+
-+ if (sec->dofs_offset > len || sec->dofs_size > len ||
-+ sec->dofs_offset + sec->dofs_size > len) {
-+ dtrace_dof_error(dof, "corrupt section header");
-+ return -1;
-+ }
-+
-+ if (sec->dofs_type == DOF_SECT_STRTAB && *((char *)daddr +
-+ sec->dofs_offset + sec->dofs_size - 1) != '\0') {
-+ dtrace_dof_error(dof, "non-terminating string table");
-+ return -1;
-+ }
-+ }
-+
-+ /*
-+ * Take a second pass through the sections and locate and perform any
-+ * relocations that are present. We do this after the first pass to
-+ * be sure that all sections have had their headers validated.
-+ */
-+ dt_dbg_dof(" DOF 0x%p Performing relocations...\n", dof);
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(daddr + (uintptr_t)dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ /*
-+ * Skip sections that are not loadable.
-+ */
-+ if (!(sec->dofs_flags & DOF_SECF_LOAD))
-+ continue;
-+
-+ switch (sec->dofs_type) {
-+ case DOF_SECT_URELHDR:
-+ if (dtrace_dof_relocate(dof, sec, ubase) != 0)
-+ return -1;
-+ break;
-+ }
-+ }
-+
-+ dt_dbg_dof(" DOF 0x%p Processing enablings...\n", dof);
-+
-+ enab = *enabp;
-+ if (enab == NULL)
-+ enab = *enabp = dtrace_enabling_create(vstate);
-+
-+ if (enab == NULL) {
-+ dt_dbg_dof(" DOF 0x%p Done slurping - no enablings\n", dof);
-+ return -1;
-+ }
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(daddr + (uintptr_t)dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (sec->dofs_type != DOF_SECT_ECBDESC)
-+ continue;
-+
-+ ep = dtrace_dof_ecbdesc(dof, sec, vstate, cr);
-+ if (ep == NULL) {
-+ dt_dbg_dof(" DOF 0x%p Done slurping - ECB problem\n",
-+ dof);
-+ dtrace_enabling_destroy(enab);
-+ *enabp = NULL;
-+ return -1;
-+ }
-+
-+ dtrace_enabling_add(enab, ep);
-+ }
-+
-+ dt_dbg_dof(" DOF 0x%p Enablings processed\n", dof);
-+ dt_dbg_dof(" DOF 0x%p Done slurping\n", dof);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Process DOF for any options. This should be called after the DOF has been
-+ * processed by dtrace_dof_slurp().
-+ */
-+int dtrace_dof_options(struct dof_hdr *dof, struct dtrace_state *state)
-+{
-+ int i, rval;
-+ uint32_t entsize;
-+ size_t offs;
-+ struct dof_optdesc *desc;
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)((uintptr_t)dof +
-+ (uintptr_t)dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (sec->dofs_type != DOF_SECT_OPTDESC)
-+ continue;
-+
-+ if (sec->dofs_align != sizeof(uint64_t)) {
-+ dtrace_dof_error(
-+ dof, "bad alignment in option description");
-+ return -EINVAL;
-+ }
-+
-+ entsize = sec->dofs_entsize;
-+ if (entsize == 0) {
-+ dtrace_dof_error(dof, "zeroed option entry size");
-+ return -EINVAL;
-+ }
-+
-+ if (entsize < sizeof(struct dof_optdesc)) {
-+ dtrace_dof_error(dof, "bad option entry size");
-+ return -EINVAL;
-+ }
-+
-+ for (offs = 0; offs < sec->dofs_size; offs += entsize) {
-+ desc = (struct dof_optdesc *)((uintptr_t)dof +
-+ (uintptr_t)sec->dofs_offset +
-+ offs);
-+
-+ if (desc->dofo_strtab != DOF_SECIDX_NONE) {
-+ dtrace_dof_error(
-+ dof, "non-zero option string");
-+ return -EINVAL;
-+ }
-+
-+ if (desc->dofo_value == DTRACEOPT_UNSET) {
-+ dtrace_dof_error(dof, "unset option");
-+ return -EINVAL;
-+ }
-+
-+ rval = dtrace_state_option(state, desc->dofo_option,
-+ desc->dofo_value);
-+ if (rval != 0) {
-+ dtrace_dof_error(dof, "rejected option");
-+ return rval;
-+ }
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static struct dtrace_helpers *dtrace_helpers_create(struct task_struct *curr)
-+{
-+ struct dtrace_helpers *dth;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (curr->dt_task == NULL)
-+ return NULL;
-+
-+ ASSERT(curr->dt_task->dt_helpers == NULL);
-+
-+ dth = kzalloc(sizeof(struct dtrace_helpers), GFP_KERNEL);
-+ if (dth == NULL)
-+ return NULL;
-+
-+ dth->dthps_actions = vzalloc(sizeof(struct dtrace_helper_action *) *
-+ DTRACE_NHELPER_ACTIONS);
-+ if (dth->dthps_actions == NULL) {
-+ kfree(dth);
-+ return NULL;
-+ }
-+
-+ curr->dt_task->dt_helpers = dth;
-+ dtrace_helpers++;
-+
-+ dt_dbg_dof(" Helpers allocated for task 0x%p (%d system-wide)\n",
-+ curr, dtrace_helpers);
-+
-+ return dth;
-+}
-+
-+static int dtrace_helper_validate(struct dtrace_helper_action *helper)
-+{
-+ int err = 0, i;
-+ struct dtrace_difo *dp;
-+
-+ dp = helper->dtha_predicate;
-+ if (dp != NULL)
-+ err += dtrace_difo_validate_helper(dp);
-+
-+ for (i = 0; i < helper->dtha_nactions; i++)
-+ err += dtrace_difo_validate_helper(helper->dtha_actions[i]);
-+
-+ return (err == 0);
-+}
-+
-+static int dtrace_helper_provider_validate(struct dof_hdr *dof,
-+ struct dof_sec *sec)
-+{
-+ uintptr_t daddr = (uintptr_t)dof;
-+ struct dof_sec *str_sec, *prb_sec, *arg_sec, *off_sec,
-+ *enoff_sec;
-+ struct dof_provider *prov;
-+ struct dof_probe *prb;
-+ uint8_t *arg;
-+ char *strtab, *typestr;
-+ dof_stridx_t typeidx;
-+ size_t typesz;
-+ uint_t nprobes, j, k;
-+
-+ ASSERT(sec->dofs_type == DOF_SECT_PROVIDER);
-+
-+ if (sec->dofs_offset & (sizeof(uint_t) - 1)) {
-+ dtrace_dof_error(dof, "misaligned section offset");
-+ return -1;
-+ }
-+
-+ /*
-+ * The section needs to be large enough to contain the DOF provider
-+ * structure appropriate for the given version.
-+ */
-+ if (sec->dofs_size <
-+ ((dof->dofh_ident[DOF_ID_VERSION] == DOF_VERSION_1)
-+ ? offsetof(struct dof_provider, dofpv_prenoffs)
-+ : sizeof(struct dof_provider))) {
-+ dtrace_dof_error(dof, "provider section too small");
-+ return -1;
-+ }
-+
-+ prov = (struct dof_provider *)(uintptr_t)(daddr + sec->dofs_offset);
-+ str_sec = dtrace_dof_sect(dof, DOF_SECT_STRTAB, prov->dofpv_strtab);
-+ prb_sec = dtrace_dof_sect(dof, DOF_SECT_PROBES, prov->dofpv_probes);
-+ arg_sec = dtrace_dof_sect(dof, DOF_SECT_PRARGS, prov->dofpv_prargs);
-+ off_sec = dtrace_dof_sect(dof, DOF_SECT_PROFFS, prov->dofpv_proffs);
-+
-+ if (str_sec == NULL || prb_sec == NULL ||
-+ arg_sec == NULL || off_sec == NULL)
-+ return -1;
-+
-+ enoff_sec = NULL;
-+
-+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 &&
-+ prov->dofpv_prenoffs != DOF_SECT_NONE) {
-+ enoff_sec = dtrace_dof_sect(dof, DOF_SECT_PRENOFFS,
-+ prov->dofpv_prenoffs);
-+
-+ if (enoff_sec == NULL)
-+ return -1;
-+ }
-+
-+ strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset);
-+
-+ if (prov->dofpv_name >= str_sec->dofs_size ||
-+ strlen(strtab + prov->dofpv_name) >= DTRACE_PROVNAMELEN) {
-+ dtrace_dof_error(dof, "invalid provider name");
-+ return -1;
-+ }
-+
-+ if (prb_sec->dofs_entsize == 0 ||
-+ prb_sec->dofs_entsize > prb_sec->dofs_size) {
-+ dtrace_dof_error(dof, "invalid entry size");
-+ return -1;
-+ }
-+
-+ if (prb_sec->dofs_entsize & (sizeof(uintptr_t) - 1)) {
-+ dtrace_dof_error(dof, "misaligned entry size");
-+ return -1;
-+ }
-+
-+ if (off_sec->dofs_entsize != sizeof(uint32_t)) {
-+ dtrace_dof_error(dof, "invalid entry size");
-+ return -1;
-+ }
-+
-+ if (off_sec->dofs_offset & (sizeof(uint32_t) - 1)) {
-+ dtrace_dof_error(dof, "misaligned section offset");
-+ return -1;
-+ }
-+
-+ if (arg_sec->dofs_entsize != sizeof(uint8_t)) {
-+ dtrace_dof_error(dof, "invalid entry size");
-+ return -1;
-+ }
-+
-+ arg = (uint8_t *)(uintptr_t)(daddr + arg_sec->dofs_offset);
-+ nprobes = prb_sec->dofs_size / prb_sec->dofs_entsize;
-+
-+ dt_dbg_dof(" DOF 0x%p %s::: with %d probes\n",
-+ dof, strtab + prov->dofpv_name, nprobes);
-+
-+ /*
-+ * Take a pass through the probes to check for errors.
-+ */
-+ for (j = 0; j < nprobes; j++) {
-+ prb = (struct dof_probe *)(uintptr_t)
-+ (daddr + prb_sec->dofs_offset +
-+ j * prb_sec->dofs_entsize);
-+
-+ if (prb->dofpr_func >= str_sec->dofs_size) {
-+ dtrace_dof_error(dof, "invalid function name");
-+ return -1;
-+ }
-+
-+ if (strlen(strtab + prb->dofpr_func) >= DTRACE_FUNCNAMELEN) {
-+ dtrace_dof_error(dof, "function name too long");
-+ return -1;
-+ }
-+
-+ if (prb->dofpr_name >= str_sec->dofs_size ||
-+ strlen(strtab + prb->dofpr_name) >= DTRACE_NAMELEN) {
-+ dtrace_dof_error(dof, "invalid probe name");
-+ return -1;
-+ }
-+
-+ /*
-+ * The offset count must not wrap the index, and the offsets
-+ * must also not overflow the section's data.
-+ */
-+ if (prb->dofpr_offidx + prb->dofpr_noffs < prb->dofpr_offidx ||
-+ (prb->dofpr_offidx + prb->dofpr_noffs) *
-+ off_sec->dofs_entsize > off_sec->dofs_size) {
-+ dtrace_dof_error(dof, "invalid probe offset");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1) {
-+ /*
-+ * If there's no is-enabled offset section, make sure
-+ * there aren't any is-enabled offsets. Otherwise
-+ * perform the same checks as for probe offsets
-+ * (immediately above).
-+ */
-+ if (enoff_sec == NULL) {
-+ if (prb->dofpr_enoffidx != 0 ||
-+ prb->dofpr_nenoffs != 0) {
-+ dtrace_dof_error(dof,
-+ "is-enabled offsets "
-+ "with null section");
-+ return -1;
-+ }
-+ } else if (prb->dofpr_enoffidx + prb->dofpr_nenoffs <
-+ prb->dofpr_enoffidx ||
-+ (prb->dofpr_enoffidx + prb->dofpr_nenoffs) *
-+ enoff_sec->dofs_entsize >
-+ enoff_sec->dofs_size) {
-+ dtrace_dof_error(dof, "invalid is-enabled "
-+ "offset");
-+ return -1;
-+ }
-+
-+ if (prb->dofpr_noffs + prb->dofpr_nenoffs == 0) {
-+ dtrace_dof_error(dof, "zero probe and "
-+ "is-enabled offsets");
-+ return -1;
-+ }
-+ } else if (prb->dofpr_noffs == 0) {
-+ dtrace_dof_error(dof, "zero probe offsets");
-+ return -1;
-+ }
-+
-+ if (prb->dofpr_argidx + prb->dofpr_xargc < prb->dofpr_argidx ||
-+ (prb->dofpr_argidx + prb->dofpr_xargc) *
-+ arg_sec->dofs_entsize > arg_sec->dofs_size) {
-+ dtrace_dof_error(dof, "invalid args");
-+ return -1;
-+ }
-+
-+ typeidx = prb->dofpr_nargv;
-+ typestr = strtab + prb->dofpr_nargv;
-+ for (k = 0; k < prb->dofpr_nargc; k++) {
-+ if (typeidx >= str_sec->dofs_size) {
-+ dtrace_dof_error(dof, "bad native argument "
-+ "type");
-+ return -1;
-+ }
-+
-+ typesz = strlen(typestr) + 1;
-+ if (typesz > DTRACE_ARGTYPELEN) {
-+ dtrace_dof_error(dof, "native argument type "
-+ "too long");
-+ return -1;
-+ }
-+
-+ typeidx += typesz;
-+ typestr += typesz;
-+ }
-+
-+ typeidx = prb->dofpr_xargv;
-+ typestr = strtab + prb->dofpr_xargv;
-+ for (k = 0; k < prb->dofpr_xargc; k++) {
-+ if (arg[prb->dofpr_argidx + k] > prb->dofpr_nargc) {
-+ dtrace_dof_error(dof, "bad native argument "
-+ "index");
-+ return -1;
-+ }
-+
-+ if (typeidx >= str_sec->dofs_size) {
-+ dtrace_dof_error(dof, "bad translated "
-+ "argument type");
-+ return -1;
-+ }
-+
-+ typesz = strlen(typestr) + 1;
-+ if (typesz > DTRACE_ARGTYPELEN) {
-+ dtrace_dof_error(dof, "translated argument "
-+ "type too long");
-+ return -1;
-+ }
-+
-+ typeidx += typesz;
-+ typestr += typesz;
-+ }
-+
-+ dt_dbg_dof(" Probe %d %s:%s:%s:%s with %d offsets, "
-+ "%d is-enabled offsets\n", j,
-+ strtab + prov->dofpv_name, "",
-+ strtab + prb->dofpr_func, strtab + prb->dofpr_name,
-+ prb->dofpr_noffs, prb->dofpr_nenoffs);
-+ }
-+
-+ return 0;
-+}
-+
-+static void dtrace_helper_action_destroy(struct dtrace_helper_action *helper,
-+ struct dtrace_vstate *vstate)
-+{
-+ int i;
-+
-+ if (helper->dtha_predicate != NULL)
-+ dtrace_difo_release(helper->dtha_predicate, vstate);
-+
-+ for (i = 0; i < helper->dtha_nactions; i++) {
-+ ASSERT(helper->dtha_actions[i] != NULL);
-+ dtrace_difo_release(helper->dtha_actions[i], vstate);
-+ }
-+
-+ vfree(helper->dtha_actions);
-+ kfree(helper);
-+}
-+
-+static int dtrace_helper_action_add(int which, struct dtrace_ecbdesc *ep)
-+{
-+ struct dtrace_helpers *dth;
-+ struct dtrace_helper_action *helper, *last;
-+ struct dtrace_actdesc *act;
-+ struct dtrace_vstate *vstate;
-+ struct dtrace_predicate *pred;
-+ int count = 0, nactions = 0, i;
-+
-+ if (which < 0 || which >= DTRACE_NHELPER_ACTIONS)
-+ return -EINVAL;
-+
-+ if (current->dt_task == NULL)
-+ return -ENOMEM;
-+
-+ dth = current->dt_task->dt_helpers;
-+ last = dth->dthps_actions[which];
-+ vstate = &dth->dthps_vstate;
-+
-+ for (count = 0; last != NULL; last = last->dtha_next) {
-+ count++;
-+ if (last->dtha_next == NULL)
-+ break;
-+ }
-+
-+ /*
-+ * If we already have dtrace_helper_actions_max helper actions for this
-+ * helper action type, we'll refuse to add a new one.
-+ */
-+ if (count >= dtrace_helper_actions_max)
-+ return -ENOSPC;
-+
-+ helper = kzalloc(sizeof(struct dtrace_helper_action), GFP_KERNEL);
-+ if (helper == NULL)
-+ return -ENOMEM;
-+
-+ helper->dtha_generation = dth->dthps_generation;
-+
-+ pred = ep->dted_pred.dtpdd_predicate;
-+ if (pred != NULL) {
-+ ASSERT(pred->dtp_difo != NULL);
-+ dtrace_difo_hold(pred->dtp_difo);
-+ helper->dtha_predicate = pred->dtp_difo;
-+ }
-+
-+ for (act = ep->dted_action; act != NULL; act = act->dtad_next) {
-+ if (act->dtad_kind != DTRACEACT_DIFEXPR)
-+ goto err;
-+
-+ if (act->dtad_difo == NULL)
-+ goto err;
-+
-+ nactions++;
-+ }
-+
-+ helper->dtha_actions = vzalloc(sizeof(struct dtrace_difo *) *
-+ (helper->dtha_nactions = nactions));
-+ if (helper->dtha_actions == NULL)
-+ goto err;
-+
-+ for (act = ep->dted_action, i = 0; act != NULL; act = act->dtad_next) {
-+ dtrace_difo_hold(act->dtad_difo);
-+ helper->dtha_actions[i++] = act->dtad_difo;
-+ }
-+
-+ if (!dtrace_helper_validate(helper))
-+ goto err;
-+
-+ if (last == NULL)
-+ dth->dthps_actions[which] = helper;
-+ else
-+ last->dtha_next = helper;
-+
-+ if (vstate->dtvs_nlocals > dtrace_helptrace_nlocals) {
-+ dtrace_helptrace_nlocals = vstate->dtvs_nlocals;
-+ dtrace_helptrace_next = 0;
-+ }
-+
-+ return 0;
-+
-+err:
-+ dtrace_helper_action_destroy(helper, vstate);
-+ if (helper->dtha_actions != NULL)
-+ vfree(helper->dtha_actions);
-+ else
-+ return -ENOMEM;
-+
-+ return -EINVAL;
-+}
-+
-+static int dtrace_helper_provider_add(struct dof_helper *dofhp, int gen)
-+{
-+ struct dtrace_helpers *dth;
-+ struct dtrace_helper_provider *hprov, **tmp_provs;
-+ uint_t tmp_maxprovs, i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (current->dt_task == NULL)
-+ return -ENOMEM;
-+
-+ dth = current->dt_task->dt_helpers;
-+ ASSERT(dth != NULL);
-+
-+ /*
-+ * If we already have dtrace_helper_providers_max helper providers,
-+ * we're refuse to add a new one.
-+ */
-+ if (dth->dthps_nprovs >= dtrace_helper_providers_max)
-+ return -ENOSPC;
-+
-+ /*
-+ * Check to make sure this isn't a duplicate.
-+ */
-+ for (i = 0; i < dth->dthps_nprovs; i++) {
-+ if (dofhp->dofhp_addr ==
-+ dth->dthps_provs[i]->dthp_prov.dofhp_addr)
-+ return -EALREADY;
-+ }
-+
-+ hprov = kzalloc(sizeof(struct dtrace_helper_provider), GFP_KERNEL);
-+ if (hprov == NULL)
-+ return -ENOMEM;
-+ hprov->dthp_prov = *dofhp;
-+ hprov->dthp_ref = 1;
-+ hprov->dthp_generation = gen;
-+
-+ /*
-+ * Allocate a bigger table for helper providers if it's already full.
-+ */
-+ if (dth->dthps_maxprovs == dth->dthps_nprovs) {
-+ tmp_maxprovs = dth->dthps_maxprovs;
-+ tmp_provs = dth->dthps_provs;
-+
-+ if (dth->dthps_maxprovs == 0)
-+ dth->dthps_maxprovs = 2;
-+ else
-+ dth->dthps_maxprovs *= 2;
-+
-+ if (dth->dthps_maxprovs > dtrace_helper_providers_max)
-+ dth->dthps_maxprovs = dtrace_helper_providers_max;
-+
-+ ASSERT(tmp_maxprovs < dth->dthps_maxprovs);
-+
-+ dth->dthps_provs =
-+ vzalloc(dth->dthps_maxprovs *
-+ sizeof(struct dtrace_helper_provider *));
-+
-+ if (dth->dthps_provs == NULL) {
-+ kfree(hprov);
-+ return -ENOMEM;
-+ }
-+
-+ if (tmp_provs != NULL) {
-+ memcpy(dth->dthps_provs, tmp_provs,
-+ tmp_maxprovs *
-+ sizeof(struct dtrace_helper_provider *));
-+ vfree(tmp_provs);
-+ }
-+ }
-+
-+ dth->dthps_provs[dth->dthps_nprovs] = hprov;
-+ dth->dthps_nprovs++;
-+
-+ return 0;
-+}
-+
-+static void dtrace_helper_provider_destroy(struct dtrace_helper_provider *hprov)
-+{
-+ mutex_lock(&dtrace_lock);
-+
-+ if (--hprov->dthp_ref == 0) {
-+ struct dof_hdr *dof;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ dof = (struct dof_hdr *)(uintptr_t)hprov->dthp_prov.dofhp_dof;
-+ dtrace_dof_destroy(dof);
-+ kfree(hprov);
-+ } else
-+ mutex_unlock(&dtrace_lock);
-+}
-+
-+static void dtrace_dofattr2attr(struct dtrace_attribute *attr,
-+ const dof_attr_t dofattr)
-+{
-+ attr->dtat_name = DOF_ATTR_NAME(dofattr);
-+ attr->dtat_data = DOF_ATTR_DATA(dofattr);
-+ attr->dtat_class = DOF_ATTR_CLASS(dofattr);
-+}
-+
-+static void dtrace_dofprov2hprov(struct dtrace_helper_provdesc *hprov,
-+ const struct dof_provider *dofprov,
-+ char *strtab)
-+{
-+ hprov->dthpv_provname = strtab + dofprov->dofpv_name;
-+ dtrace_dofattr2attr(&hprov->dthpv_pattr.dtpa_provider,
-+ dofprov->dofpv_provattr);
-+ dtrace_dofattr2attr(&hprov->dthpv_pattr.dtpa_mod,
-+ dofprov->dofpv_modattr);
-+ dtrace_dofattr2attr(&hprov->dthpv_pattr.dtpa_func,
-+ dofprov->dofpv_funcattr);
-+ dtrace_dofattr2attr(&hprov->dthpv_pattr.dtpa_name,
-+ dofprov->dofpv_nameattr);
-+ dtrace_dofattr2attr(&hprov->dthpv_pattr.dtpa_args,
-+ dofprov->dofpv_argsattr);
-+}
-+
-+static void dtrace_helper_provider_remove_one(struct dof_helper *dhp,
-+ struct dof_sec *sec, pid_t pid)
-+{
-+ uintptr_t daddr = (uintptr_t)dhp->dofhp_dof;
-+ struct dof_hdr *dof = (struct dof_hdr *)daddr;
-+ struct dof_sec *str_sec;
-+ struct dof_provider *prov;
-+ char *strtab;
-+ struct dtrace_helper_provdesc dhpv;
-+ struct dtrace_meta *meta = dtrace_meta_pid;
-+ struct dtrace_mops *mops = &meta->dtm_mops;
-+
-+ prov = (struct dof_provider *)(uintptr_t)(daddr + sec->dofs_offset);
-+ str_sec = (struct dof_sec *)(uintptr_t)(daddr + dof->dofh_secoff +
-+ prov->dofpv_strtab *
-+ dof->dofh_secsize);
-+
-+ strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset);
-+
-+ /*
-+ * Create the provider.
-+ */
-+ dtrace_dofprov2hprov(&dhpv, prov, strtab);
-+
-+ dt_dbg_dof(" Removing provider %s for PID %d\n",
-+ dhpv.dthpv_provname, pid);
-+
-+ mops->dtms_remove_pid(meta->dtm_arg, &dhpv, pid);
-+
-+ meta->dtm_count--;
-+}
-+
-+static void dtrace_helper_provider_remove(struct dof_helper *dhp, pid_t pid)
-+{
-+ uintptr_t daddr = (uintptr_t)dhp->dofhp_dof;
-+ struct dof_hdr *dof = (struct dof_hdr *)daddr;
-+ int i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_meta_lock));
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(uintptr_t) (daddr + dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (sec->dofs_type != DOF_SECT_PROVIDER)
-+ continue;
-+
-+ dtrace_helper_provider_remove_one(dhp, sec, pid);
-+ }
-+}
-+
-+static void dtrace_helper_provide_one(struct dof_helper *dhp,
-+ struct dof_sec *sec,
-+ pid_t pid)
-+{
-+ uintptr_t daddr = (uintptr_t)dhp->dofhp_dof;
-+ uint32_t *off, *enoff;
-+ uint8_t *arg;
-+ char *strtab;
-+ uint_t i, nprobes;
-+ void *parg;
-+
-+ struct dof_hdr *dof = (struct dof_hdr *)daddr;
-+ struct dof_sec *str_sec, *prb_sec, *arg_sec, *off_sec,
-+ *enoff_sec;
-+ struct dof_provider *prov;
-+ struct dof_probe *probe;
-+ struct dtrace_helper_provdesc dhpv;
-+ struct dtrace_helper_probedesc dhpb;
-+ struct dtrace_meta *meta = dtrace_meta_pid;
-+ struct dtrace_mops *mops = &meta->dtm_mops;
-+
-+ prov = (struct dof_provider *)(uintptr_t)(daddr + sec->dofs_offset);
-+ str_sec = (struct dof_sec *)(uintptr_t)(daddr + dof->dofh_secoff +
-+ prov->dofpv_strtab *
-+ dof->dofh_secsize);
-+ prb_sec = (struct dof_sec *)(uintptr_t)(daddr + dof->dofh_secoff +
-+ prov->dofpv_probes *
-+ dof->dofh_secsize);
-+ arg_sec = (struct dof_sec *)(uintptr_t)(daddr + dof->dofh_secoff +
-+ prov->dofpv_prargs *
-+ dof->dofh_secsize);
-+ off_sec = (struct dof_sec *)(uintptr_t)(daddr + dof->dofh_secoff +
-+ prov->dofpv_proffs *
-+ dof->dofh_secsize);
-+
-+ strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset);
-+ off = (uint32_t *)(uintptr_t)(daddr + off_sec->dofs_offset);
-+ arg = (uint8_t *)(uintptr_t)(daddr + arg_sec->dofs_offset);
-+ enoff = NULL;
-+
-+ /*
-+ * See dtrace_helper_provider_validate().
-+ */
-+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 &&
-+ prov->dofpv_prenoffs != DOF_SECT_NONE) {
-+ enoff_sec = (struct dof_sec *)(uintptr_t)
-+ (daddr + dof->dofh_secoff +
-+ prov->dofpv_prenoffs * dof->dofh_secsize);
-+ enoff = (uint32_t *)(uintptr_t)
-+ (daddr + enoff_sec->dofs_offset);
-+ }
-+
-+ nprobes = prb_sec->dofs_size / prb_sec->dofs_entsize;
-+
-+ /*
-+ * Create the provider.
-+ */
-+ dtrace_dofprov2hprov(&dhpv, prov, strtab);
-+
-+ dt_dbg_dof(" Creating provider %s for PID %d\n",
-+ strtab + prov->dofpv_name, pid);
-+
-+ /*
-+ * This used to just 'return;' when parg is NULL, but that causes the
-+ * cleanup code (dtrace_helper_provider_remove[_one]) to make a call
-+ * to dtms_remove_pid() for a provider that never got created.
-+ *
-+ * If we fail to provide this provider, mark it as something to ignore,
-+ * so we don't try to process it during cleanup.
-+ */
-+ parg = mops->dtms_provide_pid(meta->dtm_arg, &dhpv, pid);
-+ if (parg == NULL) {
-+ sec->dofs_type = DOF_SECT_NONE;
-+ return;
-+ }
-+
-+ meta->dtm_count++;
-+
-+ /*
-+ * Create the probes.
-+ */
-+ for (i = 0; i < nprobes; i++) {
-+ probe = (struct dof_probe *)(uintptr_t)(daddr +
-+ prb_sec->dofs_offset +
-+ i * prb_sec->dofs_entsize);
-+
-+ dhpb.dthpb_mod = dhp->dofhp_mod;
-+ dhpb.dthpb_func = strtab + probe->dofpr_func;
-+ dhpb.dthpb_name = strtab + probe->dofpr_name;
-+ dhpb.dthpb_base = probe->dofpr_addr;
-+ dhpb.dthpb_offs = off + probe->dofpr_offidx;
-+ dhpb.dthpb_noffs = probe->dofpr_noffs;
-+
-+ if (enoff != NULL) {
-+ dhpb.dthpb_enoffs = enoff + probe->dofpr_enoffidx;
-+ dhpb.dthpb_nenoffs = probe->dofpr_nenoffs;
-+ } else {
-+ dhpb.dthpb_enoffs = NULL;
-+ dhpb.dthpb_nenoffs = 0;
-+ }
-+
-+ dhpb.dthpb_args = arg + probe->dofpr_argidx;
-+ dhpb.dthpb_nargc = probe->dofpr_nargc;
-+ dhpb.dthpb_xargc = probe->dofpr_xargc;
-+ dhpb.dthpb_ntypes = strtab + probe->dofpr_nargv;
-+ dhpb.dthpb_xtypes = strtab + probe->dofpr_xargv;
-+
-+ dt_dbg_dof(" Creating probe %s:%s:%s:%s\n",
-+ strtab + prov->dofpv_name, "", dhpb.dthpb_func,
-+ dhpb.dthpb_name);
-+
-+ mops->dtms_create_probe(meta->dtm_arg, parg, &dhpb);
-+ }
-+}
-+
-+void dtrace_helper_provide(struct dof_helper *dhp, pid_t pid)
-+{
-+ uintptr_t daddr = (uintptr_t)dhp->dofhp_dof;
-+ struct dof_hdr *dof = (struct dof_hdr *)daddr;
-+ int i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_meta_lock));
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(uintptr_t) (daddr + dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (sec->dofs_type != DOF_SECT_PROVIDER)
-+ continue;
-+
-+ dtrace_helper_provide_one(dhp, sec, pid);
-+ }
-+
-+ /*
-+ * We may have just created probes, so we must now rematch against any
-+ * retained enablings. Note that this call will acquire both cpu_lock
-+ * and dtrace_lock; the fact that we are holding dtrace_meta_lock now
-+ * is what defines the ordering with respect to these three locks.
-+ */
-+ dt_dbg_dof(" Re-matching against any retained enablings\n");
-+ dtrace_enabling_matchall();
-+}
-+
-+static void dtrace_helper_provider_register(struct task_struct *tsk,
-+ struct dtrace_helpers *dth,
-+ struct dof_helper *dofhp)
-+{
-+ ASSERT(!MUTEX_HELD(&dtrace_lock));
-+
-+ mutex_lock(&dtrace_meta_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (!dtrace_attached() || dtrace_meta_pid == NULL) {
-+ dt_dbg_dof(" No meta provider registered -- deferred\n");
-+
-+ /*
-+ * If the dtrace module is loaded but not attached, or if there
-+ * isn't a meta provider registered to deal with these provider
-+ * descriptions, we need to postpone creating the actual
-+ * providers until later.
-+ */
-+ if (dth->dthps_next == NULL && dth->dthps_prev == NULL &&
-+ dtrace_deferred_pid != dth) {
-+ dth->dthps_deferred = 1;
-+ dth->dthps_pid = tsk->pid;
-+ dth->dthps_next = dtrace_deferred_pid;
-+ dth->dthps_prev = NULL;
-+ if (dtrace_deferred_pid != NULL)
-+ dtrace_deferred_pid->dthps_prev = dth;
-+ dtrace_deferred_pid = dth;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+ } else if (dofhp != NULL) {
-+ /*
-+ * If the dtrace module is loaded and we have a particular
-+ * helper provider description, pass that off to the meta
-+ * provider.
-+ */
-+ mutex_unlock(&dtrace_lock);
-+
-+ dtrace_helper_provide(dofhp, tsk->pid);
-+ } else {
-+ /*
-+ * Otherwise, just pass all the helper provider descriptions
-+ * off to the meta provider.
-+ */
-+ int i;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ for (i = 0; i < dth->dthps_nprovs; i++) {
-+ dtrace_helper_provide(&dth->dthps_provs[i]->dthp_prov,
-+ tsk->pid);
-+ }
-+ }
-+
-+ mutex_unlock(&dtrace_meta_lock);
-+}
-+
-+int dtrace_helper_slurp(struct dof_hdr *dof, struct dof_helper *dhp)
-+{
-+ struct dtrace_helpers *dth;
-+ struct dtrace_vstate *vstate;
-+ struct dtrace_enabling *enab = NULL;
-+ int i, gen, rv;
-+ int nhelpers = 0, nprovs = 0, destroy = 1;
-+ uintptr_t daddr = (uintptr_t)dof;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (current->dt_task == NULL)
-+ return -1;
-+
-+ dth = current->dt_task->dt_helpers;
-+ if (dth == NULL)
-+ dth = dtrace_helpers_create(current);
-+
-+ if (dth == NULL) {
-+ dtrace_dof_destroy(dof);
-+ return -1;
-+ }
-+
-+ dt_dbg_dof("DOF 0x%p from helper {'%s', %p, %p}...\n",
-+ dof, dhp ? dhp->dofhp_mod : "<none>",
-+ dhp ? (void *)(dhp->dofhp_addr) : NULL,
-+ dhp ? (void *)(dhp->dofhp_dof) : NULL);
-+
-+ vstate = &dth->dthps_vstate;
-+
-+ rv = dtrace_dof_slurp(dof, vstate, NULL, &enab,
-+ dhp != NULL ? dhp->dofhp_addr : 0, FALSE);
-+ if (rv != 0) {
-+ dtrace_dof_destroy(dof);
-+ return rv;
-+ }
-+
-+ /*
-+ * Look for helper providers and validate their descriptions.
-+ */
-+ if (dhp != NULL) {
-+ dt_dbg_dof(" DOF 0x%p Validating providers...\n", dof);
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(uintptr_t)
-+ (daddr + dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (sec->dofs_type != DOF_SECT_PROVIDER)
-+ continue;
-+
-+ if (dtrace_helper_provider_validate(dof, sec) != 0) {
-+ dtrace_enabling_destroy(enab);
-+ dtrace_dof_destroy(dof);
-+ return -1;
-+ }
-+
-+ nprovs++;
-+ }
-+ }
-+
-+ /*
-+ * Now we need to walk through the ECB descriptions in the enabling.
-+ */
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_ecbdesc *ep = enab->dten_desc[i];
-+ struct dtrace_probedesc *desc = &ep->dted_probe;
-+
-+ dt_dbg_dof(" ECB Desc %s:%s:%s:%s\n",
-+ desc->dtpd_provider, desc->dtpd_mod,
-+ desc->dtpd_func, desc->dtpd_name);
-+ if (strcmp(desc->dtpd_provider, "dtrace") != 0)
-+ continue;
-+
-+ if (strcmp(desc->dtpd_mod, "helper") != 0)
-+ continue;
-+
-+ if (strcmp(desc->dtpd_func, "ustack") != 0)
-+ continue;
-+
-+ rv = dtrace_helper_action_add(DTRACE_HELPER_ACTION_USTACK, ep);
-+ if (rv != 0) {
-+ /*
-+ * Adding this helper action failed -- we are now going
-+ * to rip out the entire generation and return failure.
-+ */
-+ dtrace_helper_destroygen(dth->dthps_generation);
-+ dtrace_enabling_destroy(enab);
-+ dtrace_dof_destroy(dof);
-+ return -1;
-+ }
-+
-+ nhelpers++;
-+ }
-+
-+ if (nhelpers < enab->dten_ndesc)
-+ dtrace_dof_error(dof, "unmatched helpers");
-+
-+ gen = dth->dthps_generation++;
-+ dtrace_enabling_destroy(enab);
-+
-+ if (dhp != NULL && nprovs > 0) {
-+ dt_dbg_dof(" DOF 0x%p Adding and registering providers\n",
-+ dof);
-+
-+ dhp->dofhp_dof = (uint64_t)(uintptr_t)dof;
-+ if (dtrace_helper_provider_add(dhp, gen) == 0) {
-+ mutex_unlock(&dtrace_lock);
-+ dtrace_helper_provider_register(current, dth, dhp);
-+ mutex_lock(&dtrace_lock);
-+
-+ destroy = 0;
-+ }
-+ }
-+
-+ if (destroy)
-+ dtrace_dof_destroy(dof);
-+
-+ return gen;
-+}
-+
-+void dtrace_helpers_destroy(struct task_struct *tsk)
-+{
-+ struct dtrace_helpers *help;
-+ struct dtrace_vstate *vstate;
-+ int i;
-+
-+ if (tsk->dt_task == NULL)
-+ return;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ ASSERT(tsk->dt_task->dt_helpers != NULL);
-+ ASSERT(dtrace_helpers > 0);
-+
-+ dt_dbg_dof("Helper cleanup: PID %d\n", tsk->pid);
-+
-+ help = tsk->dt_task->dt_helpers;
-+ vstate = &help->dthps_vstate;
-+
-+ /*
-+ * We're now going to lose the help from this process.
-+ */
-+ tsk->dt_task->dt_helpers = NULL;
-+ dtrace_sync();
-+
-+ /*
-+ * Destroy the helper actions.
-+ */
-+ for (i = 0; i < DTRACE_NHELPER_ACTIONS; i++) {
-+ struct dtrace_helper_action *h, *next;
-+
-+ for (h = help->dthps_actions[i]; h != NULL; h = next) {
-+ next = h->dtha_next;
-+ dtrace_helper_action_destroy(h, vstate);
-+ h = next;
-+ }
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ /*
-+ * Destroy the helper providers.
-+ */
-+ if (help->dthps_maxprovs > 0) {
-+ mutex_lock(&dtrace_meta_lock);
-+ if (dtrace_meta_pid != NULL) {
-+ ASSERT(dtrace_deferred_pid == NULL);
-+
-+ for (i = 0; i < help->dthps_nprovs; i++) {
-+ dtrace_helper_provider_remove(
-+ &help->dthps_provs[i]->dthp_prov,
-+ tsk->pid);
-+ }
-+ } else {
-+ mutex_lock(&dtrace_lock);
-+ ASSERT(help->dthps_deferred == 0 ||
-+ help->dthps_next != NULL ||
-+ help->dthps_prev != NULL ||
-+ help == dtrace_deferred_pid);
-+
-+ /*
-+ * Remove the helper from the deferred list.
-+ */
-+ if (help->dthps_next != NULL)
-+ help->dthps_next->dthps_prev = help->dthps_prev;
-+ if (help->dthps_prev != NULL)
-+ help->dthps_prev->dthps_next = help->dthps_next;
-+ if (dtrace_deferred_pid == help) {
-+ dtrace_deferred_pid = help->dthps_next;
-+ ASSERT(help->dthps_prev == NULL);
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+ }
-+
-+ mutex_unlock(&dtrace_meta_lock);
-+
-+ for (i = 0; i < help->dthps_nprovs; i++)
-+ dtrace_helper_provider_destroy(help->dthps_provs[i]);
-+
-+ vfree(help->dthps_provs);
-+ }
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ dtrace_vstate_fini(&help->dthps_vstate);
-+ vfree(help->dthps_actions);
-+ kfree(help);
-+
-+ --dtrace_helpers;
-+ mutex_unlock(&dtrace_lock);
-+}
-+
-+void dtrace_helpers_duplicate(struct task_struct *from, struct task_struct *to)
-+{
-+ struct dtrace_task *dfrom = from->dt_task;
-+ struct dtrace_task *dto = to->dt_task;
-+ struct dtrace_helpers *help, *newhelp;
-+ struct dtrace_helper_action *helper, *new, *last;
-+ struct dtrace_difo *dp;
-+ struct dtrace_vstate *vstate;
-+
-+ int i, j, sz, hasprovs = 0;
-+
-+ if (dfrom == NULL || dto == NULL)
-+ return;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ ASSERT(dfrom->dt_helpers != NULL);
-+ ASSERT(dtrace_helpers > 0);
-+
-+ help = dfrom->dt_helpers;
-+ newhelp = dtrace_helpers_create(to);
-+
-+ ASSERT(dto->dt_helpers != NULL);
-+
-+ newhelp->dthps_generation = help->dthps_generation;
-+ vstate = &newhelp->dthps_vstate;
-+
-+ /*
-+ * Duplicate the helper actions.
-+ */
-+ for (i = 0; i < DTRACE_NHELPER_ACTIONS; i++) {
-+ helper = help->dthps_actions[i];
-+ if (helper == NULL)
-+ continue;
-+
-+ for (last = NULL; helper != NULL; helper = helper->dtha_next) {
-+ new = kzalloc(sizeof(struct dtrace_helper_action),
-+ GFP_KERNEL);
-+ new->dtha_generation = helper->dtha_generation;
-+
-+ dp = helper->dtha_predicate;
-+ if (dp != NULL) {
-+ dp = dtrace_difo_duplicate(dp, vstate);
-+ new->dtha_predicate = dp;
-+ }
-+
-+ new->dtha_nactions = helper->dtha_nactions;
-+ sz = sizeof(struct dtrace_difo *) * new->dtha_nactions;
-+ new->dtha_actions = vmalloc(sz);
-+
-+ for (j = 0; j < new->dtha_nactions; j++) {
-+ struct dtrace_difo *dp;
-+
-+ dp = helper->dtha_actions[j];
-+ ASSERT(dp != NULL);
-+
-+ dp = dtrace_difo_duplicate(dp, vstate);
-+ new->dtha_actions[j] = dp;
-+ }
-+
-+ if (last != NULL)
-+ last->dtha_next = new;
-+ else
-+ newhelp->dthps_actions[i] = new;
-+
-+ last = new;
-+ }
-+ }
-+
-+ /*
-+ * Duplicate the helper providers and register them with the
-+ * DTrace framework.
-+ */
-+ if (help->dthps_nprovs > 0) {
-+ newhelp->dthps_nprovs = help->dthps_nprovs;
-+ newhelp->dthps_maxprovs = help->dthps_nprovs;
-+ newhelp->dthps_provs = vmalloc(
-+ newhelp->dthps_nprovs *
-+ sizeof(struct dtrace_helper_provider *));
-+
-+ for (i = 0; i < newhelp->dthps_nprovs; i++) {
-+ newhelp->dthps_provs[i] = help->dthps_provs[i];
-+ newhelp->dthps_provs[i]->dthp_ref++;
-+ }
-+
-+ hasprovs = 1;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (hasprovs)
-+ dtrace_helper_provider_register(to, newhelp, NULL);
-+}
-+
-+int dtrace_helper_destroygen(int gen)
-+{
-+ struct task_struct *p = current;
-+ struct dtrace_helpers *dth;
-+ struct dtrace_vstate *vstate;
-+ int i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (current->dt_task == NULL)
-+ return -ENOMEM;
-+
-+ dth = current->dt_task->dt_helpers;
-+
-+ if (dth == NULL || gen > dth->dthps_generation)
-+ return -EINVAL;
-+
-+ vstate = &dth->dthps_vstate;
-+
-+ for (i = 0; i < DTRACE_NHELPER_ACTIONS; i++) {
-+ struct dtrace_helper_action *last = NULL, *h, *next;
-+
-+ for (h = dth->dthps_actions[i]; h != NULL; h = next) {
-+ next = h->dtha_next;
-+
-+ dt_dbg_dof(" Comparing action (agen %d vs rgen %d)\n",
-+ h->dtha_generation, gen);
-+
-+ if (h->dtha_generation == gen) {
-+ if (last != NULL)
-+ last->dtha_next = next;
-+ else
-+ dth->dthps_actions[i] = next;
-+
-+ dtrace_helper_action_destroy(h, vstate);
-+ } else
-+ last = h;
-+ }
-+ }
-+
-+ /*
-+ * Iterate until we've cleared out all helper providers with the given
-+ * generation number.
-+ */
-+ for (;;) {
-+ struct dtrace_helper_provider *prov = NULL;
-+
-+ /*
-+ * Look for a helper provider with the right generation. We
-+ * have to start back at the beginning of the list each time
-+ * because we drop dtrace_lock. It's unlikely that we'll make
-+ * more than two passes.
-+ */
-+ for (i = 0; i < dth->dthps_nprovs; i++) {
-+ prov = dth->dthps_provs[i];
-+
-+ if (prov->dthp_generation == gen)
-+ break;
-+ }
-+
-+ /*
-+ * If there were no matches, we are done.
-+ */
-+ if (i == dth->dthps_nprovs)
-+ break;
-+
-+ dt_dbg_dof(" Found provider with gen %d\n", gen);
-+
-+ /*
-+ * Move the last helper provider into this slot.
-+ */
-+ dth->dthps_nprovs--;
-+ dth->dthps_provs[i] = dth->dthps_provs[dth->dthps_nprovs];
-+ dth->dthps_provs[dth->dthps_nprovs] = NULL;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ /*
-+ * If we have a meta provider, remove this helper provider.
-+ */
-+ mutex_lock(&dtrace_meta_lock);
-+
-+ if (dtrace_meta_pid != NULL) {
-+ ASSERT(dtrace_deferred_pid == NULL);
-+
-+ dtrace_helper_provider_remove(&prov->dthp_prov,
-+ p->pid);
-+ }
-+
-+ mutex_unlock(&dtrace_meta_lock);
-+
-+ dtrace_helper_provider_destroy(prov);
-+
-+ mutex_lock(&dtrace_lock);
-+ }
-+
-+ return 0;
-+}
-+
-+static void dtrace_helper_trace(struct dtrace_helper_action *helper,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate, int where)
-+{
-+ uint32_t size, next, nnext, i;
-+ struct dtrace_helptrace *ent;
-+ uint16_t flags = this_cpu_core->cpuc_dtrace_flags;
-+
-+ if (!dtrace_helptrace_enabled)
-+ return;
-+
-+ ASSERT(vstate->dtvs_nlocals <= dtrace_helptrace_nlocals);
-+
-+ /*
-+ * What would a tracing framework be without its own tracing
-+ * framework? (Well, a hell of a lot simpler, for starters...)
-+ */
-+ size = sizeof(struct dtrace_helptrace) + dtrace_helptrace_nlocals *
-+ sizeof(uint64_t) - sizeof(uint64_t);
-+
-+ /*
-+ * Iterate until we can allocate a slot in the trace buffer.
-+ */
-+ do {
-+ next = dtrace_helptrace_next;
-+
-+ if (next + size < dtrace_helptrace_bufsize)
-+ nnext = next + size;
-+ else
-+ nnext = size;
-+ } while (cmpxchg(&dtrace_helptrace_next, next, nnext) != next);
-+
-+ /*
-+ * We have our slot; fill it in.
-+ */
-+ if (nnext == size)
-+ next = 0;
-+
-+ ent = (struct dtrace_helptrace *)&dtrace_helptrace_buffer[next];
-+ ent->dtht_helper = helper;
-+ ent->dtht_where = where;
-+ ent->dtht_nlocals = vstate->dtvs_nlocals;
-+
-+ ent->dtht_fltoffs = (mstate->dtms_present & DTRACE_MSTATE_FLTOFFS)
-+ ? mstate->dtms_fltoffs
-+ : -1;
-+ ent->dtht_fault = DTRACE_FLAGS2FLT(flags);
-+ ent->dtht_illval = this_cpu_core->cpuc_dtrace_illval;
-+
-+ for (i = 0; i < vstate->dtvs_nlocals; i++) {
-+ struct dtrace_statvar *svar;
-+
-+ svar = vstate->dtvs_locals[i];
-+ if (svar == NULL)
-+ continue;
-+
-+ ASSERT(svar->dtsv_size >= NR_CPUS * sizeof(uint64_t));
-+ ent->dtht_locals[i] =
-+ ((uint64_t *)(uintptr_t)svar->dtsv_data)[
-+ smp_processor_id()];
-+ }
-+}
-+
-+uint64_t dtrace_helper(int which, struct dtrace_mstate *mstate,
-+ struct dtrace_state *state, uint64_t arg0,
-+ uint64_t arg1)
-+{
-+ uint16_t *flags = &this_cpu_core->cpuc_dtrace_flags;
-+ uint64_t sarg0 = mstate->dtms_arg[0];
-+ uint64_t sarg1 = mstate->dtms_arg[1];
-+ uint64_t rval = 0;
-+ struct dtrace_helpers *helpers;
-+ struct dtrace_helper_action *helper;
-+ struct dtrace_vstate *vstate;
-+ struct dtrace_difo *pred;
-+ int i, trace = dtrace_helptrace_enabled;
-+
-+ ASSERT(which >= 0 && which < DTRACE_NHELPER_ACTIONS);
-+
-+ if (current->dt_task == NULL)
-+ return 0;
-+
-+ helpers = current->dt_task->dt_helpers;
-+ if (helpers == NULL)
-+ return 0;
-+
-+ helper = helpers->dthps_actions[which];
-+ if (helper == NULL)
-+ return 0;
-+
-+ vstate = &helpers->dthps_vstate;
-+ mstate->dtms_arg[0] = arg0;
-+ mstate->dtms_arg[1] = arg1;
-+
-+ /*
-+ * Now iterate over each helper. If its predicate evaluates to 'true',
-+ * we'll call the corresponding actions. Note that the below calls
-+ * to dtrace_dif_emulate() may set faults in machine state. This is
-+ * okay: our caller (the outer dtrace_dif_emulate()) will simply plow
-+ * the stored DIF offset with its own (which is the desired behavior).
-+ * Also, note the calls to dtrace_dif_emulate() may allocate scratch
-+ * from machine state; this is okay, too.
-+ */
-+ for (; helper != NULL; helper = helper->dtha_next) {
-+ pred = helper->dtha_predicate;
-+ if (pred != NULL) {
-+ if (trace)
-+ dtrace_helper_trace(helper, mstate, vstate, 0);
-+
-+ if (!dtrace_dif_emulate(pred, mstate, vstate, state))
-+ goto next;
-+
-+ if (*flags & CPU_DTRACE_FAULT)
-+ goto err;
-+ }
-+
-+ for (i = 0; i < helper->dtha_nactions; i++) {
-+ if (trace)
-+ dtrace_helper_trace(helper, mstate, vstate,
-+ i + 1);
-+
-+ rval = dtrace_dif_emulate(helper->dtha_actions[i],
-+ mstate, vstate, state);
-+
-+ if (*flags & CPU_DTRACE_FAULT)
-+ goto err;
-+ }
-+
-+next:
-+ if (trace)
-+ dtrace_helper_trace(helper, mstate, vstate,
-+ DTRACE_HELPTRACE_NEXT);
-+ }
-+
-+ if (trace)
-+ dtrace_helper_trace(helper, mstate, vstate,
-+ DTRACE_HELPTRACE_DONE);
-+
-+ /*
-+ * Restore the arg0 that we saved upon entry.
-+ */
-+ mstate->dtms_arg[0] = sarg0;
-+ mstate->dtms_arg[1] = sarg1;
-+
-+ return rval;
-+
-+err:
-+ if (trace)
-+ dtrace_helper_trace(helper, mstate, vstate,
-+ DTRACE_HELPTRACE_ERR);
-+
-+ /*
-+ * Restore the arg0 that we saved upon entry.
-+ */
-+ mstate->dtms_arg[0] = sarg0;
-+ mstate->dtms_arg[1] = sarg1;
-+
-+ return 0;
-+}
-diff --git a/dtrace/dtrace_ecb.c b/dtrace/dtrace_ecb.c
-new file mode 100644
-index 000000000000..cc04d1a14661
---- /dev/null
-+++ b/dtrace/dtrace_ecb.c
-@@ -0,0 +1,936 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_ecb.c
-+ * DESCRIPTION: DTrace - ECB implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+struct dtrace_ecb *dtrace_ecb_create_cache;
-+
-+static struct dtrace_action *
-+dtrace_ecb_aggregation_create(struct dtrace_ecb *ecb,
-+ struct dtrace_actdesc *desc)
-+{
-+ struct dtrace_aggregation *agg;
-+ size_t size = sizeof(uint64_t);
-+ int ntuple = desc->dtad_ntuple;
-+ struct dtrace_action *act;
-+ struct dtrace_recdesc *frec;
-+ dtrace_aggid_t aggid;
-+ struct dtrace_state *state = ecb->dte_state;
-+
-+ agg = kzalloc(sizeof(struct dtrace_aggregation), GFP_KERNEL);
-+ if (agg == NULL)
-+ return NULL;
-+
-+ agg->dtag_ecb = ecb;
-+
-+ ASSERT(DTRACEACT_ISAGG(desc->dtad_kind));
-+
-+ switch (desc->dtad_kind) {
-+ case DTRACEAGG_MIN:
-+ agg->dtag_initial = INT64_MAX;
-+ agg->dtag_aggregate = dtrace_aggregate_min;
-+ break;
-+
-+ case DTRACEAGG_MAX:
-+ agg->dtag_initial = INT64_MIN;
-+ agg->dtag_aggregate = dtrace_aggregate_max;
-+ break;
-+
-+ case DTRACEAGG_COUNT:
-+ agg->dtag_aggregate = dtrace_aggregate_count;
-+ break;
-+
-+ case DTRACEAGG_QUANTIZE:
-+ agg->dtag_aggregate = dtrace_aggregate_quantize;
-+ size = (((sizeof(uint64_t) * NBBY) - 1) * 2 + 1) *
-+ sizeof(uint64_t);
-+ break;
-+
-+ case DTRACEAGG_LQUANTIZE: {
-+ uint16_t step = DTRACE_LQUANTIZE_STEP(desc->dtad_arg);
-+ uint16_t levels =
-+ DTRACE_LQUANTIZE_LEVELS(desc->dtad_arg);
-+
-+ agg->dtag_initial = desc->dtad_arg;
-+ agg->dtag_aggregate = dtrace_aggregate_lquantize;
-+
-+ if (step == 0 || levels == 0)
-+ goto err;
-+
-+ size = levels * sizeof(uint64_t) + 3 * sizeof(uint64_t);
-+ break;
-+ }
-+
-+ case DTRACEAGG_LLQUANTIZE: {
-+ uint16_t factor = DTRACE_LLQUANTIZE_FACTOR(desc->dtad_arg);
-+ uint16_t lmag = DTRACE_LLQUANTIZE_LMAG(desc->dtad_arg);
-+ uint16_t hmag = DTRACE_LLQUANTIZE_HMAG(desc->dtad_arg);
-+ uint16_t steps = DTRACE_LLQUANTIZE_STEPS(desc->dtad_arg);
-+ uint64_t buf64s;
-+
-+ agg->dtag_initial = desc->dtad_arg;
-+ agg->dtag_aggregate = dtrace_aggregate_llquantize;
-+
-+ /*
-+ * 64 is the largest hmag can practically be (for the smallest
-+ * possible value of factor, 2). libdtrace has already checked
-+ * for overflow, so if hmag > 64, we have corrupted DOF.
-+ */
-+ if (factor < 2 || steps == 0 || hmag > 64)
-+ goto err;
-+
-+ /*
-+ * The size of the buffer for an llquantize() is given by:
-+ * (hmag-lmag+1) logarithmic ranges
-+ * x
-+ * (steps - steps/factor) bins per range
-+ * x
-+ * 2 signs
-+ * +
-+ * two overflow bins
-+ * +
-+ * one underflow bin
-+ * +
-+ * beginning word to encode factor,lmag,hmag,steps
-+ */
-+ buf64s = ((hmag-lmag+1)*(steps-steps/factor)*2+4);
-+ size = buf64s * sizeof(uint64_t);
-+ break;
-+ }
-+
-+ case DTRACEAGG_AVG:
-+ agg->dtag_aggregate = dtrace_aggregate_avg;
-+ size = sizeof(uint64_t) * 2;
-+ break;
-+
-+ case DTRACEAGG_STDDEV:
-+ agg->dtag_aggregate = dtrace_aggregate_stddev;
-+ size = sizeof(uint64_t) * 4;
-+ break;
-+
-+ case DTRACEAGG_SUM:
-+ agg->dtag_aggregate = dtrace_aggregate_sum;
-+ break;
-+
-+ default:
-+ goto err;
-+ }
-+
-+ agg->dtag_action.dta_rec.dtrd_size = size;
-+
-+ if (ntuple == 0)
-+ goto err;
-+
-+ for (act = ecb->dte_action_last; act != NULL; act = act->dta_prev) {
-+ if (DTRACEACT_ISAGG(act->dta_kind))
-+ break;
-+
-+ if (--ntuple == 0) {
-+ agg->dtag_first = act;
-+ goto success;
-+ }
-+ }
-+
-+ ASSERT(ntuple != 0);
-+err:
-+ kfree(agg);
-+ return NULL;
-+
-+success:
-+ ASSERT(ecb->dte_action_last != NULL);
-+ act = ecb->dte_action_last;
-+
-+ if (act->dta_kind == DTRACEACT_DIFEXPR) {
-+ ASSERT(act->dta_difo != NULL);
-+
-+ if (act->dta_difo->dtdo_rtype.dtdt_size == 0)
-+ agg->dtag_hasarg = 1;
-+ }
-+
-+ /*
-+ * Get an ID for the aggregation (add it to the idr).
-+ */
-+ idr_preload(GFP_KERNEL);
-+ aggid = idr_alloc_cyclic(&state->dts_agg_idr, agg, 0, 0, GFP_NOWAIT);
-+ idr_preload_end();
-+ if (aggid < 0) {
-+ /* FIXME: need to handle this */
-+ }
-+
-+ state->dts_naggs++;
-+ agg->dtag_id = aggid;
-+
-+ frec = &agg->dtag_first->dta_rec;
-+ if (frec->dtrd_alignment < sizeof(dtrace_aggid_t))
-+ frec->dtrd_alignment = sizeof(dtrace_aggid_t);
-+
-+ for (act = agg->dtag_first; act != NULL; act = act->dta_next) {
-+ ASSERT(!act->dta_intuple);
-+
-+ act->dta_intuple = 1;
-+ }
-+
-+ return &agg->dtag_action;
-+}
-+
-+void dtrace_ecb_aggregation_destroy(struct dtrace_ecb *ecb,
-+ struct dtrace_action *act)
-+{
-+ struct dtrace_aggregation *agg = (struct dtrace_aggregation *)act;
-+ struct dtrace_state *state = ecb->dte_state;
-+
-+ ASSERT(DTRACEACT_ISAGG(act->dta_kind));
-+
-+ idr_remove(&state->dts_agg_idr, agg->dtag_id);
-+ state->dts_naggs--;
-+
-+ kfree(agg);
-+}
-+
-+static int dtrace_ecb_action_add(struct dtrace_ecb *ecb,
-+ struct dtrace_actdesc *desc)
-+{
-+ struct dtrace_action *action, *last;
-+ struct dtrace_difo *dp = desc->dtad_difo;
-+ uint32_t size = 0, align = sizeof(uint8_t), mask;
-+ uint16_t format = 0;
-+ struct dtrace_recdesc *rec;
-+ struct dtrace_state *state = ecb->dte_state;
-+ dtrace_optval_t *opt = state->dts_options, nframes, strsize;
-+ uint64_t arg = desc->dtad_arg;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(ecb->dte_action == NULL || ecb->dte_action->dta_refcnt == 1);
-+
-+ if (DTRACEACT_ISAGG(desc->dtad_kind)) {
-+ struct dtrace_action *act;
-+
-+ for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
-+ if (act->dta_kind == DTRACEACT_COMMIT)
-+ return -EINVAL;
-+
-+ if (act->dta_kind == DTRACEACT_SPECULATE)
-+ return -EINVAL;
-+ }
-+
-+ action = dtrace_ecb_aggregation_create(ecb, desc);
-+ if (action == NULL)
-+ return -EINVAL;
-+ } else {
-+ if (DTRACEACT_ISDESTRUCTIVE(desc->dtad_kind) ||
-+ (desc->dtad_kind == DTRACEACT_DIFEXPR &&
-+ dp != NULL && dp->dtdo_destructive))
-+ state->dts_destructive = 1;
-+
-+ switch (desc->dtad_kind) {
-+ case DTRACEACT_PRINTF:
-+ case DTRACEACT_PRINTA:
-+ case DTRACEACT_SYSTEM:
-+ case DTRACEACT_FREOPEN:
-+ if ((void *)(uintptr_t)arg == NULL) {
-+ ASSERT(desc->dtad_kind == DTRACEACT_PRINTA);
-+
-+ format = 0;
-+ } else {
-+ ASSERT((void *)(uintptr_t)arg != NULL);
-+#ifdef FIXME
-+ ASSERT(arg > KERNELBASE);
-+#endif
-+
-+ format = dtrace_format_add(
-+ state, (char *)(uintptr_t)arg);
-+ }
-+ /* fallthru */
-+
-+ case DTRACEACT_TRACEMEM:
-+ case DTRACEACT_LIBACT:
-+ case DTRACEACT_DIFEXPR:
-+ if (dp == NULL)
-+ return -EINVAL;
-+
-+ size = dp->dtdo_rtype.dtdt_size;
-+ if (size != 0)
-+ break;
-+
-+ if (dp->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING) {
-+ if (!(dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF))
-+ return -EINVAL;
-+
-+ size = opt[DTRACEOPT_STRSIZE];
-+ }
-+
-+ break;
-+
-+ case DTRACEACT_STACK:
-+ nframes = arg;
-+ if (nframes == 0) {
-+ nframes = opt[DTRACEOPT_STACKFRAMES];
-+
-+ ASSERT(nframes > 0);
-+
-+ arg = nframes;
-+ }
-+
-+ size = nframes * sizeof(uint64_t);
-+ break;
-+
-+ case DTRACEACT_JSTACK:
-+ strsize = DTRACE_USTACK_STRSIZE(arg);
-+ if (strsize == 0)
-+ strsize = opt[DTRACEOPT_JSTACKSTRSIZE];
-+
-+ nframes = DTRACE_USTACK_NFRAMES(arg);
-+ if (nframes == 0)
-+ nframes = opt[DTRACEOPT_JSTACKFRAMES];
-+
-+ arg = DTRACE_USTACK_ARG(nframes, strsize);
-+ /* fallthru */
-+
-+ case DTRACEACT_USTACK:
-+ if (desc->dtad_kind != DTRACEACT_JSTACK &&
-+ (nframes = DTRACE_USTACK_NFRAMES(arg)) == 0) {
-+ strsize = DTRACE_USTACK_STRSIZE(arg);
-+ nframes = opt[DTRACEOPT_USTACKFRAMES];
-+
-+ ASSERT(nframes > 0);
-+
-+ arg = DTRACE_USTACK_ARG(nframes, strsize);
-+ }
-+
-+ size = (nframes + 2) * sizeof(uint64_t);
-+ size += DTRACE_USTACK_STRSIZE(arg);
-+ size = P2ROUNDUP(size, (uint32_t)(sizeof(uintptr_t)));
-+
-+ break;
-+
-+ case DTRACEACT_SYM:
-+ case DTRACEACT_MOD:
-+ if (dp == NULL || ((size = dp->dtdo_rtype.dtdt_size) !=
-+ sizeof(uint64_t)) ||
-+ (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF))
-+ return -EINVAL;
-+
-+ break;
-+
-+ case DTRACEACT_USYM:
-+ case DTRACEACT_UMOD:
-+ case DTRACEACT_UADDR:
-+ if (dp == NULL ||
-+ (dp->dtdo_rtype.dtdt_size != sizeof(uint64_t)) ||
-+ (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF))
-+ return -EINVAL;
-+
-+ size = 3 * sizeof(uint64_t);
-+
-+ break;
-+
-+ case DTRACEACT_STOP:
-+ case DTRACEACT_BREAKPOINT:
-+ case DTRACEACT_PANIC:
-+ break;
-+
-+ case DTRACEACT_CHILL:
-+ case DTRACEACT_DISCARD:
-+ case DTRACEACT_RAISE:
-+ if (dp == NULL)
-+ return -EINVAL;
-+
-+ break;
-+
-+ case DTRACEACT_EXIT:
-+ if (dp == NULL || (size = dp->dtdo_rtype.dtdt_size) !=
-+ sizeof(int) ||
-+ (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF))
-+ return -EINVAL;
-+
-+ break;
-+
-+ case DTRACEACT_SPECULATE:
-+ if (ecb->dte_size > sizeof(dtrace_epid_t))
-+ return -EINVAL;
-+
-+ if (dp == NULL)
-+ return -EINVAL;
-+
-+ state->dts_speculates = 1;
-+
-+ break;
-+
-+ case DTRACEACT_COMMIT: {
-+ struct dtrace_action *act = ecb->dte_action;
-+
-+ for (; act != NULL; act = act->dta_next) {
-+ if (act->dta_kind == DTRACEACT_COMMIT)
-+ return -EINVAL;
-+ }
-+
-+ if (dp == NULL)
-+ return -EINVAL;
-+
-+ break;
-+ }
-+
-+ case DTRACEACT_PCAP:
-+ size = dp->dtdo_rtype.dtdt_size;
-+ break;
-+
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ if (size != 0 || desc->dtad_kind == DTRACEACT_SPECULATE) {
-+ struct dtrace_action *act = ecb->dte_action;
-+
-+ for (; act != NULL; act = act->dta_next) {
-+ if (act->dta_kind == DTRACEACT_COMMIT)
-+ return -EINVAL;
-+ }
-+ }
-+
-+ action = kzalloc(sizeof(struct dtrace_action), GFP_KERNEL);
-+ if (action == NULL)
-+ return -ENOMEM;
-+
-+ action->dta_rec.dtrd_size = size;
-+ }
-+
-+ action->dta_refcnt = 1;
-+ rec = &action->dta_rec;
-+ size = rec->dtrd_size;
-+
-+ for (mask = sizeof(uint64_t) - 1; size != 0 && mask > 0; mask >>= 1) {
-+ if (!(size & mask)) {
-+ align = mask + 1;
-+
-+ break;
-+ }
-+ }
-+
-+ action->dta_kind = desc->dtad_kind;
-+
-+ action->dta_difo = dp;
-+ if (action->dta_difo != NULL)
-+ dtrace_difo_hold(dp);
-+
-+ rec->dtrd_action = action->dta_kind;
-+ rec->dtrd_arg = arg;
-+ rec->dtrd_uarg = desc->dtad_uarg;
-+ rec->dtrd_alignment = (uint16_t)align;
-+ rec->dtrd_format = format;
-+
-+ last = ecb->dte_action_last;
-+ if (last != NULL) {
-+ ASSERT(ecb->dte_action != NULL);
-+
-+ action->dta_prev = last;
-+ last->dta_next = action;
-+ } else {
-+ ASSERT(ecb->dte_action == NULL);
-+
-+ ecb->dte_action = action;
-+ }
-+
-+ ecb->dte_action_last = action;
-+
-+ return 0;
-+}
-+
-+static void dtrace_ecb_action_remove(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_action *act = ecb->dte_action, *next;
-+ struct dtrace_vstate *vstate = &ecb->dte_state->dts_vstate;
-+ struct dtrace_difo *dp;
-+ uint16_t format;
-+
-+ if (act != NULL && act->dta_refcnt > 1) {
-+ ASSERT(act->dta_next == NULL || act->dta_next->dta_refcnt == 1);
-+
-+ act->dta_refcnt--;
-+ } else {
-+ for (; act != NULL; act = next) {
-+ next = act->dta_next;
-+ ASSERT(next != NULL || act == ecb->dte_action_last);
-+ ASSERT(act->dta_refcnt == 1);
-+
-+ format = act->dta_rec.dtrd_format;
-+ if (format != 0)
-+ dtrace_format_remove(ecb->dte_state, format);
-+
-+ dp = act->dta_difo;
-+ if (dp != NULL)
-+ dtrace_difo_release(dp, vstate);
-+
-+ if (DTRACEACT_ISAGG(act->dta_kind))
-+ dtrace_ecb_aggregation_destroy(ecb, act);
-+ else
-+ kfree(act);
-+ }
-+ }
-+
-+ ecb->dte_action = NULL;
-+ ecb->dte_action_last = NULL;
-+ ecb->dte_size = sizeof(dtrace_epid_t);
-+}
-+
-+/*
-+ * Disable the ECB by removing it from its probe.
-+ */
-+void dtrace_ecb_disable(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_ecb *pecb, *prev = NULL;
-+ struct dtrace_probe *probe = ecb->dte_probe;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (probe == NULL)
-+ return;
-+
-+ for (pecb = probe->dtpr_ecb; pecb != NULL; pecb = pecb->dte_next) {
-+ if (pecb == ecb)
-+ break;
-+
-+ prev = pecb;
-+ }
-+
-+ ASSERT(pecb != NULL);
-+
-+ if (prev == NULL)
-+ probe->dtpr_ecb = ecb->dte_next;
-+ else
-+ prev->dte_next = ecb->dte_next;
-+
-+ if (ecb == probe->dtpr_ecb_last) {
-+ ASSERT(ecb->dte_next == NULL);
-+ probe->dtpr_ecb_last = prev;
-+ }
-+
-+ /*
-+ * The ECB has been disconnected from the probe; now sync to assure
-+ * that all CPUs have seen the change before returning.
-+ */
-+ dtrace_sync();
-+
-+ if (probe->dtpr_ecb == NULL) {
-+ /*
-+ * That was the last ECB on the probe; clear the predicate
-+ * cache ID for the probe, disable it and sync one more time
-+ * to assure that we'll never hit it again.
-+ */
-+ struct dtrace_provider *prov = probe->dtpr_provider;
-+
-+ ASSERT(ecb->dte_next == NULL);
-+ ASSERT(probe->dtpr_ecb_last == NULL);
-+
-+ probe->dtpr_predcache = DTRACE_CACHEIDNONE;
-+ prov->dtpv_pops.dtps_disable(prov->dtpv_arg,
-+ probe->dtpr_id, probe->dtpr_arg);
-+
-+ dtrace_sync();
-+ } else {
-+ /*
-+ * There is at least one ECB remaining on the probe. If there
-+ * is _exactly_ one, set the probe's predicate cache ID to be
-+ * the predicate cache ID of the remaining ECB.
-+ */
-+ ASSERT(probe->dtpr_ecb_last != NULL);
-+ ASSERT(probe->dtpr_predcache == DTRACE_CACHEIDNONE);
-+
-+ if (probe->dtpr_ecb == probe->dtpr_ecb_last) {
-+ struct dtrace_predicate *p =
-+ probe->dtpr_ecb->dte_predicate;
-+
-+ ASSERT(probe->dtpr_ecb->dte_next == NULL);
-+
-+ if (p != NULL)
-+ probe->dtpr_predcache = p->dtp_cacheid;
-+ }
-+
-+ ecb->dte_next = NULL;
-+ }
-+}
-+
-+static struct dtrace_ecb *dtrace_ecb_add(struct dtrace_state *state,
-+ struct dtrace_probe *probe)
-+{
-+ struct dtrace_ecb *ecb;
-+ dtrace_epid_t epid;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ ecb = kzalloc(sizeof(struct dtrace_ecb), GFP_KERNEL);
-+ if (ecb == NULL)
-+ return NULL;
-+
-+ ecb->dte_predicate = NULL;
-+ ecb->dte_probe = probe;
-+ ecb->dte_size = ecb->dte_needed = sizeof(dtrace_epid_t);
-+ ecb->dte_alignment = sizeof(dtrace_epid_t);
-+
-+ epid = state->dts_epid++;
-+
-+ if (epid - 1 >= state->dts_necbs) {
-+ struct dtrace_ecb **oecbs = state->dts_ecbs, **ecbs;
-+ int necbs = state->dts_necbs << 1;
-+
-+ ASSERT(epid == state->dts_necbs + 1);
-+
-+ if (necbs == 0) {
-+ ASSERT(oecbs == NULL);
-+
-+ necbs = 1;
-+ }
-+
-+ ecbs = vzalloc(necbs * sizeof(*ecbs));
-+ if (ecbs == NULL) {
-+ kfree(ecb);
-+ return NULL;
-+ }
-+
-+ if (oecbs != NULL)
-+ memcpy(ecbs, oecbs, state->dts_necbs * sizeof(*ecbs));
-+
-+ dtrace_membar_producer();
-+
-+ state->dts_ecbs = ecbs;
-+
-+ if (oecbs != NULL) {
-+ if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE)
-+ dtrace_sync();
-+
-+ vfree(oecbs);
-+ }
-+
-+ dtrace_membar_producer();
-+
-+ state->dts_necbs = necbs;
-+ }
-+
-+ ecb->dte_state = state;
-+
-+ ASSERT(state->dts_ecbs[epid - 1] == NULL);
-+
-+ dtrace_membar_producer();
-+
-+ state->dts_ecbs[(ecb->dte_epid = epid) - 1] = ecb;
-+
-+ return ecb;
-+}
-+
-+static struct dtrace_ecb * dtrace_ecb_create(struct dtrace_state *state,
-+ struct dtrace_probe *probe,
-+ struct dtrace_enabling *enab)
-+{
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_predicate *pred;
-+ struct dtrace_actdesc *act;
-+ struct dtrace_provider *prov;
-+ struct dtrace_ecbdesc *desc = enab->dten_current;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(state != NULL);
-+
-+ ecb = dtrace_ecb_add(state, probe);
-+ if (ecb == NULL)
-+ return NULL;
-+
-+ ecb->dte_uarg = desc->dted_uarg;
-+
-+ pred = desc->dted_pred.dtpdd_predicate;
-+ if (pred != NULL) {
-+ dtrace_predicate_hold(pred);
-+ ecb->dte_predicate = pred;
-+ }
-+
-+ if (probe != NULL) {
-+ prov = probe->dtpr_provider;
-+
-+ if (!(state->dts_cred.dcr_visible & DTRACE_CRV_ALLPROC) &&
-+ (prov->dtpv_priv.dtpp_flags & DTRACE_PRIV_USER))
-+ ecb->dte_cond |= DTRACE_COND_OWNER;
-+
-+ if (!(state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL) &&
-+ (prov->dtpv_priv.dtpp_flags & DTRACE_PRIV_KERNEL))
-+ ecb->dte_cond |= DTRACE_COND_USERMODE;
-+ }
-+
-+ if (dtrace_ecb_create_cache != NULL) {
-+ struct dtrace_ecb *cached = dtrace_ecb_create_cache;
-+ struct dtrace_action *act = cached->dte_action;
-+
-+ if (act != NULL) {
-+ ASSERT(act->dta_refcnt > 0);
-+
-+ act->dta_refcnt++;
-+ ecb->dte_action = act;
-+ ecb->dte_action_last = cached->dte_action_last;
-+ ecb->dte_needed = cached->dte_needed;
-+ ecb->dte_size = cached->dte_size;
-+ ecb->dte_alignment = cached->dte_alignment;
-+ }
-+
-+ return ecb;
-+ }
-+
-+ for (act = desc->dted_action; act != NULL; act = act->dtad_next) {
-+ enab->dten_error = dtrace_ecb_action_add(ecb, act);
-+ if (enab->dten_error != 0) {
-+ dtrace_ecb_destroy(ecb);
-+ return NULL;
-+ }
-+ }
-+
-+ dtrace_ecb_resize(ecb);
-+
-+ return (dtrace_ecb_create_cache = ecb);
-+}
-+
-+int dtrace_ecb_create_enable(struct dtrace_probe *probe, void *arg)
-+{
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_enabling *enab = arg;
-+ struct dtrace_state *state = enab->dten_vstate->dtvs_state;
-+
-+ ASSERT(state != NULL);
-+
-+ if (probe != NULL && probe->dtpr_gen < enab->dten_probegen)
-+ return DTRACE_MATCH_NEXT;
-+
-+ ecb = dtrace_ecb_create(state, probe, enab);
-+ if (ecb == NULL)
-+ return DTRACE_MATCH_DONE;
-+
-+ if (dtrace_ecb_enable(ecb) < 0)
-+ return DTRACE_MATCH_FAIL;
-+
-+ return DTRACE_MATCH_NEXT;
-+}
-+
-+void dtrace_ecb_destroy(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_state *state = ecb->dte_state;
-+ struct dtrace_vstate *vstate = &state->dts_vstate;
-+ struct dtrace_predicate *pred;
-+ dtrace_epid_t epid = ecb->dte_epid;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(ecb->dte_next == NULL);
-+ ASSERT(ecb->dte_probe == NULL || ecb->dte_probe->dtpr_ecb != ecb);
-+
-+ pred = ecb->dte_predicate;
-+ if (pred != NULL)
-+ dtrace_predicate_release(pred, vstate);
-+
-+ dtrace_ecb_action_remove(ecb);
-+
-+ ASSERT(state->dts_ecbs[epid - 1] == ecb);
-+ state->dts_ecbs[epid - 1] = NULL;
-+
-+ kfree(ecb);
-+}
-+
-+void dtrace_ecb_resize(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_action *act;
-+ uint32_t maxalign = sizeof(dtrace_epid_t);
-+ uint32_t align = sizeof(uint8_t), offs, diff;
-+ int wastuple = 0;
-+ uint32_t aggbase = UINT32_MAX;
-+ struct dtrace_state *state = ecb->dte_state;
-+
-+ /*
-+ * If we record anything, we always record the epid. (And we always
-+ * record it first.)
-+ */
-+ offs = sizeof(dtrace_epid_t);
-+ ecb->dte_size = ecb->dte_needed = sizeof(dtrace_epid_t);
-+
-+ for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
-+ struct dtrace_recdesc *rec = &act->dta_rec;
-+
-+ align = rec->dtrd_alignment;
-+ if (align > maxalign)
-+ maxalign = align;
-+
-+ if (!wastuple && act->dta_intuple) {
-+ /*
-+ * This is the first record in a tuple. Align the
-+ * offset to be at offset 4 in an 8-byte aligned
-+ * block.
-+ */
-+ diff = offs + sizeof(dtrace_aggid_t);
-+
-+ diff &= sizeof(uint64_t) - 1;
-+ if (diff)
-+ offs += sizeof(uint64_t) - diff;
-+
-+ aggbase = offs - sizeof(dtrace_aggid_t);
-+ ASSERT(!(aggbase & (sizeof(uint64_t) - 1)));
-+ }
-+
-+ if (rec->dtrd_size != 0) {
-+ diff = offs & (align - 1);
-+ if (diff)
-+ /*
-+ * The current offset is not properly
-+ * aligned; align it.
-+ */
-+ offs += align - diff;
-+ }
-+
-+ rec->dtrd_offset = offs;
-+
-+ if (offs + rec->dtrd_size > ecb->dte_needed) {
-+ ecb->dte_needed = offs + rec->dtrd_size;
-+
-+ if (ecb->dte_needed > state->dts_needed)
-+ state->dts_needed = ecb->dte_needed;
-+ }
-+
-+ if (DTRACEACT_ISAGG(act->dta_kind)) {
-+ struct dtrace_aggregation *agg;
-+ struct dtrace_action *first, *prev;
-+
-+ agg = (struct dtrace_aggregation *)act;
-+ first = agg->dtag_first;
-+
-+ ASSERT(rec->dtrd_size != 0 && first != NULL);
-+ ASSERT(wastuple);
-+ ASSERT(aggbase != UINT32_MAX);
-+
-+ agg->dtag_base = aggbase;
-+
-+ while ((prev = first->dta_prev) != NULL &&
-+ DTRACEACT_ISAGG(prev->dta_kind)) {
-+ agg = (struct dtrace_aggregation *)prev;
-+ first = agg->dtag_first;
-+ }
-+
-+ if (prev != NULL) {
-+ offs = prev->dta_rec.dtrd_offset +
-+ prev->dta_rec.dtrd_size;
-+ } else
-+ offs = sizeof(dtrace_epid_t);
-+
-+ wastuple = 0;
-+ } else {
-+ if (!act->dta_intuple)
-+ ecb->dte_size = offs + rec->dtrd_size;
-+
-+ offs += rec->dtrd_size;
-+ }
-+
-+ wastuple = act->dta_intuple;
-+ }
-+
-+ act = ecb->dte_action;
-+ if (act != NULL &&
-+ !(act->dta_kind == DTRACEACT_SPECULATE && act->dta_next == NULL) &&
-+ ecb->dte_size == sizeof(dtrace_epid_t)) {
-+ /*
-+ * If the size is still sizeof(dtrace_epid_t), then all
-+ * actions store no data; set the size to 0.
-+ */
-+ ecb->dte_alignment = maxalign;
-+ ecb->dte_size = 0;
-+
-+ /*
-+ * If the needed space is still sizeof(dtrace_epid_t), then
-+ * all actions need no additional space; set the needed
-+ * size to 0.
-+ */
-+ if (ecb->dte_needed == sizeof(dtrace_epid_t))
-+ ecb->dte_needed = 0;
-+
-+ return;
-+ }
-+
-+ /*
-+ * Set our alignment, and make sure that the dte_size and dte_needed
-+ * are aligned to the size of an EPID.
-+ */
-+ ecb->dte_alignment = maxalign;
-+ ecb->dte_size = (ecb->dte_size + (sizeof(dtrace_epid_t) - 1)) &
-+ ~(sizeof(dtrace_epid_t) - 1);
-+ ecb->dte_needed = (ecb->dte_needed + (sizeof(dtrace_epid_t) - 1)) &
-+ ~(sizeof(dtrace_epid_t) - 1);
-+ ASSERT(ecb->dte_size <= ecb->dte_needed);
-+}
-+
-+int dtrace_ecb_enable(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_probe *probe = ecb->dte_probe;
-+
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(ecb->dte_next == NULL);
-+
-+ if (probe == NULL)
-+ return 0;
-+
-+ if (probe->dtpr_ecb == NULL) {
-+ struct dtrace_provider *prov = probe->dtpr_provider;
-+
-+ probe->dtpr_ecb = probe->dtpr_ecb_last = ecb;
-+
-+
-+ if (ecb->dte_predicate != NULL)
-+ probe->dtpr_predcache = ecb->dte_predicate->dtp_cacheid;
-+
-+ return prov->dtpv_pops.dtps_enable(prov->dtpv_arg,
-+ probe->dtpr_id,
-+ probe->dtpr_arg);
-+ } else {
-+ ASSERT(probe->dtpr_ecb_last != NULL);
-+
-+ probe->dtpr_ecb_last->dte_next = ecb;
-+ probe->dtpr_ecb_last = ecb;
-+ probe->dtpr_predcache = 0;
-+
-+ dtrace_sync();
-+
-+ return 0;
-+ }
-+}
-+
-+struct dtrace_ecb *dtrace_epid2ecb(struct dtrace_state *state,
-+ dtrace_epid_t id)
-+{
-+ struct dtrace_ecb *ecb;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (id == 0 || id > state->dts_necbs)
-+ return NULL;
-+
-+ ASSERT(state->dts_necbs > 0 && state->dts_ecbs != NULL);
-+ ecb = state->dts_ecbs[id - 1];
-+ ASSERT(ecb == NULL || ecb->dte_epid == id);
-+
-+ return ecb;
-+}
-+
-+struct dtrace_aggregation *dtrace_aggid2agg(struct dtrace_state *state,
-+ dtrace_aggid_t id)
-+{
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ return idr_find(&state->dts_agg_idr, id);
-+}
-diff --git a/dtrace/dtrace_enable.c b/dtrace/dtrace_enable.c
-new file mode 100644
-index 000000000000..72f30149cb9c
---- /dev/null
-+++ b/dtrace/dtrace_enable.c
-@@ -0,0 +1,449 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_enable.c
-+ * DESCRIPTION: DTrace - probe enabling implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/mutex.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+size_t dtrace_retain_max = 1024;
-+struct dtrace_enabling *dtrace_retained;
-+dtrace_genid_t dtrace_retained_gen;
-+
-+struct dtrace_enabling *dtrace_enabling_create(struct dtrace_vstate *vstate)
-+{
-+ struct dtrace_enabling *enab;
-+
-+ enab = kzalloc(sizeof(struct dtrace_enabling), GFP_KERNEL);
-+ if (enab == NULL)
-+ return NULL;
-+
-+ enab->dten_vstate = vstate;
-+
-+ return enab;
-+}
-+
-+void dtrace_enabling_add(struct dtrace_enabling *enab,
-+ struct dtrace_ecbdesc *ecb)
-+{
-+ struct dtrace_ecbdesc **ndesc;
-+ size_t osize, nsize;
-+
-+ /*
-+ * We can't add to enablings after we've enabled them, or after we've
-+ * retained them.
-+ */
-+ ASSERT(enab->dten_probegen == 0);
-+ ASSERT(enab->dten_next == NULL && enab->dten_prev == NULL);
-+
-+ if (enab->dten_ndesc < enab->dten_maxdesc) {
-+ enab->dten_desc[enab->dten_ndesc++] = ecb;
-+ return;
-+ }
-+
-+ osize = enab->dten_maxdesc * sizeof(struct dtrace_enabling *);
-+
-+ if (enab->dten_maxdesc == 0)
-+ enab->dten_maxdesc = 1;
-+ else
-+ enab->dten_maxdesc <<= 1;
-+
-+ ASSERT(enab->dten_ndesc < enab->dten_maxdesc);
-+
-+ nsize = enab->dten_maxdesc * sizeof(struct dtrace_enabling *);
-+ ndesc = vzalloc(nsize);
-+ memcpy(ndesc, enab->dten_desc, osize);
-+ vfree(enab->dten_desc);
-+
-+ enab->dten_desc = ndesc;
-+ enab->dten_desc[enab->dten_ndesc++] = ecb;
-+}
-+
-+static void dtrace_enabling_addlike(struct dtrace_enabling *enab,
-+ struct dtrace_ecbdesc *ecb,
-+ struct dtrace_probedesc *pd)
-+{
-+ struct dtrace_ecbdesc *new;
-+ struct dtrace_predicate *pred;
-+ struct dtrace_actdesc *act;
-+
-+ /*
-+ * We're going to create a new ECB description that matches the
-+ * specified ECB in every way, but has the specified probe description.
-+ */
-+ new = kzalloc(sizeof(struct dtrace_ecbdesc), GFP_KERNEL);
-+
-+ pred = ecb->dted_pred.dtpdd_predicate;
-+ if (pred != NULL)
-+ dtrace_predicate_hold(pred);
-+
-+ for (act = ecb->dted_action; act != NULL; act = act->dtad_next)
-+ dtrace_actdesc_hold(act);
-+
-+ new->dted_action = ecb->dted_action;
-+ new->dted_pred = ecb->dted_pred;
-+ new->dted_probe = *pd;
-+ new->dted_uarg = ecb->dted_uarg;
-+
-+ dtrace_enabling_add(enab, new);
-+}
-+
-+void dtrace_enabling_dump(struct dtrace_enabling *enab)
-+{
-+ int i;
-+
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_probedesc *desc =
-+ &enab->dten_desc[i]->dted_probe;
-+
-+ pr_info("enabling probe %d (%s:%s:%s:%s)",
-+ i, desc->dtpd_provider, desc->dtpd_mod,
-+ desc->dtpd_func, desc->dtpd_name);
-+ }
-+}
-+
-+void dtrace_enabling_destroy(struct dtrace_enabling *enab)
-+{
-+ int i;
-+ struct dtrace_ecbdesc *ep;
-+ struct dtrace_vstate *vstate = enab->dten_vstate;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_actdesc *act, *next;
-+ struct dtrace_predicate *pred;
-+
-+ ep = enab->dten_desc[i];
-+
-+ pred = ep->dted_pred.dtpdd_predicate;
-+ if (pred != NULL)
-+ dtrace_predicate_release(pred, vstate);
-+
-+ for (act = ep->dted_action; act != NULL; act = next) {
-+ next = act->dtad_next;
-+ dtrace_actdesc_release(act, vstate);
-+ }
-+
-+ kfree(ep);
-+ }
-+
-+ vfree(enab->dten_desc);
-+
-+ /*
-+ * If this was a retained enabling, decrement the dts_nretained count
-+ * and remove it from the dtrace_retained list.
-+ */
-+ if (enab->dten_prev != NULL || enab->dten_next != NULL ||
-+ dtrace_retained == enab) {
-+ ASSERT(enab->dten_vstate->dtvs_state != NULL);
-+ ASSERT(enab->dten_vstate->dtvs_state->dts_nretained > 0);
-+ enab->dten_vstate->dtvs_state->dts_nretained--;
-+ dtrace_retained_gen++;
-+ }
-+
-+ if (enab->dten_prev == NULL) {
-+ if (dtrace_retained == enab) {
-+ dtrace_retained = enab->dten_next;
-+
-+ if (dtrace_retained != NULL)
-+ dtrace_retained->dten_prev = NULL;
-+ }
-+ } else {
-+ ASSERT(enab != dtrace_retained);
-+ ASSERT(dtrace_retained != NULL);
-+ enab->dten_prev->dten_next = enab->dten_next;
-+ }
-+
-+ if (enab->dten_next != NULL) {
-+ ASSERT(dtrace_retained != NULL);
-+ enab->dten_next->dten_prev = enab->dten_prev;
-+ }
-+
-+ kfree(enab);
-+}
-+
-+int dtrace_enabling_retain(struct dtrace_enabling *enab)
-+{
-+ struct dtrace_state *state;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(enab->dten_next == NULL && enab->dten_prev == NULL);
-+ ASSERT(enab->dten_vstate != NULL);
-+
-+ state = enab->dten_vstate->dtvs_state;
-+ ASSERT(state != NULL);
-+
-+ /*
-+ * We only allow each state to retain dtrace_retain_max enablings.
-+ */
-+ if (state->dts_nretained >= dtrace_retain_max)
-+ return -ENOSPC;
-+
-+ state->dts_nretained++;
-+ dtrace_retained_gen++;
-+
-+ if (dtrace_retained == NULL) {
-+ dtrace_retained = enab;
-+ return 0;
-+ }
-+
-+ enab->dten_next = dtrace_retained;
-+ dtrace_retained->dten_prev = enab;
-+ dtrace_retained = enab;
-+
-+ return 0;
-+}
-+
-+int dtrace_enabling_replicate(struct dtrace_state *state,
-+ struct dtrace_probedesc *match,
-+ struct dtrace_probedesc *create)
-+{
-+ struct dtrace_enabling *new, *enab;
-+ int found = 0, err = -ENOENT;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(strlen(match->dtpd_provider) < DTRACE_PROVNAMELEN);
-+ ASSERT(strlen(match->dtpd_mod) < DTRACE_MODNAMELEN);
-+ ASSERT(strlen(match->dtpd_func) < DTRACE_FUNCNAMELEN);
-+ ASSERT(strlen(match->dtpd_name) < DTRACE_NAMELEN);
-+
-+ new = dtrace_enabling_create(&state->dts_vstate);
-+ if (new == NULL)
-+ return -ENOMEM;
-+
-+ /*
-+ * Iterate over all retained enablings, looking for enablings that
-+ * match the specified state.
-+ */
-+ for (enab = dtrace_retained; enab != NULL; enab = enab->dten_next) {
-+ int i;
-+
-+ /*
-+ * dtvs_state can only be NULL for helper enablings -- and
-+ * helper enablings can't be retained.
-+ */
-+ ASSERT(enab->dten_vstate->dtvs_state != NULL);
-+
-+ if (enab->dten_vstate->dtvs_state != state)
-+ continue;
-+
-+ /*
-+ * Now iterate over each probe description; we're looking for
-+ * an exact match to the specified probe description.
-+ */
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_ecbdesc *ep = enab->dten_desc[i];
-+ struct dtrace_probedesc *pd = &ep->dted_probe;
-+
-+ if (strcmp(pd->dtpd_provider, match->dtpd_provider))
-+ continue;
-+
-+ if (strcmp(pd->dtpd_mod, match->dtpd_mod))
-+ continue;
-+
-+ if (strcmp(pd->dtpd_func, match->dtpd_func))
-+ continue;
-+
-+ if (strcmp(pd->dtpd_name, match->dtpd_name))
-+ continue;
-+
-+ /*
-+ * We have a winning probe! Add it to our growing
-+ * enabling.
-+ */
-+ found = 1;
-+ dtrace_enabling_addlike(new, ep, create);
-+ }
-+ }
-+
-+ if (!found || (err = dtrace_enabling_retain(new)) != 0) {
-+ dtrace_enabling_destroy(new);
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+void dtrace_enabling_retract(struct dtrace_state *state)
-+{
-+ struct dtrace_enabling *enab, *next;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ /*
-+ * Iterate over all retained enablings, destroy the enablings retained
-+ * for the specified state.
-+ */
-+ for (enab = dtrace_retained; enab != NULL; enab = next) {
-+ next = enab->dten_next;
-+
-+ /*
-+ * dtvs_state can only be NULL for helper enablings, and helper
-+ * enablings can't be retained.
-+ */
-+ ASSERT(enab->dten_vstate->dtvs_state != NULL);
-+
-+ if (enab->dten_vstate->dtvs_state == state) {
-+ ASSERT(state->dts_nretained > 0);
-+ dtrace_enabling_destroy(enab);
-+ }
-+ }
-+
-+ ASSERT(state->dts_nretained == 0);
-+}
-+
-+int dtrace_enabling_match(struct dtrace_enabling *enab, int *nmatched)
-+{
-+ int i;
-+ int total_matched = 0, matched = 0;
-+
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_ecbdesc *ep = enab->dten_desc[i];
-+
-+ enab->dten_current = ep;
-+ enab->dten_error = 0;
-+
-+ dt_dbg_enable(" Matching enabling %p[%d] for %s:%s:%s:%s\n",
-+ enab, i, ep->dted_probe.dtpd_provider,
-+ ep->dted_probe.dtpd_mod,
-+ ep->dted_probe.dtpd_func,
-+ ep->dted_probe.dtpd_name);
-+
-+ matched = dtrace_probe_enable(&ep->dted_probe, enab);
-+ if (matched < 0) {
-+ dt_dbg_enable(" Matching enabling %p[%d] failed: "
-+ "busy\n", enab, i);
-+ return -EBUSY;
-+ }
-+
-+ dt_dbg_enable(" Matching enabling %p[%d] found %d matches.\n",
-+ enab, i, matched);
-+
-+ total_matched += matched;
-+
-+ if (enab->dten_error != 0) {
-+ if (nmatched == NULL)
-+ pr_warn("%s error on %p: %d\n", __func__,
-+ (void *)ep, enab->dten_error);
-+
-+ return enab->dten_error;
-+ }
-+ }
-+
-+ enab->dten_probegen = dtrace_probegen;
-+ if (nmatched != NULL)
-+ *nmatched = total_matched;
-+
-+ return 0;
-+}
-+
-+void dtrace_enabling_matchall(void)
-+{
-+ struct dtrace_enabling *enab;
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ for (enab = dtrace_retained; enab != NULL; enab = enab->dten_next)
-+ (void) dtrace_enabling_match(enab, NULL);
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+}
-+
-+/*
-+ * If an enabling is to be enabled without having matched probes (that is, if
-+ * dtrace_state_go() is to be called on the underlying dtrace_state_t), the
-+ * enabling must be _primed_ by creating an ECB for every ECB description.
-+ * This must be done to assure that we know the number of speculations, the
-+ * number of aggregations, the minimum buffer size needed, etc. before we
-+ * transition out of DTRACE_ACTIVITY_INACTIVE. To do this without actually
-+ * enabling any probes, we create ECBs for every ECB description, but with a
-+ * NULL probe -- which is exactly what this function does.
-+ */
-+void dtrace_enabling_prime(struct dtrace_state *state)
-+{
-+ struct dtrace_enabling *enab;
-+ int i;
-+
-+ for (enab = dtrace_retained; enab != NULL; enab = enab->dten_next) {
-+ ASSERT(enab->dten_vstate->dtvs_state != NULL);
-+
-+ if (enab->dten_vstate->dtvs_state != state)
-+ continue;
-+
-+ /*
-+ * We don't want to prime an enabling more than once, lest
-+ * we allow a malicious user to induce resource exhaustion.
-+ * (The ECBs that result from priming an enabling aren't
-+ * leaked -- but they also aren't deallocated until the
-+ * consumer state is destroyed.)
-+ */
-+ if (enab->dten_primed)
-+ continue;
-+
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ enab->dten_current = enab->dten_desc[i];
-+ dtrace_probe_enable(NULL, enab);
-+ }
-+
-+ enab->dten_primed = 1;
-+ }
-+}
-+
-+void dtrace_enabling_provide(struct dtrace_provider *prv)
-+{
-+ int all = 0;
-+ dtrace_genid_t gen;
-+
-+ if (prv == NULL) {
-+ all = 1;
-+ prv = dtrace_provider;
-+ }
-+
-+ do {
-+ struct dtrace_enabling *enab;
-+ void *parg = prv->dtpv_arg;
-+
-+retry:
-+ gen = dtrace_retained_gen;
-+ for (enab = dtrace_retained; enab != NULL;
-+ enab = enab->dten_next) {
-+ int i;
-+
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_probedesc desc;
-+
-+ desc = enab->dten_desc[i]->dted_probe;
-+ mutex_unlock(&dtrace_lock);
-+ prv->dtpv_pops.dtps_provide(parg, &desc);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (gen != dtrace_retained_gen)
-+ goto retry;
-+ }
-+ }
-+ } while (all && (prv = prv->dtpv_next) != NULL);
-+
-+ mutex_unlock(&dtrace_lock);
-+ dtrace_probe_provide(NULL, all ? NULL : prv);
-+ mutex_lock(&dtrace_lock);
-+}
-diff --git a/dtrace/dtrace_fmt.c b/dtrace/dtrace_fmt.c
-new file mode 100644
-index 000000000000..78fcc8e6efb8
---- /dev/null
-+++ b/dtrace/dtrace_fmt.c
-@@ -0,0 +1,104 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_fmt.c
-+ * DESCRIPTION: DTrace - format string implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+uint16_t dtrace_format_add(struct dtrace_state *state, char *str)
-+{
-+ char *fmt, **new;
-+ uint16_t ndx;
-+
-+ fmt = dtrace_strdup(str);
-+ if (fmt == NULL)
-+ return 0;
-+
-+ for (ndx = 0; ndx < state->dts_nformats; ndx++) {
-+ if (state->dts_formats[ndx] == NULL) {
-+ state->dts_formats[ndx] = fmt;
-+
-+ return ndx + 1;
-+ }
-+ }
-+
-+ if (state->dts_nformats == UINT16_MAX) {
-+ kfree(fmt);
-+
-+ return 0;
-+ }
-+
-+ ndx = state->dts_nformats;
-+ new = vmalloc((ndx + 1) * sizeof(char *));
-+ if (new == NULL) {
-+ kfree(fmt);
-+ return 0;
-+ }
-+
-+ state->dts_nformats++;
-+
-+ if (state->dts_formats != NULL) {
-+ ASSERT(ndx != 0);
-+ memcpy(new, state->dts_formats, ndx * sizeof(char *));
-+ vfree(state->dts_formats);
-+ }
-+
-+ state->dts_formats = new;
-+ state->dts_formats[ndx] = fmt;
-+
-+ return ndx + 1;
-+}
-+
-+void dtrace_format_remove(struct dtrace_state *state, uint16_t format)
-+{
-+ char *fmt;
-+
-+ ASSERT(state->dts_formats != NULL);
-+ ASSERT(format <= state->dts_nformats);
-+ ASSERT(state->dts_formats[format - 1] != NULL);
-+
-+ fmt = state->dts_formats[format - 1];
-+ kfree(fmt);
-+ state->dts_formats[format - 1] = NULL;
-+}
-+
-+void dtrace_format_destroy(struct dtrace_state *state)
-+{
-+ int i;
-+
-+ if (state->dts_nformats == 0) {
-+ ASSERT(state->dts_formats == NULL);
-+ return;
-+ }
-+
-+ ASSERT(state->dts_formats != NULL);
-+
-+ for (i = 0; i < state->dts_nformats; i++) {
-+ char *fmt = state->dts_formats[i];
-+
-+ if (fmt == NULL)
-+ continue;
-+
-+ kfree(fmt);
-+ }
-+
-+ vfree(state->dts_formats);
-+ state->dts_nformats = 0;
-+ state->dts_formats = NULL;
-+}
-diff --git a/dtrace/dtrace_hash.c b/dtrace/dtrace_hash.c
-new file mode 100644
-index 000000000000..0773c60e7897
---- /dev/null
-+++ b/dtrace/dtrace_hash.c
-@@ -0,0 +1,266 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_hash.c
-+ * DESCRIPTION: DTrace - hash table implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+#define DTRACE_HASHSTR(hash, probe) \
-+ dtrace_hash_str(*((char **)((uintptr_t)(probe) + (hash)->dth_stroffs)))
-+#define DTRACE_HASHEQ(hash, lhs, rhs) \
-+ (strcmp(*((char **)((uintptr_t)(lhs) + (hash)->dth_stroffs)), \
-+ *((char **)((uintptr_t)(rhs) + (hash)->dth_stroffs))) == 0)
-+
-+static uint_t dtrace_hash_str(char *p)
-+{
-+ uint_t g;
-+ uint_t hval = 0;
-+
-+ while (*p) {
-+ hval = (hval << 4) + *p++;
-+ g = hval & 0xf0000000;
-+ if (g != 0)
-+ hval ^= g >> 24;
-+
-+ hval &= ~g;
-+ }
-+
-+ return hval;
-+}
-+
-+struct dtrace_hash *dtrace_hash_create(uintptr_t stroffs, uintptr_t nextoffs,
-+ uintptr_t prevoffs)
-+{
-+ struct dtrace_hash *hash;
-+
-+ hash = kzalloc(sizeof(struct dtrace_hash), GFP_KERNEL);
-+ if (hash == NULL)
-+ return NULL;
-+
-+ hash->dth_stroffs = stroffs;
-+ hash->dth_nextoffs = nextoffs;
-+ hash->dth_prevoffs = prevoffs;
-+
-+ hash->dth_size = 1;
-+ hash->dth_mask = hash->dth_size - 1;
-+
-+ hash->dth_tab = vzalloc(hash->dth_size *
-+ sizeof(struct dtrace_hashbucket *));
-+
-+ if (hash->dth_tab == NULL) {
-+ kfree(hash);
-+ return NULL;
-+ }
-+
-+ return hash;
-+}
-+
-+void dtrace_hash_destroy(struct dtrace_hash *hash)
-+{
-+#ifdef DEBUG
-+ int i;
-+
-+ for (i = 0; i < hash->dth_size; i++)
-+ ASSERT(hash->dth_tab[i] == NULL);
-+#endif
-+
-+ if (hash == NULL)
-+ return;
-+
-+ vfree(hash->dth_tab);
-+ kfree(hash);
-+}
-+
-+static int dtrace_hash_resize(struct dtrace_hash *hash)
-+{
-+ int size = hash->dth_size, i, ndx;
-+ int new_size = hash->dth_size << 1;
-+ int new_mask = new_size - 1;
-+ struct dtrace_hashbucket **new_tab, *bucket, *next;
-+
-+ ASSERT((new_size & new_mask) == 0);
-+
-+ new_tab = vzalloc(new_size * sizeof(void *));
-+ if (new_tab == NULL)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < size; i++) {
-+ for (bucket = hash->dth_tab[i]; bucket != NULL;
-+ bucket = next) {
-+ struct dtrace_probe *probe = bucket->dthb_chain;
-+
-+ ASSERT(probe != NULL);
-+ ndx = DTRACE_HASHSTR(hash, probe) & new_mask;
-+
-+ next = bucket->dthb_next;
-+ bucket->dthb_next = new_tab[ndx];
-+ new_tab[ndx] = bucket;
-+ }
-+ }
-+
-+ vfree(hash->dth_tab);
-+ hash->dth_tab = new_tab;
-+ hash->dth_size = new_size;
-+ hash->dth_mask = new_mask;
-+
-+ return 0;
-+}
-+
-+int dtrace_hash_add(struct dtrace_hash *hash, struct dtrace_probe *new)
-+{
-+ int hashval = DTRACE_HASHSTR(hash, new);
-+ int ndx = hashval & hash->dth_mask;
-+ struct dtrace_hashbucket *bucket = hash->dth_tab[ndx];
-+ struct dtrace_probe **nextp, **prevp;
-+
-+ for (; bucket != NULL; bucket = bucket->dthb_next) {
-+ if (DTRACE_HASHEQ(hash, bucket->dthb_chain, new))
-+ goto add;
-+ }
-+
-+ if ((hash->dth_nbuckets >> 1) > hash->dth_size) {
-+ int err = 0;
-+
-+ err = dtrace_hash_resize(hash);
-+ if (err != 0)
-+ return err;
-+
-+ dtrace_hash_add(hash, new);
-+ return 0;
-+ }
-+
-+ bucket = kzalloc(sizeof(struct dtrace_hashbucket), GFP_KERNEL);
-+ if (bucket == NULL)
-+ return -ENOMEM;
-+
-+ bucket->dthb_next = hash->dth_tab[ndx];
-+ hash->dth_tab[ndx] = bucket;
-+ hash->dth_nbuckets++;
-+
-+add:
-+ nextp = DTRACE_HASHNEXT(hash, new);
-+
-+ ASSERT(*nextp == NULL && *(DTRACE_HASHPREV(hash, new)) == NULL);
-+
-+ *nextp = bucket->dthb_chain;
-+
-+ if (bucket->dthb_chain != NULL) {
-+ prevp = DTRACE_HASHPREV(hash, bucket->dthb_chain);
-+
-+ ASSERT(*prevp == NULL);
-+
-+ *prevp = new;
-+ }
-+
-+ bucket->dthb_chain = new;
-+ bucket->dthb_len++;
-+
-+ return 0;
-+}
-+
-+struct dtrace_probe *dtrace_hash_lookup(struct dtrace_hash *hash,
-+ struct dtrace_probe *template)
-+{
-+ int hashval = DTRACE_HASHSTR(hash, template);
-+ int ndx = hashval & hash->dth_mask;
-+
-+ struct dtrace_hashbucket *bucket = hash->dth_tab[ndx];
-+
-+ for (; bucket != NULL; bucket = bucket->dthb_next) {
-+ if (DTRACE_HASHEQ(hash, bucket->dthb_chain, template))
-+ return bucket->dthb_chain;
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * FIXME:
-+ * It would be more accurate to calculate a lookup cost based on the number
-+ * of buckets in the hash table slot, the length of the chain, and the length
-+ * of the string being looked up.
-+ * The hash tables can also be optimized by storing the hashval in each element
-+ * rather than always performing string comparisons.
-+ */
-+int dtrace_hash_collisions(struct dtrace_hash *hash,
-+ struct dtrace_probe *template)
-+{
-+ int hashval = DTRACE_HASHSTR(hash, template);
-+ int ndx = hashval & hash->dth_mask;
-+
-+ struct dtrace_hashbucket *bucket = hash->dth_tab[ndx];
-+
-+ for (; bucket != NULL; bucket = bucket->dthb_next) {
-+ if (DTRACE_HASHEQ(hash, bucket->dthb_chain, template))
-+ return bucket->dthb_len;
-+ }
-+
-+ return 0;
-+}
-+
-+void dtrace_hash_remove(struct dtrace_hash *hash, struct dtrace_probe *probe)
-+{
-+ int ndx = DTRACE_HASHSTR(hash, probe) & hash->dth_mask;
-+
-+ struct dtrace_hashbucket *bucket = hash->dth_tab[ndx];
-+ struct dtrace_probe **prevp = DTRACE_HASHPREV(hash, probe);
-+ struct dtrace_probe **nextp = DTRACE_HASHNEXT(hash, probe);
-+
-+ for (; bucket != NULL; bucket = bucket->dthb_next) {
-+ if (DTRACE_HASHEQ(hash, bucket->dthb_chain, probe))
-+ break;
-+ }
-+
-+ ASSERT(bucket != NULL);
-+
-+ if (*prevp == NULL) {
-+ if (*nextp == NULL) {
-+ /*
-+ * This is the last probe in the bucket; we can remove
-+ * the bucket.
-+ */
-+ struct dtrace_hashbucket *b = hash->dth_tab[ndx];
-+
-+ ASSERT(bucket->dthb_chain == probe);
-+ ASSERT(b != NULL);
-+
-+ if (b == bucket)
-+ hash->dth_tab[ndx] = bucket->dthb_next;
-+ else {
-+ while (b->dthb_next != bucket)
-+ b = b->dthb_next;
-+
-+ b->dthb_next = bucket->dthb_next;
-+ }
-+
-+ ASSERT(hash->dth_nbuckets > 0);
-+
-+ hash->dth_nbuckets--;
-+ kfree(bucket);
-+
-+ return;
-+ }
-+
-+ bucket->dthb_chain = *nextp;
-+ } else
-+ *(DTRACE_HASHNEXT(hash, *prevp)) = *nextp;
-+
-+ if (*nextp != NULL)
-+ *(DTRACE_HASHPREV(hash, *nextp)) = *prevp;
-+}
-diff --git a/dtrace/dtrace_isa.c b/dtrace/dtrace_isa.c
-new file mode 100644
-index 000000000000..f84ce1cd52cc
---- /dev/null
-+++ b/dtrace/dtrace_isa.c
-@@ -0,0 +1,361 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_isa.c
-+ * DESCRIPTION: DTrace - architecture specific code
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/hardirq.h>
-+#include <linux/mm.h>
-+#include <linux/smp.h>
-+#include <linux/uaccess.h>
-+#include <linux/cpumask.h>
-+#include <asm/cacheflush.h>
-+#include <asm/ptrace.h>
-+#include <asm/stacktrace.h>
-+
-+#include "dtrace.h"
-+
-+DEFINE_MUTEX(cpu_lock);
-+EXPORT_SYMBOL(cpu_lock);
-+
-+int dtrace_getipl(void)
-+{
-+ return in_interrupt();
-+}
-+
-+void dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg)
-+{
-+ if (cpu == DTRACE_CPUALL)
-+ smp_call_function(func, arg, 1);
-+ else
-+ smp_call_function_single(cpu, func, arg, 1);
-+}
-+
-+void dtrace_toxic_ranges(void (*func)(uintptr_t, uintptr_t))
-+{
-+ /* FIXME */
-+}
-+
-+/*
-+ * Note: not called from probe context. This function is called
-+ * asynchronously (and at a regular interval) from outside of probe context
-+ * by the DTrace framework to sync shared data which DTrace probe context
-+ * may access without locks.
-+ *
-+ * Whenever the framework updates data which can be accessed from probe context,
-+ * the framework then calls dtrace_sync(). dtrace_sync() guarantees all probes
-+ * are using the new data before returning.
-+ *
-+ * See the comment in dtrace_impl.h which describes this algorithm.
-+ * The cpuc_in_probe_ctxt flag is an increasing 16-bit count. It is odd when
-+ * in DTrace probe context and even when not in DTrace probe context.
-+ * The upper 15 bits are a counter which are incremented when exiting DTrace
-+ * probe context. These upper 15 bits are used to detect "sample aliasing":
-+ * i.e. the target CPU is not in DTrace probe context between samples but
-+ * continually enters probe context just before being sampled.
-+ *
-+ * dtrace_sync() loops over NCPUs. CPUs which are not in DTrace probe context
-+ * (cpuc_in_probe_ctxt is even) are removed from the list. This is repeated
-+ * until there are no CPUs left in the sync list.
-+ *
-+ * In the rare cases where dtrace_sync() loops over all NCPUs more than
-+ * dtrace_sync_sample_count times, dtrace_sync() then spins on one CPU's
-+ * cpuc_in_probe_ctxt count until the count increments. This is intended to
-+ * avoid sample aliasing.
-+ */
-+void dtrace_sync(void)
-+{
-+ /*
-+ * sync_cpus is a bitmap of CPUs that need to be synced with.
-+ */
-+ cpumask_t sync_cpus;
-+ uint64_t sample_count = 0;
-+ int cpuid, sample_cpuid = 0;
-+ int outstanding;
-+
-+ /*
-+ * Create bitmap of CPUs that need to be synced with.
-+ */
-+ cpumask_copy(&sync_cpus, cpu_online_mask);
-+ outstanding = 0;
-+ for_each_cpu(cpuid, &sync_cpus) {
-+ ++outstanding;
-+
-+ /*
-+ * Set a flag to let the CPU know we are syncing with it.
-+ */
-+ DTRACE_SYNC_START(cpuid);
-+ }
-+
-+ /*
-+ * The preceding stores by DTRACE_SYNC_START() must complete before
-+ * subsequent loads or stores. No membar is needed because the
-+ * atomic-add operation in DTRACE_SYNC_START is a memory barrier on
-+ * SPARC and X86.
-+ */
-+
-+ while (outstanding > 0) {
-+ /*
-+ * Loop over the map of CPUs that need to be synced with.
-+ */
-+ for_each_cpu(cpuid, &sync_cpus) {
-+ if (!DTRACE_SYNC_IN_CRITICAL(cpuid)) {
-+
-+ /* Clear the CPU's sync request flag */
-+ DTRACE_SYNC_END(cpuid);
-+
-+ /*
-+ * remove cpuid from list of CPUs that
-+ * still need to be synced with.
-+ */
-+ DTRACE_SYNC_DONE(cpuid, &sync_cpus);
-+ --outstanding;
-+ } else {
-+ /*
-+ * Remember one of the outstanding CPUs to spin
-+ * on once we reach the sampling limit.
-+ */
-+ sample_cpuid = cpuid;
-+ }
-+ }
-+
-+ /*
-+ * dtrace_probe may be running in sibling threads in this core.
-+ */
-+ if (outstanding > 0) {
-+ dtrace_safe_smt_pause();
-+
-+ /*
-+ * After sample_count loops, spin on one CPU's count
-+ * instead of just checking for odd/even.
-+ */
-+ if (++sample_count > dtrace_sync_sample_count) {
-+ uint64_t count =
-+ DTRACE_SYNC_CRITICAL_COUNT(sample_cpuid);
-+
-+ /*
-+ * Spin until critical section count increments.
-+ */
-+ if (DTRACE_SYNC_IN_CRITICAL(sample_cpuid)) {
-+ while (count ==
-+ DTRACE_SYNC_CRITICAL_COUNT(
-+ sample_cpuid)) {
-+
-+ dtrace_safe_smt_pause();
-+ }
-+ }
-+
-+ DTRACE_SYNC_END(sample_cpuid);
-+ DTRACE_SYNC_DONE(sample_cpuid, &sync_cpus);
-+ --outstanding;
-+ }
-+ }
-+ }
-+
-+/*
-+ * All preceding loads by DTRACE_SYNC_IN_CRITICAL() and
-+ * DTRACE_SYNC_CRITICAL_COUNT() must complete before subsequent loads
-+ * or stores. No membar is needed because the atomic-add operation in
-+ * DTRACE_SYNC_END() is a memory barrier on SPARC and X86.
-+ */
-+}
-+
-+/*
-+ * Handle a few special cases where we store information in kernel memory that
-+ * in other systems is typically found in userspace.
-+ */
-+static int dtrace_fake_copyin(intptr_t addr, size_t size)
-+{
-+ struct dtrace_psinfo *psinfo;
-+ uintptr_t argv;
-+ unsigned long argc;
-+ uintptr_t envp;
-+ unsigned long envc;
-+
-+ if (current->dt_task == NULL)
-+ return 0;
-+
-+ psinfo = current->dt_task->dt_psinfo;
-+ if (psinfo == NULL)
-+ return 0;
-+
-+ argv = (uintptr_t)psinfo->dtps_argv;
-+ argc = psinfo->dtps_argc;
-+ envp = (uintptr_t)psinfo->dtps_envp;
-+ envc = psinfo->dtps_envc;
-+
-+ /*
-+ * Ensure addr is within the argv array (or the envp array):
-+ * addr in [argv..argv + argc * sizeof(psinfo->argv[0])[
-+ * Ensure that addr + size is within the same array
-+ * addr + size in [argv..argv * sizeof(psinfo->argv[0])]
-+ *
-+ * To guard against overflows on (addr + size) we rewrite this basic
-+ * equation:
-+ * addr + size <= argv + argc * sizeof(psinfo->argv[0])
-+ * into:
-+ * addr - argv <= argc * sizeof(psinfo->argv[0]) - size
-+ */
-+ return (addr >= argv &&
-+ addr - argv < argc * sizeof(psinfo->dtps_argv[0]) &&
-+ addr - argv <= argc * sizeof(psinfo->dtps_argv[0]) - size) ||
-+ (addr >= envp &&
-+ addr - envp < envc * sizeof(psinfo->dtps_envp[0]) &&
-+ addr - envp <= envc * sizeof(psinfo->dtps_envp[0]) - size);
-+}
-+
-+void dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_fake_copyin(uaddr, size)) {
-+ memcpy((char *)kaddr, (char *)uaddr, size);
-+ return;
-+ }
-+
-+ dtrace_copyin_arch(uaddr, kaddr, size, flags);
-+}
-+
-+void dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_fake_copyin(uaddr, size)) {
-+ strncpy((char *)kaddr, (char *)uaddr,
-+ min(size, (size_t)PR_PSARGS_SZ));
-+ return;
-+ }
-+
-+ dtrace_copyinstr_arch(uaddr, kaddr, size, flags);
-+}
-+
-+/*
-+ * FIXME: aframes + 3 should really be aframes + 1, dtrace_stacktrace() in the
-+ * kernel should do its own aframes + 2
-+ */
-+void dtrace_getpcstack(uint64_t *pcstack, int pcstack_limit, int aframes,
-+ uint32_t *intrpc)
-+{
-+ struct stacktrace_state st = {
-+ pcstack,
-+ NULL,
-+ pcstack_limit,
-+ aframes + 3,
-+ STACKTRACE_KERNEL
-+ };
-+
-+ dtrace_stacktrace(&st);
-+
-+ while (st.depth < st.limit)
-+ pcstack[st.depth++] = 0;
-+}
-+EXPORT_SYMBOL(dtrace_getpcstack);
-+
-+/*
-+ * Get user stack entries up to the pcstack_limit; return the number of entries
-+ * acquired. If pcstack is NULL, return the number of entries potentially
-+ * acquirable.
-+ */
-+unsigned long dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack,
-+ int pcstack_limit)
-+{
-+ struct task_struct *p = current;
-+ struct stacktrace_state st;
-+ unsigned long depth;
-+
-+ if (pcstack) {
-+ if (unlikely(pcstack_limit < 2)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return 0;
-+ }
-+ *pcstack++ = (uint64_t)p->pid;
-+ *pcstack++ = (uint64_t)p->tgid;
-+ pcstack_limit -= 2;
-+ }
-+
-+ st.pcs = pcstack;
-+ st.fps = fpstack;
-+ st.limit = pcstack_limit;
-+ st.depth = 0;
-+ st.flags = STACKTRACE_USER;
-+
-+ dtrace_stacktrace(&st);
-+
-+ depth = st.depth;
-+ if (pcstack) {
-+ while (st.depth < st.limit) {
-+ pcstack[st.depth++] = 0;
-+ if (fpstack)
-+ fpstack[st.depth++] = 0;
-+ }
-+ }
-+
-+ return depth;
-+}
-+
-+void dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
-+{
-+ dtrace_getufpstack(pcstack, NULL, pcstack_limit);
-+}
-+
-+/*
-+ * FIXME: aframes + 3 should really be aframes + 1, dtrace_stacktrace() in the
-+ * kernel should do its own aframes + 2
-+ */
-+int dtrace_getstackdepth(struct dtrace_mstate *mstate, int aframes)
-+{
-+ uintptr_t old = mstate->dtms_scratch_ptr;
-+ struct stacktrace_state st = {
-+ NULL,
-+ NULL,
-+ 0,
-+ aframes + 3,
-+ STACKTRACE_KERNEL
-+ };
-+
-+ st.pcs = (uint64_t *)ALIGN(old, 8);
-+ if ((uintptr_t)st.pcs >
-+ mstate->dtms_scratch_base + mstate->dtms_scratch_size) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ return 0;
-+ }
-+
-+ /*
-+ * Calculate how many (64-bit) PCs we can fit in the remaining scratch
-+ * memory.
-+ */
-+ st.limit = (mstate->dtms_scratch_base + mstate->dtms_scratch_size -
-+ (uintptr_t)st.pcs) >> 3;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_stacktrace(&st);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ mstate->dtms_scratch_ptr = old;
-+
-+ return st.depth;
-+}
-+
-+int dtrace_getustackdepth(void)
-+{
-+ return dtrace_getufpstack(NULL, NULL, INT_MAX);
-+}
-+
-+void dtrace_probe_error(struct dtrace_state *state, dtrace_epid_t epid,
-+ int act, int fltoffs, int flags, uintptr_t addr)
-+{
-+ dtrace_probe(dtrace_probeid_error, (uintptr_t)state, epid, act,
-+ fltoffs, flags, addr, 0);
-+}
-diff --git a/dtrace/dtrace_match.c b/dtrace/dtrace_match.c
-new file mode 100644
-index 000000000000..a63e3f8be1cd
---- /dev/null
-+++ b/dtrace/dtrace_match.c
-@@ -0,0 +1,364 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_match.c
-+ * DESCRIPTION: DTrace - probe match implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include "dtrace.h"
-+
-+struct dtrace_hash *dtrace_bymod;
-+struct dtrace_hash *dtrace_byfunc;
-+struct dtrace_hash *dtrace_byname;
-+
-+int dtrace_match_priv(const struct dtrace_probe *prp, uint32_t priv,
-+ kuid_t uid)
-+{
-+ if (priv != DTRACE_PRIV_ALL) {
-+ uint32_t ppriv =
-+ prp->dtpr_provider->dtpv_priv.dtpp_flags;
-+ uint32_t match = priv & ppriv;
-+
-+ if ((priv & (DTRACE_PRIV_PROC | DTRACE_PRIV_USER |
-+ DTRACE_PRIV_KERNEL)) == 0)
-+ return 0;
-+
-+ if (match == 0 && ppriv != 0)
-+ return 0;
-+
-+ if (((ppriv & ~match) & DTRACE_PRIV_OWNER) != 0 &&
-+ !uid_eq(uid, make_kuid(init_user_namespace,
-+ prp->dtpr_provider->dtpv_priv.dtpp_uid)))
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+int dtrace_match_probe(const struct dtrace_probe *prp,
-+ const struct dtrace_probekey *pkp,
-+ uint32_t priv, kuid_t uid)
-+{
-+ struct dtrace_provider *pvp = prp->dtpr_provider;
-+ int rv;
-+
-+ if (pvp->dtpv_defunct)
-+ return 0;
-+
-+ rv = pkp->dtpk_pmatch(pvp->dtpv_name, pkp->dtpk_prov, 0);
-+ if (rv <= 0)
-+ return rv;
-+
-+ rv = pkp->dtpk_mmatch(prp->dtpr_mod, pkp->dtpk_mod, 0);
-+ if (rv <= 0)
-+ return rv;
-+
-+ rv = pkp->dtpk_fmatch(prp->dtpr_func, pkp->dtpk_func, 0);
-+ if (rv <= 0)
-+ return rv;
-+
-+ rv = pkp->dtpk_nmatch(prp->dtpr_name, pkp->dtpk_name, 0);
-+ if (rv <= 0)
-+ return rv;
-+
-+ if (dtrace_match_priv(prp, priv, uid) == 0)
-+ return 0;
-+
-+ return rv;
-+}
-+
-+int dtrace_match_glob(const char *s, const char *p, int depth)
-+{
-+ const char *olds;
-+ char s1, c;
-+ int gs;
-+
-+ if (depth > DTRACE_PROBEKEY_MAXDEPTH)
-+ return -1;
-+
-+ if (s == NULL)
-+ s = "";
-+
-+top:
-+ olds = s;
-+ s1 = *s++;
-+
-+ if (p == NULL)
-+ return 0;
-+
-+ c = *p++;
-+ if (c == '\0')
-+ return s1 == '\0';
-+
-+ switch (c) {
-+ case '[':
-+ {
-+ int ok = 0, notflag = 0;
-+ char lc = '\0';
-+
-+ if (s1 == '\0')
-+ return 0;
-+
-+ if (*p == '!') {
-+ notflag = 1;
-+ p++;
-+ }
-+
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+
-+ do {
-+ if (c == '-' && lc != '\0' && *p != ']') {
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+ if (c == '\\') {
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+ }
-+ if (notflag) {
-+ if (s1 < lc || s1 > c)
-+ ok++;
-+ else
-+ return 0;
-+ } else if (lc <= s1 && s1 <= c)
-+ ok++;
-+ } else if (c == '\\') {
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+ }
-+ lc = c;
-+
-+ if (notflag) {
-+ if (s1 != c)
-+ ok++;
-+ else
-+ return 0;
-+ } else if (s1 == c)
-+ ok++;
-+
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+ } while (c != ']');
-+
-+ if (ok)
-+ goto top;
-+
-+ return 0;
-+ }
-+
-+ case '\\':
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+ /* fallthru */
-+ default:
-+ if (c != s1)
-+ return 0;
-+ /* fallthru */
-+
-+ case '?':
-+ if (s1 != '\0')
-+ goto top;
-+
-+ return 0;
-+
-+ case '*':
-+ while (*p == '*')
-+ p++;
-+
-+ if (*p == '\0')
-+ return 1;
-+
-+ for (s = olds; *s != '\0'; s++) {
-+ gs = dtrace_match_glob(s, p, depth + 1);
-+ if (gs != 0)
-+ return gs;
-+ }
-+
-+ return 0;
-+ }
-+}
-+
-+int dtrace_match_string(const char *s, const char *p, int depth)
-+{
-+ return s != NULL && strcmp(s, p) == 0;
-+}
-+
-+int dtrace_match_nul(const char *s, const char *p, int depth)
-+{
-+ return 1;
-+}
-+
-+int dtrace_match_nonzero(const char *s, const char *p, int depth)
-+{
-+ return s != NULL && s[0] != '\0';
-+}
-+
-+struct probe_match {
-+ const struct dtrace_probekey *pkp;
-+ uint32_t priv;
-+ kuid_t uid;
-+ int (*matched)(struct dtrace_probe *, void *);
-+ void *arg;
-+ int nmatched;
-+};
-+
-+static int dtrace_match_one(int id, void *p, void *data)
-+{
-+ struct probe_match *pbm = (struct probe_match *)data;
-+ struct dtrace_probe *probe = (struct dtrace_probe *)p;
-+ int rc;
-+
-+ if (dtrace_match_probe(probe, pbm->pkp, pbm->priv, pbm->uid) <= 0)
-+ return 0;
-+
-+ pbm->nmatched++;
-+
-+ rc = (pbm->matched)(probe, pbm->arg);
-+ if (rc != DTRACE_MATCH_NEXT) {
-+ if (rc == DTRACE_MATCH_FAIL)
-+ return DTRACE_MATCH_FAIL;
-+ }
-+
-+ return 0;
-+}
-+
-+int dtrace_match(const struct dtrace_probekey *pkp, uint32_t priv, kuid_t uid,
-+ int (*matched)(struct dtrace_probe *, void *), void *arg)
-+{
-+ struct dtrace_probe template, *probe;
-+ struct dtrace_hash *hash = NULL;
-+ int len, rc, best = INT_MAX, nmatched = 0;
-+
-+ if (pkp->dtpk_id != DTRACE_IDNONE) {
-+ probe = dtrace_probe_lookup_id(pkp->dtpk_id);
-+ if (probe != NULL &&
-+ dtrace_match_probe(probe, pkp, priv, uid) > 0) {
-+ if ((*matched)(probe, arg) == DTRACE_MATCH_FAIL)
-+ return DTRACE_MATCH_FAIL;
-+
-+ nmatched++;
-+ }
-+
-+ return nmatched;
-+ }
-+
-+ template.dtpr_mod = (char *)pkp->dtpk_mod;
-+ template.dtpr_func = (char *)pkp->dtpk_func;
-+ template.dtpr_name = (char *)pkp->dtpk_name;
-+
-+ if (pkp->dtpk_mmatch == &dtrace_match_string) {
-+ len = dtrace_hash_collisions(dtrace_bymod, &template);
-+ if (len < best) {
-+ best = len;
-+ hash = dtrace_bymod;
-+ }
-+ }
-+
-+ if (pkp->dtpk_fmatch == &dtrace_match_string) {
-+ len = dtrace_hash_collisions(dtrace_byfunc, &template);
-+ if (len < best) {
-+ best = len;
-+ hash = dtrace_byfunc;
-+ }
-+ }
-+
-+ if (pkp->dtpk_nmatch == &dtrace_match_string) {
-+ len = dtrace_hash_collisions(dtrace_byname, &template);
-+ if (len < best) {
-+ best = len;
-+ hash = dtrace_byname;
-+ }
-+ }
-+
-+ if (hash == NULL) {
-+ struct probe_match pbm;
-+
-+ pbm.pkp = pkp;
-+ pbm.priv = priv;
-+ pbm.uid = uid;
-+ pbm.matched = matched;
-+ pbm.arg = arg;
-+ pbm.nmatched = 0;
-+
-+ rc = dtrace_probe_for_each(dtrace_match_one, &pbm);
-+ if (rc == DTRACE_MATCH_FAIL)
-+ return DTRACE_MATCH_FAIL;
-+
-+ return pbm.nmatched;
-+ }
-+
-+ for (probe = dtrace_hash_lookup(hash, &template); probe != NULL;
-+ probe = *(DTRACE_HASHNEXT(hash, probe))) {
-+ if (dtrace_match_probe(probe, pkp, priv, uid) <= 0)
-+ continue;
-+
-+ nmatched++;
-+
-+ rc = (*matched)(probe, arg);
-+ if (rc != DTRACE_MATCH_NEXT) {
-+ if (rc == DTRACE_MATCH_FAIL)
-+ return DTRACE_MATCH_FAIL;
-+
-+ break;
-+ }
-+ }
-+
-+ return nmatched;
-+}
-+
-+static dtrace_probekey_f *dtrace_probekey_func(const char *p)
-+{
-+ char c;
-+
-+ if (p == NULL || *p == '\0')
-+ return &dtrace_match_nul;
-+
-+ while ((c = *p++) != '\0') {
-+ if (c == '[' || c == '?' || c == '*' || c == '\\')
-+ return &dtrace_match_glob;
-+ }
-+
-+ return &dtrace_match_string;
-+}
-+
-+void dtrace_probekey(const struct dtrace_probedesc *pdp,
-+ struct dtrace_probekey *pkp)
-+{
-+ pkp->dtpk_prov = pdp->dtpd_provider;
-+ pkp->dtpk_pmatch = dtrace_probekey_func(pdp->dtpd_provider);
-+
-+ pkp->dtpk_mod = pdp->dtpd_mod;
-+ pkp->dtpk_mmatch = dtrace_probekey_func(pdp->dtpd_mod);
-+
-+ pkp->dtpk_func = pdp->dtpd_func;
-+ pkp->dtpk_fmatch = dtrace_probekey_func(pdp->dtpd_func);
-+
-+ pkp->dtpk_name = pdp->dtpd_name;
-+ pkp->dtpk_nmatch = dtrace_probekey_func(pdp->dtpd_name);
-+
-+ pkp->dtpk_id = pdp->dtpd_id;
-+
-+ if (pkp->dtpk_id == DTRACE_IDNONE &&
-+ pkp->dtpk_pmatch == &dtrace_match_nul &&
-+ pkp->dtpk_mmatch == &dtrace_match_nul &&
-+ pkp->dtpk_fmatch == &dtrace_match_nul &&
-+ pkp->dtpk_nmatch == &dtrace_match_nul)
-+ pkp->dtpk_fmatch = &dtrace_match_nonzero;
-+}
-diff --git a/dtrace/dtrace_mod.c b/dtrace/dtrace_mod.c
-new file mode 100644
-index 000000000000..4da08c3cd816
---- /dev/null
-+++ b/dtrace/dtrace_mod.c
-@@ -0,0 +1,45 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_mod.c
-+ * DESCRIPTION: DTrace - framework kernel module
-+ *
-+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace_dev.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("Dynamic Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+/*
-+ * Initialize the module.
-+ */
-+static int __init dtrace_init(void)
-+{
-+ return dtrace_dev_init();
-+}
-+
-+/*
-+ * Perform cleanup before the module is removed.
-+ */
-+static void __exit dtrace_exit(void)
-+{
-+ dtrace_dev_exit();
-+}
-+
-+module_init(dtrace_init);
-+module_exit(dtrace_exit);
-diff --git a/dtrace/dtrace_predicate.c b/dtrace/dtrace_predicate.c
-new file mode 100644
-index 000000000000..004a1c542c76
---- /dev/null
-+++ b/dtrace/dtrace_predicate.c
-@@ -0,0 +1,80 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_predicate.c
-+ * DESCRIPTION: DTrace - predicate cache implementation
-+ *
-+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/slab.h>
-+
-+#include "dtrace.h"
-+
-+static dtrace_cacheid_t dtrace_predcache_id = DTRACE_CACHEIDNONE + 1;
-+
-+struct dtrace_predicate *dtrace_predicate_create(struct dtrace_difo *dp)
-+{
-+ struct dtrace_predicate *pred;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dp->dtdo_refcnt != 0);
-+
-+ pred = kzalloc(sizeof(struct dtrace_predicate), GFP_KERNEL);
-+ if (pred == NULL)
-+ return NULL;
-+
-+ pred->dtp_difo = dp;
-+ pred->dtp_refcnt = 1;
-+
-+ if (!dtrace_difo_cacheable(dp))
-+ return pred;
-+
-+ /*
-+ * This is only theoretically possible -- we have had 2^32 cacheable
-+ * predicates on this machine. We cannot allow any more predicates to
-+ * become cacheable: as unlikely as it is, there may be a thread
-+ * caching a (now stale) predicate cache ID. (N.B.: the temptation is
-+ * being successfully resisted to have this cmn_err() "Holy shit -- we
-+ * executed this code!")
-+ */
-+ if (dtrace_predcache_id == DTRACE_CACHEIDNONE)
-+ return pred;
-+
-+ pred->dtp_cacheid = dtrace_predcache_id++;
-+
-+ return pred;
-+}
-+
-+void dtrace_predicate_hold(struct dtrace_predicate *pred)
-+{
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(pred->dtp_difo != NULL && pred->dtp_difo->dtdo_refcnt != 0);
-+ ASSERT(pred->dtp_refcnt > 0);
-+
-+ pred->dtp_refcnt++;
-+}
-+
-+void dtrace_predicate_release(struct dtrace_predicate *pred,
-+ struct dtrace_vstate *vstate)
-+{
-+ struct dtrace_difo *dp = pred->dtp_difo;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dp != NULL && dp->dtdo_refcnt != 0);
-+ ASSERT(pred->dtp_refcnt > 0);
-+
-+ if (--pred->dtp_refcnt == 0) {
-+ dtrace_difo_release(dp, vstate);
-+ kfree(pred);
-+ }
-+}
-diff --git a/dtrace/dtrace_priv.c b/dtrace/dtrace_priv.c
-new file mode 100644
-index 000000000000..f50133de572d
---- /dev/null
-+++ b/dtrace/dtrace_priv.c
-@@ -0,0 +1,120 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_priv.c
-+ * DESCRIPTION: DTrace - privilege support implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+
-+#include "dtrace.h"
-+
-+/*
-+ * This privilege check should be used by actions and subroutines to
-+ * verify that the user credentials of the process that enabled the
-+ * invoking ECB match the target credentials
-+ */
-+int dtrace_priv_proc_common_user(struct dtrace_state *state)
-+{
-+ const struct cred *cr, *s_cr = state->dts_cred.dcr_cred;
-+
-+ /*
-+ * We should always have a non-NULL state cred here, since if cred
-+ * is null (anonymous tracing), we fast-path bypass this routine.
-+ */
-+ ASSERT(s_cr != NULL);
-+
-+ cr = current_cred();
-+ if (cr != NULL &&
-+ uid_eq(s_cr->euid, cr->euid) &&
-+ uid_eq(s_cr->euid, cr->uid) &&
-+ uid_eq(s_cr->euid, cr->suid) &&
-+ gid_eq(s_cr->egid, cr->egid) &&
-+ gid_eq(s_cr->egid, cr->gid) &&
-+ gid_eq(s_cr->egid, cr->sgid))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/*
-+ * This privilege check should be used by actions and subroutines to
-+ * verify that the process has not setuid or changed credentials.
-+ */
-+int dtrace_priv_proc_common_nocd(void)
-+{
-+#ifdef FIXME
-+ proc_t *proc;
-+
-+ proc = ttoproc(curthread);
-+ if (proc != NULL && !(proc->p_flag & SNOCD))
-+ return 1;
-+#endif
-+
-+ return 0;
-+}
-+
-+int dtrace_priv_proc_destructive(struct dtrace_state *state)
-+{
-+ int action = state->dts_cred.dcr_action;
-+
-+ if (((action & DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER) == 0) &&
-+ dtrace_priv_proc_common_user(state) == 0)
-+ goto bad;
-+
-+ if (((action & DTRACE_CRA_PROC_DESTRUCTIVE_CREDCHG) == 0) &&
-+ dtrace_priv_proc_common_nocd() == 0)
-+ goto bad;
-+
-+ return 1;
-+
-+bad:
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_UPRIV);
-+
-+ return 0;
-+}
-+
-+int dtrace_priv_proc_control(struct dtrace_state *state)
-+{
-+ if (state->dts_cred.dcr_action & DTRACE_CRA_PROC_CONTROL)
-+ return 1;
-+
-+ if (dtrace_priv_proc_common_user(state) &&
-+ dtrace_priv_proc_common_nocd())
-+ return 1;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_UPRIV);
-+
-+ return 0;
-+}
-+
-+int dtrace_priv_proc(struct dtrace_state *state)
-+{
-+ if (state->dts_cred.dcr_action & DTRACE_CRA_PROC)
-+ return 1;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_UPRIV);
-+
-+ return 0;
-+}
-+
-+int dtrace_priv_kernel(struct dtrace_state *state)
-+{
-+ if (state->dts_cred.dcr_action & DTRACE_CRA_KERNEL)
-+ return 1;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
-+
-+ return 0;
-+}
-diff --git a/dtrace/dtrace_probe.c b/dtrace/dtrace_probe.c
-new file mode 100644
-index 000000000000..8e2e04cb9c13
---- /dev/null
-+++ b/dtrace/dtrace_probe.c
-@@ -0,0 +1,1542 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_probe.c
-+ * DESCRIPTION: DTrace - probe implementation
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/hardirq.h>
-+#include <linux/highmem.h>
-+#include <linux/idr.h>
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <asm/pgtable.h>
-+#include <asm/cmpxchg.h>
-+#include <linux/sched/signal.h>
-+
-+#include "dtrace.h"
-+
-+ktime_t dtrace_chill_interval =
-+ KTIME_INIT(1, 0);
-+ktime_t dtrace_chill_max =
-+ KTIME_INIT(0,
-+ 500 * (NANOSEC / MILLISEC));
-+
-+dtrace_genid_t dtrace_probegen;
-+struct kmem_cache *dtrace_probe_cachep;
-+
-+static struct idr dtrace_probe_idr;
-+
-+static struct task_struct *dtrace_panicked;
-+
-+/*
-+ * Free probe structure (including partially filled in ones).
-+ */
-+void dtrace_probe_free(struct dtrace_probe *probe)
-+{
-+ if (probe == NULL)
-+ return;
-+
-+ dtrace_probe_remove_id(probe->dtpr_id);
-+
-+ kfree(probe->dtpr_mod);
-+ kfree(probe->dtpr_func);
-+ kfree(probe->dtpr_name);
-+
-+ kmem_cache_free(dtrace_probe_cachep, probe);
-+}
-+
-+/*
-+ * Create a new probe.
-+ */
-+dtrace_id_t dtrace_probe_create(dtrace_provider_id_t prov, const char *mod,
-+ const char *func, const char *name,
-+ int aframes, void *arg)
-+{
-+ struct dtrace_probe *probe;
-+ struct dtrace_provider *provider = (struct dtrace_provider *)prov;
-+ dtrace_id_t id;
-+
-+ probe = kmem_cache_alloc(dtrace_probe_cachep, GFP_KERNEL);
-+ if (probe == NULL)
-+ goto err_probe;
-+
-+ /*
-+ * The idr_preload() should be called without holding locks as it may
-+ * block. At the same time it is required to protect DTrace structures.
-+ * We can't drop it before idr_preload() and acquire after it because
-+ * we can't sleep in atomic context (until we reach idr_preload_end()).
-+ *
-+ * It is better to delay DTrace framework than traced host so the lock
-+ * is being held for the duration of idr allocation.
-+ *
-+ * When the provider is the DTrace core itself, dtrace_lock will be
-+ * held when we enter this function.
-+ */
-+ if (provider == dtrace_provider)
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ else
-+ mutex_lock(&dtrace_lock);
-+
-+ idr_preload(GFP_KERNEL);
-+ id = idr_alloc_cyclic(&dtrace_probe_idr, probe, 0, 0, GFP_NOWAIT);
-+ idr_preload_end();
-+ if (id < 0)
-+ goto err_probe;
-+
-+ probe->dtpr_id = id;
-+ probe->dtpr_ecb = NULL;
-+ probe->dtpr_ecb_last = NULL;
-+ probe->dtpr_arg = arg;
-+ probe->dtpr_predcache = DTRACE_CACHEIDNONE;
-+ probe->dtpr_aframes = aframes;
-+ probe->dtpr_provider = provider;
-+
-+ probe->dtpr_mod = dtrace_strdup(mod);
-+ if (probe->dtpr_mod == NULL)
-+ goto err_probe;
-+
-+ probe->dtpr_func = dtrace_strdup(func);
-+ if (probe->dtpr_func == NULL)
-+ goto err_probe;
-+
-+ probe->dtpr_name = dtrace_strdup(name);
-+ if (probe->dtpr_name == NULL)
-+ goto err_probe;
-+
-+ probe->dtpr_nextmod = probe->dtpr_prevmod = NULL;
-+ probe->dtpr_nextfunc = probe->dtpr_prevfunc = NULL;
-+ probe->dtpr_nextname = probe->dtpr_prevname = NULL;
-+ probe->dtpr_gen = dtrace_probegen++;
-+
-+ if (dtrace_hash_add(dtrace_bymod, probe) != 0)
-+ goto err_probe;
-+
-+ if (dtrace_hash_add(dtrace_byfunc, probe) != 0)
-+ goto err_hash_byfunc;
-+
-+ if (dtrace_hash_add(dtrace_byname, probe) != 0)
-+ goto err_hash_byname;
-+
-+ if (provider != dtrace_provider)
-+ mutex_unlock(&dtrace_lock);
-+
-+ return id;
-+
-+err_hash_byname:
-+ dtrace_hash_remove(dtrace_byfunc, probe);
-+err_hash_byfunc:
-+ dtrace_hash_remove(dtrace_bymod, probe);
-+err_probe:
-+ dtrace_probe_free(probe);
-+ if (provider != dtrace_provider)
-+ mutex_unlock(&dtrace_lock);
-+ return DTRACE_IDNONE;
-+}
-+EXPORT_SYMBOL(dtrace_probe_create);
-+
-+int dtrace_probe_enable(const struct dtrace_probedesc *desc,
-+ struct dtrace_enabling *enab)
-+{
-+ struct dtrace_probekey pkey;
-+ uint32_t priv;
-+ kuid_t uid;
-+
-+ dtrace_ecb_create_cache = NULL;
-+
-+ if (desc == NULL) {
-+ (void) dtrace_ecb_create_enable(NULL, enab);
-+
-+ return 0;
-+ }
-+
-+ dtrace_probekey(desc, &pkey);
-+ dtrace_cred2priv(enab->dten_vstate->dtvs_state->dts_cred.dcr_cred,
-+ &priv, &uid);
-+
-+ return dtrace_match(&pkey, priv, uid, dtrace_ecb_create_enable, enab);
-+}
-+
-+/*
-+ * Return the probe argument associated with the specified probe.
-+ */
-+void *dtrace_probe_arg(dtrace_provider_id_t id, dtrace_id_t pid)
-+{
-+ struct dtrace_probe *probe;
-+ void *rval = NULL;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ probe = dtrace_probe_lookup_id(pid);
-+ if (probe != NULL &&
-+ probe->dtpr_provider == (struct dtrace_provider *)id)
-+ rval = probe->dtpr_arg;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ return rval;
-+}
-+EXPORT_SYMBOL(dtrace_probe_arg);
-+
-+/*
-+ * Copy a probe into a probe description.
-+ */
-+void dtrace_probe_description(const struct dtrace_probe *prp,
-+ struct dtrace_probedesc *pdp)
-+{
-+ memset(pdp, 0, sizeof(struct dtrace_probedesc));
-+ pdp->dtpd_id = prp->dtpr_id;
-+
-+ strncpy(pdp->dtpd_provider, prp->dtpr_provider->dtpv_name,
-+ DTRACE_PROVNAMELEN - 1);
-+
-+ strncpy(pdp->dtpd_mod, prp->dtpr_mod, DTRACE_MODNAMELEN - 1);
-+ strncpy(pdp->dtpd_func, prp->dtpr_func, DTRACE_FUNCNAMELEN - 1);
-+ strncpy(pdp->dtpd_name, prp->dtpr_name, DTRACE_NAMELEN - 1);
-+}
-+
-+void dtrace_probe_provide(struct dtrace_probedesc *desc,
-+ struct dtrace_provider *prv)
-+{
-+ int all = 0;
-+
-+ if (prv == NULL) {
-+ all = 1;
-+ prv = dtrace_provider;
-+ }
-+
-+ do {
-+ prv->dtpv_pops.dtps_provide(prv->dtpv_arg, desc);
-+ dtrace_for_each_module(prv->dtpv_pops.dtps_provide_module,
-+ prv->dtpv_arg);
-+ } while (all && (prv = prv->dtpv_next) != NULL);
-+}
-+
-+/*
-+ * Atomically increment a specified error counter from probe context.
-+ */
-+static void dtrace_error(uint32_t *counter)
-+{
-+ /*
-+ * Most counters stored to in probe context are per-CPU counters.
-+ * However, there are some error conditions that are sufficiently
-+ * arcane that they don't merit per-CPU storage. If these counters
-+ * are incremented concurrently on different CPUs, scalability will be
-+ * adversely affected -- but we don't expect them to be white-hot in a
-+ * correctly constructed enabling...
-+ */
-+ uint32_t oval, nval;
-+
-+ do {
-+ oval = *counter;
-+
-+ nval = oval + 1;
-+ if (nval == 0) {
-+ /*
-+ * If the counter would wrap, set it to 1 -- assuring
-+ * that the counter is never zero when we have seen
-+ * errors. (The counter must be 32-bits because we
-+ * aren't guaranteed a 64-bit compare&swap operation.)
-+ * To save this code both the infamy of being fingered
-+ * by a priggish news story and the indignity of being
-+ * the target of a neo-puritan witch trial, we're
-+ * carefully avoiding any colorful description of the
-+ * likelihood of this condition -- but suffice it to
-+ * say that it is only slightly more likely than the
-+ * overflow of predicate cache IDs, as discussed in
-+ * dtrace_predicate_create().
-+ */
-+ nval = 1;
-+ }
-+ } while (cmpxchg(counter, oval, nval) != oval);
-+}
-+
-+static int dtrace_priv_kernel_destructive(struct dtrace_state *state)
-+{
-+ if (state->dts_cred.dcr_action & DTRACE_CRA_KERNEL_DESTRUCTIVE)
-+ return 1;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
-+
-+ return 0;
-+}
-+
-+static void dtrace_action_breakpoint(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_probe *probe = ecb->dte_probe;
-+ struct dtrace_provider *prov = probe->dtpr_provider;
-+ char c[DTRACE_FULLNAMELEN + 80], *str;
-+ char *msg = "dtrace: breakpoint action at probe ";
-+ char *ecbmsg = " (ecb ";
-+ uintptr_t mask = (0xf << (sizeof(uintptr_t) * NBBY / 4));
-+ uintptr_t val = (uintptr_t)ecb;
-+ int shift = (sizeof(uintptr_t) * NBBY) - 4, i = 0;
-+
-+ if (dtrace_destructive_disallow)
-+ return;
-+
-+ /*
-+ * It's impossible to be taking action on the NULL probe.
-+ */
-+ ASSERT(probe != NULL);
-+
-+ /*
-+ * This is a poor man's (destitute man's?) sprintf(): we want to
-+ * print the provider name, module name, function name and name of
-+ * the probe, along with the hex address of the ECB with the breakpoint
-+ * action -- all of which we must place in the character buffer by
-+ * hand.
-+ */
-+ while (*msg != '\0')
-+ c[i++] = *msg++;
-+
-+ for (str = prov->dtpv_name; *str != '\0'; str++)
-+ c[i++] = *str;
-+ c[i++] = ':';
-+
-+ for (str = probe->dtpr_mod; *str != '\0'; str++)
-+ c[i++] = *str;
-+ c[i++] = ':';
-+
-+ for (str = probe->dtpr_func; *str != '\0'; str++)
-+ c[i++] = *str;
-+ c[i++] = ':';
-+
-+ for (str = probe->dtpr_name; *str != '\0'; str++)
-+ c[i++] = *str;
-+
-+ while (*ecbmsg != '\0')
-+ c[i++] = *ecbmsg++;
-+
-+ while (shift >= 0) {
-+ mask = (uintptr_t)0xf << shift;
-+
-+ if (val >= ((uintptr_t)1 << shift))
-+ c[i++] = "0123456789abcdef"[(val & mask) >> shift];
-+
-+ shift -= 4;
-+ }
-+
-+ c[i++] = ')';
-+ c[i] = '\0';
-+
-+// debug_enter(c); /* FIXME */
-+}
-+
-+static void dtrace_action_panic(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_probe *probe = ecb->dte_probe;
-+
-+ /*
-+ * It's impossible to be taking action on the NULL probe.
-+ */
-+ ASSERT(probe != NULL);
-+
-+ if (dtrace_destructive_disallow)
-+ return;
-+
-+ if (dtrace_panicked != NULL)
-+ return;
-+
-+ if (cmpxchg(&dtrace_panicked, NULL, current) != NULL)
-+ return;
-+
-+ /*
-+ * We won the right to panic. (We want to be sure that only one
-+ * thread calls panic() from dtrace_probe(), and that panic() is
-+ * called exactly once.)
-+ */
-+ dtrace_panic(KERN_EMERG
-+ "dtrace: panic action at probe %s:%s:%s:%s (ecb %p)",
-+ probe->dtpr_provider->dtpv_name, probe->dtpr_mod,
-+ probe->dtpr_func, probe->dtpr_name, (void *)ecb);
-+}
-+
-+static void dtrace_action_raise(uint64_t sig)
-+{
-+ if (current->dt_task == NULL)
-+ return;
-+
-+ if (dtrace_destructive_disallow)
-+ return;
-+
-+ if (sig >= _NSIG) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return;
-+ }
-+
-+ /*
-+ * raise() has a queue depth of 1 -- we ignore all subsequent
-+ * invocations of the raise() action.
-+ */
-+ if (current->dt_task->dt_sig == 0)
-+ current->dt_task->dt_sig = (uint8_t)sig;
-+}
-+
-+static void dtrace_action_stop(void)
-+{
-+ if (current->dt_task == NULL)
-+ return;
-+
-+ if (dtrace_destructive_disallow)
-+ return;
-+
-+ if (!current->dt_task->dt_stop) {
-+ current->dt_task->dt_stop = 1;
-+// current->sig_check = 1; /* FIXME */
-+// aston(current); /* FIXME */
-+ }
-+}
-+
-+static void dtrace_action_chill(struct dtrace_mstate *mstate, ktime_t val)
-+{
-+ ktime_t now;
-+ volatile uint16_t *flags;
-+ struct cpu_core *cpu = this_cpu_core;
-+
-+ if (dtrace_destructive_disallow)
-+ return;
-+
-+ flags = (volatile uint16_t *)&cpu->cpuc_dtrace_flags;
-+
-+ now = dtrace_gethrtime();
-+
-+ if (ktime_gt(ktime_sub(now, cpu->cpu_dtrace_chillmark),
-+ dtrace_chill_interval)) {
-+ /*
-+ * We need to advance the mark to current time.
-+ */
-+ cpu->cpu_dtrace_chillmark = now;
-+ cpu->cpu_dtrace_chilled = ktime_set(0, 0);
-+ }
-+
-+ /*
-+ * Now check to see if the requested chill time would take us over
-+ * the maximum amount of time allowed in the chill interval. (Or
-+ * worse, if the calculation itself induces overflow.)
-+ */
-+ if (ktime_gt(ktime_add(cpu->cpu_dtrace_chilled, val),
-+ dtrace_chill_max) ||
-+ ktime_lt(ktime_add(cpu->cpu_dtrace_chilled, val),
-+ cpu->cpu_dtrace_chilled)) {
-+ *flags |= CPU_DTRACE_ILLOP;
-+ return;
-+ }
-+
-+ while (ktime_lt(ktime_sub(dtrace_gethrtime(), now), val))
-+ continue;
-+
-+ /*
-+ * Normally, we assure that the value of the variable "timestamp" does
-+ * not change within an ECB. The presence of chill() represents an
-+ * exception from this rule, however.
-+ */
-+ mstate->dtms_present &= ~DTRACE_MSTATE_TIMESTAMP;
-+ cpu->cpu_dtrace_chilled = ktime_add(cpu->cpu_dtrace_chilled, val);
-+}
-+
-+static void dtrace_action_ustack(struct dtrace_mstate *mstate,
-+ struct dtrace_state *state, uint64_t *buf,
-+ uint64_t arg)
-+{
-+ int nframes = DTRACE_USTACK_NFRAMES(arg);
-+ int strsize = DTRACE_USTACK_STRSIZE(arg);
-+ uint64_t *pcs = &buf[2], *fps;
-+ char *str = (char *)&pcs[nframes];
-+ int size, offs = 0, i, j;
-+ uintptr_t old = mstate->dtms_scratch_ptr, saved;
-+ uint16_t *flags = &this_cpu_core->cpuc_dtrace_flags;
-+ char *sym;
-+
-+ /*
-+ * Should be taking a faster path if string space has not been
-+ * allocated.
-+ */
-+ ASSERT(strsize != 0);
-+
-+ /*
-+ * We will first allocate some temporary space for the frame pointers.
-+ */
-+ fps = (uint64_t *)P2ROUNDUP(mstate->dtms_scratch_ptr, 8);
-+ size = (uintptr_t)fps - mstate->dtms_scratch_ptr +
-+ (nframes * sizeof(uint64_t));
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ /*
-+ * Not enough room for our frame pointers -- need to indicate
-+ * that we ran out of scratch space.
-+ */
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ return;
-+ }
-+
-+ mstate->dtms_scratch_ptr += size;
-+ saved = mstate->dtms_scratch_ptr;
-+
-+ /*
-+ * Now get a stack with both program counters and frame pointers.
-+ */
-+ dtrace_getufpstack(buf, fps, nframes + 2);
-+
-+ /*
-+ * If that faulted, we're cooked.
-+ */
-+ if (*flags & CPU_DTRACE_FAULT)
-+ goto out;
-+
-+ /*
-+ * Now we want to walk up the stack, calling the USTACK helper. For
-+ * each iteration, we restore the scratch pointer.
-+ */
-+ for (i = 0; i < nframes; i++) {
-+ mstate->dtms_scratch_ptr = saved;
-+
-+ if (offs >= strsize)
-+ break;
-+
-+ sym = (char *)(uintptr_t)dtrace_helper(
-+ DTRACE_HELPER_ACTION_USTACK,
-+ mstate, state, pcs[i], fps[i]);
-+
-+ /*
-+ * If we faulted while running the helper, we're going to
-+ * clear the fault and null out the corresponding string.
-+ */
-+ if (*flags & CPU_DTRACE_FAULT) {
-+ *flags &= ~CPU_DTRACE_FAULT;
-+ str[offs++] = '\0';
-+ continue;
-+ }
-+
-+ if (sym == NULL) {
-+ str[offs++] = '\0';
-+ continue;
-+ }
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+
-+ /*
-+ * Now copy in the string that the helper returned to us.
-+ */
-+ for (j = 0; offs + j < strsize; j++) {
-+ str[offs + j] = sym[j];
-+ if (str[offs + j] == '\0')
-+ break;
-+ }
-+
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ offs += j + 1;
-+ }
-+
-+ /*
-+ * If we didn't have room for all of the strings, we don't abort
-+ * processing -- this needn't be a fatal error -- but we still want
-+ * to increment a counter (dts_stkstroverflows) to allow this condition
-+ * to be warned about. (If this is from a jstack() action, it is
-+ * easily tuned via jstackstrsize.)
-+ */
-+ if (offs >= strsize)
-+ dtrace_error(&state->dts_stkstroverflows);
-+
-+ while (offs < strsize)
-+ str[offs++] = '\0';
-+
-+out:
-+ mstate->dtms_scratch_ptr = old;
-+}
-+
-+/*
-+ * This macro is used by dtrace_probe_pcap() below. See linux/skbuff.h for the
-+ * original. Only change is we pass in an already dereferenced page.p as
-+ * the fragment f.
-+ */
-+#define dtrace_skb_frag_foreach_page(f, f_off, f_len, p, p_off, p_len, copied) \
-+ for (p = f + ((f_off) >> PAGE_SHIFT), \
-+ p_off = (f_off) & (PAGE_SIZE - 1), \
-+ p_len = skb_frag_must_loop(p) ? \
-+ min_t(u32, f_len, PAGE_SIZE - p_off) : f_len, \
-+ copied = 0; \
-+ copied < f_len; \
-+ copied += p_len, p++, p_off = 0, \
-+ p_len = min_t(u32, f_len - copied, PAGE_SIZE)) \
-+
-+
-+/*
-+ * Capture skb data in linear and non-linear portions. Returns 0 on success,
-+ * -1 if an error is encountered.
-+ */
-+static __always_inline int dtrace_probe_pcap(uint64_t val, size_t *valoffs,
-+ size_t size, caddr_t tomax,
-+ ktime_t now,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate,
-+ volatile uint16_t *flags)
-+
-+{
-+ uintptr_t start = *valoffs, end = *valoffs + size;
-+ uintptr_t skb_head, skb_data, skb_tail, shinfo;
-+ uint32_t skb_end, tail, skb_len = 0;
-+ uintptr_t baddr = val;
-+ uint8_t nr_frags, f;
-+ uint32_t data_len;
-+
-+ DTRACE_STORE(uint64_t, tomax, start, ktime_to_ns(now));
-+
-+ *valoffs += (2 * sizeof(uint64_t));
-+
-+ /*
-+ * Skip capture of NULL skbs.
-+ */
-+ if ((void *)baddr == NULL)
-+ goto pcap_done;
-+
-+ if (!dtrace_canload(baddr, sizeof(struct sk_buff), mstate, vstate))
-+ return -1;
-+
-+ skb_data = dtrace_loadptr(baddr + offsetof(struct sk_buff, data));
-+ skb_head = dtrace_loadptr(baddr + offsetof(struct sk_buff, head));
-+ skb_len = dtrace_load32(baddr + offsetof(struct sk_buff, len));
-+ tail = dtrace_load32(baddr + offsetof(struct sk_buff, tail));
-+ skb_tail = skb_head + tail;
-+
-+ if (skb_tail < skb_data) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ return -1;
-+ }
-+ while (*valoffs < end && skb_data < skb_tail) {
-+ DTRACE_STORE(uint8_t, tomax, (*valoffs)++,
-+ dtrace_load8(skb_data++));
-+ }
-+
-+ data_len = dtrace_load32(baddr + offsetof(struct sk_buff, data_len));
-+
-+ /*
-+ * If skb is linear, no need to explore fragments.
-+ */
-+ if (data_len == 0)
-+ goto pcap_done;
-+
-+ skb_end = dtrace_load32(baddr + offsetof(struct sk_buff, end));
-+ shinfo = skb_head + skb_end;
-+
-+ if (!dtrace_canload(shinfo, sizeof(struct skb_shared_info),
-+ mstate, vstate))
-+ return -1;
-+
-+ nr_frags = dtrace_load8(shinfo + offsetof(struct skb_shared_info,
-+ nr_frags));
-+
-+ /*
-+ * See skb_frag_foreach_page() macro usage elsewhere to understand the
-+ * manipulations here; the reason we need this complexity is to support
-+ * compound pages.
-+ */
-+ for (f = 0; f < nr_frags; f++) {
-+ uint32_t poff, plen, copied, flen;
-+ struct page *p, *frag;
-+ uintptr_t foff, v;
-+ void *vaddr;
-+
-+ flen = dtrace_load32(shinfo + offsetof(struct skb_shared_info,
-+ frags[f].bv_len));
-+ foff = dtrace_load32(shinfo + offsetof(struct skb_shared_info,
-+ frags[f].bv_offset));
-+ frag = (struct page *)dtrace_loadptr(shinfo + offsetof(
-+ struct skb_shared_info,
-+ frags[f].bv_page));
-+
-+ dtrace_skb_frag_foreach_page(frag, foff, flen,
-+ p, poff, plen, copied) {
-+ if (data_len == 0)
-+ break;
-+
-+ vaddr = kmap_atomic(p);
-+ v = (uintptr_t)vaddr + poff;
-+ if (!dtrace_canload(v, plen, mstate, vstate)) {
-+ kunmap_atomic(vaddr);
-+ return -1;
-+ }
-+ while (*valoffs < end && data_len-- > 0) {
-+ DTRACE_STORE(uint8_t, tomax, (*valoffs)++,
-+ dtrace_load8(v++));
-+ }
-+ kunmap_atomic(vaddr);
-+ }
-+ }
-+
-+pcap_done:
-+ /*
-+ * Note that we store the skb len here rather than the portion of it we
-+ * capture; we can determine the latter when collecting data by using
-+ * the "pcapsize" option. Packet capture headers specify a packet size
-+ * and a capture size, so we want to be able to provide both. Since
-+ * the capture size can be determined from the packet length when
-+ * consuming records, we don't need to store it.
-+ */
-+ DTRACE_STORE(uint64_t, tomax, start + sizeof(uint64_t),
-+ (uint64_t)skb_len);
-+
-+ return 0;
-+}
-+void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
-+ uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
-+ uintptr_t arg5, uintptr_t arg6)
-+{
-+ processorid_t cpuid;
-+ dtrace_icookie_t cookie;
-+ struct dtrace_probe *probe;
-+ struct dtrace_mstate mstate;
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_action *act;
-+ intptr_t offs;
-+ size_t size;
-+ int onintr;
-+ int vtime;
-+ volatile uint16_t *flags;
-+ ktime_t now;
-+ uint32_t re_entry;
-+ struct dtrace_task *dtsk = current->dt_task;
-+ dtrace_id_t old_id;
-+
-+#ifdef FIXME
-+ /*
-+ * Kick out immediately if this CPU is still being born (in which case
-+ * curthread will be set to -1) or the current thread can't allow
-+ * probes in its current context.
-+ */
-+ if (((uintptr_t)curthread & 1) || (curthread->t_flag & T_DONTDTRACE))
-+ return;
-+#endif
-+
-+ DTRACE_SYNC_ENTER_CRITICAL(cookie, re_entry);
-+
-+ /*
-+ * Probe context is not re-entrant, unless we're getting called to
-+ * process an ERROR probe.
-+ */
-+ flags = (volatile uint16_t *)&this_cpu_core->cpuc_dtrace_flags;
-+ cpuid = smp_processor_id();
-+ if (re_entry && id != dtrace_probeid_error) {
-+ dt_dbg_probe("Attempt to fire probe from within a probe " \
-+ "(ID %d, oID %d, CPU %d)\n", id,
-+ (int)this_cpu_core->cpuc_current_probe, cpuid);
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+ return;
-+ }
-+
-+ probe = dtrace_probe_lookup_id(id);
-+ onintr = in_interrupt();
-+
-+ if (!onintr && probe->dtpr_predcache != DTRACE_CACHEIDNONE &&
-+ dtsk != NULL && probe->dtpr_predcache == dtsk->dt_predcache) {
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+ return;
-+ }
-+
-+ if (oops_in_progress) {
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+ return;
-+ }
-+
-+ old_id = this_cpu_core->cpuc_current_probe;
-+ this_cpu_core->cpuc_current_probe = id;
-+
-+ now = dtrace_gethrtime();
-+ vtime = (dtrace_vtime_references > 0);
-+
-+ if (vtime && dtsk != NULL && ktime_nz(dtsk->dt_start))
-+ dtsk->dt_vtime = ktime_add(dtsk->dt_vtime,
-+ ktime_sub(now, dtsk->dt_start));
-+
-+ mstate.dtms_difo = NULL;
-+ mstate.dtms_probe = probe;
-+ mstate.dtms_strtok = (uintptr_t)NULL;
-+ mstate.dtms_arg[0] = arg0;
-+ mstate.dtms_arg[1] = arg1;
-+ mstate.dtms_arg[2] = arg2;
-+ mstate.dtms_arg[3] = arg3;
-+ mstate.dtms_arg[4] = arg4;
-+ mstate.dtms_arg[5] = arg5;
-+ mstate.dtms_arg[6] = arg6;
-+
-+ for (ecb = probe->dtpr_ecb; ecb != NULL; ecb = ecb->dte_next) {
-+ struct dtrace_predicate *pred = ecb->dte_predicate;
-+ struct dtrace_state *state = ecb->dte_state;
-+ struct dtrace_buffer *buf = &state->dts_buffer[cpuid];
-+ struct dtrace_buffer *aggbuf = &state->dts_aggbuffer[cpuid];
-+ struct dtrace_vstate *vstate = &state->dts_vstate;
-+ struct dtrace_provider *prov = probe->dtpr_provider;
-+ int committed = 0;
-+ caddr_t tomax;
-+
-+ /*
-+ * A little subtlety with the following (seemingly innocuous)
-+ * declaration of the automatic 'val': by looking at the
-+ * code, you might think that it could be declared in the
-+ * action processing loop, below. (That is, it's only used in
-+ * the action processing loop.) However, it must be declared
-+ * out of that scope because in the case of DIF expression
-+ * arguments to aggregating actions, one iteration of the
-+ * action loop will use the last iteration's value.
-+ */
-+ uint64_t val = 0;
-+
-+ mstate.dtms_present = DTRACE_MSTATE_ARGS | DTRACE_MSTATE_PROBE;
-+ *flags &= ~CPU_DTRACE_ERROR;
-+
-+ if (prov == dtrace_provider) {
-+ /*
-+ * If dtrace itself is the provider of this probe,
-+ * we're only going to continue processing the ECB if
-+ * arg0 (the dtrace_state_t) is equal to the ECB's
-+ * creating state. (This prevents disjoint consumers
-+ * from seeing one another's metaprobes.)
-+ */
-+ if (arg0 != (uint64_t)(uintptr_t)state)
-+ continue;
-+ }
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_ACTIVE) {
-+ /*
-+ * We're not currently active. If our provider isn't
-+ * the dtrace pseudo provider, we're not interested.
-+ */
-+ if (prov != dtrace_provider)
-+ continue;
-+
-+ /*
-+ * Now we must further check if we are in the BEGIN
-+ * probe. If we are, we will only continue orocessing
-+ * if we're still in WARMUP -- if one BEGIN enabling
-+ * has invoked the exit() action, we don't want to
-+ * evaluate subsequent BEGIN enablings.
-+ */
-+ if (probe->dtpr_id == dtrace_probeid_begin &&
-+ state->dts_activity != DTRACE_ACTIVITY_WARMUP) {
-+ ASSERT(state->dts_activity ==
-+ DTRACE_ACTIVITY_DRAINING);
-+ continue;
-+ }
-+ }
-+
-+ dt_dbg_probe("Probe (ID %d EPID %d) on CPU %d...\n",
-+ id, ecb->dte_epid, cpuid);
-+ if (ecb->dte_cond) {
-+ /*
-+ * If the dte_cond bits indicate that this
-+ * consumer is only allowed to see user-mode firings
-+ * of this probe, call the provider's dtps_usermode()
-+ * entry point to check that the probe was fired
-+ * while in a user context. Skip this ECB if that's
-+ * not the case.
-+ */
-+ if ((ecb->dte_cond & DTRACE_COND_USERMODE) &&
-+ prov->dtpv_pops.dtps_usermode(
-+ prov->dtpv_arg, probe->dtpr_id, probe->dtpr_arg
-+ ) == 0) {
-+ dt_dbg_probe("Probe (ID %d EPID %d) Skipped\n",
-+ id, ecb->dte_epid);
-+ continue;
-+ }
-+
-+ /*
-+ * This is more subtle than it looks. We have to be
-+ * absolutely certain that current_cred() isn't going
-+ * to change out from under us so it's only legit to
-+ * examine that structure if we're in constrained
-+ * situations. Currently, the only times we'll use this
-+ * check is if a non-super-user has enabled the
-+ * profile or syscall providers -- providers that
-+ * allow visibility of all processes. For the
-+ * profile case, the check above will ensure that
-+ * we're examining a user context.
-+ */
-+ if (ecb->dte_cond & DTRACE_COND_OWNER) {
-+ const struct cred *cr;
-+ const struct cred *s_cr =
-+ ecb->dte_state->dts_cred.dcr_cred;
-+
-+ ASSERT(s_cr != NULL);
-+
-+ cr = current_cred();
-+ if (cr == NULL ||
-+ !uid_eq(s_cr->euid, cr->euid) ||
-+ !uid_eq(s_cr->euid, cr->uid) ||
-+ !uid_eq(s_cr->euid, cr->suid) ||
-+ !gid_eq(s_cr->egid, cr->egid) ||
-+ !gid_eq(s_cr->egid, cr->gid) ||
-+ !gid_eq(s_cr->egid, cr->sgid)) {
-+ dt_dbg_probe("Probe (ID %d EPID %d) "
-+ "Skipped\n",
-+ id, ecb->dte_epid);
-+ continue;
-+ }
-+ }
-+ }
-+
-+ if (ktime_gt(ktime_sub(now, state->dts_alive),
-+ dtrace_deadman_timeout)) {
-+ /*
-+ * We seem to be dead. Unless we (a) have kernel
-+ * destructive permissions (b) have expicitly enabled
-+ * destructive actions and (c) destructive actions have
-+ * not been disabled, we're going to transition into
-+ * the KILLED state, from which no further processing
-+ * on this state will be performed.
-+ */
-+ if (!dtrace_priv_kernel_destructive(state) ||
-+ !state->dts_cred.dcr_destructive ||
-+ dtrace_destructive_disallow) {
-+ enum dtrace_activity *activity =
-+ &state->dts_activity;
-+ enum dtrace_activity curr;
-+
-+ do {
-+ curr = state->dts_activity;
-+ } while (cmpxchg(activity, curr,
-+ DTRACE_ACTIVITY_KILLED) != curr);
-+
-+ dt_dbg_probe("Probe (ID %d EPID %d) Skipped\n",
-+ id, ecb->dte_epid);
-+ continue;
-+ }
-+ }
-+
-+ offs = dtrace_buffer_reserve(buf, ecb->dte_needed,
-+ ecb->dte_alignment, state,
-+ &mstate);
-+ if (offs < 0) {
-+ dt_dbg_probe("Probe (ID %d EPID %d) Skipped\n",
-+ id, ecb->dte_epid);
-+ continue;
-+ }
-+
-+ tomax = buf->dtb_tomax;
-+ ASSERT(tomax != NULL);
-+
-+ if (ecb->dte_size != 0) {
-+ DTRACE_STORE(uint32_t, tomax, offs, ecb->dte_epid);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- %d [EPID] "
-+ "(from %s::%d)\n",
-+ buf, offs, offs + sizeof(uint32_t) - 1,
-+ ecb->dte_epid, __func__, __LINE__);
-+ }
-+
-+ mstate.dtms_epid = ecb->dte_epid;
-+ mstate.dtms_present |= DTRACE_MSTATE_EPID;
-+
-+ if (state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL)
-+ mstate.dtms_access = DTRACE_ACCESS_KERNEL;
-+ else
-+ mstate.dtms_access = 0;
-+
-+ if (pred != NULL) {
-+ struct dtrace_difo *dp = pred->dtp_difo;
-+ int rval;
-+
-+ dt_dbg_probe(" Evaluating predicate...\n");
-+
-+ rval = dtrace_dif_emulate(dp, &mstate, vstate, state);
-+
-+ if (!(*flags & CPU_DTRACE_ERROR) && !rval) {
-+ dtrace_cacheid_t cid =
-+ probe->dtpr_predcache;
-+
-+ if (cid != DTRACE_CACHEIDNONE && !onintr) {
-+ /*
-+ * Update the predicate cache...
-+ */
-+ ASSERT(cid == pred->dtp_cacheid);
-+ if (dtsk != NULL)
-+ dtsk->dt_predcache = cid;
-+ }
-+
-+ dt_dbg_probe(" Predicate not met (%d)\n",
-+ rval);
-+ dt_dbg_probe("Probe (ID %d EPID %d) Done\n",
-+ id, ecb->dte_epid);
-+ continue;
-+ }
-+
-+ dt_dbg_probe(" Predicate met (%d)\n", rval);
-+ }
-+
-+ for (act = ecb->dte_action;
-+ !(*flags & CPU_DTRACE_ERROR) && act != NULL;
-+ act = act->dta_next) {
-+ size_t valoffs;
-+ struct dtrace_difo *dp;
-+ struct dtrace_recdesc *rec = &act->dta_rec;
-+
-+ dt_dbg_probe(" Evaluating action %p (kind %d)...\n",
-+ act, act->dta_kind);
-+
-+ size = rec->dtrd_size;
-+ valoffs = offs + rec->dtrd_offset;
-+
-+ if (DTRACEACT_ISAGG(act->dta_kind)) {
-+ uint64_t v = 0xbad;
-+ struct dtrace_aggregation *agg;
-+
-+ agg = (struct dtrace_aggregation *)act;
-+
-+ dp = act->dta_difo;
-+ if (dp != NULL)
-+ v = dtrace_dif_emulate(dp, &mstate,
-+ vstate, state);
-+
-+ if (*flags & CPU_DTRACE_ERROR)
-+ continue;
-+
-+ /*
-+ * Note that we always pass the expression
-+ * value from the previous iteration of the
-+ * action loop. This value will only be used
-+ * if there is an expression argument to the
-+ * aggregating action, denoted by the
-+ * dtag_hasarg field.
-+ */
-+ dtrace_aggregate(agg, buf, offs, aggbuf, v,
-+ val);
-+ continue;
-+ }
-+
-+ switch (act->dta_kind) {
-+ case DTRACEACT_STOP:
-+ if (dtrace_priv_proc_destructive(state))
-+ dtrace_action_stop();
-+ continue;
-+
-+ case DTRACEACT_BREAKPOINT:
-+ if (dtrace_priv_kernel_destructive(state))
-+ dtrace_action_breakpoint(ecb);
-+ continue;
-+
-+ case DTRACEACT_PANIC:
-+ if (dtrace_priv_kernel_destructive(state))
-+ dtrace_action_panic(ecb);
-+ continue;
-+
-+ case DTRACEACT_STACK:
-+ if (!dtrace_priv_kernel(state))
-+ continue;
-+
-+ dtrace_getpcstack(
-+ (uint64_t *)(tomax + valoffs),
-+ size / sizeof(pc_t),
-+ probe->dtpr_aframes + 1,
-+ DTRACE_ANCHORED(probe)
-+ ? NULL
-+ : (uint32_t *)arg0);
-+
-+ continue;
-+
-+ case DTRACEACT_JSTACK:
-+ case DTRACEACT_USTACK:
-+ if (!dtrace_priv_proc(state))
-+ continue;
-+
-+ /*
-+ * See comment in DIF_VAR_PID.
-+ */
-+ if (DTRACE_ANCHORED(mstate.dtms_probe) &&
-+ in_interrupt()) {
-+ int depth = DTRACE_USTACK_NFRAMES(
-+ rec->dtrd_arg) + 2;
-+
-+ dtrace_bzero((void *)(tomax + valoffs),
-+ DTRACE_USTACK_STRSIZE(
-+ rec->dtrd_arg) +
-+ depth * sizeof(uint64_t));
-+
-+ continue;
-+ }
-+
-+ if (DTRACE_USTACK_STRSIZE(rec->dtrd_arg) != 0 &&
-+ dtsk != NULL && dtsk->dt_helpers != NULL) {
-+ /*
-+ * This is the slow path -- we have
-+ * allocated string space, and we're
-+ * getting the stack of a process that
-+ * has helpers. Call into a separate
-+ * routine to perform this processing.
-+ */
-+ dtrace_action_ustack(
-+ &mstate, state,
-+ (uint64_t *)(tomax + valoffs),
-+ rec->dtrd_arg);
-+ continue;
-+ }
-+
-+ dtrace_getupcstack(
-+ (uint64_t *)(tomax + valoffs),
-+ DTRACE_USTACK_NFRAMES(rec->dtrd_arg) +
-+ 2);
-+ continue;
-+
-+ default:
-+ break;
-+ }
-+
-+ dp = act->dta_difo;
-+ ASSERT(dp != NULL);
-+
-+ val = dtrace_dif_emulate(dp, &mstate, vstate, state);
-+
-+ if (*flags & CPU_DTRACE_ERROR)
-+ continue;
-+
-+ switch (act->dta_kind) {
-+ case DTRACEACT_SPECULATE:
-+ ASSERT(buf == &state->dts_buffer[cpuid]);
-+ buf = dtrace_speculation_buffer(state, cpuid,
-+ val);
-+
-+ if (buf == NULL) {
-+ *flags |= CPU_DTRACE_DROP;
-+ continue;
-+ }
-+
-+ offs = dtrace_buffer_reserve(buf,
-+ ecb->dte_needed,
-+ ecb->dte_alignment,
-+ state, NULL);
-+
-+ if (offs < 0) {
-+ *flags |= CPU_DTRACE_DROP;
-+ continue;
-+ }
-+
-+ tomax = buf->dtb_tomax;
-+ ASSERT(tomax != NULL);
-+
-+ if (ecb->dte_size != 0) {
-+ DTRACE_STORE(uint32_t, tomax, offs,
-+ ecb->dte_epid);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] "
-+ "<- %d [EPID] "
-+ "(from %s::%d)\n",
-+ buf, offs,
-+ offs + sizeof(uint32_t) - 1,
-+ ecb->dte_epid,
-+ __FUNCTION__, __LINE__);
-+ }
-+
-+ continue;
-+
-+ case DTRACEACT_CHILL:
-+ if (dtrace_priv_kernel_destructive(state))
-+ dtrace_action_chill(&mstate,
-+ ns_to_ktime(val));
-+
-+ continue;
-+
-+ case DTRACEACT_RAISE:
-+ if (dtrace_priv_proc_destructive(state))
-+ dtrace_action_raise(val);
-+
-+ continue;
-+
-+ case DTRACEACT_COMMIT:
-+ ASSERT(!committed);
-+
-+ /*
-+ * We need to commit our buffer state.
-+ */
-+ if (ecb->dte_size) {
-+ buf->dtb_offset = offs + ecb->dte_size;
-+ dt_dbg_buf(" Consume: %p[%ld .. "
-+ "%lld]\n",
-+ buf, offs,
-+ buf->dtb_offset - 1);
-+ }
-+
-+ buf = &state->dts_buffer[cpuid];
-+ dtrace_speculation_commit(state, cpuid, val);
-+ committed = 1;
-+ continue;
-+
-+ case DTRACEACT_DISCARD:
-+ dtrace_speculation_discard(state, cpuid, val);
-+ continue;
-+
-+ case DTRACEACT_DIFEXPR:
-+ case DTRACEACT_LIBACT:
-+ case DTRACEACT_PRINTF:
-+ case DTRACEACT_PRINTA:
-+ case DTRACEACT_SYSTEM:
-+ case DTRACEACT_FREOPEN:
-+ case DTRACEACT_TRACEMEM:
-+ case DTRACEACT_PCAP:
-+ break;
-+
-+ case DTRACEACT_SYM:
-+ case DTRACEACT_MOD:
-+ if (!dtrace_priv_kernel(state))
-+ continue;
-+ break;
-+
-+ case DTRACEACT_USYM:
-+ case DTRACEACT_UMOD:
-+ case DTRACEACT_UADDR: {
-+ pid_t pid = current->pid;
-+ pid_t tgid = current->tgid;
-+
-+ if (!dtrace_priv_proc(state))
-+ continue;
-+
-+ DTRACE_STORE(uint64_t, tomax, valoffs,
-+ (uint64_t)pid);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- %lld "
-+ "[PID] (from %s::%d)\n",
-+ buf, valoffs,
-+ valoffs + sizeof(uint64_t) - 1,
-+ (uint64_t)pid,
-+ __FUNCTION__, __LINE__);
-+ DTRACE_STORE(uint64_t, tomax,
-+ valoffs + sizeof(uint64_t),
-+ (uint64_t)tgid);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- %lld "
-+ "[TGID] (from %s::%d)\n",
-+ buf, valoffs + sizeof(uint64_t),
-+ valoffs + 2 * sizeof(uint64_t) - 1,
-+ (uint64_t)tgid,
-+ __FUNCTION__, __LINE__);
-+ DTRACE_STORE(uint64_t, tomax,
-+ valoffs + 2 * sizeof(uint64_t),
-+ val);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- %lld "
-+ "(from %s::%d)\n",
-+ buf, valoffs + 2 * sizeof(uint64_t),
-+ valoffs + 3 * sizeof(uint64_t) - 1,
-+ val, __FUNCTION__, __LINE__);
-+
-+ continue;
-+ }
-+
-+ case DTRACEACT_EXIT: {
-+ /*
-+ * For the exit action, we are going to attempt
-+ * to atomically set our activity to be
-+ * draining. If this fails (either because
-+ * another CPU has beat us to the exit action,
-+ * or because our current activity is something
-+ * other than ACTIVE or WARMUP), we will
-+ * continue. This assures that the exit action
-+ * can be successfully recorded at most once
-+ * when we're in the ACTIVE state. If we're
-+ * encountering the exit() action while in
-+ * COOLDOWN, however, we want to honor the new
-+ * status code. (We know that we're the only
-+ * thread in COOLDOWN, so there is no race.)
-+ */
-+ enum dtrace_activity *activity =
-+ &state->dts_activity;
-+ enum dtrace_activity curr =
-+ state->dts_activity;
-+
-+ if (curr == DTRACE_ACTIVITY_COOLDOWN)
-+ break;
-+
-+ if (curr != DTRACE_ACTIVITY_WARMUP)
-+ curr = DTRACE_ACTIVITY_ACTIVE;
-+
-+ if (cmpxchg(activity, curr,
-+ DTRACE_ACTIVITY_DRAINING) != curr) {
-+ *flags |= CPU_DTRACE_DROP;
-+ continue;
-+ }
-+
-+ break;
-+ }
-+
-+ default:
-+ ASSERT(0);
-+ }
-+
-+ if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF) {
-+ uintptr_t end = valoffs + size;
-+
-+ if (!dtrace_vcanload((void *)(uintptr_t)val,
-+ &dp->dtdo_rtype, &mstate,
-+ vstate))
-+ continue;
-+
-+ if (act->dta_kind == DTRACEACT_PCAP) {
-+ if (dtrace_probe_pcap(val, &valoffs,
-+ size, tomax, now,
-+ &mstate, vstate,
-+ flags) == -1)
-+ break;
-+ continue;
-+ }
-+
-+ /*
-+ * If this is a string, we're going to only
-+ * load until we find the zero byte -- after
-+ * which we'll store zero bytes.
-+ */
-+ if (dp->dtdo_rtype.dtdt_kind ==
-+ DIF_TYPE_STRING) {
-+ char c = '\0' + 1;
-+ int intuple = act->dta_intuple;
-+ size_t s;
-+
-+ for (s = 0; s < size; s++) {
-+ if (c != '\0')
-+ c = dtrace_load8(val++);
-+
-+ DTRACE_STORE(uint8_t, tomax,
-+ valoffs++, c);
-+ dt_dbg_buf(" Store: %p[%ld]"
-+ " <- %d (from "
-+ "%s::%d)\n",
-+ buf, valoffs, c,
-+ __FUNCTION__,
-+ __LINE__);
-+
-+ if (c == '\0' && intuple)
-+ break;
-+ }
-+
-+ continue;
-+ }
-+
-+ while (valoffs < end) {
-+ DTRACE_STORE(uint8_t, tomax, valoffs++,
-+ dtrace_load8(val++));
-+ dt_dbg_buf(" Store: %p[%ld] <- ??? "
-+ "(from %s::%d)\n",
-+ buf, valoffs,
-+ __FUNCTION__, __LINE__);
-+ }
-+
-+ continue;
-+ }
-+
-+ switch (size) {
-+ case 0:
-+ break;
-+ case sizeof(uint8_t):
-+ DTRACE_STORE(uint8_t, tomax, valoffs, val);
-+ dt_dbg_buf(" Store: %p[%ld] <- %d "
-+ "(from %s::%d)\n",
-+ buf, valoffs, (uint8_t)val,
-+ __FUNCTION__, __LINE__);
-+ break;
-+ case sizeof(uint16_t):
-+ DTRACE_STORE(uint16_t, tomax, valoffs, val);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- %d "
-+ "(from %s::%d)\n",
-+ buf, valoffs,
-+ valoffs + sizeof(uint16_t) - 1,
-+ (uint16_t)val,
-+ __FUNCTION__, __LINE__);
-+ break;
-+ case sizeof(uint32_t):
-+ DTRACE_STORE(uint32_t, tomax, valoffs, val);
-+ dt_dbg_buf(" Store: %p[%ld] <- %d "
-+ "(from %s::%d)\n",
-+ buf, valoffs,
-+ (uint32_t)val,
-+ __FUNCTION__, __LINE__);
-+ break;
-+ case sizeof(uint64_t):
-+ DTRACE_STORE(uint64_t, tomax, valoffs, val);
-+ dt_dbg_buf(" Store: %p[%ld] <- %lld "
-+ "(from %s::%d)\n",
-+ buf, valoffs,
-+ val,
-+ __FUNCTION__, __LINE__);
-+ break;
-+ default:
-+ /*
-+ * Any other size should have been returned by
-+ * reference, not by value.
-+ */
-+ ASSERT(0);
-+ break;
-+ }
-+ }
-+
-+ if (*flags & CPU_DTRACE_DROP) {
-+ dt_dbg_probe(" -> Dropped\n");
-+ continue;
-+ }
-+
-+ if (*flags & CPU_DTRACE_FAULT) {
-+ int ndx;
-+ struct dtrace_action *err;
-+
-+ dt_dbg_probe(" -> Failed (%x)\n", *flags);
-+
-+ buf->dtb_errors++;
-+
-+ if (probe->dtpr_id == dtrace_probeid_error) {
-+ /*
-+ * There's nothing we can do -- we had an
-+ * error on the error probe. We bump an
-+ * error counter to at least indicate that
-+ * this condition happened.
-+ */
-+ dtrace_error(&state->dts_dblerrors);
-+ continue;
-+ }
-+
-+ if (vtime && dtsk != NULL)
-+ /*
-+ * Before recursing on dtrace_probe(), we
-+ * need to explicitly clear out our start
-+ * time to prevent it from being accumulated
-+ * into the dtrace_vtime.
-+ */
-+ dtsk->dt_start = ktime_set(0, 0);
-+
-+ /*
-+ * Iterate over the actions to figure out which action
-+ * we were processing when we experienced the error.
-+ * Note that act points _past_ the faulting action; if
-+ * act is ecb->dte_action, the fault was in the
-+ * predicate, if it's ecb->dte_action->dta_next it's
-+ * in action #1, and so on.
-+ */
-+ for (err = ecb->dte_action, ndx = 0;
-+ err != act; err = err->dta_next, ndx++)
-+ continue;
-+
-+ dtrace_probe_error(
-+ state, ecb->dte_epid, ndx,
-+ (mstate.dtms_present & DTRACE_MSTATE_FLTOFFS)
-+ ? mstate.dtms_fltoffs
-+ : -1,
-+ DTRACE_FLAGS2FLT(*flags),
-+ this_cpu_core->cpuc_dtrace_illval);
-+
-+ continue;
-+ }
-+
-+ if (!committed) {
-+ buf->dtb_offset = offs + ecb->dte_size;
-+ dt_dbg_buf(" Consume: %p[%ld .. %lld]\n",
-+ buf, offs, buf->dtb_offset);
-+ }
-+
-+ dt_dbg_probe("Probe (ID %d EPID %d) Done\n",
-+ id, ecb->dte_epid);
-+ }
-+
-+ if (vtime && dtsk != NULL)
-+ dtsk->dt_start = dtrace_gethrtime();
-+
-+ this_cpu_core->cpuc_current_probe = old_id;
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+
-+ if (dtsk != NULL && dtsk->dt_sig != 0) {
-+ int sig = dtsk->dt_sig;
-+
-+ dtsk->dt_sig = 0;
-+
-+ send_sig(sig, current, 0);
-+ }
-+}
-+EXPORT_SYMBOL(dtrace_probe);
-+
-+int dtrace_probe_init(void)
-+{
-+ dtrace_id_t id;
-+
-+ dtrace_probe_cachep = KMEM_CACHE(dtrace_probe, SLAB_HWCACHE_ALIGN);
-+ if (dtrace_probe_cachep == NULL)
-+ return -ENOMEM;
-+
-+ idr_init(&dtrace_probe_idr);
-+
-+ /*
-+ * We create a ID 0 entry as a sentinel, so we can always depend on it
-+ * being the very first entry. This is used in functionality that runs
-+ * through the list of probes.
-+ */
-+ idr_preload(GFP_KERNEL);
-+ id = idr_alloc_cyclic(&dtrace_probe_idr, NULL, 0, 0, GFP_NOWAIT);
-+ idr_preload_end();
-+
-+ return id == 0 ? 0 : -EAGAIN;
-+}
-+
-+void dtrace_probe_exit(void)
-+{
-+ idr_destroy(&dtrace_probe_idr);
-+ kmem_cache_destroy(dtrace_probe_cachep);
-+}
-+
-+void dtrace_probe_remove_id(dtrace_id_t id)
-+{
-+ idr_remove(&dtrace_probe_idr, id);
-+}
-+
-+struct dtrace_probe *dtrace_probe_lookup_id(dtrace_id_t id)
-+{
-+ return idr_find(&dtrace_probe_idr, id);
-+}
-+
-+static int dtrace_probe_lookup_match(struct dtrace_probe *probe, void *arg)
-+{
-+ *((dtrace_id_t *)arg) = probe->dtpr_id;
-+
-+ return DTRACE_MATCH_DONE;
-+}
-+
-+dtrace_id_t dtrace_probe_lookup(dtrace_provider_id_t prid, const char *mod,
-+ const char *func, const char *name)
-+{
-+ struct dtrace_probekey pkey;
-+ dtrace_id_t id;
-+ int match;
-+
-+ pkey.dtpk_prov = ((struct dtrace_provider *)prid)->dtpv_name;
-+ pkey.dtpk_pmatch = &dtrace_match_string;
-+ pkey.dtpk_mod = mod;
-+ pkey.dtpk_mmatch = mod ? &dtrace_match_string : &dtrace_match_nul;
-+ pkey.dtpk_func = func;
-+ pkey.dtpk_fmatch = func ? &dtrace_match_string : &dtrace_match_nul;
-+ pkey.dtpk_name = name;
-+ pkey.dtpk_nmatch = name ? &dtrace_match_string : &dtrace_match_nul;
-+ pkey.dtpk_id = DTRACE_IDNONE;
-+
-+ mutex_lock(&dtrace_lock);
-+ match = dtrace_match(&pkey, DTRACE_PRIV_ALL,
-+ make_kuid(init_user_namespace, 0),
-+ dtrace_probe_lookup_match, &id);
-+ mutex_unlock(&dtrace_lock);
-+
-+ ASSERT(match == 1 || match == 0);
-+
-+ return match ? id : 0;
-+}
-+EXPORT_SYMBOL(dtrace_probe_lookup);
-+
-+struct dtrace_probe *dtrace_probe_get_next(dtrace_id_t *idp)
-+{
-+ return idr_get_next(&dtrace_probe_idr, idp);
-+}
-+
-+int dtrace_probe_for_each(int (*fn)(int id, void *p, void *data), void *data)
-+{
-+ return idr_for_each(&dtrace_probe_idr, fn, data);
-+}
-diff --git a/dtrace/dtrace_probe_ctx.c b/dtrace/dtrace_probe_ctx.c
-new file mode 100644
-index 000000000000..f04b5b269222
---- /dev/null
-+++ b/dtrace/dtrace_probe_ctx.c
-@@ -0,0 +1,659 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_probe_ctx.c
-+ * DESCRIPTION: DTrace - probe context safe functions
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+
-+#include "dtrace.h"
-+
-+void dtrace_panic(const char *fmt, ...)
-+{
-+ va_list alist;
-+
-+ va_start(alist, fmt);
-+ vprintk(fmt, alist);
-+ va_end(alist);
-+
-+ BUG();
-+}
-+EXPORT_SYMBOL(dtrace_panic);
-+
-+int dtrace_assfail(const char *a, const char *f, int l)
-+{
-+ dtrace_panic(KERN_EMERG "assertion failed: %s, file: %s, line: %d",
-+ a, f, l);
-+
-+ /*
-+ * FIXME: We can do better than this. The OpenSolaris DTrace source
-+ * states that this cannot be optimized away.
-+ */
-+ return a[(uintptr_t)f];
-+}
-+EXPORT_SYMBOL(dtrace_assfail);
-+
-+#define DT_MASK_LO 0x00000000FFFFFFFFULL
-+
-+static void dtrace_add_128(uint64_t *addend1, uint64_t *addend2, uint64_t *sum)
-+{
-+ uint64_t result[2];
-+
-+ result[0] = addend1[0] + addend2[0];
-+ result[1] = addend1[1] + addend2[1] +
-+ (result[0] < addend1[0] || result[0] < addend2[0] ? 1 : 0);
-+
-+ sum[0] = result[0];
-+ sum[1] = result[1];
-+}
-+
-+static void dtrace_shift_128(uint64_t *a, int b)
-+{
-+ uint64_t mask;
-+
-+ if (b == 0)
-+ return;
-+
-+ if (b < 0) {
-+ b = -b;
-+
-+ if (b >= 64) {
-+ a[0] = a[1] >> (b - 64);
-+ a[1] = 0;
-+ } else {
-+ a[0] >>= b;
-+ mask = 1LL << (64 - b);
-+ mask -= 1;
-+ a[0] |= ((a[1] & mask) << (64 - b));
-+ a[1] >>= b;
-+ }
-+ } else {
-+ if (b >= 64) {
-+ a[1] = a[0] << (b - 64);
-+ a[0] = 0;
-+ } else {
-+ a[1] <<= b;
-+ mask = a[0] >> (64 - b);
-+ a[1] |= mask;
-+ a[0] <<= b;
-+ }
-+ }
-+}
-+
-+static void dtrace_multiply_128(uint64_t factor1, uint64_t factor2,
-+ uint64_t *product)
-+{
-+ uint64_t hi1, hi2, lo1, lo2;
-+ uint64_t tmp[2];
-+
-+ hi1 = factor1 >> 32;
-+ hi2 = factor2 >> 32;
-+
-+ lo1 = factor1 & DT_MASK_LO;
-+ lo2 = factor2 & DT_MASK_LO;
-+
-+ product[0] = lo1 * lo2;
-+ product[1] = hi1 * hi2;
-+
-+ tmp[0] = hi1 * lo2;
-+ tmp[1] = 0;
-+ dtrace_shift_128(tmp, 32);
-+ dtrace_add_128(product, tmp, product);
-+
-+ tmp[0] = hi2 * lo1;
-+ tmp[1] = 0;
-+ dtrace_shift_128(tmp, 32);
-+ dtrace_add_128(product, tmp, product);
-+}
-+
-+void dtrace_aggregate_min(uint64_t *oval, uint64_t nval, uint64_t arg)
-+{
-+ if ((int64_t)nval < (int64_t)*oval)
-+ *oval = nval;
-+}
-+
-+void dtrace_aggregate_max(uint64_t *oval, uint64_t nval, uint64_t arg)
-+{
-+ if ((int64_t)nval > (int64_t)*oval)
-+ *oval = nval;
-+}
-+
-+void dtrace_aggregate_quantize(uint64_t *quanta, uint64_t nval, uint64_t incr)
-+{
-+ int i, zero = DTRACE_QUANTIZE_ZEROBUCKET;
-+ int64_t val = (int64_t)nval;
-+
-+ if (val < 0) {
-+ for (i = 0; i < zero; i++) {
-+ if (val <= DTRACE_QUANTIZE_BUCKETVAL(i)) {
-+ quanta[i] += incr;
-+
-+ return;
-+ }
-+ }
-+ } else {
-+ for (i = zero + 1; i < DTRACE_QUANTIZE_NBUCKETS; i++) {
-+ if (val < DTRACE_QUANTIZE_BUCKETVAL(i)) {
-+ quanta[i - 1] += incr;
-+
-+ return;
-+ }
-+ }
-+
-+ quanta[DTRACE_QUANTIZE_NBUCKETS - 1] += incr;
-+
-+ return;
-+ }
-+
-+ ASSERT(0);
-+}
-+
-+void dtrace_aggregate_lquantize(uint64_t *lquanta, uint64_t nval,
-+ uint64_t incr)
-+{
-+ uint64_t arg = *lquanta++;
-+ int32_t base = DTRACE_LQUANTIZE_BASE(arg);
-+ uint16_t step = DTRACE_LQUANTIZE_STEP(arg);
-+ uint16_t levels = DTRACE_LQUANTIZE_LEVELS(arg);
-+ int64_t val = (int64_t)nval, level;
-+
-+ ASSERT(step != 0);
-+ ASSERT(levels != 0);
-+
-+ if (val < base) {
-+ lquanta[0] += incr;
-+
-+ return;
-+ }
-+
-+ level = (val - base) / step;
-+
-+ if (level < levels) {
-+ lquanta[level + 1] += incr;
-+
-+ return;
-+ }
-+
-+ lquanta[levels + 1] += incr;
-+}
-+
-+static uint64_t dtrace_pow(uint64_t base, uint64_t exp)
-+{
-+ uint64_t p, r;
-+
-+ p = base;
-+ r = 1;
-+ while (exp > 0) {
-+ if (exp & 1)
-+ r *= p;
-+
-+ p *= p;
-+ exp >>= 1;
-+ }
-+
-+ return (r);
-+}
-+
-+void dtrace_aggregate_llquantize(uint64_t *llquanta, uint64_t nval,
-+ uint64_t incr)
-+{
-+ uint64_t arg = *llquanta++;
-+ int factor = DTRACE_LLQUANTIZE_FACTOR(arg);
-+ int lmag = DTRACE_LLQUANTIZE_LMAG(arg);
-+ int hmag = DTRACE_LLQUANTIZE_HMAG(arg);
-+ int steps = DTRACE_LLQUANTIZE_STEPS(arg);
-+ int i, signbit, steps_factor, mag, underflow_bin;
-+ uint64_t val, bucket_max;
-+
-+ ASSERT(steps != 0);
-+ ASSERT(factor > 1);
-+
-+ if (nval >> (64 - 1)) {
-+ signbit = -1;
-+ val = 1 + ~nval;
-+ } else {
-+ signbit = +1;
-+ val = nval;
-+ }
-+
-+ /*
-+ * Compute steps/factor.
-+ * Notice that while we say there are "steps" bins per logarithmic
-+ * range, steps/factor of them actually overlap with lower ranges.
-+ * E.g., if factor=10 and steps=20, for mag=2 we have the 20 bins
-+ * 0 50 100 150 200 250 300 350 ... 800 850 900 950
-+ * but the first two actually belong to lower ranges.
-+ */
-+ steps_factor = steps/factor;
-+
-+ /* the underflow bin is in the middle */
-+ underflow_bin = 1 + (hmag-lmag+1) * (steps-steps_factor);
-+
-+ bucket_max = dtrace_pow(factor, lmag);
-+
-+ /* check for "underflow" (smaller than the smallest bin) */
-+ if (val < bucket_max) {
-+ llquanta[underflow_bin] += incr;
-+ return;
-+ }
-+
-+ /* loop over the logarithmic ranges */
-+ i = 0;
-+ for (mag = lmag; mag <= hmag; mag++) {
-+ bucket_max *= factor;
-+ if (val >= bucket_max)
-+ continue;
-+
-+ /*
-+ * We want
-+ * i = val * steps / bucket_max;
-+ * but val*steps could overflow. An alternative is
-+ * i = val / ( bucket_max/steps )
-+ * but bucket_max/steps might not divide evenly.
-+ * (Plus, we end up with an extra divide.)
-+ *
-+ * From Solaris, we inherit constraints on factor and steps
-+ * that mean bucket_max/steps divides evenly when mag>0.
-+ * Meanwhile, if mag==0, val*steps cannot overflow.
-+ * So between our two expressions for i, at least one
-+ * will work and we just have to pick which one to use.
-+ */
-+ if (mag == 0)
-+ i = val * steps / bucket_max;
-+ else
-+ i = val / (bucket_max/steps);
-+
-+ // shift for low indices that can never happen
-+ i -= steps_factor;
-+ break;
-+ }
-+ i = underflow_bin+signbit*((steps-steps_factor)*(mag-lmag)+i+1);
-+ llquanta[i] += incr;
-+}
-+
-+void dtrace_aggregate_avg(uint64_t *data, uint64_t nval, uint64_t arg)
-+{
-+ data[0]++;
-+ data[1] += nval;
-+}
-+
-+void dtrace_aggregate_stddev(uint64_t *data, uint64_t nval, uint64_t arg)
-+{
-+ int64_t snval = (int64_t)nval;
-+ uint64_t tmp[2];
-+
-+ data[0]++;
-+ data[1] += nval;
-+
-+ if (snval < 0)
-+ snval = -snval;
-+
-+ dtrace_multiply_128((uint64_t)snval, (uint64_t)snval, tmp);
-+ dtrace_add_128(data + 2, tmp, data + 2);
-+}
-+
-+void dtrace_aggregate_count(uint64_t *oval, uint64_t nval, uint64_t arg)
-+{
-+ *oval = *oval + 1;
-+}
-+
-+void dtrace_aggregate_sum(uint64_t *oval, uint64_t nval, uint64_t arg)
-+{
-+ *oval += nval;
-+}
-+
-+/*
-+ * DTrace Aggregation Buffers
-+ *
-+ * Aggregation buffers use much of the same mechanism as described above
-+ * ("DTrace Buffers"). However, because an aggregation is fundamentally a
-+ * hash, there exists dynamic metadata associated with an aggregation buffer
-+ * that is not associated with other kinds of buffers. This aggregation
-+ * metadata is _only_ relevant for the in-kernel implementation of
-+ * aggregations; it is not actually relevant to user-level consumers. To do
-+ * this, we allocate dynamic aggregation data (hash keys and hash buckets)
-+ * starting below the _limit_ of the buffer, and we allocate data from the
-+ * _base_ of the buffer. When the aggregation buffer is copied out, _only_ the
-+ * data is copied out; the metadata is simply discarded. Schematically,
-+ * aggregation buffers look like:
-+ *
-+ * base of data buffer ---> +-------+------+-----------+-------+
-+ * | aggid | key | value | aggid |
-+ * +-------+------+-----------+-------+
-+ * | key |
-+ * +-------+-------+-----+------------+
-+ * | value | aggid | key | value |
-+ * +-------+------++-----+------+-----+
-+ * | aggid | key | value | |
-+ * +-------+------+-------------+ |
-+ * | || |
-+ * | || |
-+ * | \/ |
-+ * : :
-+ * . .
-+ * . .
-+ * . .
-+ * : :
-+ * | /\ |
-+ * | || +------------+
-+ * | || | |
-+ * +---------------------+ |
-+ * | hash keys |
-+ * | (dtrace_aggkey structures) |
-+ * | |
-+ * +----------------------------------+
-+ * | hash buckets |
-+ * | (dtrace_aggbuffer structure) |
-+ * | |
-+ * limit of data buffer ---> +----------------------------------+
-+ *
-+ * As implied above, just as we assure that ECBs always store a constant
-+ * amount of data, we assure that a given aggregation -- identified by its
-+ * aggregation ID -- always stores data of a constant quantity and type.
-+ * As with EPIDs, this allows the aggregation ID to serve as the metadata for a
-+ * given record.
-+ *
-+ * Note that the size of the dtrace_aggkey structure must be sizeof (uintptr_t)
-+ * aligned. (If this the structure changes such that this becomes false, an
-+ * assertion will fail in dtrace_aggregate().)
-+ */
-+#define DTRACE_AGGHASHSIZE_SLEW 17
-+
-+struct dtrace_aggkey {
-+ uint32_t dtak_hashval; /* hash value */
-+ uint32_t dtak_action:4; /* action -- 4 bits */
-+ uint32_t dtak_size:28; /* size -- 28 bits */
-+ caddr_t dtak_data; /* data pointer */
-+ struct dtrace_aggkey *dtak_next; /* next in hash chain */
-+};
-+
-+struct dtrace_aggbuffer {
-+ uintptr_t dtagb_hashsize; /* number of buckets */
-+ uintptr_t dtagb_free; /* free list of keys */
-+ struct dtrace_aggkey **dtagb_hash; /* hash table */
-+};
-+
-+#define DTRACEACT_ISSTRING(act) \
-+ ((act)->dta_kind == DTRACEACT_DIFEXPR && \
-+ (act)->dta_difo->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING)
-+
-+/*
-+ * Aggregate given the tuple in the principal data buffer, and the aggregating
-+ * action denoted by the specified dtrace_aggregation_t. The aggregation
-+ * buffer is specified as the buf parameter. This routine does not return
-+ * failure; if there is no space in the aggregation buffer, the data will be
-+ * dropped, and a corresponding counter incremented.
-+ */
-+void dtrace_aggregate(struct dtrace_aggregation *agg,
-+ struct dtrace_buffer *dbuf,
-+ intptr_t offset, struct dtrace_buffer *buf,
-+ uint64_t expr, uint64_t arg)
-+{
-+ struct dtrace_recdesc *rec = &agg->dtag_action.dta_rec;
-+ uint32_t i, ndx, size, fsize;
-+ uint32_t align = sizeof(uint64_t) - 1;
-+ struct dtrace_aggbuffer *agb;
-+ struct dtrace_aggkey *key;
-+ uint32_t hashval = 0, limit, isstr;
-+ caddr_t tomax, data, kdata;
-+ dtrace_actkind_t action;
-+ struct dtrace_action *act;
-+ uintptr_t offs;
-+
-+ if (buf == NULL)
-+ return;
-+
-+ if (!agg->dtag_hasarg)
-+ /*
-+ * Currently, only quantize(), lquantize() and llquantize()
-+ * take additional arguments, and they have the same semantics:
-+ * an increment value that defaults to 1 when not present. If
-+ * additional aggregating actions take arguments, the setting
-+ * of the default argument value will presumably have to
-+ * become more sophisticated...
-+ */
-+ arg = 1;
-+
-+ action = agg->dtag_action.dta_kind - DTRACEACT_AGGREGATION;
-+ size = rec->dtrd_offset - agg->dtag_base;
-+ fsize = size + rec->dtrd_size;
-+
-+ ASSERT(dbuf->dtb_tomax != NULL);
-+ data = dbuf->dtb_tomax + offset + agg->dtag_base;
-+
-+ tomax = buf->dtb_tomax;
-+ if (tomax == NULL) {
-+ dtrace_buffer_drop(buf);
-+ return;
-+ }
-+
-+ /*
-+ * The metastructure is always at the bottom of the buffer.
-+ */
-+ agb = (struct dtrace_aggbuffer *)(tomax + buf->dtb_size -
-+ sizeof(struct dtrace_aggbuffer));
-+
-+ if (buf->dtb_offset == 0) {
-+ /*
-+ * We just kludge up approximately 1/8th of the size to be
-+ * buckets. If this guess ends up being routinely
-+ * off-the-mark, we may need to dynamically readjust this
-+ * based on past performance.
-+ */
-+ uintptr_t hashsize = (buf->dtb_size >> 3) /
-+ sizeof(uintptr_t);
-+
-+ if ((uintptr_t)agb - hashsize * sizeof(struct dtrace_aggkey *) <
-+ (uintptr_t)tomax || hashsize == 0) {
-+ /*
-+ * We've been given a ludicrously small buffer;
-+ * increment our drop count and leave.
-+ */
-+ dtrace_buffer_drop(buf);
-+ return;
-+ }
-+
-+ /*
-+ * And now, a pathetic attempt to try to get a an odd (or
-+ * perchance, a prime) hash size for better hash distribution.
-+ */
-+ if (hashsize > (DTRACE_AGGHASHSIZE_SLEW << 3))
-+ hashsize -= DTRACE_AGGHASHSIZE_SLEW;
-+
-+ agb->dtagb_hashsize = hashsize;
-+ agb->dtagb_hash = (struct dtrace_aggkey **)((uintptr_t)agb -
-+ agb->dtagb_hashsize * sizeof(struct dtrace_aggkey *));
-+ agb->dtagb_free = (uintptr_t)agb->dtagb_hash;
-+
-+ for (i = 0; i < agb->dtagb_hashsize; i++)
-+ agb->dtagb_hash[i] = NULL;
-+ }
-+
-+ ASSERT(agg->dtag_first != NULL);
-+ ASSERT(agg->dtag_first->dta_intuple);
-+
-+ /*
-+ * Calculate the hash value based on the key. Note that we _don't_
-+ * include the aggid in the hashing (but we will store it as part of
-+ * the key). The hashing algorithm is Bob Jenkins' "One-at-a-time"
-+ * algorithm: a simple, quick algorithm that has no known funnels, and
-+ * gets good distribution in practice. The efficacy of the hashing
-+ * algorithm (and a comparison with other algorithms) may be found by
-+ * running the ::dtrace_aggstat MDB dcmd.
-+ */
-+ for (act = agg->dtag_first; act->dta_intuple; act = act->dta_next) {
-+ i = act->dta_rec.dtrd_offset - agg->dtag_base;
-+ limit = i + act->dta_rec.dtrd_size;
-+ ASSERT(limit <= size);
-+ isstr = DTRACEACT_ISSTRING(act);
-+
-+ for (; i < limit; i++) {
-+ hashval += data[i];
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+
-+ if (isstr && data[i] == '\0')
-+ break;
-+ }
-+ }
-+
-+ hashval += (hashval << 3);
-+ hashval ^= (hashval >> 11);
-+ hashval += (hashval << 15);
-+
-+ /*
-+ * Yes, the divide here is expensive -- but it's generally the least
-+ * of the performance issues given the amount of data that we iterate
-+ * over to compute hash values, compare data, etc.
-+ */
-+ ndx = hashval % agb->dtagb_hashsize;
-+
-+ for (key = agb->dtagb_hash[ndx]; key != NULL; key = key->dtak_next) {
-+ ASSERT((caddr_t)key >= tomax);
-+ ASSERT((caddr_t)key < tomax + buf->dtb_size);
-+
-+ if (hashval != key->dtak_hashval || key->dtak_size != size)
-+ continue;
-+
-+ kdata = key->dtak_data;
-+ ASSERT(kdata >= tomax && kdata < tomax + buf->dtb_size);
-+
-+ for (act = agg->dtag_first; act->dta_intuple;
-+ act = act->dta_next) {
-+ i = act->dta_rec.dtrd_offset - agg->dtag_base;
-+ limit = i + act->dta_rec.dtrd_size;
-+ ASSERT(limit <= size);
-+ isstr = DTRACEACT_ISSTRING(act);
-+
-+ for (; i < limit; i++) {
-+ if (kdata[i] != data[i])
-+ goto next;
-+
-+ if (isstr && data[i] == '\0')
-+ break;
-+ }
-+ }
-+
-+ if (action != key->dtak_action) {
-+ /*
-+ * We are aggregating on the same value in the same
-+ * aggregation with two different aggregating actions.
-+ * (This should have been picked up in the compiler,
-+ * so we may be dealing with errant or devious DIF.)
-+ * This is an error condition; we indicate as much,
-+ * and return.
-+ */
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return;
-+ }
-+
-+ /*
-+ * This is a hit: we need to apply the aggregator to
-+ * the value at this key.
-+ */
-+ dt_dbg_agg(" Aggregate [accum]: Buf %p, offs %d, act %d, "
-+ "%lld (%lld, %lld)\n",
-+ buf, size,
-+ agg->dtag_action.dta_kind - DTRACEACT_AGGREGATION,
-+ *(uint64_t *)(kdata + size), expr, arg);
-+ agg->dtag_aggregate((uint64_t *)(kdata + size), expr, arg);
-+ return;
-+next:
-+ continue;
-+ }
-+
-+ /*
-+ * We didn't find it. We need to allocate some zero-filled space,
-+ * link it into the hash table appropriately, and apply the aggregator
-+ * to the (zero-filled) value.
-+ */
-+ offs = buf->dtb_offset;
-+ while (offs & (align - 1))
-+ offs += sizeof(uint32_t);
-+
-+ /*
-+ * If we don't have enough room to both allocate a new key _and_
-+ * its associated data, increment the drop count and return.
-+ */
-+ if ((uintptr_t)tomax + offs + fsize >
-+ agb->dtagb_free - sizeof(struct dtrace_aggkey)) {
-+ dtrace_buffer_drop(buf);
-+ return;
-+ }
-+
-+ ASSERT(!(sizeof(struct dtrace_aggkey) & (sizeof(uintptr_t) - 1)));
-+ key = (struct dtrace_aggkey *)
-+ (agb->dtagb_free - sizeof(struct dtrace_aggkey));
-+ agb->dtagb_free -= sizeof(struct dtrace_aggkey);
-+
-+ key->dtak_data = kdata = tomax + offs;
-+ buf->dtb_offset = offs + fsize;
-+
-+ /*
-+ * Now copy the data across.
-+ */
-+ *((dtrace_aggid_t *)kdata) = agg->dtag_id;
-+
-+ for (i = sizeof(dtrace_aggid_t); i < size; i++)
-+ kdata[i] = data[i];
-+
-+ /*
-+ * Because strings are not zeroed out by default, we need to iterate
-+ * looking for actions that store strings, and we need to explicitly
-+ * pad these strings out with zeroes.
-+ */
-+ for (act = agg->dtag_first; act->dta_intuple; act = act->dta_next) {
-+ int nul;
-+
-+ if (!DTRACEACT_ISSTRING(act))
-+ continue;
-+
-+ i = act->dta_rec.dtrd_offset - agg->dtag_base;
-+ limit = i + act->dta_rec.dtrd_size;
-+ ASSERT(limit <= size);
-+
-+ for (nul = 0; i < limit; i++) {
-+ if (nul) {
-+ kdata[i] = '\0';
-+ continue;
-+ }
-+
-+ if (data[i] != '\0')
-+ continue;
-+
-+ nul = 1;
-+ }
-+ }
-+
-+ for (i = size; i < fsize; i++)
-+ kdata[i] = 0;
-+
-+ key->dtak_hashval = hashval;
-+ key->dtak_size = size;
-+ key->dtak_action = action;
-+ key->dtak_next = agb->dtagb_hash[ndx];
-+ agb->dtagb_hash[ndx] = key;
-+
-+ /*
-+ * Finally, apply the aggregator.
-+ */
-+ *((uint64_t *)(key->dtak_data + size)) = agg->dtag_initial;
-+ dt_dbg_agg(" Aggregate [initial]: Buf %p, offs %d, act %d, "
-+ "%lld (%lld, %lld)\n",
-+ buf, size,
-+ agg->dtag_action.dta_kind - DTRACEACT_AGGREGATION,
-+ *(uint64_t *)(key->dtak_data + size), expr, arg);
-+ agg->dtag_aggregate((uint64_t *)(key->dtak_data + size), expr, arg);
-+}
-diff --git a/dtrace/dtrace_ptofapi.c b/dtrace/dtrace_ptofapi.c
-new file mode 100644
-index 000000000000..c42a8471879c
---- /dev/null
-+++ b/dtrace/dtrace_ptofapi.c
-@@ -0,0 +1,649 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_ptofapi.c
-+ * DESCRIPTION: DTrace - (meta) provider-to-framework API
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/idr.h>
-+#include <linux/list.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+
-+#include "dtrace.h"
-+
-+struct dtrace_provider *dtrace_provider;
-+struct dtrace_meta *dtrace_meta_pid;
-+struct dtrace_helpers *dtrace_deferred_pid;
-+
-+DEFINE_MUTEX(dtrace_provider_lock);
-+DEFINE_MUTEX(dtrace_meta_lock);
-+
-+/*
-+ * Register the calling provider with the DTrace core. This should generally
-+ * be called by providers during module initialization.
-+ */
-+int dtrace_register(const char *name, const struct dtrace_pattr *pap,
-+ uint32_t priv, const struct cred *cr,
-+ const struct dtrace_pops *pops, void *arg,
-+ dtrace_provider_id_t *idp)
-+{
-+ struct dtrace_provider *provider;
-+
-+ if (name == NULL || pap == NULL || pops == NULL || idp == NULL) {
-+ pr_warn("Failed to register provider %s: invalid args\n",
-+ name ? name : "<NULL>");
-+ return -EINVAL;
-+ }
-+
-+ if (name[0] == '\0' || dtrace_badname(name)) {
-+ pr_warn("Failed to register provider %s: invalid name\n",
-+ name);
-+ return -EINVAL;
-+ }
-+
-+ if ((pops->dtps_provide == NULL && pops->dtps_provide_module == NULL) ||
-+ pops->dtps_enable == NULL || pops->dtps_disable == NULL ||
-+ pops->dtps_destroy == NULL ||
-+ ((pops->dtps_resume == NULL) != (pops->dtps_suspend == NULL))) {
-+ pr_warn("Failed to register provider %s: invalid ops\n",
-+ name);
-+ return -EINVAL;
-+ }
-+
-+ if (dtrace_badattr(&pap->dtpa_provider) ||
-+ dtrace_badattr(&pap->dtpa_mod) ||
-+ dtrace_badattr(&pap->dtpa_func) ||
-+ dtrace_badattr(&pap->dtpa_name) ||
-+ dtrace_badattr(&pap->dtpa_args)) {
-+ pr_warn("Failed to register provider %s: invalid attributes\n",
-+ name);
-+ return -EINVAL;
-+ }
-+
-+ if (priv & ~DTRACE_PRIV_ALL) {
-+ pr_warn("Failed to register provider %s: invalid privilege "
-+ "attributes\n", name);
-+ return -EINVAL;
-+ }
-+
-+ if ((priv & DTRACE_PRIV_KERNEL) &&
-+ (priv & (DTRACE_PRIV_USER | DTRACE_PRIV_OWNER)) &&
-+ pops->dtps_usermode == NULL) {
-+ pr_warn("Failed to register provider %s: need "
-+ "dtps_usermode() op for given privilege "
-+ "attributes\n", name);
-+ return -EINVAL;
-+ }
-+
-+ dt_dbg_prov("Registering provider '%s'...\n", name);
-+ provider = kzalloc(sizeof(struct dtrace_provider), GFP_KERNEL);
-+ if (provider == NULL) {
-+ dt_dbg_prov(" Failed to allocate provider struct\n");
-+ return -ENOMEM;
-+ }
-+ provider->dtpv_name = dtrace_strdup(name);
-+ if (provider->dtpv_name == NULL) {
-+ kfree(provider);
-+ dt_dbg_prov(" Failed to allocate provider name\n");
-+ return -ENOMEM;
-+ }
-+ provider->dtpv_attr = *pap;
-+ provider->dtpv_priv.dtpp_flags = priv;
-+
-+ if (cr != NULL) {
-+ provider->dtpv_priv.dtpp_uid =
-+ from_kuid(init_user_namespace, get_cred(cr)->uid);
-+ put_cred(cr);
-+ }
-+
-+ provider->dtpv_pops = *pops;
-+
-+ if (pops->dtps_provide == NULL) {
-+ ASSERT(pops->dtps_provide_module != NULL);
-+ provider->dtpv_pops.dtps_provide =
-+ (void (*)(void *, const struct dtrace_probedesc *))
-+ dtrace_nullop;
-+ }
-+
-+ if (pops->dtps_provide_module == NULL) {
-+ ASSERT(pops->dtps_provide != NULL);
-+ provider->dtpv_pops.dtps_provide_module =
-+ (void (*)(void *, struct module *))dtrace_nullop;
-+ }
-+
-+ if (pops->dtps_destroy_module == NULL) {
-+ provider->dtpv_pops.dtps_destroy_module =
-+ (void (*)(void *, struct module *))dtrace_nullop;
-+ }
-+
-+ if (pops->dtps_suspend == NULL) {
-+ ASSERT(pops->dtps_resume == NULL);
-+ provider->dtpv_pops.dtps_suspend =
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop;
-+ provider->dtpv_pops.dtps_resume =
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop;
-+ }
-+
-+ provider->dtpv_arg = arg;
-+ *idp = (dtrace_provider_id_t)provider;
-+
-+ if (pops == &dtrace_provider_ops) {
-+ ASSERT(MUTEX_HELD(&dtrace_provider_lock));
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dtrace_anon.dta_enabling == NULL);
-+
-+ /*
-+ * The DTrace provider must be at the head of the provider
-+ * chain.
-+ */
-+ provider->dtpv_next = dtrace_provider;
-+ dtrace_provider = provider;
-+
-+ dt_dbg_prov(" Done registering %s\n", name);
-+
-+ return 0;
-+ }
-+
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ /*
-+ * If there is at least one provider registered, we'll add this new one
-+ * after the first provider.
-+ */
-+ if (dtrace_provider != NULL) {
-+ provider->dtpv_next = dtrace_provider->dtpv_next;
-+ dtrace_provider->dtpv_next = provider;
-+ } else
-+ dtrace_provider = provider;
-+
-+ if (dtrace_retained != NULL) {
-+ dt_dbg_prov(" Processing retained enablings for %s\n", name);
-+ dtrace_enabling_provide(provider);
-+
-+ /*
-+ * We must now call dtrace_enabling_matchall() which needs to
-+ * acquire cpu_lock and dtrace_lock. We therefore need to drop
-+ * our locks before calling it.
-+ */
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+ dtrace_enabling_matchall();
-+
-+ dt_dbg_prov(" Done registering %s\n", name);
-+
-+ return 0;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ dt_dbg_prov(" Done registering %s\n", name);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_register);
-+
-+struct unreg_state {
-+ struct dtrace_provider *prov;
-+ struct dtrace_probe *first;
-+};
-+
-+/*
-+ * Check whether the given probe is still enabled for the given provider.
-+ */
-+static int dtrace_unregister_check(int id, void *p, void *data)
-+{
-+ struct dtrace_probe *probe = (struct dtrace_probe *)p;
-+ struct unreg_state *st = (struct unreg_state *)data;
-+
-+ if (probe->dtpr_provider != st->prov)
-+ return 0;
-+
-+ if (probe->dtpr_ecb == NULL)
-+ return 0;
-+
-+ return -EBUSY;
-+}
-+
-+/*
-+ * Remove the given probe from the hash tables and the probe IDR, if it is
-+ * associated with the given provider. The probes are chained for further
-+ * processing.
-+ */
-+static int dtrace_unregister_probe(int id, void *p, void *data)
-+{
-+ struct dtrace_probe *probe = (struct dtrace_probe *)p;
-+ struct unreg_state *st = (struct unreg_state *)data;
-+
-+ if (probe->dtpr_provider != st->prov)
-+ return 0;
-+
-+ dtrace_hash_remove(dtrace_bymod, probe);
-+ dtrace_hash_remove(dtrace_byfunc, probe);
-+ dtrace_hash_remove(dtrace_byname, probe);
-+
-+ if (st->first == NULL) {
-+ st->first = probe;
-+ probe->dtpr_nextmod = NULL;
-+ } else {
-+ probe->dtpr_nextmod = st->first;
-+ st->first = probe;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Remove the given probe from the hash tables and the probe IDR, if it is
-+ * associated with the given provider and if it does not have any enablings.
-+ * The probes are chained for further processing.
-+ */
-+static int dtrace_condense_probe(int id, void *p, void *data)
-+{
-+ struct dtrace_probe *probe = (struct dtrace_probe *)p;
-+ struct unreg_state *st = (struct unreg_state *)data;
-+
-+ if (probe->dtpr_provider != st->prov)
-+ return 0;
-+
-+ if (probe->dtpr_ecb == NULL)
-+ return 0;
-+
-+ dtrace_hash_remove(dtrace_bymod, probe);
-+ dtrace_hash_remove(dtrace_byfunc, probe);
-+ dtrace_hash_remove(dtrace_byname, probe);
-+
-+ if (st->first == NULL) {
-+ st->first = probe;
-+ probe->dtpr_nextmod = NULL;
-+ } else {
-+ probe->dtpr_nextmod = st->first;
-+ st->first = probe;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Unregister the specified provider from the DTrace core. This should be
-+ * called by provider during module cleanup.
-+ *
-+ * The mutex_lock is already held during this call.
-+ */
-+int dtrace_unregister(dtrace_provider_id_t id)
-+{
-+ struct dtrace_provider *old = (struct dtrace_provider *)id;
-+ struct dtrace_provider *prev = NULL;
-+ int err, self = 0;
-+ struct dtrace_probe *probe;
-+ struct unreg_state st = { old, NULL };
-+
-+ ASSERT(MUTEX_HELD(&module_mutex));
-+
-+ dt_dbg_prov("Unregistering provider '%s'...\n", old->dtpv_name);
-+
-+ if (old->dtpv_pops.dtps_enable ==
-+ (int (*)(void *, dtrace_id_t, void *))dtrace_enable_nullop) {
-+ /*
-+ * When the provider is the DTrace core itself, we're called
-+ * with locks already held.
-+ */
-+ ASSERT(old == dtrace_provider);
-+ ASSERT(MUTEX_HELD(&dtrace_provider_lock));
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ self = 1;
-+
-+ if (dtrace_provider->dtpv_next != NULL) {
-+ /*
-+ * We cannot and should not remove the DTrace provider
-+ * if there is any other provider left.
-+ */
-+ dt_dbg_prov(" Failed to unregister %s - not last\n",
-+ old->dtpv_name);
-+
-+ return -EBUSY;
-+ }
-+ } else {
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+ }
-+
-+ /*
-+ * If /dev/dtrace/dtrace is still held open by a process, or if there
-+ * are anonymous probes that are still enabled, we refuse to deregister
-+ * providers, unless the provider has been invalidated explicitly.
-+ */
-+ if (!old->dtpv_defunct &&
-+ (dtrace_opens || (dtrace_anon.dta_state != NULL &&
-+ dtrace_anon.dta_state->dts_necbs > 0))) {
-+ if (!self) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ }
-+
-+ dt_dbg_prov(" Failed to unregister %s - dtrace in use\n",
-+ old->dtpv_name);
-+
-+ return -EBUSY;
-+ }
-+
-+ /*
-+ * Check whether any of the probes associated with this provider are
-+ * still enabled (having at least one ECB). If any are found, we
-+ * cannot remove this provider.
-+ */
-+ st.prov = old;
-+ err = dtrace_probe_for_each(dtrace_unregister_check, &st);
-+ if (err < 0) {
-+ if (!self) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ }
-+
-+ dt_dbg_prov(" Failed to unregister %s - provider in use\n",
-+ old->dtpv_name);
-+
-+ return err;
-+ }
-+
-+ /*
-+ * All the probes associated with this provider are disabled. We can
-+ * safely remove these probes from the hashtables and the probe array.
-+ * We chain all the probes together for further processing.
-+ */
-+ dtrace_probe_for_each(dtrace_unregister_probe, &st);
-+
-+ /*
-+ * The probes associated with the provider have been removed. Ensure
-+ * synchronization on probe IDR processing.
-+ */
-+ dtrace_sync();
-+
-+ /*
-+ * Now get rid of the actual probes.
-+ */
-+ for (probe = st.first; probe != NULL; probe = st.first) {
-+ int probe_id = probe->dtpr_id;
-+
-+ st.first = probe->dtpr_nextmod;
-+
-+ old->dtpv_pops.dtps_destroy(old->dtpv_arg, probe_id,
-+ probe->dtpr_arg);
-+
-+ kfree(probe->dtpr_mod);
-+ kfree(probe->dtpr_func);
-+ kfree(probe->dtpr_name);
-+ kmem_cache_free(dtrace_probe_cachep, probe);
-+
-+ dtrace_probe_remove_id(probe_id);
-+ }
-+
-+ prev = dtrace_provider;
-+ if (prev == old) {
-+ /*
-+ * We are removing the provider at the head of the chain.
-+ */
-+ ASSERT(self);
-+ ASSERT(old->dtpv_next == NULL);
-+
-+ dtrace_provider = old->dtpv_next;
-+ } else {
-+ while (prev != NULL && prev->dtpv_next != old)
-+ prev = prev->dtpv_next;
-+
-+ if (prev == NULL) {
-+ pr_err("Attempt to unregister non-existent DTrace "
-+ "provider %p\n", (void *)id);
-+ BUG();
-+ }
-+
-+ prev->dtpv_next = old->dtpv_next;
-+ }
-+
-+ if (!self) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ }
-+
-+ kfree(old->dtpv_name);
-+ kfree(old);
-+
-+ dt_dbg_prov(" Done unregistering\n");
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_unregister);
-+
-+/*
-+ * Invalidate the specified provider. All subsequent probe lookups for the
-+ * specified provider will fail, but the probes will not be removed.
-+ */
-+void dtrace_invalidate(dtrace_provider_id_t id)
-+{
-+ struct dtrace_provider *pvp = (struct dtrace_provider *)id;
-+
-+ ASSERT(pvp->dtpv_pops.dtps_enable !=
-+ (int (*)(void *, dtrace_id_t, void *))dtrace_enable_nullop);
-+
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ pvp->dtpv_defunct = 1;
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+}
-+EXPORT_SYMBOL(dtrace_invalidate);
-+
-+/*
-+ * Indicate whether or not DTrace has attached.
-+ */
-+int dtrace_attached(void)
-+{
-+ /*
-+ * dtrace_provider will be non-NULL iff the DTrace driver has
-+ * attached. (It's non-NULL because DTrace is always itself a
-+ * provider.)
-+ */
-+ return dtrace_provider != NULL;
-+}
-+EXPORT_SYMBOL(dtrace_attached);
-+
-+/*
-+ * Remove all the unenabled probes for the given provider. This function is
-+ * not unlike dtrace_unregister(), except that it doesn't remove the provider
-+ * -- just as many of its associated probes as it can.
-+ */
-+int dtrace_condense(dtrace_provider_id_t id)
-+{
-+ struct dtrace_provider *prov = (struct dtrace_provider *)id;
-+ struct dtrace_probe *probe;
-+ struct unreg_state st = { prov, NULL };
-+
-+ /*
-+ * Make sure this isn't the DTrace provider itself.
-+ */
-+ ASSERT(prov->dtpv_pops.dtps_enable !=
-+ (int (*)(void *, dtrace_id_t, void *))dtrace_enable_nullop);
-+
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ /*
-+ * Attempt to destroy the probes associated with this provider.
-+ */
-+ dtrace_probe_for_each(dtrace_condense_probe, &st);
-+
-+ /*
-+ * The probes associated with the provider have been removed. Ensure
-+ * synchronization on probe IDR processing.
-+ */
-+ dtrace_sync();
-+
-+ /*
-+ * Now get rid of the actual probes.
-+ */
-+ for (probe = st.first; probe != NULL; probe = st.first) {
-+ int probe_id = probe->dtpr_id;
-+
-+ st.first = probe->dtpr_nextmod;
-+
-+ prov->dtpv_pops.dtps_destroy(prov->dtpv_arg, probe_id,
-+ probe->dtpr_arg);
-+
-+ kfree(probe->dtpr_mod);
-+ kfree(probe->dtpr_func);
-+ kfree(probe->dtpr_name);
-+ kfree(probe);
-+
-+ dtrace_probe_remove_id(probe_id);
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_condense);
-+
-+int dtrace_meta_register(const char *name, const struct dtrace_mops *mops,
-+ void *arg, dtrace_meta_provider_id_t *idp)
-+{
-+ struct dtrace_meta *meta;
-+ struct dtrace_helpers *help, *next;
-+ int i;
-+
-+ *idp = DTRACE_METAPROVNONE;
-+
-+ /*
-+ * We strictly don't need the name, but we hold onto it for
-+ * debuggability. All hail error queues!
-+ */
-+ if (name == NULL) {
-+ pr_warn("failed to register meta-provider: invalid name\n");
-+ return -EINVAL;
-+ }
-+
-+ if (mops == NULL ||
-+ mops->dtms_create_probe == NULL ||
-+ mops->dtms_provide_pid == NULL ||
-+ mops->dtms_remove_pid == NULL) {
-+ pr_warn("failed to register meta-register %s: invalid ops\n",
-+ name);
-+ return -EINVAL;
-+ }
-+
-+ dt_dbg_prov("Registering provider '%s'...\n", name);
-+ meta = kzalloc(sizeof(struct dtrace_meta), GFP_KERNEL);
-+ if (meta == NULL) {
-+ dt_dbg_prov(" Failed to allocate meta provider struct\n");
-+ return -ENOMEM;
-+ }
-+ meta->dtm_mops = *mops;
-+ meta->dtm_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
-+ if (meta->dtm_name == NULL) {
-+ kfree(meta);
-+ dt_dbg_prov(" Failed to allocate meta provider name\n");
-+ return -ENOMEM;
-+ }
-+ strcpy(meta->dtm_name, name);
-+ meta->dtm_arg = arg;
-+
-+ mutex_lock(&dtrace_meta_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (dtrace_meta_pid != NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_meta_lock);
-+ pr_warn("failed to register meta-register %s: user-land "
-+ "meta-provider exists", name);
-+ kfree(meta->dtm_name);
-+ kfree(meta);
-+ return -EINVAL;
-+ }
-+
-+ dtrace_meta_pid = meta;
-+ *idp = (dtrace_meta_provider_id_t)meta;
-+
-+ /*
-+ * If there are providers and probes ready to go, pass them
-+ * off to the new meta provider now.
-+ */
-+ help = dtrace_deferred_pid;
-+ dtrace_deferred_pid = NULL;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ while (help != NULL) {
-+ for (i = 0; i < help->dthps_nprovs; i++) {
-+ dtrace_helper_provide(&help->dthps_provs[i]->dthp_prov,
-+ help->dthps_pid);
-+ }
-+
-+ next = help->dthps_next;
-+ help->dthps_next = NULL;
-+ help->dthps_prev = NULL;
-+ help->dthps_deferred = 0;
-+ help = next;
-+ }
-+
-+ mutex_unlock(&dtrace_meta_lock);
-+
-+ dt_dbg_prov(" Done registering %s\n", name);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_meta_register);
-+
-+int dtrace_meta_unregister(dtrace_meta_provider_id_t id)
-+{
-+ struct dtrace_meta **pp, *old = (struct dtrace_meta *)id;
-+
-+ dt_dbg_prov("Unregistering meta provider '%s'...\n", old->dtm_name);
-+ mutex_lock(&dtrace_meta_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (old == dtrace_meta_pid) {
-+ pp = &dtrace_meta_pid;
-+ } else {
-+ pr_err("Attempt to unregister non-existent DTrace meta-"
-+ "provider %p\n", (void *)old);
-+ BUG();
-+ }
-+
-+ if (old->dtm_count != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_meta_lock);
-+ return -EBUSY;
-+ }
-+
-+ *pp = NULL;
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_meta_lock);
-+
-+ kfree(old->dtm_name);
-+ kfree(old);
-+
-+ dt_dbg_prov(" Done unregistering\n");
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_meta_unregister);
-diff --git a/dtrace/dtrace_spec.c b/dtrace/dtrace_spec.c
-new file mode 100644
-index 000000000000..4ca9bb7a6427
---- /dev/null
-+++ b/dtrace/dtrace_spec.c
-@@ -0,0 +1,434 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_spec.c
-+ * DESCRIPTION: DTrace - speculation implementation
-+ *
-+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/smp.h>
-+#include <asm/cmpxchg.h>
-+
-+#include "dtrace.h"
-+
-+/*
-+ * Given consumer state, this routine finds a speculation in the INACTIVE
-+ * state and transitions it into the ACTIVE state. If there is no speculation
-+ * in the INACTIVE state, 0 is returned. In this case, no error counter is
-+ * incremented -- it is up to the caller to take appropriate action.
-+ */
-+int dtrace_speculation(struct dtrace_state *state)
-+{
-+ int i = 0;
-+ uint32_t count, *stat = &state->dts_speculations_unavail;
-+ enum dtrace_speculation_state curr;
-+
-+ while (i < state->dts_nspeculations) {
-+ struct dtrace_speculation *spec = &state->dts_speculations[i];
-+
-+ curr = spec->dtsp_state;
-+
-+ if (curr != DTRACESPEC_INACTIVE) {
-+ if (curr == DTRACESPEC_COMMITTINGMANY ||
-+ curr == DTRACESPEC_COMMITTING ||
-+ curr == DTRACESPEC_DISCARDING)
-+ stat = &state->dts_speculations_busy;
-+
-+ i++;
-+ continue;
-+ }
-+
-+ if (cmpxchg((uint32_t *)&spec->dtsp_state, curr,
-+ DTRACESPEC_ACTIVE) == curr)
-+ return i + 1;
-+ }
-+
-+ /*
-+ * We couldn't find a speculation. If we found as much as a single
-+ * busy speculation buffer, we'll attribute this failure as "busy"
-+ * instead of "unavail".
-+ */
-+ do {
-+ count = *stat;
-+ } while (cmpxchg(stat, count, count + 1) != count);
-+
-+ return 0;
-+}
-+
-+/*
-+ * This routine commits an active speculation. If the specified speculation
-+ * is not in a valid state to perform a commit(), this routine will silently do
-+ * nothing. The state of the specified speculation is transitioned according
-+ * to the state transition diagram outlined in <sys/dtrace_impl.h>
-+ */
-+void dtrace_speculation_commit(struct dtrace_state *state, processorid_t cpu,
-+ dtrace_specid_t which)
-+{
-+ struct dtrace_speculation *spec;
-+ struct dtrace_buffer *src, *dest;
-+ uintptr_t daddr, saddr, dlimit;
-+ enum dtrace_speculation_state curr, new = 0;
-+ intptr_t offs;
-+
-+ if (which == 0)
-+ return;
-+
-+ if (which > state->dts_nspeculations) {
-+ per_cpu_core(cpu)->cpuc_dtrace_flags |= CPU_DTRACE_ILLOP;
-+ return;
-+ }
-+
-+ spec = &state->dts_speculations[which - 1];
-+ src = &spec->dtsp_buffer[cpu];
-+ dest = &state->dts_buffer[cpu];
-+
-+ do {
-+ curr = spec->dtsp_state;
-+
-+ if (curr == DTRACESPEC_COMMITTINGMANY)
-+ break;
-+
-+ switch (curr) {
-+ case DTRACESPEC_INACTIVE:
-+ case DTRACESPEC_DISCARDING:
-+ return;
-+
-+ case DTRACESPEC_COMMITTING:
-+ /*
-+ * This is only possible if we are (a) commit()'ing
-+ * without having done a prior speculate() on this CPU
-+ * and (b) racing with another commit() on a different
-+ * CPU. There's nothing to do -- we just assert that
-+ * our offset is 0.
-+ */
-+ ASSERT(src->dtb_offset == 0);
-+ return;
-+
-+ case DTRACESPEC_ACTIVE:
-+ new = DTRACESPEC_COMMITTING;
-+ break;
-+
-+ case DTRACESPEC_ACTIVEONE:
-+ /*
-+ * This speculation is active on one CPU. If our
-+ * buffer offset is non-zero, we know that the one CPU
-+ * must be us. Otherwise, we are committing on a
-+ * different CPU from the speculate(), and we must
-+ * rely on being asynchronously cleaned.
-+ */
-+ if (src->dtb_offset != 0) {
-+ new = DTRACESPEC_COMMITTING;
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+
-+ case DTRACESPEC_ACTIVEMANY:
-+ new = DTRACESPEC_COMMITTINGMANY;
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ }
-+ } while (cmpxchg((uint32_t *)&spec->dtsp_state, curr, new) !=
-+ curr);
-+
-+ /*
-+ * We have set the state to indicate that we are committing this
-+ * speculation. Now reserve the necessary space in the destination
-+ * buffer.
-+ */
-+ offs = dtrace_buffer_reserve(dest, src->dtb_offset, sizeof(uint64_t),
-+ state, NULL);
-+ if (offs < 0) {
-+ dtrace_buffer_drop(dest);
-+ goto out;
-+ }
-+
-+ /*
-+ * We have the space; copy the buffer across. (Note that this is a
-+ * highly subobtimal bcopy(); in the unlikely event that this becomes
-+ * a serious performance issue, a high-performance DTrace-specific
-+ * bcopy() should obviously be invented.)
-+ */
-+ daddr = (uintptr_t)dest->dtb_tomax + offs;
-+ dlimit = daddr + src->dtb_offset;
-+ saddr = (uintptr_t)src->dtb_tomax;
-+
-+ /*
-+ * First, the aligned portion.
-+ */
-+ while (dlimit - daddr >= sizeof(uint64_t)) {
-+ *((uint64_t *)daddr) = *((uint64_t *)saddr);
-+ *((uint64_t *)daddr) = *((uint64_t *)saddr);
-+
-+ daddr += sizeof(uint64_t);
-+ saddr += sizeof(uint64_t);
-+ }
-+
-+ /*
-+ * Now any left-over bit...
-+ */
-+ while (dlimit - daddr)
-+ *((uint8_t *)daddr++) = *((uint8_t *)saddr++);
-+
-+ /*
-+ * Finally, commit the reserved space in the destination buffer.
-+ */
-+ dest->dtb_offset = offs + src->dtb_offset;
-+
-+out:
-+ /*
-+ * If we're lucky enough to be the only active CPU on this speculation
-+ * buffer, we can just set the state back to DTRACESPEC_INACTIVE.
-+ */
-+ if (curr == DTRACESPEC_ACTIVE ||
-+ (curr == DTRACESPEC_ACTIVEONE && new == DTRACESPEC_COMMITTING)) {
-+ /*
-+ * Will cause unused warning if DEBUG is not defined.
-+ */
-+ uint32_t rval =
-+ cmpxchg((uint32_t *)&spec->dtsp_state,
-+ DTRACESPEC_COMMITTING,
-+ DTRACESPEC_INACTIVE);
-+
-+ ASSERT(rval == DTRACESPEC_COMMITTING);
-+ rval = 0; /* Avoid warning about unused variable if !DEBUG */
-+ }
-+
-+ src->dtb_offset = 0;
-+ src->dtb_xamot_drops += src->dtb_drops;
-+ src->dtb_drops = 0;
-+}
-+
-+/*
-+ * This routine discards an active speculation. If the specified speculation
-+ * is not in a valid state to perform a discard(), this routine will silently
-+ * do nothing. The state of the specified speculation is transitioned
-+ * according to the state transition diagram outlined in <sys/dtrace_impl.h>
-+ */
-+void dtrace_speculation_discard(struct dtrace_state *state, processorid_t cpu,
-+ dtrace_specid_t which)
-+{
-+ struct dtrace_speculation *spec;
-+ enum dtrace_speculation_state curr, new = 0;
-+ struct dtrace_buffer *buf;
-+
-+ if (which == 0)
-+ return;
-+
-+ if (which > state->dts_nspeculations) {
-+ per_cpu_core(cpu)->cpuc_dtrace_flags |= CPU_DTRACE_ILLOP;
-+ return;
-+ }
-+
-+ spec = &state->dts_speculations[which - 1];
-+ buf = &spec->dtsp_buffer[cpu];
-+
-+ do {
-+ curr = spec->dtsp_state;
-+
-+ switch (curr) {
-+ case DTRACESPEC_INACTIVE:
-+ case DTRACESPEC_COMMITTINGMANY:
-+ case DTRACESPEC_COMMITTING:
-+ case DTRACESPEC_DISCARDING:
-+ return;
-+
-+ case DTRACESPEC_ACTIVE:
-+ case DTRACESPEC_ACTIVEMANY:
-+ new = DTRACESPEC_DISCARDING;
-+ break;
-+
-+ case DTRACESPEC_ACTIVEONE:
-+ if (buf->dtb_offset != 0)
-+ new = DTRACESPEC_INACTIVE;
-+ else
-+ new = DTRACESPEC_DISCARDING;
-+
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ }
-+ } while (cmpxchg((uint32_t *)&spec->dtsp_state, curr, new) != curr);
-+
-+ buf->dtb_offset = 0;
-+ buf->dtb_drops = 0;
-+}
-+
-+/*
-+ * Note: not called from probe context. This function is called
-+ * asynchronously from cross call context to clean any speculations that are
-+ * in the COMMITTINGMANY or DISCARDING states. These speculations may not be
-+ * transitioned back to the INACTIVE state until all CPUs have cleaned the
-+ * speculation.
-+ */
-+void dtrace_speculation_clean_here(struct dtrace_state *state)
-+{
-+ dtrace_icookie_t cookie;
-+ processorid_t cpu = smp_processor_id();
-+ struct dtrace_buffer *dest = &state->dts_buffer[cpu];
-+ dtrace_specid_t i;
-+ uint32_t re_entry;
-+
-+ DTRACE_SYNC_ENTER_CRITICAL(cookie, re_entry);
-+
-+ if (dest->dtb_tomax == NULL) {
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+ return;
-+ }
-+
-+ for (i = 0; i < state->dts_nspeculations; i++) {
-+ struct dtrace_speculation *spec = &state->dts_speculations[i];
-+ struct dtrace_buffer *src = &spec->dtsp_buffer[cpu];
-+
-+ if (src->dtb_tomax == NULL)
-+ continue;
-+
-+ if (spec->dtsp_state == DTRACESPEC_DISCARDING) {
-+ src->dtb_offset = 0;
-+ continue;
-+ }
-+
-+ if (spec->dtsp_state != DTRACESPEC_COMMITTINGMANY)
-+ continue;
-+
-+ if (src->dtb_offset == 0)
-+ continue;
-+
-+ dtrace_speculation_commit(state, cpu, i + 1);
-+ }
-+
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+}
-+
-+void dtrace_speculation_clean(struct dtrace_state *state)
-+{
-+ int work = 0, rv;
-+ dtrace_specid_t i;
-+
-+ for (i = 0; i < state->dts_nspeculations; i++) {
-+ struct dtrace_speculation *spec = &state->dts_speculations[i];
-+
-+ ASSERT(!spec->dtsp_cleaning);
-+
-+ if (spec->dtsp_state != DTRACESPEC_DISCARDING &&
-+ spec->dtsp_state != DTRACESPEC_COMMITTINGMANY)
-+ continue;
-+
-+ work++;
-+ spec->dtsp_cleaning = 1;
-+ }
-+
-+ if (!work)
-+ return;
-+
-+ dtrace_xcall(DTRACE_CPUALL,
-+ (dtrace_xcall_t)dtrace_speculation_clean_here, state);
-+
-+ /*
-+ * We now know that all CPUs have committed or discarded their
-+ * speculation buffers, as appropriate. We can now set the state
-+ * to inactive.
-+ */
-+ for (i = 0; i < state->dts_nspeculations; i++) {
-+ struct dtrace_speculation *spec =
-+ &state->dts_speculations[i];
-+ enum dtrace_speculation_state curr, new;
-+
-+ if (!spec->dtsp_cleaning)
-+ continue;
-+
-+ curr = spec->dtsp_state;
-+ ASSERT(curr == DTRACESPEC_DISCARDING ||
-+ curr == DTRACESPEC_COMMITTINGMANY);
-+
-+ new = DTRACESPEC_INACTIVE;
-+
-+ rv = cmpxchg((uint32_t *)&spec->dtsp_state, curr, new);
-+ ASSERT(rv == curr);
-+ spec->dtsp_cleaning = 0;
-+ }
-+}
-+
-+/*
-+ * Called as part of a speculate() to get the speculative buffer associated
-+ * with a given speculation. Returns NULL if the specified speculation is not
-+ * in an ACTIVE state. If the speculation is in the ACTIVEONE state -- and
-+ * the active CPU is not the specified CPU -- the speculation will be
-+ * atomically transitioned into the ACTIVEMANY state.
-+ */
-+struct dtrace_buffer *dtrace_speculation_buffer(struct dtrace_state *state,
-+ processorid_t cpu,
-+ dtrace_specid_t which)
-+{
-+ struct dtrace_speculation *spec;
-+ enum dtrace_speculation_state curr, new = 0;
-+ struct dtrace_buffer *buf;
-+
-+ if (which == 0)
-+ return NULL;
-+
-+ if (which > state->dts_nspeculations) {
-+ per_cpu_core(cpu)->cpuc_dtrace_flags |= CPU_DTRACE_ILLOP;
-+ return NULL;
-+ }
-+
-+ spec = &state->dts_speculations[which - 1];
-+ buf = &spec->dtsp_buffer[cpu];
-+
-+ do {
-+ curr = spec->dtsp_state;
-+
-+ switch (curr) {
-+ case DTRACESPEC_INACTIVE:
-+ case DTRACESPEC_COMMITTINGMANY:
-+ case DTRACESPEC_DISCARDING:
-+ return NULL;
-+
-+ case DTRACESPEC_COMMITTING:
-+ ASSERT(buf->dtb_offset == 0);
-+ return NULL;
-+
-+ case DTRACESPEC_ACTIVEONE:
-+ /*
-+ * This speculation is currently active on one CPU.
-+ * Check the offset in the buffer; if it's non-zero,
-+ * that CPU must be us (and we leave the state alone).
-+ * If it's zero, assume that we're starting on a new
-+ * CPU -- and change the state to indicate that the
-+ * speculation is active on more than one CPU.
-+ */
-+ if (buf->dtb_offset != 0)
-+ return buf;
-+
-+ new = DTRACESPEC_ACTIVEMANY;
-+ break;
-+
-+ case DTRACESPEC_ACTIVEMANY:
-+ return buf;
-+
-+ case DTRACESPEC_ACTIVE:
-+ new = DTRACESPEC_ACTIVEONE;
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ }
-+ } while (cmpxchg((uint32_t *)&spec->dtsp_state, curr, new) != curr);
-+
-+ ASSERT(new == DTRACESPEC_ACTIVEONE || new == DTRACESPEC_ACTIVEMANY);
-+
-+ return buf;
-+}
-diff --git a/dtrace/dtrace_state.c b/dtrace/dtrace_state.c
-new file mode 100644
-index 000000000000..7fb696e8f1a9
---- /dev/null
-+++ b/dtrace/dtrace_state.c
-@@ -0,0 +1,1108 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_state.c
-+ * DESCRIPTION: DTrace - consumer state implementation
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/cyclic.h>
-+#include <linux/fs.h>
-+#include <linux/idr.h>
-+#include <linux/slab.h>
-+#include <linux/smp.h>
-+#include <linux/vmalloc.h>
-+#include <asm/cmpxchg.h>
-+
-+#include "dtrace.h"
-+
-+int dtrace_destructive_disallow = 0;
-+dtrace_optval_t dtrace_nspec_default = 1;
-+dtrace_optval_t dtrace_specsize_default = 32 * 1024;
-+dtrace_optval_t dtrace_dstate_defsize = 1 * 1024 * 1024;
-+size_t dtrace_strsize_default = 256;
-+dtrace_optval_t dtrace_stackframes_default = 20;
-+dtrace_optval_t dtrace_ustackframes_default = 100;
-+dtrace_optval_t dtrace_cleanrate_default = 9900990;
-+dtrace_optval_t dtrace_cleanrate_min = 20000;
-+dtrace_optval_t dtrace_cleanrate_max = (uint64_t)60 * NANOSEC;
-+dtrace_optval_t dtrace_aggrate_default = NANOSEC;
-+dtrace_optval_t dtrace_switchrate_default = NANOSEC;
-+dtrace_optval_t dtrace_statusrate_default = NANOSEC;
-+dtrace_optval_t dtrace_statusrate_max = (uint64_t)10 * NANOSEC;
-+dtrace_optval_t dtrace_jstackframes_default = 50;
-+dtrace_optval_t dtrace_jstackstrsize_default = 512;
-+ktime_t dtrace_deadman_interval = KTIME_INIT(1, 0);
-+ktime_t dtrace_deadman_timeout = KTIME_INIT(10, 0);
-+ktime_t dtrace_deadman_user = KTIME_INIT(30, 0);
-+
-+ /* Sampling before counting */
-+uint64_t dtrace_sync_sample_count = 100;
-+
-+dtrace_id_t dtrace_probeid_begin;
-+dtrace_id_t dtrace_probeid_end;
-+dtrace_id_t dtrace_probeid_error;
-+
-+struct dtrace_dynvar dtrace_dynhash_sink;
-+
-+#define DTRACE_DYNHASH_FREE 0
-+#define DTRACE_DYNHASH_SINK 1
-+#define DTRACE_DYNHASH_VALID 2
-+
-+#define DTRACE_DYNVAR_CHUNKSIZE 256
-+
-+static void dtrace_dynvar_clean(struct dtrace_dstate *dstate)
-+{
-+ struct dtrace_dynvar *dirty;
-+ struct dtrace_dstate_percpu *dcpu;
-+ int i, work = 0;
-+
-+ for (i = 0; i < NR_CPUS; i++) {
-+ dcpu = &dstate->dtds_percpu[i];
-+
-+ ASSERT(dcpu->dtdsc_rinsing == NULL);
-+
-+ /*
-+ * If the dirty list is NULL, there is no dirty work to do.
-+ */
-+ if (dcpu->dtdsc_dirty == NULL)
-+ continue;
-+
-+ /*
-+ * If the clean list is non-NULL, then we're not going to do
-+ * any work for this CPU -- it means that there has not been
-+ * a dtrace_dynvar() allocation on this CPU (or from this CPU)
-+ * since the last time we cleaned house.
-+ */
-+ if (dcpu->dtdsc_clean != NULL)
-+ continue;
-+
-+ work = 1;
-+
-+ /*
-+ * Atomically move the dirty list aside.
-+ */
-+ do {
-+ dirty = dcpu->dtdsc_dirty;
-+
-+ /*
-+ * Before we zap the dirty list, set the rinsing list.
-+ * (This allows for a potential assertion in
-+ * dtrace_dynvar(): if a free dynamic variable appears
-+ * on a hash chain, either the dirty list or the
-+ * rinsing list for some CPU must be non-NULL.)
-+ */
-+ dcpu->dtdsc_rinsing = dirty;
-+ dtrace_membar_producer();
-+ } while (cmpxchg(&dcpu->dtdsc_dirty, dirty, NULL) != dirty);
-+ }
-+
-+ /*
-+ * No work to do; return.
-+ */
-+ if (!work)
-+ return;
-+
-+ dtrace_sync();
-+
-+ for (i = 0; i < NR_CPUS; i++) {
-+ dcpu = &dstate->dtds_percpu[i];
-+
-+ if (dcpu->dtdsc_rinsing == NULL)
-+ continue;
-+
-+ /*
-+ * We are now guaranteed that no hash chain contains a pointer
-+ * into this dirty list; we can make it clean.
-+ */
-+ ASSERT(dcpu->dtdsc_clean == NULL);
-+ dcpu->dtdsc_clean = dcpu->dtdsc_rinsing;
-+ dcpu->dtdsc_rinsing = NULL;
-+ }
-+
-+ /*
-+ * Before we actually set the state to be DTRACE_DSTATE_CLEAN, make
-+ * sure that all CPUs have seen all of the dtdsc_clean pointers.
-+ * This prevents a race whereby a CPU incorrectly decides that
-+ * the state should be something other than DTRACE_DSTATE_CLEAN
-+ * after dtrace_dynvar_clean() has completed.
-+ */
-+ dtrace_sync();
-+
-+ dstate->dtds_state = DTRACE_DSTATE_CLEAN;
-+}
-+
-+int dtrace_dstate_init(struct dtrace_dstate *dstate, size_t size)
-+{
-+ size_t hashsize, maxper, min,
-+ chunksize = dstate->dtds_chunksize;
-+ void *base, *percpu;
-+ uintptr_t limit;
-+ struct dtrace_dynvar *dvar, *next, *start;
-+ int i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dstate->dtds_base == NULL && dstate->dtds_percpu == NULL);
-+
-+ memset(dstate, 0, sizeof(struct dtrace_dstate));
-+
-+ dstate->dtds_chunksize = chunksize;
-+ if (dstate->dtds_chunksize == 0)
-+ dstate->dtds_chunksize = DTRACE_DYNVAR_CHUNKSIZE;
-+
-+ min = dstate->dtds_chunksize + sizeof(struct dtrace_dynhash);
-+ if (size < min)
-+ size = min;
-+
-+ base = dtrace_vzalloc_try(size);
-+ if (base == NULL)
-+ return -ENOMEM;
-+ percpu = kmem_cache_alloc(dtrace_state_cachep, GFP_KERNEL);
-+ if (percpu == NULL) {
-+ vfree(base);
-+ return -ENOMEM;
-+ }
-+
-+ dstate->dtds_size = size;
-+ dstate->dtds_base = base;
-+ dstate->dtds_percpu = percpu;
-+ memset(dstate->dtds_percpu, 0,
-+ NR_CPUS * sizeof(struct dtrace_dstate_percpu));
-+
-+ hashsize = size /
-+ (dstate->dtds_chunksize + sizeof(struct dtrace_dynhash));
-+
-+ if (hashsize != 1 && (hashsize & 1))
-+ hashsize--;
-+
-+ dstate->dtds_hashsize = hashsize;
-+ dstate->dtds_hash = dstate->dtds_base;
-+
-+ /*
-+ * Set all of our hash buckets to point to the single sink, and (if
-+ * it hasn't already been set), set the sink's hash value to be the
-+ * sink sentinel value. The sink is needed for dynamic variable
-+ * lookups to know that they have iterated over an entire, valid hash
-+ * chain.
-+ */
-+ for (i = 0; i < hashsize; i++)
-+ dstate->dtds_hash[i].dtdh_chain = &dtrace_dynhash_sink;
-+
-+ if (dtrace_dynhash_sink.dtdv_hashval != DTRACE_DYNHASH_SINK)
-+ dtrace_dynhash_sink.dtdv_hashval = DTRACE_DYNHASH_SINK;
-+
-+ /*
-+ * Determine number of active CPUs. Divide free list evenly among
-+ * active CPUs.
-+ */
-+ start = (struct dtrace_dynvar *)((uintptr_t)base +
-+ hashsize * sizeof(struct dtrace_dynhash));
-+ limit = (uintptr_t)base + size;
-+
-+ maxper = (limit - (uintptr_t)start) / NR_CPUS;
-+ maxper = (maxper / dstate->dtds_chunksize) * dstate->dtds_chunksize;
-+
-+ for (i = 0; i < NR_CPUS; i++) {
-+ dstate->dtds_percpu[i].dtdsc_free = dvar = start;
-+
-+ /*
-+ * If we don't even have enough chunks to make it once through
-+ * NCPUs, we're just going to allocate everything to the first
-+ * CPU. And if we're on the last CPU, we're going to allocate
-+ * whatever is left over. In either case, we set the limit to
-+ * be the limit of the dynamic variable space.
-+ */
-+ if (maxper == 0 || i == NR_CPUS - 1) {
-+ limit = (uintptr_t)base + size;
-+ start = NULL;
-+ } else {
-+ limit = (uintptr_t)start + maxper;
-+ start = (struct dtrace_dynvar *)limit;
-+ }
-+
-+ ASSERT(limit <= (uintptr_t)base + size);
-+
-+ for (;;) {
-+ next = (struct dtrace_dynvar *)((uintptr_t)dvar +
-+ dstate->dtds_chunksize);
-+
-+ if ((uintptr_t)next + dstate->dtds_chunksize >= limit)
-+ break;
-+
-+ dvar->dtdv_next = next;
-+ dvar = next;
-+ }
-+
-+ if (maxper == 0)
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+void dtrace_dstate_fini(struct dtrace_dstate *dstate)
-+{
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+ if (dstate->dtds_base == NULL)
-+ return;
-+
-+ vfree(dstate->dtds_base);
-+ kmem_cache_free(dtrace_state_cachep, dstate->dtds_percpu);
-+}
-+
-+void dtrace_vstate_fini(struct dtrace_vstate *vstate)
-+{
-+ /*
-+ * If only there was a logical XOR operator...
-+ */
-+ ASSERT((vstate->dtvs_nglobals == 0) ^ (vstate->dtvs_globals != NULL));
-+
-+ if (vstate->dtvs_nglobals > 0)
-+ vfree(vstate->dtvs_globals);
-+
-+ if (vstate->dtvs_ntlocals > 0)
-+ vfree(vstate->dtvs_tlocals);
-+
-+ ASSERT((vstate->dtvs_nlocals == 0) ^ (vstate->dtvs_locals != NULL));
-+
-+ if (vstate->dtvs_nlocals > 0)
-+ vfree(vstate->dtvs_locals);
-+}
-+
-+static void dtrace_state_clean(struct dtrace_state *state)
-+{
-+ dtrace_optval_t *opt = state->dts_options;
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_ACTIVE &&
-+ state->dts_activity != DTRACE_ACTIVITY_DRAINING)
-+ return;
-+
-+ dtrace_dynvar_clean(&state->dts_vstate.dtvs_dynvars);
-+ dtrace_speculation_clean(state);
-+
-+ cyclic_reprogram(state->dts_cleaner, ns_to_ktime(
-+ opt[DTRACEOPT_CLEANRATE]));
-+}
-+
-+static void dtrace_state_deadman(struct dtrace_state *state)
-+{
-+ ktime_t now;
-+
-+ dtrace_sync();
-+
-+ now = dtrace_gethrtime();
-+ if (state != dtrace_anon.dta_state &&
-+ ktime_ge(ktime_sub(now, state->dts_laststatus),
-+ dtrace_deadman_user))
-+ return;
-+
-+ /*
-+ * We must be sure that dts_alive never appears to be less than the
-+ * value upon entry to dtrace_state_deadman(), and because we lack a
-+ * dtrace_cas64(), we cannot store to it atomically. We thus instead
-+ * store KTIME_MAX to it, followed by a memory barrier, followed by
-+ * the new value. This assures that dts_alive never appears to be
-+ * less than its true value, regardless of the order in which the
-+ * stores to the underlying storage are issued.
-+ */
-+ state->dts_alive = ktime_set(KTIME_SEC_MAX, 0);
-+ dtrace_membar_producer();
-+ state->dts_alive = now;
-+}
-+
-+struct dtrace_state *dtrace_state_create(struct file *file)
-+{
-+ struct dtrace_state *state;
-+ dtrace_optval_t *opt;
-+ int bufsize = NR_CPUS * sizeof(struct dtrace_buffer), i;
-+#ifdef FIXME
-+ const struct cred *cr = file->f_cred;
-+#endif
-+ dtrace_aggid_t aggid;
-+
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ state = kzalloc(sizeof(struct dtrace_state), GFP_KERNEL);
-+ if (state == NULL)
-+ return NULL;
-+
-+ state->dts_epid = DTRACE_EPIDNONE + 1;
-+ state->dts_buffer = vzalloc(bufsize);
-+ if (state->dts_buffer == NULL) {
-+ kfree(state);
-+ return NULL;
-+ }
-+
-+ state->dts_aggbuffer = vzalloc(bufsize);
-+ if (state->dts_aggbuffer == NULL) {
-+ vfree(state->dts_buffer);
-+ kfree(state);
-+ return NULL;
-+ }
-+
-+ idr_init(&state->dts_agg_idr);
-+ state->dts_naggs = 0;
-+ state->dts_cleaner = 0;
-+ state->dts_deadman = 0;
-+ state->dts_vstate.dtvs_state = state;
-+
-+ /*
-+ * Create a first entry in the aggregation IDR, so that ID 0 is used as
-+ * that gets used as meaning 'none'.
-+ */
-+ idr_preload(GFP_KERNEL);
-+ aggid = idr_alloc_cyclic(&state->dts_agg_idr, NULL, 0, 0, GFP_NOWAIT);
-+ idr_preload_end();
-+
-+ ASSERT(aggid == 0);
-+
-+ for (i = 0; i < DTRACEOPT_MAX; i++)
-+ state->dts_options[i] = DTRACEOPT_UNSET;
-+
-+ /*
-+ * Set the default options.
-+ */
-+ opt = state->dts_options;
-+ opt[DTRACEOPT_BUFPOLICY] = DTRACEOPT_BUFPOLICY_SWITCH;
-+ opt[DTRACEOPT_BUFRESIZE] = DTRACEOPT_BUFRESIZE_AUTO;
-+ opt[DTRACEOPT_NSPEC] = dtrace_nspec_default;
-+ opt[DTRACEOPT_SPECSIZE] = dtrace_specsize_default;
-+ opt[DTRACEOPT_CPU] = (dtrace_optval_t)DTRACE_CPUALL;
-+ opt[DTRACEOPT_STRSIZE] = dtrace_strsize_default;
-+ opt[DTRACEOPT_STACKFRAMES] = dtrace_stackframes_default;
-+ opt[DTRACEOPT_USTACKFRAMES] = dtrace_ustackframes_default;
-+ opt[DTRACEOPT_CLEANRATE] = dtrace_cleanrate_default;
-+ opt[DTRACEOPT_AGGRATE] = dtrace_aggrate_default;
-+ opt[DTRACEOPT_SWITCHRATE] = dtrace_switchrate_default;
-+ opt[DTRACEOPT_STATUSRATE] = dtrace_statusrate_default;
-+ opt[DTRACEOPT_JSTACKFRAMES] = dtrace_jstackframes_default;
-+ opt[DTRACEOPT_JSTACKSTRSIZE] = dtrace_jstackstrsize_default;
-+
-+ state->dts_activity = DTRACE_ACTIVITY_INACTIVE;
-+
-+#ifdef FIXME
-+ /*
-+ * Set probe visibility and destructiveness based on user credential
-+ * information. For actual anonymous tracing or if all privileges are
-+ * set, checks are bypassed.
-+ */
-+ if (cr == NULL ||
-+ PRIV_POLICY_ONLY(cr, PRIV_ALL, FALSE)) {
-+ state->dts_cred.dcr_visible = DTRACE_CRV_ALL;
-+ state->dts_cred.dcr_action = DTRACE_CRA_ALL;
-+ } else {
-+ state->dts_cred.dcr_cred = get_cred(cr);
-+
-+ /*
-+ * CRA_PROC means "we have *some* privilege for dtrace" and
-+ * it unlocks the use of variables like pid, etc.
-+ */
-+ if (PRIV_POLICY_ONLY(cr, PRIV_DTRACE_USER, FALSE) ||
-+ PRIV_POLICY_ONLY(cr, PRIV_DTRACE_PROC, FALSE))
-+ state->dts_cred.dcr_action |= DTRACE_CRA_PROC;
-+
-+ /*
-+ * The DTRACE_USER privilege allows the use of syscall and
-+ * profile providers. If the user also has PROC_OWNER, we
-+ * extend the scope to include additional visibility and
-+ * destructive power.
-+ */
-+ if (PRIV_POLICY_ONLY(cr, PRIV_DTRACE_USER, FALSE)) {
-+ if (PRIV_POLICY_ONLY(cr, PRIV_PROC_OWNER, FALSE))
-+ state->dts_cred.dcr_visible |=
-+ DTRACE_CRV_ALLPROC;
-+
-+ state->dts_cred.dcr_action |=
-+ DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER;
-+ }
-+
-+ /*
-+ * Holding the DTRACE_KERNEL privilege also implies that
-+ * the user has the DTRACE_USER privilege from a visibility
-+ * perspective. But without further privileges, some
-+ * destructive actions are not available.
-+ */
-+ if (PRIV_POLICY_ONLY(cr, PRIV_DTRACE_KERNEL, FALSE)) {
-+ /*
-+ * Make all probes in all zones visible. However,
-+ * this doesn't mean that all actions become available
-+ * to all zones.
-+ */
-+ state->dts_cred.dcr_visible |= DTRACE_CRV_KERNEL |
-+ DTRACE_CRV_ALLPROC;
-+ state->dts_cred.dcr_action |= DTRACE_CRA_KERNEL |
-+ DTRACE_CRA_PROC;
-+
-+ /*
-+ * Holding PROC_OWNER means that destructive actions
-+ * are allowed.
-+ */
-+ if (PRIV_POLICY_ONLY(cr, PRIV_PROC_OWNER, FALSE))
-+ state->dts_cred.dcr_action |=
-+ DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER;
-+ }
-+
-+ /*
-+ * Holding the DTRACE_PROC privilege gives control over the
-+ * fasttrap and pid providers. We need to grant wider
-+ * destructive privileges in the event that the user has
-+ * PROC_OWNER .
-+ */
-+ if (PRIV_POLICY_ONLY(cr, PRIV_DTRACE_PROC, FALSE)) {
-+ if (PRIV_POLICY_ONLY(cr, PRIV_PROC_OWNER, FALSE))
-+ state->dts_cred.dcr_action |=
-+ DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER;
-+ }
-+ }
-+#else
-+ state->dts_cred.dcr_visible = DTRACE_CRV_ALLPROC | DTRACE_CRV_KERNEL;
-+ state->dts_cred.dcr_action = DTRACE_CRA_ALL;
-+#endif
-+
-+ return state;
-+}
-+
-+static int dtrace_state_buffer(struct dtrace_state *state,
-+ struct dtrace_buffer *buf, int which)
-+{
-+ dtrace_optval_t *opt = state->dts_options, size;
-+ processorid_t cpu = DTRACE_CPUALL;
-+ int flags = 0, rval;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+ ASSERT(which < DTRACEOPT_MAX);
-+ ASSERT(state->dts_activity == DTRACE_ACTIVITY_INACTIVE ||
-+ (state == dtrace_anon.dta_state &&
-+ state->dts_activity == DTRACE_ACTIVITY_ACTIVE));
-+
-+ if (opt[which] == DTRACEOPT_UNSET || opt[which] == 0)
-+ return 0;
-+
-+ if (opt[DTRACEOPT_CPU] != DTRACEOPT_UNSET)
-+ cpu = opt[DTRACEOPT_CPU];
-+
-+ if (which == DTRACEOPT_SPECSIZE)
-+ flags |= DTRACEBUF_NOSWITCH;
-+
-+ if (which == DTRACEOPT_BUFSIZE) {
-+ if (opt[DTRACEOPT_BUFPOLICY] == DTRACEOPT_BUFPOLICY_RING)
-+ flags |= DTRACEBUF_RING;
-+
-+ if (opt[DTRACEOPT_BUFPOLICY] == DTRACEOPT_BUFPOLICY_FILL)
-+ flags |= DTRACEBUF_FILL;
-+
-+ if (state != dtrace_anon.dta_state ||
-+ state->dts_activity != DTRACE_ACTIVITY_ACTIVE)
-+ flags |= DTRACEBUF_INACTIVE;
-+ }
-+
-+ for (size = opt[which]; size >= sizeof(uint64_t); size >>= 1) {
-+ /*
-+ * The size must be 8-byte aligned. If the size is not 8-byte
-+ * aligned, drop it down by the difference.
-+ */
-+ if (size & (sizeof(uint64_t) - 1))
-+ size -= size & (sizeof(uint64_t) - 1);
-+
-+ if (size < state->dts_reserve) {
-+ /*
-+ * Buffers always must be large enough to accommodate
-+ * their prereserved space. We return -E2BIG instead
-+ * of ENOMEM in this case to allow for user-level
-+ * software to differentiate the cases.
-+ */
-+ return -E2BIG;
-+ }
-+
-+ rval = dtrace_buffer_alloc(buf, size, flags, cpu);
-+ if (rval != -ENOMEM) {
-+ opt[which] = size;
-+ return rval;
-+ }
-+
-+ if (opt[DTRACEOPT_BUFRESIZE] == DTRACEOPT_BUFRESIZE_MANUAL)
-+ return rval;
-+ }
-+
-+ return -ENOMEM;
-+}
-+
-+static int dtrace_state_buffers(struct dtrace_state *state)
-+{
-+ struct dtrace_speculation *spec = state->dts_speculations;
-+ int rval, i;
-+
-+ rval = dtrace_state_buffer(state, state->dts_buffer, DTRACEOPT_BUFSIZE);
-+ if (rval != 0)
-+ return rval;
-+
-+ rval = dtrace_state_buffer(state, state->dts_aggbuffer,
-+ DTRACEOPT_AGGSIZE);
-+ if (rval != 0)
-+ return rval;
-+
-+ for (i = 0; i < state->dts_nspeculations; i++) {
-+ rval = dtrace_state_buffer(state, spec[i].dtsp_buffer,
-+ DTRACEOPT_SPECSIZE);
-+ if (rval != 0)
-+ return rval;
-+ }
-+
-+ return 0;
-+}
-+
-+static void dtrace_begin_probe(struct dtrace_state *state)
-+{
-+ processorid_t cpuid = smp_processor_id();
-+
-+ ASSERT(state->dts_buffer[cpuid].dtb_flags & DTRACEBUF_INACTIVE);
-+ state->dts_buffer[cpuid].dtb_flags &= ~DTRACEBUF_INACTIVE;
-+
-+ dtrace_probe(dtrace_probeid_begin, (uint64_t)(uintptr_t)state, 0, 0, 0,
-+ 0, 0, 0);
-+
-+ /*
-+ * We may have had an exit action from a BEGIN probe; only change our
-+ * state to ACTIVE if we're still in WARMUP.
-+ */
-+ ASSERT(state->dts_activity == DTRACE_ACTIVITY_WARMUP ||
-+ state->dts_activity == DTRACE_ACTIVITY_DRAINING);
-+
-+ if (state->dts_activity == DTRACE_ACTIVITY_WARMUP)
-+ state->dts_activity = DTRACE_ACTIVITY_ACTIVE;
-+
-+ dtrace_membar_enter();
-+}
-+
-+static void dtrace_state_prereserve(struct dtrace_state *state)
-+{
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_probe *probe;
-+
-+ state->dts_reserve = 0;
-+
-+ if (state->dts_options[DTRACEOPT_BUFPOLICY] != DTRACEOPT_BUFPOLICY_FILL)
-+ return;
-+
-+ /*
-+ * If our buffer policy is a "fill" buffer policy, we need to set the
-+ * prereserved space to be the space required by the END probes.
-+ */
-+ probe = dtrace_probe_lookup_id(dtrace_probeid_end);
-+ ASSERT(probe != NULL);
-+
-+ for (ecb = probe->dtpr_ecb; ecb != NULL; ecb = ecb->dte_next) {
-+ if (ecb->dte_state != state)
-+ continue;
-+
-+ state->dts_reserve += ecb->dte_needed + ecb->dte_alignment;
-+ }
-+}
-+
-+int dtrace_state_go(struct dtrace_state *state, processorid_t *cpu)
-+{
-+ dtrace_optval_t *opt = state->dts_options, sz, nspec;
-+ struct dtrace_speculation *spec;
-+ struct dtrace_buffer *buf;
-+ struct cyc_handler hdlr;
-+ struct cyc_time when;
-+ processorid_t cpuid;
-+ int rval = 0, i, bufsize = NR_CPUS * sizeof(struct dtrace_buffer);
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE) {
-+ rval = -EBUSY;
-+ goto out;
-+ }
-+
-+ /*
-+ * Before we can perform any checks, we must prime all of the
-+ * retained enablings that correspond to this state.
-+ */
-+ dtrace_enabling_prime(state);
-+
-+ if (state->dts_destructive && !state->dts_cred.dcr_destructive) {
-+ rval = -EACCES;
-+ goto out;
-+ }
-+
-+ dtrace_state_prereserve(state);
-+
-+ /*
-+ * If a cpu has been selected check if its value is valid and
-+ * the cpu is online.
-+ */
-+ cpuid = opt[DTRACEOPT_CPU];
-+ if (cpuid != DTRACE_CPUALL &&
-+ (cpuid < 0 || cpuid >= NR_CPUS || !cpu_online(cpuid))) {
-+ rval = -ENXIO;
-+ goto out;
-+ }
-+
-+ /*
-+ * Now we want to do is try to allocate our speculations.
-+ * We do not automatically resize the number of speculations; if
-+ * this fails, we will fail the operation.
-+ */
-+ nspec = opt[DTRACEOPT_NSPEC];
-+ ASSERT(nspec != DTRACEOPT_UNSET);
-+
-+ if (nspec > INT_MAX) {
-+ rval = -ENOMEM;
-+ goto out;
-+ }
-+
-+ spec = vzalloc(nspec * sizeof(struct dtrace_speculation));
-+ if (spec == NULL) {
-+ rval = -ENOMEM;
-+ goto out;
-+ }
-+
-+ state->dts_speculations = spec;
-+ state->dts_nspeculations = (int)nspec;
-+
-+ for (i = 0; i < nspec; i++) {
-+ buf = vzalloc(bufsize);
-+ if (buf == NULL) {
-+ rval = -ENOMEM;
-+ goto err;
-+ }
-+
-+ spec[i].dtsp_buffer = buf;
-+ }
-+
-+ if (opt[DTRACEOPT_GRABANON] != DTRACEOPT_UNSET) {
-+ if (dtrace_anon.dta_state == NULL) {
-+ rval = -ENOENT;
-+ goto out;
-+ }
-+
-+ if (state->dts_necbs != 0) {
-+ rval = -EALREADY;
-+ goto out;
-+ }
-+
-+ state->dts_anon = dtrace_anon_grab();
-+ ASSERT(state->dts_anon != NULL);
-+ state = state->dts_anon;
-+
-+ /*
-+ * We want "grabanon" to be set in the grabbed state, so we'll
-+ * copy that option value from the grabbing state into the
-+ * grabbed state.
-+ */
-+ state->dts_options[DTRACEOPT_GRABANON] =
-+ opt[DTRACEOPT_GRABANON];
-+
-+ *cpu = dtrace_anon.dta_beganon;
-+
-+ /*
-+ * If the anonymous state is active (as it almost certainly
-+ * is if the anonymous enabling ultimately matched anything),
-+ * we don't allow any further option processing -- but we
-+ * don't return failure.
-+ */
-+ if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE)
-+ goto out;
-+ }
-+
-+ if (opt[DTRACEOPT_AGGSIZE] != DTRACEOPT_UNSET &&
-+ opt[DTRACEOPT_AGGSIZE] != 0) {
-+ if (state->dts_naggs == 0) {
-+ /*
-+ * We're not going to create an aggregation buffer
-+ * because we don't have any ECBs that contain
-+ * aggregations -- set this option to 0.
-+ */
-+ opt[DTRACEOPT_AGGSIZE] = 0;
-+ } else {
-+ /*
-+ * If we have an aggregation buffer, we must also have
-+ * a buffer to use as scratch.
-+ */
-+ if (opt[DTRACEOPT_BUFSIZE] == DTRACEOPT_UNSET ||
-+ opt[DTRACEOPT_BUFSIZE] < state->dts_needed)
-+ opt[DTRACEOPT_BUFSIZE] = state->dts_needed;
-+ }
-+ }
-+
-+ if (opt[DTRACEOPT_SPECSIZE] != DTRACEOPT_UNSET &&
-+ opt[DTRACEOPT_SPECSIZE] != 0) {
-+ /*
-+ * We are not going to create speculation buffers if we do not
-+ * have any ECBs that actually speculate.
-+ */
-+ if (!state->dts_speculates)
-+ opt[DTRACEOPT_SPECSIZE] = 0;
-+ }
-+
-+ /*
-+ * The bare minimum size for any buffer that we're actually going to
-+ * do anything to is sizeof (uint64_t).
-+ */
-+ sz = sizeof(uint64_t);
-+
-+ if ((state->dts_needed != 0 && opt[DTRACEOPT_BUFSIZE] < sz) ||
-+ (state->dts_speculates && opt[DTRACEOPT_SPECSIZE] < sz) ||
-+ (state->dts_naggs != 0 && opt[DTRACEOPT_AGGSIZE] < sz)) {
-+ /*
-+ * A buffer size has been explicitly set to 0 (or to a size
-+ * that will be adjusted to 0) and we need the space -- we
-+ * need to return failure. We return -ENOSPC to differentiate
-+ * it from failing to allocate a buffer due to failure to meet
-+ * the reserve (for which we return -E2BIG).
-+ */
-+ rval = -ENOSPC;
-+ goto out;
-+ }
-+
-+ rval = dtrace_state_buffers(state);
-+ if (rval != 0)
-+ goto err;
-+
-+ sz = opt[DTRACEOPT_DYNVARSIZE];
-+ if (sz == DTRACEOPT_UNSET)
-+ sz = dtrace_dstate_defsize;
-+
-+ do {
-+ rval = dtrace_dstate_init(&state->dts_vstate.dtvs_dynvars, sz);
-+
-+ if (rval == 0)
-+ break;
-+
-+ if (opt[DTRACEOPT_BUFRESIZE] == DTRACEOPT_BUFRESIZE_MANUAL)
-+ goto err;
-+ } while (sz >>= 1);
-+
-+ opt[DTRACEOPT_DYNVARSIZE] = sz;
-+
-+ if (rval != 0)
-+ goto err;
-+
-+ if (opt[DTRACEOPT_STATUSRATE] > dtrace_statusrate_max)
-+ opt[DTRACEOPT_STATUSRATE] = dtrace_statusrate_max;
-+
-+ if (opt[DTRACEOPT_CLEANRATE] == 0)
-+ opt[DTRACEOPT_CLEANRATE] = dtrace_cleanrate_max;
-+
-+ if (opt[DTRACEOPT_CLEANRATE] < dtrace_cleanrate_min)
-+ opt[DTRACEOPT_CLEANRATE] = dtrace_cleanrate_min;
-+
-+ if (opt[DTRACEOPT_CLEANRATE] > dtrace_cleanrate_max)
-+ opt[DTRACEOPT_CLEANRATE] = dtrace_cleanrate_max;
-+
-+ hdlr.cyh_func = (cyc_func_t)dtrace_state_clean;
-+ hdlr.cyh_arg = (uintptr_t)state;
-+ hdlr.cyh_level = CY_LOW_LEVEL;
-+
-+ when.cyt_when = ktime_set(0, 0);
-+ when.cyt_interval = CY_INTERVAL_INF;
-+
-+ state->dts_cleaner = cyclic_add(&hdlr, &when);
-+ cyclic_reprogram(state->dts_cleaner, ns_to_ktime(
-+ opt[DTRACEOPT_CLEANRATE]));
-+
-+ hdlr.cyh_func = (cyc_func_t)dtrace_state_deadman;
-+ hdlr.cyh_arg = (uintptr_t)state;
-+ hdlr.cyh_level = CY_LOW_LEVEL;
-+
-+ when.cyt_when = ktime_set(0, 0);
-+ when.cyt_interval = dtrace_deadman_interval;
-+
-+ state->dts_alive = state->dts_laststatus = dtrace_gethrtime();
-+ state->dts_deadman = cyclic_add(&hdlr, &when);
-+
-+ state->dts_activity = DTRACE_ACTIVITY_WARMUP;
-+
-+ /*
-+ * Issue xcall even when the BEGIN probe fires on current CPU. The
-+ * underlying implementation of SMP will turn it into direct function
-+ * call. It is not allowed to turn off interrupts so we need to pick
-+ * a cpu first and then xcall it. This way a begin probe will always
-+ * fire on the expected cpu.
-+ */
-+ *cpu = (cpuid == DTRACE_CPUALL) ? smp_processor_id() : cpuid;
-+ dtrace_xcall(*cpu, (dtrace_xcall_t)dtrace_begin_probe, state);
-+
-+ /*
-+ * Regardless of whether or not now we're in ACTIVE or DRAINING, we
-+ * want each CPU to transition its principal buffer out of the
-+ * INACTIVE state. Doing this assures that no CPU will suddenly begin
-+ * processing an ECB halfway down a probe's ECB chain; all CPUs will
-+ * atomically transition from processing none of a state's ECBs to
-+ * processing all of them.
-+ */
-+ dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_buffer_activate,
-+ state);
-+ goto out;
-+
-+err:
-+ dtrace_buffer_free(state->dts_buffer);
-+ dtrace_buffer_free(state->dts_aggbuffer);
-+
-+ nspec = state->dts_nspeculations;
-+ if (nspec == 0) {
-+ ASSERT(state->dts_speculations == NULL);
-+ goto out;
-+ }
-+
-+ spec = state->dts_speculations;
-+ ASSERT(spec != NULL);
-+
-+ for (i = 0; i < state->dts_nspeculations; i++) {
-+ buf = spec[i].dtsp_buffer;
-+ if (buf == NULL)
-+ break;
-+
-+ dtrace_buffer_free(buf);
-+ vfree(buf);
-+ }
-+
-+ vfree(spec);
-+ state->dts_nspeculations = 0;
-+ state->dts_speculations = NULL;
-+
-+out:
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+
-+ return rval;
-+}
-+
-+static void dtrace_end_probe(struct dtrace_state *state)
-+{
-+ dtrace_probe(dtrace_probeid_end, (uint64_t)(uintptr_t)state, 0, 0, 0,
-+ 0, 0, 0);
-+
-+ state->dts_activity = DTRACE_ACTIVITY_STOPPED;
-+
-+ dtrace_membar_enter();
-+}
-+
-+int dtrace_state_stop(struct dtrace_state *state, processorid_t *cpu)
-+{
-+ processorid_t cpuid = state->dts_options[DTRACEOPT_CPU];
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_ACTIVE &&
-+ state->dts_activity != DTRACE_ACTIVITY_DRAINING)
-+ return -EINVAL;
-+
-+ /*
-+ * We'll set the activity to DTRACE_ACTIVITY_DRAINING, and issue a sync
-+ * to be sure that every CPU has seen it. See below for the details
-+ * on why this is done.
-+ */
-+ state->dts_activity = DTRACE_ACTIVITY_DRAINING;
-+ dtrace_sync();
-+
-+ /*
-+ * By this point, it is impossible for any CPU to be still processing
-+ * with DTRACE_ACTIVITY_ACTIVE. We can thus set our activity to
-+ * DTRACE_ACTIVITY_COOLDOWN and know that we're not racing with any
-+ * other CPU in dtrace_buffer_reserve(). This allows dtrace_probe()
-+ * and callees to know that the activity is DTRACE_ACTIVITY_COOLDOWN
-+ * iff we're in the END probe.
-+ */
-+ state->dts_activity = DTRACE_ACTIVITY_COOLDOWN;
-+ dtrace_sync();
-+ ASSERT(state->dts_activity == DTRACE_ACTIVITY_COOLDOWN);
-+
-+ /*
-+ * Finally, we can release the reserve and call the END probe. We
-+ * disable interrupts across calling the END probe to allow us to
-+ * return the CPU on which we actually called the END probe. This
-+ * allows user-land to be sure that this CPU's principal buffer is
-+ * processed last.
-+ */
-+ state->dts_reserve = 0;
-+
-+ /*
-+ * Same as for BEGIN probe in dtrace_state_go(). The END probe must
-+ * also fire on the enabled cpu.
-+ */
-+ *cpu = (cpuid == DTRACE_CPUALL) ? smp_processor_id() : cpuid;
-+ dtrace_xcall(*cpu, (dtrace_xcall_t)dtrace_end_probe, state);
-+
-+ dtrace_sync();
-+ return 0;
-+}
-+
-+int dtrace_state_option(struct dtrace_state *state, dtrace_optid_t option,
-+ dtrace_optval_t val)
-+{
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE)
-+ return -EBUSY;
-+
-+ if (option >= DTRACEOPT_MAX)
-+ return -EINVAL;
-+
-+ if (option != DTRACEOPT_CPU && val < 0)
-+ return -EINVAL;
-+
-+ switch (option) {
-+ case DTRACEOPT_DESTRUCTIVE:
-+ if (dtrace_destructive_disallow)
-+ return -EACCES;
-+
-+ state->dts_cred.dcr_destructive = 1;
-+ break;
-+
-+ case DTRACEOPT_BUFSIZE:
-+ case DTRACEOPT_DYNVARSIZE:
-+ case DTRACEOPT_AGGSIZE:
-+ case DTRACEOPT_SPECSIZE:
-+ case DTRACEOPT_STRSIZE:
-+ if (val < 0)
-+ return -EINVAL;
-+
-+ /*
-+ * If this is an otherwise negative value, set it to the
-+ * highest multiple of 128m less than LONG_MAX. Technically,
-+ * we're adjusting the size without regard to the buffer
-+ * resizing policy, but in fact, this has no effect -- if we
-+ * set the buffer size to ~LONG_MAX and the buffer policy is
-+ * ultimately set to be "manual", the buffer allocation is
-+ * guaranteed to fail, if only because the allocation requires
-+ * two buffers. (We set the the size to the highest multiple
-+ * of 128m because it ensures that the size will remain a
-+ * multiple of a megabyte when repeatedly halved -- all the
-+ * way down to 15m.)
-+ */
-+ if (val >= LONG_MAX)
-+ val = LONG_MAX - (1 << 27) + 1;
-+ }
-+
-+ state->dts_options[option] = val;
-+
-+ return 0;
-+}
-+
-+void dtrace_state_destroy(struct dtrace_state *state)
-+{
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_vstate *vstate = &state->dts_vstate;
-+ int i;
-+ struct dtrace_speculation *spec = state->dts_speculations;
-+ int nspec = state->dts_nspeculations;
-+ uint32_t match;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+ /*
-+ * First, retract any retained enablings for this state.
-+ */
-+ dtrace_enabling_retract(state);
-+ ASSERT(state->dts_nretained == 0);
-+
-+ if (state->dts_activity == DTRACE_ACTIVITY_ACTIVE ||
-+ state->dts_activity == DTRACE_ACTIVITY_DRAINING) {
-+ /*
-+ * We have managed to come into dtrace_state_destroy() on a
-+ * hot enabling -- almost certainly because of a disorderly
-+ * shutdown of a consumer. (That is, a consumer that is
-+ * exiting without having called dtrace_stop().) In this case,
-+ * we're going to set our activity to be KILLED, and then
-+ * issue a sync to be sure that everyone is out of probe
-+ * context before we start blowing away ECBs.
-+ */
-+ state->dts_activity = DTRACE_ACTIVITY_KILLED;
-+ dtrace_sync();
-+ }
-+
-+ /*
-+ * Release the credential hold we took in dtrace_state_create().
-+ */
-+ if (state->dts_cred.dcr_cred != NULL)
-+ put_cred(state->dts_cred.dcr_cred);
-+
-+ /*
-+ * Now we can safely disable and destroy any enabled probes. Because
-+ * any DTRACE_PRIV_KERNEL probes may actually be slowing our progress
-+ * (especially if they're all enabled), we take two passes through the
-+ * ECBs: in the first, we disable just DTRACE_PRIV_KERNEL probes, and
-+ * in the second we disable whatever is left over.
-+ */
-+ for (match = DTRACE_PRIV_KERNEL; ; match = 0) {
-+ for (i = 0; i < state->dts_necbs; i++) {
-+ ecb = state->dts_ecbs[i];
-+ if (ecb == NULL)
-+ continue;
-+
-+ if (match && ecb->dte_probe != NULL) {
-+ struct dtrace_probe *probe =
-+ ecb->dte_probe;
-+ struct dtrace_provider *prov =
-+ probe->dtpr_provider;
-+
-+ if (!(prov->dtpv_priv.dtpp_flags & match))
-+ continue;
-+ }
-+
-+ dtrace_ecb_disable(ecb);
-+ dtrace_ecb_destroy(ecb);
-+ }
-+
-+ if (!match)
-+ break;
-+ }
-+
-+ /*
-+ * Before we free the buffers, perform one more sync to assure that
-+ * every CPU is out of probe context.
-+ */
-+ dtrace_sync();
-+
-+ dtrace_buffer_free(state->dts_buffer);
-+ dtrace_buffer_free(state->dts_aggbuffer);
-+
-+ for (i = 0; i < nspec; i++)
-+ dtrace_buffer_free(spec[i].dtsp_buffer);
-+
-+ if (state->dts_cleaner != CYCLIC_NONE)
-+ cyclic_remove(state->dts_cleaner);
-+
-+ if (state->dts_deadman != CYCLIC_NONE)
-+ cyclic_remove(state->dts_deadman);
-+
-+ dtrace_dstate_fini(&vstate->dtvs_dynvars);
-+ dtrace_vstate_fini(vstate);
-+ vfree(state->dts_ecbs);
-+
-+ /*
-+ * If there were aggregations allocated, they should have been cleaned
-+ * up by now, so we can get rid of the idr.
-+ */
-+ idr_destroy(&state->dts_agg_idr);
-+
-+ vfree(state->dts_buffer);
-+ vfree(state->dts_aggbuffer);
-+
-+ for (i = 0; i < nspec; i++)
-+ vfree(spec[i].dtsp_buffer);
-+
-+ vfree(spec);
-+
-+ dtrace_format_destroy(state);
-+
-+ kfree(state);
-+}
-diff --git a/dtrace/dtrace_util.c b/dtrace/dtrace_util.c
-new file mode 100644
-index 000000000000..76fdf2bd8b41
---- /dev/null
-+++ b/dtrace/dtrace_util.c
-@@ -0,0 +1,282 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_util.c
-+ * DESCRIPTION: DTrace - utility functions
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/module.h>
-+#include <linux/vmalloc.h>
-+#include <asm/pgtable.h>
-+
-+#include "dtrace.h"
-+
-+int dtrace_isglob(const char *s)
-+{
-+ char c;
-+
-+ while ((c = *s++) != '\0') {
-+ if (c == '[' || c == '?' || c == '*' || c == '\\')
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_isglob);
-+
-+int dtrace_gmatch(const char *s, const char *p)
-+{
-+ const char *olds = s;
-+ char sc;
-+ char pc;
-+
-+ sc = *s++;
-+ pc = *p++;
-+
-+ if (!pc)
-+ return !sc;
-+
-+ switch (pc) {
-+ case '[': {
-+ int ok = 0;
-+ char lc = '\0';
-+ int inv = 0;
-+
-+ if (!sc)
-+ return 0;
-+
-+ if (*p == '!') {
-+ inv = 1;
-+ p++;
-+ }
-+
-+ pc = *p++;
-+ do {
-+ if (pc == '-' && lc && *p != ']') {
-+ pc = *p++;
-+ if (pc == '\\')
-+ pc = *p++;
-+
-+ if (inv) {
-+ if (sc < lc || sc > pc)
-+ ok++;
-+ else
-+ return 0;
-+ } else {
-+ if (lc <= sc && sc <= pc)
-+ ok++;
-+ }
-+ } else if (pc == '\\') {
-+ pc = *p++;
-+ }
-+
-+ lc = sc;
-+
-+ if (inv) {
-+ if (sc != lc)
-+ ok++;
-+ else
-+ return 0;
-+ } else {
-+ if (sc == lc)
-+ ok++;
-+ }
-+
-+ pc = *p++;
-+ } while (pc != ']');
-+
-+ return ok ? dtrace_gmatch(s, p) : 0;
-+ }
-+ case '\\':
-+ pc = *p++;
-+ if (!pc)
-+ return 0;
-+
-+ /* fall-through */
-+ default:
-+ if (pc != sc)
-+ return 0;
-+
-+ /* fall-through */
-+ case '?':
-+ return sc ? dtrace_gmatch(s, p) : 0;
-+ case '*':
-+ while (*p == '*')
-+ p++;
-+
-+ if (!*p)
-+ return 1;
-+
-+ s = olds;
-+ while (*s) {
-+ if (dtrace_gmatch(s, p))
-+ return 1;
-+
-+ s++;
-+ }
-+
-+ return 0;
-+ }
-+}
-+EXPORT_SYMBOL(dtrace_gmatch);
-+
-+int dtrace_badattr(const struct dtrace_attribute *a)
-+{
-+ return a->dtat_name > DTRACE_STABILITY_MAX ||
-+ a->dtat_data > DTRACE_STABILITY_MAX ||
-+ a->dtat_class > DTRACE_CLASS_MAX;
-+}
-+
-+/*
-+ * Allocate a chunk of virtual memory in kernel space, and zero it out. This
-+ * allocation might fail (which will report a backtrace in the kernel log, yet
-+ * it is harmless).
-+ */
-+void *dtrace_vzalloc_try(unsigned long size)
-+{
-+ return __vmalloc(size,
-+ GFP_NOWAIT | __GFP_FS | __GFP_IO | __GFP_NOMEMALLOC |
-+ __GFP_NORETRY | __GFP_NOWARN | __GFP_ZERO);
-+}
-+EXPORT_SYMBOL(dtrace_vzalloc_try);
-+
-+/*
-+ * Return a duplicate copy of a string. If the specified string is NULL, this
-+ * function returs a zero-length string.
-+ */
-+char *dtrace_strdup(const char *str)
-+{
-+ return kstrdup(str ? str : "", GFP_KERNEL);
-+}
-+
-+/*
-+ * Compare two strings using safe loads.
-+ */
-+int dtrace_strncmp(char *s1, char *s2, size_t limit)
-+{
-+ uint8_t c1, c2;
-+ volatile uint16_t *flags;
-+
-+ if (s1 == s2 || limit == 0)
-+ return 0;
-+
-+ flags = (volatile uint16_t *)&this_cpu_core->cpuc_dtrace_flags;
-+
-+ do {
-+ if (s1 == NULL)
-+ c1 = '\0';
-+ else
-+ c1 = dtrace_load8((uintptr_t)s1++);
-+
-+ if (s2 == NULL)
-+ c2 = '\0';
-+ else
-+ c2 = dtrace_load8((uintptr_t)s2++);
-+
-+ if (c1 != c2)
-+ return (c1 - c2);
-+ } while (--limit && c1 != '\0' && !(*flags & CPU_DTRACE_FAULT));
-+
-+ return 0;
-+}
-+
-+/*
-+ * Compute strlen(s) for a string using safe memory accesses. The additional
-+ * len parameter is used to specify a maximum length to ensure completion.
-+ */
-+size_t dtrace_strlen(const char *s, size_t lim)
-+{
-+ uint_t len;
-+
-+ for (len = 0; len != lim; len++) {
-+ if (dtrace_load8((uintptr_t)s++) == '\0')
-+ break;
-+ }
-+
-+ return len;
-+}
-+
-+#define DTRACE_ISALPHA(c) (((c) >= 'a' && (c) <= 'z') || \
-+ ((c) >= 'A' && (c) <= 'Z'))
-+int dtrace_badname(const char *s)
-+{
-+ char c;
-+
-+ if (s == NULL)
-+ return 0;
-+
-+ c = *s++;
-+ if (c == '\0')
-+ return 0;
-+
-+ if (!DTRACE_ISALPHA(c) && c != '-' && c != '_' && c != '.')
-+ return 1;
-+
-+ while ((c = *s++) != '\0') {
-+ if (!DTRACE_ISALPHA(c) && (c < '0' || c > '9') &&
-+ c != '-' && c != '_' && c != '.' && c != '`')
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+void dtrace_cred2priv(const struct cred *cr, uint32_t *privp, kuid_t *uidp)
-+{
-+#ifdef FIXME
-+/*
-+ * This should probably be rewritten based on capabilities in the struct cred.
-+ */
-+ uint32_t priv;
-+
-+ if (cr == NULL)
-+ priv = DTRACE_PRIV_ALL;
-+ else {
-+ const struct cred *lcr = get_cred(cr);
-+
-+ if (PRIV_POLICY_ONLY(lcr, PRIV_ALL, FALSE))
-+ priv = DTRACE_PRIV_ALL;
-+ else {
-+ *uidp = lcr->uid;
-+ priv = 0;
-+
-+ if (PRIV_POLICY_ONLY(lcr, PRIV_DTRACE_KERNEL, FALSE))
-+ priv |= DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER;
-+ else if (PRIV_POLICY_ONLY(lcr, PRIV_DTRACE_USER,
-+ FALSE))
-+ priv |= DTRACE_PRIV_USER;
-+
-+ if (PRIV_POLICY_ONLY(lcr, PRIV_DTRACE_PROC, FALSE))
-+ priv |= DTRACE_PRIV_PROC;
-+ if (PRIV_POLICY_ONLY(lcr, PRIV_PROC_OWNER, FALSE))
-+ priv |= DTRACE_PRIV_OWNER;
-+ }
-+
-+ put_cred(cr);
-+ }
-+
-+ *privp = priv;
-+#else
-+ *privp = DTRACE_PRIV_ALL;
-+
-+ if (cr != NULL) {
-+ const struct cred *lcr = get_cred(cr);
-+
-+ *uidp = lcr->uid;
-+ put_cred(cr);
-+ }
-+#endif
-+}
-+
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0006-dtrace-systrace-provider-core-components.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0006-dtrace-systrace-provider-core-components.patch
deleted file mode 100644
index 16c4176cb842..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0006-dtrace-systrace-provider-core-components.patch
+++ /dev/null
@@ -1,326 +0,0 @@
-From a71a23031f2c3ae2e9b4a560bf5ed11e6d237003 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 16:55:11 +0000
-Subject: [PATCH 06/19] dtrace: systrace provider core components
-
-This implements the core (linked-in) components of the DTrace systrace
-provider, which intercepts system call invocations. As previously,
-the arch-dependent pieces needed for x86 are also provided.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/entry/syscall_32.c | 4 +
- arch/x86/entry/syscall_64.c | 4 +
- arch/x86/include/asm/dtrace_syscall.h | 3 +
- arch/x86/include/asm/dtrace_syscall_types.h | 11 +++
- arch/x86/include/asm/syscall.h | 8 ++
- arch/x86/kernel/dtrace_syscall.c | 97 +++++++++++++++++++++
- arch/x86/kernel/dtrace_syscall_stubs.S | 0
- include/linux/dtrace_syscall.h | 60 +++++++++++++
- kernel/dtrace/Kconfig | 9 ++
- kernel/dtrace/Makefile | 1 +
- 10 files changed, 197 insertions(+)
- create mode 100644 arch/x86/include/asm/dtrace_syscall.h
- create mode 100644 arch/x86/include/asm/dtrace_syscall_types.h
- create mode 100644 arch/x86/kernel/dtrace_syscall.c
- create mode 100644 arch/x86/kernel/dtrace_syscall_stubs.S
- create mode 100644 include/linux/dtrace_syscall.h
-
-diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c
-index 86eb0d89d46f..66381ebd6a9f 100644
---- a/arch/x86/entry/syscall_32.c
-+++ b/arch/x86/entry/syscall_32.c
-@@ -15,7 +15,11 @@
-
- #define __SYSCALL_I386(nr, sym) [nr] = __ia32_##sym,
-
-+#if IS_ENABLED(CONFIG_DT_SYSTRACE)
-+__visible sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = {
-+#else
- __visible const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = {
-+#endif /* CONFIG_DT_SYSTRACE || CONFIG_DT_SYSTRACE_MODULE */
- /*
- * Smells like a compiler bug -- it doesn't work
- * when the & below is removed.
-diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
-index 1594ec72bcbb..42587831ef04 100644
---- a/arch/x86/entry/syscall_64.c
-+++ b/arch/x86/entry/syscall_64.c
-@@ -17,7 +17,11 @@
-
- #define __SYSCALL_64(nr, sym) [nr] = __x64_##sym,
-
-+#if IS_ENABLED(CONFIG_DT_SYSTRACE)
-+asmlinkage sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
-+#else
- asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
-+#endif /* CONFIG_DT_SYSTRACE || CONFIG_DT_SYSTRACE_MODULE */
- /*
- * Smells like a compiler bug -- it doesn't work
- * when the & below is removed.
-diff --git a/arch/x86/include/asm/dtrace_syscall.h b/arch/x86/include/asm/dtrace_syscall.h
-new file mode 100644
-index 000000000000..402826562478
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_syscall.h
-@@ -0,0 +1,3 @@
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-diff --git a/arch/x86/include/asm/dtrace_syscall_types.h b/arch/x86/include/asm/dtrace_syscall_types.h
-new file mode 100644
-index 000000000000..2b3ee563ad14
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_syscall_types.h
-@@ -0,0 +1,11 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/dtrace_types.h>
-+
-+typedef asmlinkage long (*dt_sys_call_t)(const struct pt_regs *regs);
-+
-+#define DTRACE_SYSCALL_WRAP_PREFIX "__x64_"
-diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
-index 7cbf733d11af..3d1bce850b74 100644
---- a/arch/x86/include/asm/syscall.h
-+++ b/arch/x86/include/asm/syscall.h
-@@ -17,15 +17,23 @@
- #include <asm/unistd.h>
-
- typedef long (*sys_call_ptr_t)(const struct pt_regs *);
-+#if IS_ENABLED(CONFIG_DT_SYSTRACE)
-+extern sys_call_ptr_t sys_call_table[];
-+#else
- extern const sys_call_ptr_t sys_call_table[];
-+#endif
-
- #if defined(CONFIG_X86_32)
- #define ia32_sys_call_table sys_call_table
- #endif
-
- #if defined(CONFIG_IA32_EMULATION)
-+#if IS_ENABLED(CONFIG_DT_SYSTRACE)
-+extern sys_call_ptr_t ia32_sys_call_table[];
-+#else
- extern const sys_call_ptr_t ia32_sys_call_table[];
- #endif
-+#endif
-
- #ifdef CONFIG_X86_X32_ABI
- extern const sys_call_ptr_t x32_sys_call_table[];
-diff --git a/arch/x86/kernel/dtrace_syscall.c b/arch/x86/kernel/dtrace_syscall.c
-new file mode 100644
-index 000000000000..3328710e7050
---- /dev/null
-+++ b/arch/x86/kernel/dtrace_syscall.c
-@@ -0,0 +1,97 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_syscall.c
-+ * DESCRIPTION: Dynamic Tracing: system call tracing support (arch-specific)
-+ *
-+ * Copyright (C) 2010-2018 Oracle Corporation
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_syscall.h>
-+#include <linux/fs.h>
-+#include <linux/module.h>
-+#include <linux/namei.h>
-+#include <linux/sched.h>
-+#include <asm/insn.h>
-+#include <asm/stacktrace.h>
-+#include <asm/syscalls.h>
-+
-+/*
-+ * SYSTEM CALL TRACING SUPPORT
-+ */
-+void (*systrace_probe)(dtrace_id_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t);
-+
-+void systrace_stub(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
-+ uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
-+ uintptr_t arg5, uintptr_t arg6)
-+{
-+}
-+
-+asmlinkage long systrace_syscall(const struct pt_regs *regs);
-+
-+asmlinkage long dtrace_stub_ptregs(uintptr_t, uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t);
-+
-+static struct systrace_info systrace_info =
-+{
-+ &systrace_probe,
-+ systrace_stub,
-+ systrace_syscall,
-+ {},
-+ {
-+#define __SYSCALL_64(nr, sym) [nr] { __stringify(sym), },
-+#define __SYSCALL_COMMON(nr, sym) __SYSCALL_64(nr, sym)
-+#define __SYSCALL_X32(nt, sym)
-+#include <asm/syscalls_64.h>
-+ }
-+};
-+
-+asmlinkage long systrace_syscall(const struct pt_regs *regs)
-+{
-+ long rc = 0;
-+ unsigned long sysnum;
-+ dtrace_id_t id;
-+ struct dtrace_syscalls *sc;
-+
-+ sysnum = syscall_get_nr(current, (struct pt_regs *) regs);
-+ sc = &systrace_info.sysent[sysnum];
-+
-+ /*
-+ * Note: 64-bit syscall-specific.
-+ */
-+ id = sc->stsy_entry;
-+ if (id != DTRACE_IDNONE)
-+ (*systrace_probe)(id, regs->di, regs->si, regs->dx,
-+ regs->r10, regs->r8, regs->r9, 0);
-+
-+ /*
-+ * FIXME: Add stop functionality for DTrace.
-+ */
-+
-+ if (sc->stsy_underlying != NULL)
-+ rc = (*sc->stsy_underlying)(regs);
-+
-+ id = sc->stsy_return;
-+ if (id != DTRACE_IDNONE)
-+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
-+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0, 0);
-+
-+ return rc;
-+}
-+
-+struct systrace_info *dtrace_syscalls_init(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < NR_syscalls; i++) {
-+ systrace_info.sysent[i].stsy_tblent =
-+ (dt_sys_call_t *)&sys_call_table[i];
-+ systrace_info.sysent[i].stsy_underlying =
-+ (dt_sys_call_t)sys_call_table[i];
-+ }
-+
-+ return &systrace_info;
-+}
-+EXPORT_SYMBOL(dtrace_syscalls_init);
-diff --git a/arch/x86/kernel/dtrace_syscall_stubs.S b/arch/x86/kernel/dtrace_syscall_stubs.S
-new file mode 100644
-index 000000000000..e69de29bb2d1
-diff --git a/include/linux/dtrace_syscall.h b/include/linux/dtrace_syscall.h
-new file mode 100644
-index 000000000000..7f9e351f3783
---- /dev/null
-+++ b/include/linux/dtrace_syscall.h
-@@ -0,0 +1,60 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_SYSCALL_H_
-+#define _LINUX_DTRACE_SYSCALL_H_
-+
-+#include <linux/types.h>
-+#include <linux/dtrace_os.h>
-+#include <asm/syscall.h>
-+
-+#define DTRACE_SYSCALL_STUB(t, n) SCE_##t,
-+enum dtrace_sce_id {
-+ SCE_NONE = 0,
-+#include <asm/dtrace_syscall.h>
-+ SCE_nr_stubs
-+};
-+#undef DTRACE_SYSCALL_STUB
-+
-+#define DTRACE_SYSCALL_STUB(t, n) \
-+ asmlinkage long dtrace_stub_##n(uintptr_t, uintptr_t, uintptr_t, \
-+ uintptr_t, uintptr_t, uintptr_t, \
-+ uintptr_t);
-+#include <asm/dtrace_syscall.h>
-+#undef DTRACE_SYSCALL_STUB
-+
-+#ifndef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
-+typedef asmlinkage long (*dt_sys_call_t)(uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t);
-+
-+#define DTRACE_SYSCALL_WRAP_PREFIX ""
-+#else
-+#include <asm/dtrace_syscall_types.h>
-+#endif
-+
-+struct dtrace_syscalls {
-+ const char *name;
-+ dtrace_id_t stsy_entry;
-+ dtrace_id_t stsy_return;
-+ dt_sys_call_t stsy_underlying;
-+ dt_sys_call_t *stsy_tblent;
-+};
-+
-+typedef void (*dtrace_systrace_probe_t)(dtrace_id_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t);
-+
-+struct systrace_info {
-+ dtrace_systrace_probe_t *probep;
-+ dtrace_systrace_probe_t stub;
-+ dt_sys_call_t syscall;
-+ dt_sys_call_t stubs[SCE_nr_stubs];
-+ struct dtrace_syscalls sysent[NR_syscalls];
-+};
-+
-+extern struct systrace_info *dtrace_syscalls_init(void);
-+
-+#endif /* _LINUX_DTRACE_SYSCALL_H_ */
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-index 854e4411343f..d04ca0ab7ac9 100644
---- a/kernel/dtrace/Kconfig
-+++ b/kernel/dtrace/Kconfig
-@@ -23,6 +23,15 @@ config DT_CORE
-
- if DT_CORE
-
-+config DT_SYSTRACE
-+ tristate "System Call Tracing"
-+ default m
-+ select FTRACE
-+ select FTRACE_SYSCALLS
-+ help
-+ Provides DTrace probes at the entry and exit of all system calls,
-+ in the syscall provider.
-+
- config DT_DT_TEST
- tristate "DTrace Test Probe"
- default m
-diff --git a/kernel/dtrace/Makefile b/kernel/dtrace/Makefile
-index 872785327c3d..68fc3861e5d1 100644
---- a/kernel/dtrace/Makefile
-+++ b/kernel/dtrace/Makefile
-@@ -3,6 +3,7 @@
- #
-
- DT_CORE_ARCH_OBJS = $(addprefix ../../arch/$(SRCARCH)/kernel/, \
-+ dtrace_syscall.o dtrace_syscall_stubs.o \
- dtrace_util.o)
-
- ifdef CONFIG_DT_CORE
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0007-dtrace-systrace-provider.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0007-dtrace-systrace-provider.patch
deleted file mode 100644
index a9e8b5659cd4..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0007-dtrace-systrace-provider.patch
+++ /dev/null
@@ -1,374 +0,0 @@
-From 5d684eeadb4a16c417cfc365180a4b6a9364866f Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 17:58:09 +0000
-Subject: [PATCH 07/19] dtrace: systrace provider
-
-This implements the DTrace systrace provider, which intercepts system
-call invocations.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- dtrace/Makefile | 2 +
- dtrace/systrace.h | 33 +++++++
- dtrace/systrace_dev.c | 224 ++++++++++++++++++++++++++++++++++++++++++
- dtrace/systrace_mod.c | 52 ++++++++++
- 4 files changed, 311 insertions(+)
- create mode 100644 dtrace/systrace.h
- create mode 100644 dtrace/systrace_dev.c
- create mode 100644 dtrace/systrace_mod.c
-
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-index 36a4b97b922c..b91bc69d3802 100644
---- a/dtrace/Makefile
-+++ b/dtrace/Makefile
-@@ -3,6 +3,7 @@
- #
-
- obj-$(CONFIG_DT_CORE) += dtrace.o
-+obj-$(CONFIG_DT_SYSTRACE) += systrace.o
- obj-$(CONFIG_DT_DT_TEST) += dt_test.o
-
- dtrace-y := dtrace_mod.o dtrace_dev.o \
-@@ -14,6 +15,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \
- dtrace_probe.o dtrace_probe_ctx.o \
- dtrace_ptofapi.o dtrace_predicate.o \
- dtrace_spec.o dtrace_state.o dtrace_util.o
-+systrace-y := systrace_mod.o systrace_dev.o
- dt_test-y := dt_test_mod.o dt_test_dev.o
-
- -include arch/$(SRCARCH)/dtrace/Makefile.arch
-diff --git a/dtrace/systrace.h b/dtrace/systrace.h
-new file mode 100644
-index 000000000000..832bc613b966
---- /dev/null
-+++ b/dtrace/systrace.h
-@@ -0,0 +1,33 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - syscall tracing provider
-+ *
-+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _SYSTRACE_H_
-+#define _SYSTRACE_H_
-+
-+#include "dtrace.h"
-+
-+extern void systrace_provide(void *, const struct dtrace_probedesc *);
-+extern int systrace_enable(void *arg, dtrace_id_t, void *);
-+extern void systrace_disable(void *arg, dtrace_id_t, void *);
-+extern void systrace_destroy(void *, dtrace_id_t, void *);
-+
-+extern dtrace_provider_id_t syscall_id;
-+
-+extern int syscall_dev_init(void);
-+extern void syscall_dev_exit(void);
-+
-+#endif /* _SYSTRACE_H_ */
-diff --git a/dtrace/systrace_dev.c b/dtrace/systrace_dev.c
-new file mode 100644
-index 000000000000..2ff3ba4329a5
---- /dev/null
-+++ b/dtrace/systrace_dev.c
-@@ -0,0 +1,224 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: systrace_dev.c
-+ * DESCRIPTION: DTrace - systrace provider device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_syscall.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <asm/unistd.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "systrace.h"
-+
-+#define SYSTRACE_ARTIFICIAL_FRAMES 1
-+
-+#define SYSTRACE_SHIFT 16
-+#define SYSTRACE_ENTRY(id) ((1 << SYSTRACE_SHIFT) | (id))
-+#define SYSTRACE_RETURN(id) (id)
-+#define SYSTRACE_SYSNUM(x) ((int)(x) & ((1 << SYSTRACE_SHIFT) - 1))
-+#define SYSTRACE_ISENTRY(x) ((int)(x) >> SYSTRACE_SHIFT)
-+
-+#if ((1 << SYSTRACE_SHIFT) <= NR_syscalls)
-+# error 1 << SYSTRACE_SHIFT must exceed number of system calls
-+#endif
-+
-+static struct systrace_info *systrace_info;
-+
-+void systrace_provide(void *arg, const struct dtrace_probedesc *desc)
-+{
-+ int failed_count = 0;
-+ int i;
-+
-+ ASSERT(systrace_info != NULL);
-+
-+ if (desc != NULL)
-+ return;
-+
-+ for (i = 0; i < NR_syscalls; i++) {
-+ const char *nm = systrace_info->sysent[i].name;
-+ dtrace_id_t id;
-+ int sz;
-+ size_t wrap_len;
-+
-+ if (nm == NULL)
-+ continue;
-+
-+ if (systrace_info->sysent[i].stsy_underlying == NULL)
-+ continue;
-+
-+ wrap_len = strlen(DTRACE_SYSCALL_WRAP_PREFIX);
-+ sz = strlen(nm);
-+ if (sz > wrap_len &&
-+ memcmp(nm, DTRACE_SYSCALL_WRAP_PREFIX, wrap_len) == 0) {
-+ nm += wrap_len;
-+ sz -= wrap_len;
-+ }
-+ if (sz > 4 && memcmp(nm, "sys_", 4) == 0)
-+ nm += 4;
-+ else if (sz > 5 && memcmp(nm, "stub_", 5) == 0)
-+ nm += 5;
-+
-+ id = dtrace_probe_lookup(syscall_id, dtrace_kmod->name, nm,
-+ "entry");
-+ if (id == DTRACE_IDNONE) {
-+ id = dtrace_probe_create(syscall_id, dtrace_kmod->name,
-+ nm, "entry",
-+ SYSTRACE_ARTIFICIAL_FRAMES,
-+ (void *)((uintptr_t)SYSTRACE_ENTRY(i)));
-+ if (id == DTRACE_IDNONE)
-+ failed_count++;
-+
-+ systrace_info->sysent[i].stsy_entry = DTRACE_IDNONE;
-+ }
-+
-+ id = dtrace_probe_lookup(syscall_id, dtrace_kmod->name, nm,
-+ "return");
-+ if (id == DTRACE_IDNONE) {
-+ id = dtrace_probe_create(syscall_id, dtrace_kmod->name,
-+ nm, "return",
-+ SYSTRACE_ARTIFICIAL_FRAMES,
-+ (void *)((uintptr_t)SYSTRACE_RETURN(i)));
-+ if (id == DTRACE_IDNONE)
-+ failed_count++;
-+
-+ systrace_info->sysent[i].stsy_return = DTRACE_IDNONE;
-+ }
-+ }
-+
-+ if (failed_count > 0)
-+ pr_warn("systrace: Failed to provide %d probes (out of memory)\n", failed_count);
-+}
-+
-+static dt_sys_call_t get_intercept(int sysnum)
-+{
-+ switch (sysnum) {
-+ default:
-+ return systrace_info->syscall;
-+#define DTRACE_SYSCALL_STUB(t, n) \
-+ case __NR_##n: \
-+ return systrace_info->stubs[SCE_##t];
-+#include <asm/dtrace_syscall.h>
-+#undef DTRACE_SYSCALL_STUB
-+ }
-+}
-+
-+int systrace_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
-+ struct dtrace_syscalls *sc = &systrace_info->sysent[sysnum];
-+ int enabled = sc->stsy_entry != DTRACE_IDNONE ||
-+ sc->stsy_return != DTRACE_IDNONE;
-+ dt_sys_call_t intercept = get_intercept(sysnum);
-+
-+ if (!enabled) {
-+ if (cmpxchg(sc->stsy_tblent, sc->stsy_underlying,
-+ intercept) != sc->stsy_underlying)
-+ return 1;
-+ } else
-+ ASSERT(*sc->stsy_tblent == intercept);
-+
-+ if (SYSTRACE_ISENTRY((uintptr_t)parg))
-+ sc->stsy_entry = id;
-+ else
-+ sc->stsy_return = id;
-+
-+ return 0;
-+}
-+
-+void systrace_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
-+ struct dtrace_syscalls *sc = &systrace_info->sysent[sysnum];
-+ int enabled =
-+ (sc->stsy_entry != DTRACE_IDNONE ? 1 : 0) +
-+ (sc->stsy_return != DTRACE_IDNONE ? 1 : 0);
-+ dt_sys_call_t intercept = get_intercept(sysnum);
-+
-+ /*
-+ * Every syscall can have 2 probes associated with it. We need to keep
-+ * the interceptor in place until the last probe is getting disabled.
-+ */
-+ if (enabled == 1)
-+ (void)cmpxchg(sc->stsy_tblent, intercept, sc->stsy_underlying);
-+
-+ if (SYSTRACE_ISENTRY((uintptr_t)parg))
-+ sc->stsy_entry = DTRACE_IDNONE;
-+ else
-+ sc->stsy_return = DTRACE_IDNONE;
-+}
-+
-+void systrace_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+ int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
-+
-+ /*
-+ * Nothing to be done here - just ensure our probe has been disabled.
-+ */
-+ if (SYSTRACE_ISENTRY((uintptr_t)parg))
-+ ASSERT(systrace_info->sysent[sysnum].stsy_entry ==
-+ DTRACE_IDNONE);
-+ else
-+ ASSERT(systrace_info->sysent[sysnum].stsy_return ==
-+ DTRACE_IDNONE);
-+}
-+
-+static int systrace_open(struct inode *inode, struct file *file)
-+{
-+ return -EAGAIN;
-+}
-+
-+static int systrace_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations systrace_fops = {
-+ .owner = THIS_MODULE,
-+ .open = systrace_open,
-+ .release = systrace_close,
-+};
-+
-+static struct miscdevice systrace_dev = {
-+ .minor = DT_DEV_SYSTRACE_MINOR,
-+ .name = "systrace",
-+ .nodename = "dtrace/provider/systrace",
-+ .fops = &systrace_fops,
-+};
-+
-+int syscall_dev_init(void)
-+{
-+ int ret = 0;
-+
-+ systrace_info = dtrace_syscalls_init();
-+
-+ ret = misc_register(&systrace_dev);
-+ if (ret)
-+ pr_err("%s: Can't register misc device %d\n",
-+ systrace_dev.name, systrace_dev.minor);
-+
-+ *(systrace_info->probep) = (dtrace_systrace_probe_t)dtrace_probe;
-+
-+ return ret;
-+}
-+
-+void syscall_dev_exit(void)
-+{
-+ *(systrace_info->probep) = systrace_info->stub;
-+
-+ misc_deregister(&systrace_dev);
-+}
-diff --git a/dtrace/systrace_mod.c b/dtrace/systrace_mod.c
-new file mode 100644
-index 000000000000..d286f7d9d47a
---- /dev/null
-+++ b/dtrace/systrace_mod.c
-@@ -0,0 +1,52 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: systrace_mod.c
-+ * DESCRIPTION: DTrace - systrace provider kernel module
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "systrace.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("System Call Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+static const struct dtrace_pattr syscall_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pops syscall_pops = {
-+ .dtps_provide = systrace_provide,
-+ .dtps_provide_module = NULL,
-+ .dtps_destroy_module = NULL,
-+ .dtps_enable = systrace_enable,
-+ .dtps_disable = systrace_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = NULL,
-+ .dtps_getargval = NULL,
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = systrace_destroy
-+};
-+
-+DT_PROVIDER_MODULE(syscall, DTRACE_PRIV_USER)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0008-dtrace-sdt-provider-core-components.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0008-dtrace-sdt-provider-core-components.patch
deleted file mode 100644
index dc5efdd39ea6..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0008-dtrace-sdt-provider-core-components.patch
+++ /dev/null
@@ -1,3112 +0,0 @@
-From 0bf2a2a85df13740247a26e7b217f39eda237b0c Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 22:03:10 +0000
-Subject: [PATCH 08/19] dtrace: sdt provider core components
-
-This implements the core (linked-in) machinery needed for SDT
-tracepoints:
-
- - generate empty stub function calls __dtrace_probe_* for each probe
- point and perf-event probe point, and record their section-relative
- offset in tables in special symbols in the output; calls to
- is-enabling probes (conditionals of the form
- if (DTRACE_FOO_ENABLED(probe-name))) are translated as well
- - similarly record the names and types of arguments to probes in
- special sections
- - parse both of these at load time, and substitute in nops over the top
- of the stub functions, remembering their locations: is-enabled probes
- get 0-returns patched over the top
- - on probe enabling, patch invalid-operation traps over the top of
- those stub functions; handle these by calling the probe, then return
- as if the trap had never happened
-
-The provider module itself is added in the next commit.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- .gitignore | 6 +
- Makefile | 1 +
- arch/x86/dtrace/include/dtrace/sdt_arch.h | 28 ++
- arch/x86/include/asm/dtrace_arch.h | 8 +-
- arch/x86/include/asm/dtrace_sdt_arch.h | 11 +
- arch/x86/include/asm/dtrace_util.h | 13 +
- arch/x86/include/asm/spinlock.h | 1 +
- arch/x86/include/asm/text-patching.h | 1 +
- arch/x86/kernel/alternative.c | 2 +-
- arch/x86/kernel/dtrace_sdt.c | 76 +++
- arch/x86/kernel/dtrace_util.c | 214 +++++++-
- arch/x86/kernel/vmlinux.lds.S | 3 +-
- include/asm-generic/vmlinux.lds.h | 16 +
- include/linux/dtrace_os.h | 3 +
- include/linux/dtrace_sdt.h | 32 ++
- include/linux/module.h | 5 +
- include/linux/sdt.h | 191 +++++++
- include/linux/sdt_internal.h | 276 ++++++++++
- include/linux/tracepoint.h | 8 +-
- kernel/dtrace/Kconfig | 16 +
- kernel/dtrace/Makefile | 3 +-
- kernel/dtrace/dtrace_os.c | 83 +++
- kernel/dtrace/dtrace_sdt_core.c | 364 ++++++++++++++
- kernel/module.c | 14 +
- scripts/.gitignore | 1 +
- scripts/Makefile | 6 +
- scripts/Makefile.modfinal | 52 +-
- scripts/dtrace_sdt.sh | 588 ++++++++++++++++++++++
- scripts/kmodsdt.c | 410 +++++++++++++++
- scripts/link-vmlinux.sh | 69 ++-
- scripts/mod/modpost.c | 19 +-
- 31 files changed, 2500 insertions(+), 20 deletions(-)
- create mode 100644 arch/x86/dtrace/include/dtrace/sdt_arch.h
- create mode 100644 arch/x86/include/asm/dtrace_sdt_arch.h
- create mode 100644 arch/x86/kernel/dtrace_sdt.c
- create mode 100644 include/linux/dtrace_sdt.h
- create mode 100644 include/linux/sdt.h
- create mode 100644 include/linux/sdt_internal.h
- create mode 100644 kernel/dtrace/dtrace_sdt_core.c
- create mode 100755 scripts/dtrace_sdt.sh
- create mode 100644 scripts/kmodsdt.c
-
-diff --git a/.gitignore b/.gitignore
-index 1c10cd7ce033..13954b4624a9 100644
---- a/.gitignore
-+++ b/.gitignore
-@@ -158,3 +158,9 @@ x509.genkey
-
- # Documentation toolchain
- sphinx_*/
-+#
-+# Generated DTrace SDT files
-+#
-+*.sdtinfo.c
-+*.sdtinfo.h
-+*.sdtstub.S
-diff --git a/Makefile b/Makefile
-index 4b25be692ac1..e3f113b64681 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1883,6 +1883,7 @@ clean: $(clean-dirs)
- -o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \
- -o -name '*.dwo' -o -name '*.lst' \
- -o -name '*.su' -o -name '*.mod' \
-+ -o -name '*.sdtinfo.c' -o -name '*.sdtinfo.h' -o -name '*.sdtstub.S' \
- -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
- -o -name '*.lex.c' -o -name '*.tab.[ch]' \
- -o -name '*.asn1.[ch]' \
-diff --git a/arch/x86/dtrace/include/dtrace/sdt_arch.h b/arch/x86/dtrace/include/dtrace/sdt_arch.h
-new file mode 100644
-index 000000000000..d8616b44079b
---- /dev/null
-+++ b/arch/x86/dtrace/include/dtrace/sdt_arch.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - SDT Implementation defines
-+ *
-+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _X86_64_SDT_ARCH_H
-+#define _X86_64_SDT_ARCH_H
-+
-+#define SDT_AFRAMES 4
-+
-+#endif /* _X86_64_SDT_ARCH_H */
-diff --git a/arch/x86/include/asm/dtrace_arch.h b/arch/x86/include/asm/dtrace_arch.h
-index 74e27f08a873..88beb8e4db0b 100644
---- a/arch/x86/include/asm/dtrace_arch.h
-+++ b/arch/x86/include/asm/dtrace_arch.h
-@@ -12,16 +12,22 @@
-
- typedef uint8_t asm_instr_t;
-
-+#define ASM_CALL_SIZE 5
-+
- typedef int (*prov_exit_f)(void);
-
- /*
- * Structure to hold DTrace specific information about modules (including the
- * core kernel module). Note that each module (and the main kernel) already
-- * has one field that relates to probing:
-+ * has three fields that relate to probing:
-+ * - sdt_probes: description of SDT probes in the module
-+ * - sdt_probec: number of SDT probes in the module
- * - pdata: pointer to a dtrace_module struct (for DTrace)
- */
- struct dtrace_module {
- int enabled_cnt;
-+ size_t sdt_probe_cnt;
-+ size_t fbt_probe_cnt;
- prov_exit_f prov_exit; /* Called with module_mutex held */
- };
-
-diff --git a/arch/x86/include/asm/dtrace_sdt_arch.h b/arch/x86/include/asm/dtrace_sdt_arch.h
-new file mode 100644
-index 000000000000..59f57cb489ab
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_sdt_arch.h
-@@ -0,0 +1,11 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/* Copyright (C) 2016 Oracle, Inc. */
-+
-+#ifndef _X86_DTRACE_SDT_ARCH_H
-+#define _X86_DTRACE_SDT_ARCH_H
-+
-+#define __DTRACE_SDT_ISENABLED_PROTO void
-+#define __DTRACE_SDT_ISENABLED_ARGS
-+
-+#endif /* _X86_DTRACE_SDT_ARCH_H */
-diff --git a/arch/x86/include/asm/dtrace_util.h b/arch/x86/include/asm/dtrace_util.h
-index 4d9843bbc95b..ce28bf42a59d 100644
---- a/arch/x86/include/asm/dtrace_util.h
-+++ b/arch/x86/include/asm/dtrace_util.h
-@@ -6,11 +6,24 @@
- #ifndef _X86_DTRACE_UTIL_H
- #define _X86_DTRACE_UTIL_H
-
-+#define DTRACE_INVOP_NOPS 0x0f /* 5-byte NOP sequence */
-+#define DTRACE_INVOP_MOV_RSP_RBP 0x48 /* mov %rsp, %rbp = 48 89 e5 */
-+#define DTRACE_INVOP_PUSH_BP 0x55 /* push %rbp = 55 */
-+#define DTRACE_INVOP_NOP 0x90 /* nop = 90 */
-+#define DTRACE_INVOP_LEAVE 0xc9 /* leave = c9 */
-+#define DTRACE_INVOP_RET 0xc3 /* ret = c3 */
-+
- #ifndef __ASSEMBLY__
-
- #include <asm/dtrace_arch.h>
- #include <asm/ptrace.h>
-
-+extern int dtrace_invop_add(uint8_t (*func)(struct pt_regs *));
-+extern void dtrace_invop_remove(uint8_t (*func)(struct pt_regs *));
-+
-+extern void dtrace_invop_enable(asm_instr_t *, asm_instr_t);
-+extern void dtrace_invop_disable(asm_instr_t *, asm_instr_t);
-+
- #endif
-
- #endif /* _X86_DTRACE_UTIL_H */
-diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
-index 5b6bc7016c22..79e017f90c60 100644
---- a/arch/x86/include/asm/spinlock.h
-+++ b/arch/x86/include/asm/spinlock.h
-@@ -9,6 +9,7 @@
- #include <linux/compiler.h>
- #include <asm/paravirt.h>
- #include <asm/bitops.h>
-+#include <linux/sdt.h>
-
- /*
- * Your basic SMP spinlocks, allowing only a single CPU anywhere
-diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
-index b7421780e4e9..127a59c41e6d 100644
---- a/arch/x86/include/asm/text-patching.h
-+++ b/arch/x86/include/asm/text-patching.h
-@@ -25,6 +25,7 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
- */
- #define POKE_MAX_OPCODE_SIZE 5
-
-+extern void add_nops(void *insns, unsigned int len);
- extern void text_poke_early(void *addr, const void *opcode, size_t len);
-
- /*
-diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
-index 2400ad62f330..389c3870ce48 100644
---- a/arch/x86/kernel/alternative.c
-+++ b/arch/x86/kernel/alternative.c
-@@ -256,7 +256,7 @@ void __init arch_init_ideal_nops(void)
- }
-
- /* Use this to add nops to a buffer, then text_poke the whole buffer. */
--static void __init_or_module add_nops(void *insns, unsigned int len)
-+void __init_or_module add_nops(void *insns, unsigned int len)
- {
- while (len > 0) {
- unsigned int noplen = len;
-diff --git a/arch/x86/kernel/dtrace_sdt.c b/arch/x86/kernel/dtrace_sdt.c
-new file mode 100644
-index 000000000000..31bb962573fb
---- /dev/null
-+++ b/arch/x86/kernel/dtrace_sdt.c
-@@ -0,0 +1,76 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_sdt.c
-+ * DESCRIPTION: Dynamic Tracing: SDT registration code (arch-specific)
-+ *
-+ * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/memory.h>
-+#include <linux/module.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/sdt.h>
-+#include <linux/slab.h>
-+#include <linux/sync_core.h>
-+#include <linux/vmalloc.h>
-+#include <asm/nmi.h>
-+#include <asm/nops.h>
-+#include <asm/dtrace_arch.h>
-+#include <asm/text-patching.h>
-+
-+static uint8_t nops[ASM_CALL_SIZE];
-+static uint8_t movs[ASM_CALL_SIZE];
-+
-+#define DT_OP_REX_RAX 0x48
-+#define DT_OP_XOR_EAX_0 0x33
-+#define DT_OP_XOR_EAX_1 0xc0
-+
-+/* This code is based on apply_alternatives and text_poke_early. It needs to
-+ * run before SMP is initialized in order to avoid SMP problems with patching
-+ * code that might be accessed on another CPU.
-+ */
-+void __init_or_module dtrace_sdt_nop_multi(asm_instr_t **addrs,
-+ int *is_enabled, int cnt)
-+{
-+ int i;
-+ asm_instr_t *addr;
-+ unsigned long flags;
-+
-+ stop_nmi();
-+ local_irq_save(flags);
-+
-+ for (i = 0; i < cnt; i++) {
-+ addr = addrs[i];
-+ if (likely(!is_enabled[i]))
-+ memcpy(addr, nops, sizeof(nops));
-+ else
-+ memcpy(addr, movs, sizeof(movs));
-+ }
-+
-+ sync_core();
-+ local_irq_restore(flags);
-+ restart_nmi();
-+}
-+
-+void __init dtrace_sdt_init_arch(void)
-+{
-+ /*
-+ * A little unusual, but potentially necessary. While we could use a
-+ * single NOP sequence of length ASM_CALL_SIZE, we need to consider the
-+ * fact that when a SDT probe point is enabled, a single invalid opcode
-+ * is written on the first byte of this NOP sequence. By using a
-+ * sequence of a 1-byte NOP, followed by a (ASM_CALL_SIZE - 1) byte NOP
-+ * sequence, we play it pretty safe.
-+ */
-+ add_nops(nops, 1);
-+ add_nops(nops + 1, ASM_CALL_SIZE - 1);
-+
-+ /*
-+ * Is-enabled probe points contain an "xor %rax, %rax" when disabled.
-+ */
-+ movs[0] = DT_OP_REX_RAX;
-+ movs[1] = DT_OP_XOR_EAX_0;
-+ movs[2] = DT_OP_XOR_EAX_1;
-+ add_nops(movs + 3, ASM_CALL_SIZE - 3);
-+}
-diff --git a/arch/x86/kernel/dtrace_util.c b/arch/x86/kernel/dtrace_util.c
-index d3d552c062f7..f138fd62f555 100644
---- a/arch/x86/kernel/dtrace_util.c
-+++ b/arch/x86/kernel/dtrace_util.c
-@@ -61,6 +61,13 @@ void dtrace_handle_badaddr(struct pt_regs *regs)
- dtrace_skip_instruction(regs);
- }
-
-+struct dtrace_invop_hdlr {
-+ uint8_t (*dtih_func)(struct pt_regs *);
-+ struct dtrace_invop_hdlr *dtih_next;
-+};
-+
-+static struct dtrace_invop_hdlr *dtrace_invop_hdlrs;
-+
- /*
- * Trap notification handler.
- */
-@@ -68,6 +75,7 @@ int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
- void *args)
- {
- struct die_args *dargs = args;
-+ int orig_trapnr = 0;
-
- switch (val) {
- case DIE_PAGE_FAULT: {
-@@ -79,12 +87,141 @@ int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
- return NOTIFY_OK | NOTIFY_STOP_MASK;
- }
- case DIE_GPF: {
-- if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
-+ /*
-+ * This gets messy... For one, some versions of Xen deliver
-+ * the invalid opcode generated by the LOCK prefix (0xf0) as a
-+ * GP fault rather than a UD fault. So, we need to figure out
-+ * whether the GP we're processing here is one of those
-+ * misreported faults.
-+ *
-+ * But, it is possible that the instruction that caused the
-+ * fault (0xf0) gets overwritten by a different CPU with the
-+ * original valid opcode before we get to look at it here,
-+ * which makes it kind of hard to recognize.
-+ *
-+ * So... we're going to assume that a GP fault that gets
-+ * triggered for the LOCK prefix opcode (0xf0) *or* for an
-+ * opcode that can get overwritten with the LOCK prefix for
-+ * probing is actually a UD fault.
-+ *
-+ * If we are wrong, the handlers will simply see a fault that
-+ * isn't theirs, and return without consuming it. And in that
-+ * case, the kernel will report a UD fault that may have been
-+ * a real GP fault... Sorry.
-+ */
-+ asm_instr_t opc = *(asm_instr_t *)dargs->regs->ip;
-+
-+ if (opc != 0xf0 && opc != 0x55 && opc != 0xc3) {
-+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
-+ return NOTIFY_DONE;
-+
-+ dtrace_handle_badaddr(dargs->regs);
-+
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ }
-+
-+ /*
-+ * ... and instead treat them as the SDT probe point traps that
-+ * they are.
-+ */
-+ orig_trapnr = dargs->trapnr;
-+ dargs->trapnr = 6;
-+ }
-+ /* fallthrough */
-+ case DIE_TRAP: {
-+ struct dtrace_invop_hdlr *hdlr;
-+ int rval = 0;
-+
-+ if (dargs->trapnr != 6)
- return NOTIFY_DONE;
-
-- dtrace_handle_badaddr(dargs->regs);
-+ for (hdlr = dtrace_invop_hdlrs; hdlr != NULL;
-+ hdlr = hdlr->dtih_next) {
-+ rval = hdlr->dtih_func(dargs->regs);
-+ if (rval != 0)
-+ break;
-+ }
-
-- return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ switch (rval) {
-+ case DTRACE_INVOP_NOPS:
-+ /*
-+ * SDT probe points are encoded as either:
-+ * - a 1-byte NOP followed by a multi-byte NOP
-+ * - a multi-byte code sequence (to set AX to 0),
-+ * followed by a multi-byte NOP
-+ * In both cases, the total length of the probe point
-+ * instruction is ASM_CALL_SITE bytes, so we can safely
-+ * skip that number of bytes here.
-+ */
-+ dargs->regs->ip += ASM_CALL_SIZE;
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ case DTRACE_INVOP_MOV_RSP_RBP:
-+ case DTRACE_INVOP_NOP:
-+ case DTRACE_INVOP_PUSH_BP:
-+ case DTRACE_INVOP_RET:
-+ return notifier_from_errno(-rval);
-+ default:
-+ /*
-+ * This must not have been a trap triggered from a
-+ * probe point. Let someone else deal with it...
-+ *
-+ * If we got here because of a GPF that we thought
-+ * was a UD (due to a bug in some versions of Xen),
-+ * undo our change to dargs->trapnr.
-+ */
-+ if (unlikely(orig_trapnr))
-+ dargs->trapnr = orig_trapnr;
-+
-+ return NOTIFY_DONE;
-+ }
-+ }
-+ case DIE_INT3: {
-+ struct dtrace_invop_hdlr *hdlr;
-+ int rval = 0;
-+
-+ /*
-+ * Let's assume that this is a DTrace probe firing, so we need
-+ * to adjust the IP (to be consistent with #UD processing) so
-+ * that it reflects the address of the #BP rather than the
-+ * following intruction.
-+ *
-+ * If it turns out that this was not DTrace related, we'll have
-+ * to reverse this adjustment.
-+ */
-+ dargs->regs->ip--;
-+ for (hdlr = dtrace_invop_hdlrs; hdlr != NULL;
-+ hdlr = hdlr->dtih_next) {
-+ rval = hdlr->dtih_func(dargs->regs);
-+ if (rval != 0)
-+ break;
-+ }
-+
-+ switch (rval) {
-+ case DTRACE_INVOP_NOPS:
-+ /*
-+ * SDT probe points are encoded as either:
-+ * - a 1-byte NOP followed by a multi-byte NOP
-+ * - a multi-byte code sequence (to set AX to 0),
-+ * followed by a multi-byte NOP
-+ * In both cases, the total length of the probe point
-+ * instruction is ASM_CALL_SITE bytes, so we can safely
-+ * skip that number of bytes here.
-+ */
-+ dargs->regs->ip += ASM_CALL_SIZE;
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ case DTRACE_INVOP_MOV_RSP_RBP:
-+ case DTRACE_INVOP_NOP:
-+ case DTRACE_INVOP_PUSH_BP:
-+ case DTRACE_INVOP_RET:
-+ return notifier_from_errno(-rval);
-+ default:
-+ /*
-+ * This must not have been a trap triggered from a
-+ * probe point. Re-adjust the instruction pointer
-+ * and let someone else deal with it...
-+ */
-+ dargs->regs->ip++;
-+ }
- }
- /* fallthrough */
- default:
-@@ -92,6 +229,77 @@ int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
- }
- }
-
-+/*
-+ * Add an INVOP trap handler.
-+ */
-+int dtrace_invop_add(uint8_t (*func)(struct pt_regs *))
-+{
-+ struct dtrace_invop_hdlr *hdlr;
-+
-+ hdlr = kmalloc(sizeof(struct dtrace_invop_hdlr), GFP_KERNEL);
-+ if (hdlr == NULL) {
-+ pr_warn("Failed to add invop handler: out of memory\n");
-+ return -ENOMEM;
-+ }
-+
-+ hdlr->dtih_func = func;
-+ hdlr->dtih_next = dtrace_invop_hdlrs;
-+ dtrace_invop_hdlrs = hdlr;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_invop_add);
-+
-+/*
-+ * Remove an INVOP trap handler.
-+ */
-+void dtrace_invop_remove(uint8_t (*func)(struct pt_regs *))
-+{
-+ struct dtrace_invop_hdlr *hdlr = dtrace_invop_hdlrs, *prev = NULL;
-+
-+ for (;;) {
-+ if (hdlr == NULL)
-+ return;
-+
-+ if (hdlr->dtih_func == func)
-+ break;
-+
-+ prev = hdlr;
-+ hdlr = hdlr->dtih_next;
-+ }
-+
-+ if (prev == NULL)
-+ dtrace_invop_hdlrs = hdlr->dtih_next;
-+ else
-+ prev->dtih_next = hdlr->dtih_next;
-+
-+ kfree(hdlr);
-+}
-+EXPORT_SYMBOL(dtrace_invop_remove);
-+
-+/*
-+ * Enable an INVOP-based probe, i.e. ensure that an INVOP trap is triggered at
-+ * the specified address.
-+ */
-+void dtrace_invop_enable(asm_instr_t *addr, asm_instr_t opcode)
-+{
-+ mutex_lock(&text_mutex);
-+ text_poke(addr, ((unsigned char []){opcode}), 1);
-+ mutex_unlock(&text_mutex);
-+}
-+EXPORT_SYMBOL(dtrace_invop_enable);
-+
-+/*
-+ * Disable an INVOP-based probe.
-+ */
-+void dtrace_invop_disable(asm_instr_t *addr, asm_instr_t opcode)
-+{
-+ mutex_lock(&text_mutex);
-+ text_poke(addr, ((unsigned char []){opcode}), 1);
-+ mutex_unlock(&text_mutex);
-+}
-+EXPORT_SYMBOL(dtrace_invop_disable);
-+
- static inline int dtrace_bad_address(void *addr)
- {
- unsigned long dummy;
-diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
-index bf9e0adb5b7e..970b6cd011f6 100644
---- a/arch/x86/kernel/vmlinux.lds.S
-+++ b/arch/x86/kernel/vmlinux.lds.S
-@@ -473,7 +473,8 @@ INIT_PER_CPU(irq_stack_backing_store);
- /*
- * Build-time check on the image size:
- */
--. = ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
-+. = ASSERT(((_end < _text) ? (_end < KERNEL_IMAGE_SIZE)
-+ : (_end - _text <= KERNEL_IMAGE_SIZE)),
- "kernel image bigger than KERNEL_IMAGE_SIZE");
-
- #ifdef CONFIG_SMP
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index b2b3d81b1535..7d1517f97db2 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -214,6 +214,20 @@
- #define ERROR_INJECT_WHITELIST()
- #endif
-
-+#ifdef CONFIG_DTRACE
-+#define DTRACE_SDT_NAMES() . = ALIGN(8); \
-+ __start_dtrace_sdt_names = .; \
-+ KEEP(*(_dtrace_sdt_names)) \
-+ __stop_dtrace_sdt_names = .;
-+#define DTRACE_SDT_ARGS() . = ALIGN(8); \
-+ __start_dtrace_sdt_args = .; \
-+ KEEP(*(_dtrace_sdt_args)) \
-+ __stop_dtrace_sdt_args = .;
-+#else
-+#define DTRACE_SDT_NAMES()
-+#define DTRACE_SDT_ARGS()
-+#endif
-+
- #ifdef CONFIG_EVENT_TRACING
- #define FTRACE_EVENTS() . = ALIGN(8); \
- __start_ftrace_events = .; \
-@@ -721,6 +735,8 @@
- FTRACE_EVENTS() \
- TRACE_SYSCALLS() \
- KPROBE_BLACKLIST() \
-+ DTRACE_SDT_NAMES() \
-+ DTRACE_SDT_ARGS() \
- ERROR_INJECT_WHITELIST() \
- MEM_DISCARD(init.rodata) \
- CLK_OF_TABLES() \
-diff --git a/include/linux/dtrace_os.h b/include/linux/dtrace_os.h
-index 5bcd77e08a14..f2921ce039a7 100644
---- a/include/linux/dtrace_os.h
-+++ b/include/linux/dtrace_os.h
-@@ -25,6 +25,9 @@ extern void __init dtrace_os_init(void);
- extern void __init dtrace_psinfo_os_init(void);
- extern void __init dtrace_task_os_init(void);
-
-+extern void *dtrace_alloc_text(struct module *, unsigned long);
-+extern void dtrace_free_text(void *);
-+
- extern void dtrace_mod_pdata_alloc(struct module *);
- extern void dtrace_mod_pdata_free(struct module *);
- extern int dtrace_destroy_prov(struct module *);
-diff --git a/include/linux/dtrace_sdt.h b/include/linux/dtrace_sdt.h
-new file mode 100644
-index 000000000000..3a4d608bc3fa
---- /dev/null
-+++ b/include/linux/dtrace_sdt.h
-@@ -0,0 +1,32 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _DTRACE_SDT_H_
-+#define _DTRACE_SDT_H_
-+
-+#ifdef CONFIG_DTRACE
-+#include <linux/module.h>
-+#include <asm/dtrace_arch.h>
-+
-+extern void __init dtrace_sdt_init(void);
-+extern void __init dtrace_sdt_register(struct module *);
-+extern void dtrace_sdt_register_module(struct module *,
-+ void *sdt_names_addr, size_t,
-+ void *sdt_args_addr, size_t);
-+extern void dtrace_sdt_exit(void);
-+
-+/*
-+ * Functions to be defined in arch/<arch>/kernel/dtrace_sdt.c
-+ */
-+extern void __init_or_module dtrace_sdt_nop_multi(asm_instr_t **, int *, int);
-+
-+#ifdef CONFIG_X86_64
-+extern void __init dtrace_sdt_init_arch(void);
-+#else
-+#define dtrace_sdt_init_arch()
-+#endif /* CONFIG_X86_64 */
-+
-+#endif /* CONFIG_DTRACE */
-+#endif /* _DTRACE_SDT_H_ */
-diff --git a/include/linux/module.h b/include/linux/module.h
-index 44915ed85337..7abbaeb5d659 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -30,6 +30,8 @@
- #include <linux/percpu.h>
- #include <asm/module.h>
-
-+#include <linux/sdt.h>
-+
- /* Not Yet Implemented */
- #define MODULE_SUPPORTED_DEVICE(name)
-
-@@ -513,8 +515,11 @@ struct module {
- #endif
-
- #ifdef CONFIG_DTRACE
-+ struct sdt_probedesc *sdt_probes;
-+ unsigned int sdt_probec;
- void *pdata;
- #endif
-+
- #ifdef CONFIG_MODULE_UNLOAD
- /* What modules depend on me? */
- struct list_head source_list;
-diff --git a/include/linux/sdt.h b/include/linux/sdt.h
-new file mode 100644
-index 000000000000..8efb63cff1ac
---- /dev/null
-+++ b/include/linux/sdt.h
-@@ -0,0 +1,191 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_SDT_H_
-+#define _LINUX_SDT_H_
-+
-+#include <linux/sdt_internal.h>
-+
-+#if IS_ENABLED(CONFIG_DT_SDT)
-+
-+#include <asm/dtrace_sdt_arch.h>
-+#include <linux/stringify.h>
-+
-+#define DTRACE_PROBE(name, ...) { \
-+ extern int __dtrace_probe_##name(__DTRACE_TYPE_APPLY_DEFAULT(__DTRACE_UINTPTR_EACH, void, ## __VA_ARGS__)); \
-+ (void)__dtrace_probe_##name(__DTRACE_ARG_APPLY(__DTRACE_UINTCAST_EACH, ## __VA_ARGS__)); \
-+ asm volatile(".pushsection _dtrace_sdt_names, \"a\", @progbits\n" \
-+ ".ascii \"" __stringify(name) "\"\n" \
-+ ".byte 0\n" \
-+ ".popsection\n" \
-+ ".pushsection _dtrace_sdt_args, \"a\", @progbits\n" \
-+ __DTRACE_TYPE_APPLY_NOCOMMA(__DTRACE_TYPE_EACH, ## __VA_ARGS__) \
-+ ".byte 0\n" \
-+ ".popsection\n"); \
-+}
-+
-+#define DTRACE_PROBE_ENABLED(name) unlikely(({ \
-+ extern int __dtrace_isenabled_##name(__DTRACE_SDT_ISENABLED_PROTO); \
-+ __dtrace_isenabled_##name(__DTRACE_SDT_ISENABLED_ARGS); \
-+}))
-+
-+#ifdef CONFIG_DT_SDT_PERF
-+
-+#define __DTRACE_UINTPTR_CAST_EACH(x) ({ \
-+ union { \
-+ typeof((x)) __val; \
-+ unsigned char __c; \
-+ unsigned short __s; \
-+ unsigned int __i; \
-+ unsigned long __l; \
-+ unsigned long long __ll; } __u = { .__val = (x) }; \
-+ __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__c), __u.__c, \
-+ __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__s), __u.__s, \
-+ __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__i), __u.__i, \
-+ __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__l), __u.__l, \
-+ __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__ll), __u.__ll, \
-+ (uintptr_t)&(__u.__val)))))); })
-+
-+#define DTRACE_PROBE_TRACEPOINT(name, ...) { \
-+ extern void __dtrace_probe___perf_##name(__DTRACE_APPLY(__DTRACE_UINTPTR_EACH, ## __VA_ARGS__)); \
-+ __dtrace_probe___perf_##name(__DTRACE_APPLY(__DTRACE_UINTPTR_CAST_EACH, ## __VA_ARGS__)); \
-+}
-+
-+#define DTRACE_PROTO_TRACEPOINT(name, ...) { \
-+ asm volatile(".pushsection _dtrace_sdt_names, \"a\", @progbits\n"\
-+ ".ascii \"" __stringify(__perf_##name) "\"\n" \
-+ ".byte 0\n" \
-+ ".popsection\n" \
-+ ".pushsection _dtrace_sdt_args, \"a\", @progbits\n" \
-+ ".ascii \"" __stringify(__VA_ARGS__) "\"\n" \
-+ ".byte 0\n" \
-+ ".popsection\n"); \
-+}
-+#else
-+
-+#define DTRACE_PROBE_TRACEPOINT(name, ...)
-+#define DTRACE_PROTO_TRACEPOINT(name, ...)
-+
-+#endif
-+
-+#else /* ! IS_ENABLED(CONFIG_DT_SDT) */
-+
-+/*
-+ * This apparently redundant call serves to validate the DTRACE_PROBE has the
-+ * right number of args even when dtrace is turned off.
-+ */
-+#define DTRACE_PROBE(name, ...) \
-+ __DTRACE_DOUBLE_APPLY_NOCOMMA(__DTRACE_NONE, __DTRACE_NONE, ## __VA_ARGS__) \
-+ do { } while (0)
-+#define DTRACE_PROBE_ENABLED(name) 0
-+#define DTRACE_PROBE_TRACEPOINT(name, ...)
-+#define DTRACE_PROTO_TRACEPOINT(name, ...)
-+
-+#endif /* IS_ENABLED(CONFIG_DT_SDT) */
-+
-+#ifdef CONFIG_DTRACE
-+
-+struct sdt_probedesc {
-+ char *sdpd_name; /* probe name */
-+ char *sdpd_func; /* probe function */
-+#ifndef __GENKSYMS__
-+ const char *sdpd_args; /* arg string */
-+#endif
-+ unsigned long sdpd_offset; /* offset of call in text */
-+ struct sdt_probedesc *sdpd_next; /* next static probe */
-+};
-+
-+#endif /* CONFIG_DTRACE */
-+
-+#define DTRACE_SCHED(name, ...) \
-+ DTRACE_PROBE(__sched_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_PROC(name, ...) \
-+ DTRACE_PROBE(__proc_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_IO(name, ...) \
-+ DTRACE_PROBE(__io_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_IO_ENABLED(name) \
-+ DTRACE_PROBE_ENABLED(__io_##name)
-+
-+#define DTRACE_ISCSI(name, ...) \
-+ DTRACE_PROBE(__iscsi_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_NFSV3(name, ...) \
-+ DTRACE_PROBE(__nfsv3_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_NFSV4(name, ...) \
-+ DTRACE_PROBE(__nfsv4_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_SMB(name, ...) \
-+ DTRACE_PROBE(__smb_##name, ## __VA_ARGS__);
-+
-+/*
-+ * These definitions are used at probe points to specify the traffic direction;
-+ * this helps simplify argument translation.
-+ */
-+#define DTRACE_NET_PROBE_OUTBOUND 0x0
-+#define DTRACE_NET_PROBE_INBOUND 0x1
-+
-+#define DTRACE_IP(name, ...) \
-+ DTRACE_PROBE(__ip_##name, ## __VA_ARGS__);
-+
-+/*
-+ * Default DTRACE_TCP() and DTRACE_UDP() provider definitions specify the
-+ * probe point within an is-enabled predicate. This is to avoid the overhead
-+ * incurred during argument dereferencing (e.g. calls to ip_hdr(skb)), along
-+ * with any conditional evaluation (which would require branching) when the
-+ * probe is disabled.
-+ *
-+ * Because some TCP probe points require additional argument preparation,
-+ * we also define the is-enabled predicate directly as
-+ * DTRACE_TCP_ENABLED(probename) along with a probe point which does not
-+ * the probe in an is-enabled predicate; this allows us to handle cases such
-+ * as this:
-+ *
-+ * if (DTRACE_TCP_ENABLED(state__change)) {
-+ * ...argument preparation...
-+ * DTRACE_TCP_NOCHECK(state__change, ...);
-+ * }
-+ */
-+
-+#define DTRACE_TCP(name, ...) \
-+ if (DTRACE_PROBE_ENABLED(__tcp_##name)) \
-+ DTRACE_PROBE(__tcp_##name, ## __VA_ARGS__)
-+#define DTRACE_TCP_ENABLED(name) \
-+ DTRACE_PROBE_ENABLED(__tcp_##name)
-+#define DTRACE_TCP_NOCHECK(name, ...) \
-+ DTRACE_PROBE(__tcp_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_UDP(name, ...) \
-+ if (DTRACE_PROBE_ENABLED(__udp_##name)) \
-+ DTRACE_PROBE(__udp_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_SYSEVENT(name, ...) \
-+ DTRACE_PROBE(__sysevent_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_XPV(name, ...) \
-+ DTRACE_PROBE(__xpv_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_FC(name, ...) \
-+ DTRACE_PROBE(__fc_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_SRP(name, ...) \
-+ DTRACE_PROBE(__srp_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_LOCKSTAT_ENABLED(name) \
-+ DTRACE_PROBE_ENABLED(__lockstat_##name)
-+
-+#define DTRACE_LOCKSTAT(name, ...) \
-+ DTRACE_PROBE(__lockstat_##name, ## __VA_ARGS__)
-+
-+#define DTRACE_LOCKSTAT_RW_WRITER 0
-+#define DTRACE_LOCKSTAT_RW_READER 1
-+
-+/* Needed for lockstat probes where we cannot include ktime.h */
-+extern u64 dtrace_gethrtime_ns(void);
-+
-+#endif /* _LINUX_SDT_H_ */
-diff --git a/include/linux/sdt_internal.h b/include/linux/sdt_internal.h
-new file mode 100644
-index 000000000000..b544f8e619cf
---- /dev/null
-+++ b/include/linux/sdt_internal.h
-@@ -0,0 +1,276 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Hide away all the terrible macro magic.
-+ *
-+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_SDT_INTERNAL_H_
-+#define _LINUX_SDT_INTERNAL_H_
-+
-+#include <linux/types.h>
-+
-+/*
-+ * This counts the number of args.
-+ */
-+#define __DTRACE_NARGS_SEQ(dummy, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
-+ _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
-+ _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
-+ _31, _32, _33, _34, _35, _36, N, ...) N
-+#define __DTRACE_NARGS(...) \
-+ __DTRACE_NARGS_SEQ(dummy, ##__VA_ARGS__, 36, 35, 34, 33, 32, 31, \
-+ 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
-+ 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, \
-+ 8, 7, 6, 5, 4, 3, 2, 1, 0)
-+
-+/*
-+ * This will let macros expand before concatting them.
-+ */
-+#define __DTRACE_PRIMITIVE_CAT(x, y) x ## y
-+#define __DTRACE_CAT(x, y) __DTRACE_PRIMITIVE_CAT(x, y)
-+
-+#define __DTRACE_COMMA ,
-+#define __DTRACE_NO_COMMA
-+#define __DTRACE_NONE(x)
-+
-+/*
-+ * This will call two macros on each argument-pair passed in (the first two args
-+ * are the names of the macros to call). Its TYPE and NAME variants will throw
-+ * away the name and type arguments, respectively. __DTRACE_*_APPLY_NOCOMMA
-+ * are like DTRACE_*_APPLY, but also omit the comma between arguments in the
-+ * expansion of the macro. DTRACE_TYPE_APPLY_DEFAULT lets you specify a default
-+ * if no variadic args are provided.
-+ */
-+#define __DTRACE_DOUBLE_APPLY(type_macro, arg_macro, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(type_macro, \
-+ arg_macro, __DTRACE_COMMA, \
-+ __DTRACE_COMMA, , ## __VA_ARGS__)
-+#define __DTRACE_DOUBLE_APPLY_NOCOMMA(type_macro, arg_macro, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(type_macro, \
-+ arg_macro, __DTRACE_NO_COMMA, \
-+ __DTRACE_NO_COMMA, , ## __VA_ARGS__)
-+#define __DTRACE_TYPE_APPLY(type_macro, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(type_macro, \
-+ __DTRACE_NONE, __DTRACE_NO_COMMA, \
-+ __DTRACE_COMMA, , ## __VA_ARGS__)
-+#define __DTRACE_TYPE_APPLY_NOCOMMA(type_macro, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(type_macro, \
-+ __DTRACE_NONE, __DTRACE_NO_COMMA, \
-+ __DTRACE_NO_COMMA, , ## __VA_ARGS__)
-+#define __DTRACE_TYPE_APPLY_DEFAULT(type_macro, def, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(type_macro, \
-+ __DTRACE_NONE, __DTRACE_NO_COMMA, \
-+ __DTRACE_COMMA, def, ## __VA_ARGS__)
-+#define __DTRACE_ARG_APPLY(arg_macro, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(__DTRACE_NONE, \
-+ arg_macro, __DTRACE_NO_COMMA, \
-+ __DTRACE_COMMA, , ## __VA_ARGS__)
-+#define __DTRACE_DOUBLE_APPLY_0(t, a, comma_t, comma_a, def) def
-+#define __DTRACE_DOUBLE_APPLY_2(t, a, comma_t, comma_a, def, type1, arg1) \
-+ t(type1) comma_t a(arg1)
-+#define __DTRACE_DOUBLE_APPLY_4(t, a, comma_t, comma_a, def, type1, arg1, \
-+ type2, arg2) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2)
-+#define __DTRACE_DOUBLE_APPLY_6(t, a, comma_t, comma_a, def, type1, \
-+ arg1, type2, arg2, type3, arg3) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3)
-+#define __DTRACE_DOUBLE_APPLY_8(t, a, comma_t, comma_a, def, type1, arg1, \
-+ type2, arg2, type3, arg3, type4, arg4) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4)
-+#define __DTRACE_DOUBLE_APPLY_10(t, a, comma_t, comma_a, def, type1, arg1,\
-+ type2, arg2, type3, arg3, type4, arg4, \
-+ type5, arg5) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5)
-+#define __DTRACE_DOUBLE_APPLY_12(t, a, comma_t, comma_a, def, type1, \
-+ arg1, type2, arg2, type3, arg3, type4, \
-+ arg4, type5, arg5, type6, arg6) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6)
-+#define __DTRACE_DOUBLE_APPLY_14(t, a, comma_t, comma_a, def, type1, \
-+ arg1, type2, arg2, type3, arg3, type4, \
-+ arg4, type5, arg5, type6, arg6, type7, \
-+ arg7) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7)
-+#define __DTRACE_DOUBLE_APPLY_16(t, a, comma_t, comma_a, def, type1, \
-+ arg1, type2, arg2, type3, arg3, type4, \
-+ arg4, type5, arg5, type6, arg6, type7, \
-+ arg7, type8, arg8) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8)
-+#define __DTRACE_DOUBLE_APPLY_18(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9)
-+#define __DTRACE_DOUBLE_APPLY_20(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga)
-+#define __DTRACE_DOUBLE_APPLY_22(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb)
-+#define __DTRACE_DOUBLE_APPLY_24(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc)
-+#define __DTRACE_DOUBLE_APPLY_26(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd)
-+#define __DTRACE_DOUBLE_APPLY_28(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd, typee, arge) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd) comma_a t(typee) comma_t a(arge)
-+#define __DTRACE_DOUBLE_APPLY_30(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd, typee, arge, typef, argf) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd) comma_a t(typee) comma_t a(arge) comma_a \
-+ t(typef) comma_t a(argf)
-+#define __DTRACE_DOUBLE_APPLY_32(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd, typee, arge, typef, argf, typeg, argg) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd) comma_a t(typee) comma_t a(arge) comma_a \
-+ t(typef) comma_t a(argf) comma_a t(typeg) comma_t a(argg)
-+#define __DTRACE_DOUBLE_APPLY_34(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd, typee, arge, typef, argf, typeg, argg, typeh, argh) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd) comma_a t(typee) comma_t a(arge) comma_a \
-+ t(typef) comma_t a(argf) comma_a t(typeg) comma_t a(argg) comma_a \
-+ t(typeh) comma_t a(argh)
-+#define __DTRACE_DOUBLE_APPLY_36(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd, typee, arge, typef, argf, typeg, argg, typeh, argh, typei, argi) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd) comma_a t(typee) comma_t a(arge) comma_a \
-+ t(typef) comma_t a(argf) comma_a t(typeg) comma_t a(argg) comma_a \
-+ t(typeh) comma_t a(argh) comma_a t(typei) comma_t a(argi)
-+
-+#define __DTRACE_DOUBLE_APPLY_ERROR Error: type specified without arg.
-+#define __DTRACE_DOUBLE_APPLY_1 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_3 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_5 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_7 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_9 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_11 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_13 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_15 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_17 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_19 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_21 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_23 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_25 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_27 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_29 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_31 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_33 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_35 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_37 __DTRACE_DOUBLE_APPLY_ERROR
-+
-+#define __DTRACE_UINTPTR_EACH(x) uintptr_t
-+
-+#define __DTRACE_UINTCAST_EACH(x) (uintptr_t)(x)
-+#define __DTRACE_TYPE_EACH(x) ".ascii \"" __stringify(x) ",\"\n"
-+
-+/*
-+ * Convert everything to the appropriate integral type, unless too large to fit
-+ * into any of them, in which case its address is taken instead.
-+ */
-+
-+/*
-+ * This will call a macro on each argument passed in, with optional default for
-+ * zero args.
-+ */
-+#define __DTRACE_APPLY(macro, ...) __DTRACE_CAT(__DTRACE_APPLY_, __DTRACE_NARGS(__VA_ARGS__))(macro, , ## __VA_ARGS__)
-+#define __DTRACE_APPLY_DEFAULT(macro, def, ...) __DTRACE_CAT(__DTRACE_APPLY_, __DTRACE_NARGS(__VA_ARGS__))(macro, def, ## __VA_ARGS__)
-+#define __DTRACE_APPLY_0(m, def) def
-+#define __DTRACE_APPLY_1(m, def, x1) m(x1)
-+#define __DTRACE_APPLY_2(m, def, x1, x2) m(x1), m(x2)
-+#define __DTRACE_APPLY_3(m, def, x1, x2, x3) m(x1), m(x2), m(x3)
-+#define __DTRACE_APPLY_4(m, def, x1, x2, x3, x4) m(x1), m(x2), m(x3), m(x4)
-+#define __DTRACE_APPLY_5(m, def, x1, x2, x3, x4, x5) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5)
-+#define __DTRACE_APPLY_6(m, def, x1, x2, x3, x4, x5, x6) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6)
-+#define __DTRACE_APPLY_7(m, def, x1, x2, x3, x4, x5, x6, x7) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7)
-+#define __DTRACE_APPLY_8(m, def, x1, x2, x3, x4, x5, x6, x7, x8) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
-+#define __DTRACE_APPLY_9(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9)
-+#define __DTRACE_APPLY_10(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa)
-+#define __DTRACE_APPLY_11(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb)
-+#define __DTRACE_APPLY_12(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc)
-+#define __DTRACE_APPLY_13(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd)
-+#define __DTRACE_APPLY_14(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd), m(xe)
-+#define __DTRACE_APPLY_15(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd), m(xe), m(xf)
-+#define __DTRACE_APPLY_16(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, xg) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd), m(xe), m(xf), m(xg)
-+#define __DTRACE_APPLY_17(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, xg, xh) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd), m(xe), m(xf), m(xg), m(xh)
-+#define __DTRACE_APPLY_18(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, xg, xh, xi) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd), m(xe), m(xf), m(xg), m(xh), m(xi)
-+
-+#endif /* _LINUX_SDT_INTERNAL_H */
-diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
-index 0f21617f1a66..e847bbafd123 100644
---- a/include/linux/tracepoint.h
-+++ b/include/linux/tracepoint.h
-@@ -20,6 +20,7 @@
- #include <linux/rcupdate.h>
- #include <linux/tracepoint-defs.h>
- #include <linux/static_call.h>
-+#include <linux/sdt.h>
-
- struct module;
- struct tracepoint;
-@@ -237,6 +238,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
- extern struct tracepoint __tracepoint_##name; \
- static inline void trace_##name(proto) \
- { \
-+ DTRACE_PROBE_TRACEPOINT(name, args); \
-+ DTRACE_PROTO_TRACEPOINT(name, proto); \
- if (static_key_false(&__tracepoint_##name.key)) \
- __DO_TRACE(name, \
- TP_PROTO(data_proto), \
-@@ -332,7 +335,10 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
- #else /* !TRACEPOINTS_ENABLED */
- #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
- static inline void trace_##name(proto) \
-- { } \
-+ { \
-+ DTRACE_PROBE_TRACEPOINT(name, args); \
-+ DTRACE_PROTO_TRACEPOINT(name, proto); \
-+ } \
- static inline void trace_##name##_rcuidle(proto) \
- { } \
- static inline int \
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-index d04ca0ab7ac9..c1ec55d8750e 100644
---- a/kernel/dtrace/Kconfig
-+++ b/kernel/dtrace/Kconfig
-@@ -23,6 +23,22 @@ config DT_CORE
-
- if DT_CORE
-
-+config DT_SDT
-+ tristate "Statically Defined Tracing"
-+ default m
-+ select KALLSYMS
-+ help
-+ Statically defined tracepoints in the kernel.
-+
-+config DT_SDT_PERF
-+ bool "DTrace perf-events Probes"
-+ default y
-+ depends on DT_SDT
-+ select TRACEPOINTS
-+ help
-+ Provides the perf provider, containing a DTrace probe for each
-+ perf-events tracepoint in the system.
-+
- config DT_SYSTRACE
- tristate "System Call Tracing"
- default m
-diff --git a/kernel/dtrace/Makefile b/kernel/dtrace/Makefile
-index 68fc3861e5d1..06329cbe52cb 100644
---- a/kernel/dtrace/Makefile
-+++ b/kernel/dtrace/Makefile
-@@ -4,10 +4,11 @@
-
- DT_CORE_ARCH_OBJS = $(addprefix ../../arch/$(SRCARCH)/kernel/, \
- dtrace_syscall.o dtrace_syscall_stubs.o \
-- dtrace_util.o)
-+ dtrace_sdt.o dtrace_util.o)
-
- ifdef CONFIG_DT_CORE
- obj-y += cyclic.o dtrace_os.o dtrace_cpu.o \
-+ dtrace_sdt_core.o \
- dtrace_task.o dtrace_psinfo.o \
- $(DT_CORE_ARCH_OBJS)
- endif
-diff --git a/kernel/dtrace/dtrace_os.c b/kernel/dtrace/dtrace_os.c
-index d023f3913323..931cfd0d0fbf 100644
---- a/kernel/dtrace/dtrace_os.c
-+++ b/kernel/dtrace/dtrace_os.c
-@@ -19,6 +19,7 @@
- #include <linux/binfmts.h>
- #include <linux/dtrace_cpu.h>
- #include <linux/dtrace_os.h>
-+#include <linux/dtrace_sdt.h>
- #include <linux/fs.h>
- #include <linux/hardirq.h>
- #include <linux/interrupt.h>
-@@ -66,6 +67,46 @@ void __init dtrace_os_init(void)
- if (dtrace_pdata_cachep == NULL)
- pr_debug("Can't allocate kmem cache for pdata\n");
-
-+ /*
-+ * A little bit of magic...
-+ * We create a dummy module to represent the core Linux kernel. The
-+ * only data we're interested in is the name, the SDT probe points data
-+ * (to be filled in by dtrace_sdt_register()), and the probe data.
-+ * DTrace uses an architecture-specific structure (hidden from us here)
-+ * to hold some data.
-+ */
-+ dtrace_kmod = kmalloc(sizeof(struct module), GFP_KERNEL | __GFP_ZERO);
-+ if (dtrace_kmod == NULL) {
-+ pr_warn("%s: cannot allocate kernel pseudo-module\n",
-+ __func__);
-+ return;
-+ }
-+
-+ strlcpy(dtrace_kmod->name, "vmlinux", MODULE_NAME_LEN);
-+
-+ /*
-+ * Some sizing info is required for kernel module. We are going to use
-+ * modules VA range for trampoline anyway so lets pretend a kernel has
-+ * no init section and VA range (0, MODULES_VADDR) is occupied by
-+ * kernel itself
-+ */
-+#ifdef CONFIG_X86_64
-+ dtrace_kmod->core_layout.base = (void *)__START_KERNEL_map;
-+ dtrace_kmod->core_layout.size = KERNEL_IMAGE_SIZE;
-+#elif defined(CONFIG_SPARC64)
-+ /* Hardcoded see pgtable_64.h */
-+ dtrace_kmod->core_layout.base = (void *)0x4000000;
-+ dtrace_kmod->core_layout.size = 0x2000000;
-+#endif
-+
-+ dtrace_kmod->state = MODULE_STATE_LIVE;
-+ atomic_inc(&dtrace_kmod->refcnt);
-+
-+ dtrace_mod_pdata_alloc(dtrace_kmod);
-+
-+ INIT_LIST_HEAD(&dtrace_kmod->source_list);
-+ INIT_LIST_HEAD(&dtrace_kmod->target_list);
-+
- /*
- * We need to set up a psinfo structure for PID 0 (swapper).
- */
-@@ -73,7 +114,49 @@ void __init dtrace_os_init(void)
- dtrace_psinfo_os_init();
- dtrace_task_init(&init_task);
- dtrace_psinfo_alloc(&init_task);
-+
-+ dtrace_sdt_init();
-+ dtrace_sdt_register(dtrace_kmod);
-+}
-+
-+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-+#define TRAMP_RANGE 0x80000000
-+
-+void *dtrace_alloc_text(struct module *mp, unsigned long size)
-+{
-+ unsigned long mp_start, mp_end;
-+ unsigned long va_start, va_end;
-+ void *trampoline;
-+
-+ /* module range */
-+ mp_start = (unsigned long) mp->core_layout.base;
-+ mp_end = mp_start + mp->core_layout.size;
-+
-+ if (mp->init_layout.size) {
-+ mp_start = MIN(mp_start, (unsigned long)mp->init_layout.base);
-+ mp_end = MAX(mp_end, (unsigned long)mp->init_layout.base +
-+ mp->init_layout.size);
-+ }
-+
-+ /* get trampoline range */
-+ va_end = MIN(mp_start + TRAMP_RANGE, MODULES_END);
-+ va_start = (mp_end < TRAMP_RANGE) ? 0 : mp_end - TRAMP_RANGE;
-+ va_start = MAX(va_start, MODULES_VADDR);
-+
-+ trampoline = __vmalloc_node_range(size, 1, va_start, va_end,
-+ GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
-+ __builtin_return_address(0));
-+
-+ return trampoline;
-+}
-+EXPORT_SYMBOL(dtrace_alloc_text);
-+
-+void dtrace_free_text(void *ptr)
-+{
-+ return vfree(ptr);
- }
-+EXPORT_SYMBOL(dtrace_free_text);
-
- /*
- * MODULE SUPPORT FUNCTIONS
-diff --git a/kernel/dtrace/dtrace_sdt_core.c b/kernel/dtrace/dtrace_sdt_core.c
-new file mode 100644
-index 000000000000..90b86726f195
---- /dev/null
-+++ b/kernel/dtrace/dtrace_sdt_core.c
-@@ -0,0 +1,364 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_sdt_core.c
-+ * DESCRIPTION: DTrace - SDT probes
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/memory.h>
-+#include <linux/module.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_sdt.h>
-+#include <linux/jhash.h>
-+#include <linux/sdt.h>
-+#include <linux/slab.h>
-+#include <linux/string.h>
-+#include <linux/vmalloc.h>
-+#include <asm-generic/bitsperlong.h>
-+#include <asm-generic/sections.h>
-+
-+const char *sdt_prefix = "__dtrace_probe_";
-+int dtrace_nosdt;
-+
-+/*
-+ * Compiled-in SDT probe data.
-+ */
-+extern const unsigned long dtrace_sdt_probes[];
-+extern const char dtrace_sdt_strings[];
-+extern const unsigned long dtrace_sdt_nprobes;
-+
-+/*
-+ * Markers of core-kernel sdt_args and sdt_names sections.
-+ */
-+extern const char __start_dtrace_sdt_args[];
-+extern const char __stop_dtrace_sdt_args[];
-+extern const char __start_dtrace_sdt_names[];
-+extern const char __stop_dtrace_sdt_names[];
-+
-+static int sdt_probe_set(struct sdt_probedesc *sdp, const char *name,
-+ const char *func, uintptr_t addr, asm_instr_t **paddr,
-+ struct sdt_probedesc *prv)
-+{
-+ sdp->sdpd_name = kstrdup(name, GFP_KERNEL);
-+ if (sdp->sdpd_name == NULL) {
-+ kfree(sdp);
-+ return 1;
-+ }
-+
-+ sdp->sdpd_func = kstrdup(func, GFP_KERNEL);
-+ if (sdp->sdpd_func == NULL) {
-+ kfree(sdp->sdpd_name);
-+ kfree(sdp);
-+ return 1;
-+ }
-+
-+ sdp->sdpd_args = NULL;
-+ sdp->sdpd_offset = addr;
-+ sdp->sdpd_next = NULL;
-+
-+ *paddr = (asm_instr_t *)addr;
-+
-+ if (prv && strcmp(prv->sdpd_name, sdp->sdpd_name) == 0
-+ && strcmp(prv->sdpd_func, sdp->sdpd_func) == 0)
-+ prv->sdpd_next = sdp;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Transfer the SDT args section into the sdpd_args field left NULL above.
-+ *
-+ * The memory pointed to by args_start must have a lifetime at least as long as
-+ * that pointed to by sdpd.
-+ */
-+void dtrace_sdt_stash_args(const char *module_name,
-+ struct sdt_probedesc *sdpd, size_t nprobes,
-+ const char *names_start, size_t names_len,
-+ const char *args_start, size_t args_len)
-+{
-+ struct probe_name_hashent_t {
-+ const char *pnhe_name;
-+ const char *pnhe_args;
-+ } *args_by_name;
-+ int i;
-+ const char *namep, *argp;
-+ size_t hashsize;
-+
-+ /*
-+ * We need to find the probes (and there may be many) in the sdpd
-+ * corresponding to the probe with that name in the argtype section.
-+ *
-+ * Build a hashtable mapping from probe name -> args string, ignoring
-+ * duplicate probe names except to check (in debugging mode) that they
-+ * have the same args string as the first. Then cycle over the sdpd
-+ * looking up each probe in turn and pointing to the same place.
-+ *
-+ * We don't know how many entries there are in the table, but we do know
-+ * there cannot be more than nprobes (and are probably less).
-+ */
-+
-+ hashsize = nprobes * 4; /* arbitrary expansion factor */
-+ args_by_name = vzalloc(hashsize * sizeof(struct probe_name_hashent_t));
-+ if (args_by_name == NULL) {
-+ pr_warn("%s: cannot allocate hash for sdt args population\n",
-+ __func__);
-+ return;
-+ }
-+
-+ namep = names_start;
-+ argp = args_start;
-+ while ((namep < names_start + names_len) &&
-+ (argp < args_start + args_len)) {
-+
-+ size_t l = strlen(namep);
-+ u32 h = jhash(namep, l, 0) % hashsize;
-+
-+ while (args_by_name[h].pnhe_name != NULL &&
-+ strcmp(args_by_name[h].pnhe_name, namep) != 0) {
-+ h++;
-+ h %= hashsize;
-+ }
-+
-+ if (args_by_name[h].pnhe_name == NULL) {
-+ args_by_name[h].pnhe_name = namep;
-+ args_by_name[h].pnhe_args = argp;
-+ }
-+#if defined(CONFIG_DT_DEBUG)
-+ else if (strcmp(args_by_name[h].pnhe_name, namep) != 0)
-+ pr_warn("%s: multiple distinct arg strings for probe "
-+ "%s found: %s versus %s",
-+ module_name, namep,
-+ args_by_name[h].pnhe_args,
-+ argp);
-+#endif
-+ namep += l + 1;
-+ argp += strlen(argp) + 1;
-+ }
-+
-+#if defined(CONFIG_DT_DEBUG)
-+ if ((namep < names_start + names_len) || (argp < args_start + args_len))
-+ pr_warn("%s: Not all SDT names or args consumed: %zi "
-+ "bytes of names and %zi of args left over. "
-+ "Some arg types will be mis-assigned.\n", module_name,
-+ namep - (names_start + names_len),
-+ argp - (args_start + args_len));
-+#endif
-+
-+ for (i = 0; i < nprobes; i++) {
-+ size_t l = strlen(sdpd[i].sdpd_name);
-+ u32 h = jhash(sdpd[i].sdpd_name, l, 0) % hashsize;
-+
-+ /*
-+ * Is-enabled probes have no arg string.
-+ */
-+ if (sdpd[i].sdpd_name[0] == '?')
-+ continue;
-+
-+ while (args_by_name[h].pnhe_name != NULL &&
-+ strcmp(sdpd[i].sdpd_name,
-+ args_by_name[h].pnhe_name) != 0) {
-+ h++;
-+ h %= hashsize;
-+ }
-+
-+ if (args_by_name[h].pnhe_name == NULL) {
-+ /*
-+ * No arg string. Peculiar: report in debugging mode.
-+ */
-+#if defined(CONFIG_DT_DEBUG)
-+ pr_warn("%s: probe %s has no arg string.\n",
-+ module_name, sdpd[i].sdpd_name);
-+#endif
-+ continue;
-+ }
-+
-+ sdpd[i].sdpd_args = args_by_name[h].pnhe_args;
-+ }
-+ vfree(args_by_name);
-+}
-+
-+/*
-+ * Register the SDT probes for the core kernel, i.e. SDT probes that reside in
-+ * vmlinux. For SDT probes in kernel modules, we use dtrace_mod_notifier().
-+ */
-+void __init dtrace_sdt_register(struct module *mp)
-+{
-+ int i, cnt;
-+ struct sdt_probedesc *sdps;
-+ asm_instr_t **addrs;
-+ int *is_enabled;
-+ void *args;
-+ size_t args_len;
-+
-+ if (mp == NULL) {
-+ pr_warn("%s: no module provided - nothing registered\n",
-+ __func__);
-+ return;
-+ }
-+
-+ /*
-+ * Just in case we run into failures further on...
-+ */
-+ mp->sdt_probes = NULL;
-+ mp->sdt_probec = 0;
-+
-+ if (dtrace_sdt_nprobes == 0 || dtrace_nosdt)
-+ return;
-+
-+ /*
-+ * Allocate the array of SDT probe descriptions to be registered in the
-+ * vmlinux pseudo-module.
-+ */
-+ sdps = (struct sdt_probedesc *)vmalloc(dtrace_sdt_nprobes *
-+ sizeof(struct sdt_probedesc));
-+ if (sdps == NULL) {
-+ pr_warn("%s: cannot allocate SDT probe array\n", __func__);
-+ return;
-+ }
-+
-+ /*
-+ * Create a list of addresses (SDT probe locations) that need to be
-+ * patched with a NOP instruction (or instruction sequence), and another
-+ * array indicating whether each probe needs patching with an
-+ * arch-dependent false return instead.
-+ */
-+ addrs = (asm_instr_t **)vmalloc(dtrace_sdt_nprobes *
-+ sizeof(asm_instr_t *));
-+ is_enabled = (int *)vmalloc(dtrace_sdt_nprobes * sizeof(int));
-+ if ((addrs == NULL) || (is_enabled == NULL)) {
-+ pr_warn("%s: cannot allocate SDT probe address/is-enabled "
-+ "lists\n", __func__);
-+ vfree(sdps);
-+ vfree(addrs);
-+ vfree(is_enabled);
-+ return;
-+ }
-+
-+ for (i = cnt = 0; i < dtrace_sdt_nprobes; i++) {
-+ uintptr_t addr, poff, foff;
-+ const char *fname = &dtrace_sdt_strings[foff];
-+ const char *pname;
-+
-+ addr = dtrace_sdt_probes[i * 3]; /* address */
-+ poff = dtrace_sdt_probes[i * 3 + 1]; /* probe name offset */
-+ foff = dtrace_sdt_probes[i * 3 + 2]; /* func name offset */
-+ pname = &dtrace_sdt_strings[poff];
-+ fname = &dtrace_sdt_strings[foff];
-+
-+ is_enabled[cnt] = (pname[0] == '?');
-+
-+ if (sdt_probe_set(&sdps[cnt], pname, fname, addr, &addrs[cnt],
-+ cnt > 0 ? &sdps[cnt - 1] : NULL))
-+ pr_warn("%s: failed to add SDT probe %s for %s\n",
-+ __func__, pname, fname);
-+ else
-+ cnt++;
-+ }
-+
-+ mp->sdt_probes = sdps;
-+ mp->sdt_probec = cnt;
-+
-+ dtrace_sdt_nop_multi(addrs, is_enabled, cnt);
-+
-+ /*
-+ * Allocate space for the array of arg types, and copy it in from the
-+ * (discardable) kernel section. We will need to keep it. (The
-+ * identically-ordered array of probe names is not needed after
-+ * initialization.)
-+ */
-+ args_len = __stop_dtrace_sdt_args - __start_dtrace_sdt_args;
-+ args = vmalloc(args_len);
-+ if (args == NULL) {
-+ pr_warn("%s: cannot allocate table of SDT arg types\n",
-+ __func__);
-+ goto end;
-+ }
-+
-+ memcpy(args, __start_dtrace_sdt_args, args_len);
-+
-+ dtrace_sdt_stash_args("vmlinux", sdps, cnt,
-+ __start_dtrace_sdt_names,
-+ (__stop_dtrace_sdt_names - __start_dtrace_sdt_names),
-+ args, args_len);
-+
-+end:
-+ vfree(addrs);
-+ vfree(is_enabled);
-+}
-+
-+static int __init nosdt(char *str)
-+{
-+ dtrace_nosdt = 1;
-+
-+ return 0;
-+}
-+
-+early_param("nosdt", nosdt);
-+
-+void dtrace_sdt_register_module(struct module *mp,
-+ void *sdt_names_addr, size_t sdt_names_len,
-+ void *sdt_args_addr, size_t sdt_args_len)
-+{
-+ int i, cnt;
-+ struct sdt_probedesc *sdp;
-+ asm_instr_t **addrs;
-+ int *is_enabled;
-+
-+ if (mp->sdt_probec == 0 || mp->sdt_probes == NULL)
-+ return;
-+
-+ /*
-+ * Create a list of addresses (SDT probe locations) that need to be
-+ * patched with a NOP instruction (or instruction sequence).
-+ */
-+ addrs = (asm_instr_t **)vmalloc(mp->sdt_probec *
-+ sizeof(asm_instr_t *));
-+ is_enabled = (int *)vmalloc(mp->sdt_probec * sizeof(int));
-+ if ((addrs == NULL) || (is_enabled == NULL)) {
-+ pr_warn("%s: cannot allocate SDT probe address list (%s)\n",
-+ __func__, mp->name);
-+ vfree(addrs);
-+ vfree(is_enabled);
-+ return;
-+ }
-+
-+ for (i = cnt = 0, sdp = mp->sdt_probes; i < mp->sdt_probec;
-+ i++, sdp++) {
-+ addrs[cnt] = (asm_instr_t *)sdp->sdpd_offset;
-+ is_enabled[cnt++] = (sdp->sdpd_name[0] == '?');
-+ }
-+
-+ dtrace_sdt_nop_multi(addrs, is_enabled, cnt);
-+
-+ dtrace_sdt_stash_args(mp->name, mp->sdt_probes, mp->sdt_probec,
-+ sdt_names_addr, sdt_names_len,
-+ sdt_args_addr, sdt_args_len);
-+
-+ vfree(addrs);
-+ vfree(is_enabled);
-+}
-+
-+void __init dtrace_sdt_init(void)
-+{
-+ dtrace_sdt_init_arch();
-+}
-+
-+#if IS_ENABLED(CONFIG_DT_DT_PERF)
-+void dtrace_sdt_perf(void)
-+{
-+ DTRACE_PROBE(measure);
-+}
-+EXPORT_SYMBOL(dtrace_sdt_perf);
-+#endif
-diff --git a/kernel/module.c b/kernel/module.c
-index f4269dabc638..2f214881ae30 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -40,6 +40,7 @@
- #include <linux/string.h>
- #include <linux/mutex.h>
- #include <linux/rculist.h>
-+#include <linux/sdt.h>
- #include <linux/uaccess.h>
- #include <asm/cacheflush.h>
- #include <linux/set_memory.h>
-@@ -47,6 +48,7 @@
- #include <linux/license.h>
- #include <asm/sections.h>
- #include <linux/dtrace_os.h>
-+#include <linux/dtrace_sdt.h>
- #include <linux/tracepoint.h>
- #include <linux/ftrace.h>
- #include <linux/livepatch.h>
-@@ -3777,6 +3779,18 @@ static int complete_formation(struct module *mod, struct load_info *info)
- {
- int err;
-
-+#ifdef CONFIG_DTRACE
-+ void *sdt_args, *sdt_names;
-+ unsigned int sdt_args_len, sdt_names_len;
-+
-+ sdt_names = section_objs(info, "_dtrace_sdt_names", 1,
-+ &sdt_names_len);
-+ sdt_args = section_objs(info, "_dtrace_sdt_args", 1,
-+ &sdt_args_len);
-+ dtrace_sdt_register_module(mod, sdt_names, sdt_names_len,
-+ sdt_args, sdt_args_len);
-+#endif
-+
- mutex_lock(&module_mutex);
-
- /* Find duplicate symbols (must be called under lock). */
-diff --git a/scripts/.gitignore b/scripts/.gitignore
-index a6c11316c969..8458568004eb 100644
---- a/scripts/.gitignore
-+++ b/scripts/.gitignore
-@@ -9,3 +9,4 @@ extract-cert
- sign-file
- insert-sys-cert
- /module.lds
-+kmodsdt
-diff --git a/scripts/Makefile b/scripts/Makefile
-index efa1ff4dff95..509a73b6f269 100644
---- a/scripts/Makefile
-+++ b/scripts/Makefile
-@@ -11,6 +11,7 @@ hostprogs-always-$(CONFIG_ASN1) += asn1_compiler
- hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
- hostprogs-always-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
- hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
-+hostprogs-always-$(CONFIG_DTRACE) += kmodsdt
-
- kallsyms-objs := kallsyms.o
-
-@@ -36,6 +37,11 @@ HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
- HOSTLDLIBS_sorttable = -lpthread
- endif
-
-+ifeq ($(CONFIG_DTRACE),y)
-+HOSTCFLAGS_kmodsdt.o := -I$(srctree)/include/generated
-+HOSTLDLIBS_kmodsdt := -lelf
-+endif
-+
- # The following programs are only built on demand
- hostprogs += unifdef
-
-diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
-index 920545d75da9..50c464f248ef 100644
---- a/scripts/Makefile.modfinal
-+++ b/scripts/Makefile.modfinal
-@@ -2,7 +2,7 @@
- # ===========================================================================
- # Module final link and CTF generation
- # ===========================================================================
--# 1) compile all <module>.mod.c files
-+# 1) compute SDT offsets, generate SDT stubs, and compile all .mod.c files
- # 2) for external modules, generate CTF for the module (there is an extra,
- # externally-invoked target that does this for the entire kernel but does
- # not invoke the rst of the module-building process)
-@@ -32,11 +32,52 @@ modname = $(notdir $(@:.mod.o=))
- part-of-module = y
-
- quiet_cmd_cc_o_c = CC [M] $@
-- cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
-+ cmd_cc_o_c = $(CC) $(c_flags) -I$(dir $@) -c -o $@ $<
-+
-+quiet_cmd_as_o_S = AS $@
-+ cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
-+
-+ifdef CONFIG_DTRACE
-+
-+sdtgen = $(srctree)/scripts/dtrace_sdt.sh
-+
-+quiet_cmd_sdtinfo = SDTINF $@
-+ cmd_sdtinfo = $(sdtgen) sdtinfo $@ $< kmod $(@:.c=.h)
-+
-+quiet_cmd_sdtstub = SDTSTB $@
-+ cmd_sdtstub = $(sdtgen) sdtstub $@ $<
-+
-+# We depend on the .mod.c file to ensure that modpost runs before sdtinfo.
-+$(modules:.ko=.sdtinfo.c): %.sdtinfo.c: %.o %.mod.c
-+ $(call cmd,sdtinfo)
-+
-+# We depend on the sdtinfo file because info generation rewrites the .o,
-+# while sdtstubs reads it.
-+$(modules:.ko=.sdtstub.S) : %.sdtstub.S: %.o %.sdtinfo.c
-+ $(call cmd,sdtstub)
-+
-+%.sdtinfo.o : %.sdtinfo.c
-+ $(call if_changed_dep,cc_o_c)
-+
-+%.mod.o: %.mod.c %.sdtinfo.c FORCE
-+ $(call if_changed_dep,cc_o_c)
-+
-+$(modules:.ko=.sdtstub.o): %.sdtstub.o: %.sdtstub.S
-+ $(call if_changed,as_o_S)
-+
-+module-sdt-modular-prereq = %.sdtstub.o
-+sdtinfo-prereq = $(modules:.ko=.sdtinfo.c)
-+
-+else
-
- %.mod.o: %.mod.c FORCE
- $(call if_changed_dep,cc_o_c)
-
-+module-sdt-modular-prereq =
-+sdtinfo-prereq =
-+
-+endif
-+
- # Generate CTF for the entire kernel, or for the module alone if this is a
- # build of an external module.
-
-@@ -95,7 +136,7 @@ $(1) $(wordlist 1,1024,$(2))
- $(if $(word 1025,$(2)),$(call xargs,$(1),$(wordlist 1025,$(words $(2)),$(2))))
- endef
-
--$(ctf-filelist-raw): $(ctf-builtins-prereq) $(ctf-modules)
-+$(ctf-filelist-raw): $(ctf-builtins-prereq) $(ctf-modules) | $(sdtinfo-prereq)
- @rm -f $(ctf-filelist-raw);
- @if [ -n "$(ctf-dir-mk)" ]; then \
- mkdir -p "$(ctf-dir-mk)"; \
-@@ -123,7 +164,8 @@ vmlinux.ctfa: $(ctf-filelist)
- else
-
- # The CTF depends on the output CTF file list, and that depends
--# on the .o files for the modules
-+# on the .o files for the modules, and on the sdtinfo files, if any
-+# (for the same reason that the sdtstub does).
- $(ctf-stamp): $(ctf-filelist)
- $(call if_changed,ctf)
- @shopt -s nullglob; \
-@@ -170,7 +212,7 @@ quiet_cmd_ld_ko_o = LD [M] $@
- $(OBJCOPY) $(module-ctf-flags) $@.tmp $@ && rm -f $@.tmp ; \
- $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
-
--$(modules): %.ko: %.o %.mod.o scripts/module.lds $(module-ctfs-modular-prereq) FORCE
-+$(modules): %.ko: %.o %.mod.o %.sdtinfo.o scripts/module.lds $(module-sdt-modular-prereq) $(module-ctfs-modular-prereq) FORCE
- $(call cmd_touch_ctf)
- +$(call if_changed,ld_ko_o)
-
-diff --git a/scripts/dtrace_sdt.sh b/scripts/dtrace_sdt.sh
-new file mode 100755
-index 000000000000..2dd7ea1aebd8
---- /dev/null
-+++ b/scripts/dtrace_sdt.sh
-@@ -0,0 +1,588 @@
-+#!/bin/sh
-+# SPDX-License-Identifier: GPL-2.0
-+
-+LANG=C
-+
-+#
-+# Syntax:
-+# dtrace_sdt.sh sdtstub <S-file> <o-file>+
-+# This is used to generate DTrace SDT probe stubs based on one
-+# or more object file(s). The stubs are written to <S-file>.
-+# dtrace_sdt.sh sdtinfo <c-file> <o-file> kmod <h-file>
-+# This is used to generate DTrace SDT probe definitions for a
-+# kmod .o file. The output is written to <c-file> and <h-file>.
-+# dtrace_sdt.sh sdtinfo <S-file> <l-file>
-+# This is used to generate DTrace SDT probe definitions for a
-+# linked kernel image file <l-file>. The output is written to
-+# <S-file>.
-+#
-+
-+opr="$1"
-+shift
-+if [ -z "$opr" ]; then
-+ echo "ERROR: Missing operation" > /dev/stderr
-+ exit 1
-+fi
-+
-+tfn="$1"
-+shift
-+if [ -z "$tfn" ]; then
-+ echo "ERROR: Missing target filename" > /dev/stderr
-+ exit 1
-+fi
-+
-+ofn="$1"
-+tok="$2"
-+
-+if [ -z "$ofn" ]; then
-+ echo "ERROR: Missing object file argument" > /dev/stderr
-+ exit 1
-+fi
-+
-+if [ "$opr" = "sdtstub" ]; then
-+ ${NM} -u $* | grep -E '__dtrace_(probe|isenabled)_' | sort | uniq | \
-+ gawk -v arch=${ARCH} \
-+ '{
-+ printf("\t.globl %s\n\t.type %s,@function\n%s:\n",
-+ $2, $2, $2);
-+ count++;
-+ }
-+
-+ END {
-+ if (count) {
-+ if (arch == "x86" || arch == "x86_64") {
-+ print "\txor %eax,%eax";
-+ print "\tretq";
-+ } else if (arch == "sparc" || arch == "sparc64") {
-+ print "\tretl";
-+ print "\tnop";
-+ } else if (arch == "arm" || arch == "arm64") {
-+ print "\tmov w0, #0x0";
-+ print "\tret";
-+ }
-+ }
-+ }' > $tfn
-+ exit $?
-+fi
-+
-+if [ "$opr" != "sdtinfo" ]; then
-+ echo "ERROR: Invalid operation, should be sdtstub or sdtinfo" > /dev/stderr
-+ exit 1
-+fi
-+
-+if [ "$tok" = "kmod" ]; then
-+ hfile="$3"
-+
-+ # Pre-process the object file to handle any local functions that contain
-+ # SDT probes.
-+ scripts/kmodsdt ${ofn}
-+
-+ # Output all function symbols in the symbol table of the object file.
-+ # Subsequently, output all relocation records for DTrace SDT probes. The
-+ # probes are identified by either a __dtrace_probe_ or __dtrace_isenabled_
-+ # prefix.
-+ #
-+ # We sort the output primarily based on the section, using the value (or
-+ # offset) as secondary sort criterion The overall result is that the
-+ # output will be structured as a list of functions, and for any functions
-+ # that contain DTrace SDT probes, relocation records will follow the
-+ # function entry they are associated with.
-+ #
-+ # Relocations are reported by objdump per section, with a header line
-+ # documenting the specific section being reported:
-+ # RELOCATION RECORDS FOR [<section>]:
-+ # This is followed by a column header line, and a list of relocations.
-+ # The relocations are listed with 3 tokens per line:
-+ # <offset> <type> <value>
-+ #
-+ # Three different types can show up in the output (all with 4 tokens):
-+ # <section> <offset> F <value>
-+ # Function within a section at a specific offset.
-+ # (See STAGE 3a below.)
-+ # <section> <offset> G <value>
-+ # Global alias for a local function within a section at a specific
-+ # offset. A function can only have one alias, and there cannot be
-+ # an alias without its respective function.
-+ # (See STAGE 3a below.)
-+ # <section> <offset> R <value>
-+ # Relocation within a section at a specific offset.
-+ # (See STAGE 3b below.)
-+ #
-+ ${OBJDUMP} -tr ${ofn} | \
-+ gawk '/^RELOC/ {
-+ sect = substr($4, 2, length($4) - 3);
-+ if (sect ~ /^\.(exit|init|meminit)\.text/)
-+ sect = 0;
-+
-+ next;
-+ }
-+
-+ sect && /__dtrace_probe_/ {
-+ $3 = substr($3, 16);
-+ sub(/[\-+].*$/, "", $3);
-+ print sect " " $1 " R " $3;
-+ next;
-+ }
-+
-+ sect && /__dtrace_isenabled_/ {
-+ $3 = substr($3, 20);
-+ sub(/[\-+].*$/, "", $3);
-+ print sect " " $1 " R ?" $3;
-+ next;
-+ }
-+
-+ /file format/ {
-+ next;
-+ }
-+
-+ / F / {
-+ if ($4 ~ /^\.(exit|init|meminit)\.text/)
-+ next;
-+
-+ if ($6 == ".hidden")
-+ print $4 " " $1 " G " $7;
-+ else
-+ print $4 " " $1 " F " $6;
-+ }' | \
-+ sort -k1,2 | \
-+ gawk -v arch=${ARCH} -v hfile=${hfile} \
-+ 'function subl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ if (v0l >= v1l) {
-+ if (v0h >= v1h) {
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ if (v0h > v1h) {
-+ v0h--;
-+ v0l += 4294967296;
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 - v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ BEGIN {
-+ print "#include <linux/sdt.h>";
-+
-+ probec = 0;
-+ }
-+
-+ #
-+ # Process a symbol table definition for a function in the object
-+ # file ($ofn). As we pass through the symbol table, we record the
-+ # function name, address, and symbol table index or alias. This
-+ # information is needed for any potential DTrace probes that may exist
-+ # in the function. They will be listed in relocation records
-+ # subsequent to this function definition (and are processed in the
-+ # next action block).
-+ #
-+ NF == 4 && $3 == "F" {
-+ fname = $4;
-+ sub(/\..*$/, "", fname);
-+ alias = $4;
-+ faddr = $2;
-+ sub(/^0+/, "", faddr);
-+
-+ next;
-+ }
-+
-+ NF == 4 && $3 == "G" {
-+ alias = $4;
-+
-+ next;
-+ }
-+
-+ #
-+ # Process a relocation record associated with the preceding function.
-+ #
-+ # For kernel modules:
-+ # Convert the section offset into an offset in the function where the
-+ # DTrace probe is located, i.e. an offset from the start of the
-+ # function. This will be resolved in an absolute address at runtime
-+ # when the module is loaded.
-+ #
-+ NF == 4 && $3 == "R" {
-+ sub(/^0+/, "", $2);
-+
-+ addr = subl($2, faddr);
-+
-+ if (arch == "x86" || arch == "x86_64")
-+ addr = subl(addr, 1);
-+
-+ protom[alias] = 1;
-+ probev[probec] = sprintf(" {\042%s\042, \042%s\042 /* %s */, 0 /* sdt_args string */, (uintptr_t)%s+0x%s },", $4, fname, $1, alias, addr);
-+ probec++;
-+
-+ next;
-+ }
-+
-+ END {
-+ for (alias in protom)
-+ printf "extern void %s(void);\n", alias;
-+ print "\nstruct sdt_probedesc\t_sdt_probes[] = {";
-+ for (i = 0; i < probec; i++)
-+ print probev[i];
-+ print "};\n";
-+
-+ print "#define _sdt_probec\t" probec > hfile;
-+ print "extern struct sdt_probedesc _sdt_probes[];" >> hfile;
-+
-+ exit(errc == 0 ? 0 : 1);
-+ }' > $tfn
-+else
-+ # For a linked kernel (with relocation data), the scope of the DTrace SDT
-+ # probe discovery can be limited to CODE sections that are not included in
-+ # the init or exit code sections.
-+ #
-+ # First the sections records are parsed to order to determine the base
-+ # address for each relevant section.
-+ #
-+ # Subsequently, all function symbols that are located in the sections we
-+ # care about are read from the symbol table of the linked kernel object.
-+ # Each symbol is reported in the output stream with its section name,
-+ # address, a token identifying it as a function (or alias), and its name.
-+ #
-+ # Finally, each relocation record from relevant sections that relates to
-+ # SDT probes are written to the output stream with its section name,
-+ # address, a token # identifying it as a relocation, and its name. Probes
-+ # are identified in the relocation records as symbols with either a
-+ # __dtrace_probe_ or __dtrace_isenabled_ prefix.
-+ #
-+ # We sort the output based on the section name and address, ensuring that
-+ # the output will be a list of functions, and each function record will be
-+ # followed immediately by any DTrace SDT probe records that are used in
-+ # that function.
-+ #
-+ # Three different record types can show up in the output (4 tokens each):
-+ # <section> <address> F <name>
-+ # Named function at a specific address.
-+ # <section> <address> G <name>
-+ # Global alias for a local function at a specific offset. A
-+ # function can only have one alias, and there cannot be an alias
-+ # without its respective function.
-+ # <section> <address> R <value>
-+ # Relocation within a section at a specific address
-+ #
-+ ${OBJDUMP} -htr ${ofn} | \
-+ gawk 'function addl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8 || length(v1) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ v0l += v1l;
-+ v0h += v1h;
-+ d = sprintf("%x", v0l);
-+ if (length(d) > 8) {
-+ v0h++;
-+ v0l -= 4294967296;
-+ }
-+ d = sprintf("%x", v0h);
-+ if (length(d) <= 8) {
-+ d = sprintf("%08x%08x", v0h, v0l);
-+ } else {
-+ printf "#error Invalid addresses: %s + %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 + v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ function subl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ if (v0l >= v1l) {
-+ if (v0h >= v1h) {
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ if (v0h > v1h) {
-+ v0h--;
-+ v0l += 4294967296;
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 - v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ NF == 7 && $2 !~ /^\.(exit|init|meminit)\.text/ {
-+ snam = $2;
-+ addr = $4;
-+
-+ getline;
-+ if (/CODE/)
-+ base[snam] = addr;
-+
-+ next;
-+ }
-+
-+ NF == 5 && $2 == "g" && $NF == "_stext" {
-+ print ". " $1 " B _stext";
-+ next;
-+ }
-+
-+ /^RELOC/ {
-+ snam = substr($4, 2, length($4) - 3);
-+ if (snam in base)
-+ in_reloc = 1;
-+ else
-+ in_reloc = 0;
-+ next;
-+ }
-+
-+ in_reloc && /__dtrace_probe_/ {
-+ $3 = substr($3, 16);
-+ sub(/[\-+].*$/, "", $3);
-+ print snam " " addl(base[snam], $1) " R " $3;
-+ next;
-+ }
-+
-+ in_reloc && /__dtrace_isenabled_/ {
-+ $3 = substr($3, 20);
-+ sub(/[\-+].*$/, "", $3);
-+ print snam " " addl(base[snam], $1) " R ?" $3;
-+ next;
-+ }
-+
-+ / F / {
-+ if (!($4 in base))
-+ next;
-+
-+ if ($6 == ".hidden")
-+ print $4 " " $1 " G " $7;
-+ else
-+ print $4 " " $1 " F " $6;
-+ }' | \
-+ sort -k2 | \
-+ gawk -v arch=${ARCH} \
-+ 'function subl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ if (v0l >= v1l) {
-+ if (v0h >= v1h) {
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error Invalid addresses: %x vs %x", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ printf "#error Invalid addresses: %x vs %x", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 - v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ function map_string(str, off) {
-+ if (str in strmap)
-+ off = strmap[str];
-+ else {
-+ off = strsz;
-+ strmap[str] = strsz;
-+ strv[strc++] = str;
-+ strsz += length(str) + 1;
-+ }
-+
-+ return off;
-+ }
-+
-+ BEGIN {
-+ print "#include <asm/types.h>";
-+ print "#if BITS_PER_LONG == 64";
-+ print "# define PTR .quad";
-+ if (arch == "aarch64")
-+ print "# define ALGN .align 3";
-+ else
-+ print "# define ALGN .align 8";
-+ print "#else";
-+ print "# define PTR .long";
-+ if (arch == "aarch64")
-+ print "# define ALGN .align 2";
-+ else
-+ print "# define ALGN .align 4";
-+ print "#endif";
-+
-+ print "\t.section .rodata, \042a\042";
-+ print "";
-+
-+ print ".globl dtrace_sdt_probes";
-+ print "\tALGN";
-+ print "dtrace_sdt_probes:";
-+
-+ probec = 0;
-+ stroff = 0;
-+ strc = 0;
-+ }
-+
-+
-+ #
-+ # Record the _stext address so probe locations can be expressed
-+ # relative to that address.
-+ #
-+ NF == 4 && $1 == "." && $4 == "_stext" {
-+ stext = $2;
-+ next;
-+ }
-+
-+ #
-+ # Process a symbol table definition for a function in the .text
-+ # section of the kernel image. We record the function name and
-+ # the address, and pre-populate the alias name with the function
-+ # name.
-+ #
-+ # We also compare the address of the current symbol to the last
-+ # recorded address, and if they are the same, we do not increment
-+ # the function count.
-+ #
-+ NF == 4 && $3 == "F" {
-+ faddr = $2;
-+ fname = $4;
-+ sub(/\..*$/, "", fname);
-+ alias = $4;
-+
-+ if ($2 != prev)
-+ funcc++;
-+ prev = $2;
-+
-+ next;
-+ }
-+
-+ #
-+ # When we encounter an alias symbol, we record the name.
-+ #
-+ NF == 4 && $3 == "G" {
-+ alias = $4;
-+
-+ next;
-+ }
-+
-+ #
-+ # Process a relocation record associated with the preceding function.
-+ #
-+ # The address was resolved earlier, so we can simply generate the
-+ # numeric information for the SDT probe information record. The
-+ # text information (probe name and function name) are stored. This
-+ # allows us to weed out duplicates, and it is necessary because the
-+ # data blob with all the strings will be written to output later.
-+ #
-+ NF == 4 && $3 == "R" {
-+ sub(/^0+/, "", $2);
-+
-+ addr = subl($2, stext);
-+
-+ #
-+ # On x86, relocations point to the 2nd byte of a call instruction
-+ # so we need to adjust the address.
-+ #
-+ if (arch == "x86" || arch == "x86_64")
-+ addr = subl(addr, 1);
-+
-+ print "/*";
-+ print " * " $1 " " faddr " F " fname;
-+ print " * " $0;
-+ print " */";
-+ printf "\tPTR\t_stext + 0x%s\n", addr;
-+ printf "\tPTR\t%d\n", map_string($4);
-+ printf "\tPTR\t%d\n", map_string(fname);
-+
-+ probec++;
-+
-+ next;
-+ }
-+
-+ END {
-+ print "";
-+ print ".globl dtrace_sdt_strings";
-+ print "\tALGN";
-+ print "dtrace_sdt_strings:";
-+
-+
-+ for (i = 0; i < strc; i++)
-+ printf "\t.asciz\t\042%s\042\n", strv[i];
-+
-+ print "";
-+ print ".globl dtrace_sdt_nprobes";
-+ print ".globl dtrace_fbt_nfuncs";
-+ print "\tALGN";
-+ print "dtrace_sdt_nprobes:";
-+ printf "\tPTR\t%d\n", probec;
-+ print "dtrace_fbt_nfuncs:";
-+ printf "\tPTR\t%d\n", funcc;
-+
-+ exit(errc == 0 ? 0 : 1);
-+ }' > $tfn
-+fi
-+
-+exit $?
-diff --git a/scripts/kmodsdt.c b/scripts/kmodsdt.c
-new file mode 100644
-index 000000000000..1e35794467d7
---- /dev/null
-+++ b/scripts/kmodsdt.c
-@@ -0,0 +1,410 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright 2016 Oracle, Inc. All rights reserved.
-+ * Use is subject to license terms.
-+ */
-+
-+#include "../include/generated/autoconf.h"
-+
-+#define ELF_TARGET_ALL
-+#include <elf.h>
-+#include <gelf.h>
-+
-+#include <sys/types.h>
-+
-+#include <unistd.h>
-+#include <string.h>
-+#include <limits.h>
-+#include <stddef.h>
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <fcntl.h>
-+#include <errno.h>
-+#include <assert.h>
-+
-+typedef struct symtbl {
-+ struct symtbl *next;
-+ void *strtab;
-+ void *symtab;
-+} symtbl_t;
-+
-+static int
-+dt_elf_symtab_lookup(Elf_Data *data_sym, int nsym, uintptr_t addr, uint32_t shn,
-+ GElf_Sym *sym)
-+{
-+ int i, ret = -1;
-+ GElf_Sym s;
-+
-+ for (i = 0; i < nsym && gelf_getsym(data_sym, i, sym) != NULL; i++) {
-+ if (GELF_ST_TYPE(sym->st_info) == STT_FUNC &&
-+ shn == sym->st_shndx &&
-+ sym->st_value <= addr &&
-+ addr < sym->st_value + sym->st_size) {
-+ if (GELF_ST_BIND(sym->st_info) == STB_GLOBAL)
-+ return i;
-+
-+ ret = i;
-+ s = *sym;
-+ }
-+ }
-+
-+ if (ret >= 0)
-+ *sym = s;
-+ return ret;
-+}
-+
-+static int
-+process_obj(const char *obj)
-+{
-+ static const char dt_ppref[] = "__dtrace_probe_";
-+ static const char dt_spref[] = "__dta_";
-+ int fd, i, sidx, mod = 0;
-+ Elf *elf = NULL;
-+ GElf_Ehdr ehdr;
-+ Elf_Scn *scn_rel, *scn_sym, *scn_str;
-+ Elf_Data *data_rel, *data_sym, *data_str;
-+ GElf_Shdr shdr_rel, shdr_sym, shdr_str;
-+ GElf_Sym rsym, fsym, dsym;
-+ GElf_Rela rela;
-+ char *p, *r, *f, *a;
-+ uint32_t eclass, emachine1, emachine2;
-+ size_t symsize, nsym, nstr, isym, istr, osym, len;
-+ symtbl_t *pair, *bufs = NULL;
-+ char **alttab;
-+ const char *elferrstr = "no error";
-+
-+ fd = open(obj, O_RDWR);
-+ if (fd == -1) {
-+ fprintf(stderr, "failed to open %s: %s\n", obj,
-+ strerror(errno));
-+ return 1;
-+ }
-+
-+ if (elf_version(EV_CURRENT) == EV_NONE) {
-+ fprintf(stderr, "ELF library version too old\n");
-+ return 1;
-+ }
-+
-+ elf = elf_begin(fd, ELF_C_RDWR, NULL);
-+ if (elf == NULL) {
-+ fprintf(stderr, "failed to process %s: %s\n", obj,
-+ elf_errmsg(elf_errno()));
-+ return 1;
-+ }
-+
-+ switch (elf_kind(elf)) {
-+ case ELF_K_ELF:
-+ break;
-+ case ELF_K_AR:
-+ fprintf(stderr, "archives are not permitted; %s\n", obj);
-+ return 1;
-+ default:
-+ fprintf(stderr, "invalid file type: %s\n", obj);
-+ return 1;
-+ }
-+
-+ if (gelf_getehdr(elf, &ehdr) == NULL) {
-+ fprintf(stderr, "corrupt file: %s\n", obj);
-+ return 1;
-+ }
-+
-+#ifdef CONFIG_64BIT
-+ eclass = ELFCLASS64;
-+# if defined(__sparc)
-+ emachine1 = emachine2 = EM_SPARCV9;
-+# elif defined(__i386) || defined(__amd64)
-+ emachine1 = emachine2 = EM_X86_64;
-+# elif defined(__aarch64__)
-+ emachine1 = emachine2 = EM_AARCH64;
-+# endif
-+ symsize = sizeof(Elf64_Sym);
-+#else
-+ eclass = ELFCLASS32;
-+# if defined(__sparc)
-+ emachine1 = EM_SPARC;
-+ emachine2 = EM_SPARC32PLUS;
-+# elif defined(__i386) || defined(__amd64)
-+ emachine1 = emachine2 = EM_386;
-+# elif defined(__arm__)
-+ emachine1 = emachine2 = EM_ARM;
-+# endif
-+ symsize = sizeof(Elf32_Sym);
-+#endif
-+
-+ if (ehdr.e_ident[EI_CLASS] != eclass) {
-+ fprintf(stderr, "incorrect ELF class for %s: %d "
-+ "(expected %d)\n", obj, ehdr.e_ident[EI_CLASS],
-+ eclass);
-+ return 1;
-+ }
-+ if (ehdr.e_machine != emachine1 && ehdr.e_machine != emachine2) {
-+ fprintf(stderr, "incorrect ELF machine type for %s: %d "
-+ "(expected %d or %d)\n",
-+ obj, ehdr.e_machine, emachine1, emachine2);
-+ return 1;
-+ }
-+
-+ scn_rel = NULL;
-+ while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) {
-+ if (gelf_getshdr(scn_rel, &shdr_rel) == NULL) {
-+ elferrstr = "failed to get section header";
-+ goto elf_err;
-+ }
-+
-+ /*
-+ * Skip any non-relocation sections.
-+ */
-+ if (shdr_rel.sh_type != SHT_RELA && shdr_rel.sh_type != SHT_REL)
-+ continue;
-+
-+ data_rel = elf_getdata(scn_rel, NULL);
-+ if (data_rel == NULL) {
-+ elferrstr = "failed to get relocation data";
-+ goto elf_err;
-+ }
-+
-+ /*
-+ * Grab the section, section header and section data for the
-+ * symbol table that this relocation section references.
-+ */
-+ scn_sym = elf_getscn(elf, shdr_rel.sh_link);
-+ if (scn_sym == NULL ||
-+ gelf_getshdr(scn_sym, &shdr_sym) == NULL ||
-+ (data_sym = elf_getdata(scn_sym, NULL)) == NULL) {
-+ elferrstr = "failed to get symbol table";
-+ goto elf_err;
-+ }
-+
-+ /*
-+ * Ditto for that symbol table's string table.
-+ */
-+ scn_str = elf_getscn(elf, shdr_sym.sh_link);
-+ if (scn_str == NULL ||
-+ gelf_getshdr(scn_str, &shdr_str) == NULL ||
-+ (data_str = elf_getdata(scn_str, NULL)) == NULL) {
-+ elferrstr = "failed to get string table";
-+ goto elf_err;
-+ }
-+
-+ /*
-+ * We're looking for relocations to symbols matching this form:
-+ *
-+ * __dtrace_probe_<probe>
-+ *
-+ * If the function containing the probe is locally scoped
-+ * (static), we create an alias. The alias, a new symbol,
-+ * will be global (so that it can be referenced from sdtinfo
-+ * entries) and hidden (so that it is converted to a local
-+ * symbol at link time). Such aliases have this form:
-+ *
-+ * __dta_<function>_<symindex>
-+ *
-+ * The <symindex> is appended to ensure that aliases are unique
-+ * because they are referenced in global scope. Two local
-+ * functions with identical names need to be distrinct at the
-+ * level of the aliases.
-+ *
-+ * We take a first pass through all the relocations to
-+ * populate our string table and count the number of extra
-+ * symbols we'll require. Note that the <function> is
-+ * sanitized to ensure that it is a valid C identifier, i.e.
-+ * any periods in the name are converted to underscores.
-+ */
-+ isym = osym = data_sym->d_size / symsize;
-+ istr = data_str->d_size;
-+
-+ /*
-+ * Allocate the alias table to be the exact same size as the
-+ * symtab. If an alias is required for a specific symbol, its
-+ * corresponding entry in this alias table will contain the
-+ * alias name. Otherwise, the entry will be NULL.
-+ */
-+ alttab = (char **)calloc(isym, sizeof(char *));
-+
-+ nsym = 0;
-+ nstr = 0;
-+
-+ for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
-+ if (shdr_rel.sh_type == SHT_RELA) {
-+ if (gelf_getrela(data_rel, i, &rela) == NULL)
-+ continue;
-+ } else {
-+ GElf_Rel rel;
-+
-+ if (gelf_getrel(data_rel, i, &rel) == NULL)
-+ continue;
-+ rela.r_offset = rel.r_offset;
-+ rela.r_info = rel.r_info;
-+ rela.r_addend = 0;
-+ }
-+
-+ if (gelf_getsym(data_sym, GELF_R_SYM(rela.r_info),
-+ &rsym) == NULL) {
-+ elferrstr = "relocation symbol not found";
-+ goto elf_err;
-+ }
-+
-+ assert(rsym.st_name < data_str->d_size);
-+
-+ r = (char *)data_str->d_buf + rsym.st_name;
-+ if (strncmp(r, dt_ppref, sizeof(dt_ppref) - 1) != 0)
-+ continue;
-+
-+ sidx = dt_elf_symtab_lookup(data_sym, isym,
-+ rela.r_offset,
-+ shdr_rel.sh_info, &fsym);
-+ if (sidx < 0) {
-+ fprintf(stderr, "relocation %x not in "
-+ "function\n", i);
-+ goto err;
-+ }
-+
-+ assert(fsym.st_name < data_str->d_size);
-+ assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC);
-+
-+ if (GELF_ST_BIND(fsym.st_info) != STB_LOCAL)
-+ continue;
-+
-+ f = (char *)data_str->d_buf + fsym.st_name;
-+
-+ if (alttab[sidx] != NULL)
-+ continue;
-+
-+ len = snprintf(NULL, 0, "%s%s_%d", dt_spref, f, sidx)
-+ + 1;
-+ a = malloc(len);
-+ assert(a != NULL);
-+ nstr += snprintf(a, len, "%s%s_%d", dt_spref, f, sidx)
-+ + 1;
-+ for (p = a; *p != '\0'; p++) {
-+ if (*p == '.')
-+ *p = '_';
-+ }
-+ alttab[sidx] = a;
-+ nsym++;
-+ }
-+
-+ if (!nsym) {
-+ free(alttab);
-+ continue;
-+ }
-+
-+ pair = malloc(sizeof(symtbl_t));
-+ if (pair == NULL) {
-+ fprintf(stderr, "failed to alloc new symtbl\n");
-+ goto err;
-+ }
-+ pair->strtab = malloc(data_str->d_size + nstr);
-+ if (pair->strtab == NULL) {
-+ fprintf(stderr, "failed to alloc new symtbl->strtab\n");
-+ free(pair);
-+ goto err;
-+ }
-+ pair->symtab = malloc(data_sym->d_size + nsym * symsize);
-+ if (pair->symtab == NULL) {
-+ fprintf(stderr, "failed to alloc new symtbl->symtab\n");
-+ free(pair->strtab);
-+ free(pair);
-+ goto err;
-+ }
-+
-+ pair->next = bufs;
-+ bufs = pair;
-+
-+ memcpy(pair->strtab, data_str->d_buf, data_str->d_size);
-+ data_str->d_buf = pair->strtab;
-+ data_str->d_size += nstr;
-+ elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
-+ shdr_str.sh_size += nstr;
-+ gelf_update_shdr(scn_str, &shdr_str);
-+
-+ memcpy(pair->symtab, data_sym->d_buf, data_sym->d_size);
-+ data_sym->d_buf = pair->symtab;
-+ data_sym->d_size += nsym * symsize;
-+ elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
-+ shdr_sym.sh_size += nsym * symsize;
-+ gelf_update_shdr(scn_sym, &shdr_sym);
-+
-+ nsym += isym;
-+
-+ /*
-+ * Now that the tables have been allocated, add the aliases as
-+ * described above. Since we already know the symtab index of
-+ * the symbol that the alias refers to, we can simply run down
-+ * the alttab and add alias for any non-NULL entries.
-+ */
-+ for (i = 1; i < osym; i++) {
-+ if (alttab[i] == NULL)
-+ continue;
-+
-+ if (gelf_getsym(data_sym, i, &fsym) == NULL) {
-+ fprintf(stderr, "failed to get symbol %d: %s\n",
-+ i, elf_errmsg(elf_errno()));
-+ goto err;
-+ }
-+
-+ assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC);
-+ assert(GELF_ST_BIND(fsym.st_info) == STB_LOCAL);
-+ /*
-+ * Add the alias as a new symbol to the symtab.
-+ */
-+ dsym = fsym;
-+ dsym.st_name = istr;
-+ dsym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC);
-+ dsym.st_other = ELF64_ST_VISIBILITY(STV_HIDDEN);
-+
-+ len = strlen(alttab[i]) + 1;
-+ assert(istr + len <= data_str->d_size);
-+ a = (char *)data_str->d_buf + istr;
-+ memcpy(a, alttab[i], len);
-+
-+ gelf_update_sym(data_sym, isym, &dsym);
-+ istr += len;
-+ isym++;
-+
-+ assert(isym <= nsym);
-+
-+ mod = 1;
-+
-+ free(alttab[i]);
-+ }
-+
-+ free(alttab);
-+ }
-+
-+ if (mod && elf_update(elf, ELF_C_WRITE) == -1) {
-+ elferrstr = "Failed to update ELF object";
-+ goto elf_err;
-+ }
-+
-+ elf_end(elf);
-+ close(fd);
-+
-+ while ((pair = bufs) != NULL) {
-+ bufs = pair->next;
-+ free(pair->strtab);
-+ free(pair->symtab);
-+ free(pair);
-+ }
-+
-+ return 0;
-+
-+elf_err:
-+ fprintf(stderr, "%s: %s\n", elferrstr, elf_errmsg(elf_errno()));
-+err:
-+ fprintf(stderr, "an error was encountered while processing %s\n", obj);
-+ return 1;
-+}
-+
-+int
-+main(int argc, char *argv[])
-+{
-+ int i;
-+
-+ for (i = 1; i < argc; i++) {
-+ if (process_obj(argv[i]))
-+ exit(1);
-+ }
-+
-+ exit(0);
-+}
-diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
-index bc533252fa3c..0b2f3bb60936 100755
---- a/scripts/link-vmlinux.sh
-+++ b/scripts/link-vmlinux.sh
-@@ -43,6 +43,34 @@ info()
- fi
- }
-
-+# Generate the SDT probe point stubs object file
-+# ${1} output file
-+sdtstub()
-+{
-+ info SDTSTB ${1}
-+ ${srctree}/scripts/dtrace_sdt.sh sdtstub .tmp_sdtstub.S \
-+ ${KBUILD_VMLINUX_OBJS}
-+
-+ local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
-+ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
-+
-+ ${CC} ${aflags} -c -o ${1} .tmp_sdtstub.S
-+}
-+
-+# Generate the SDT probe info for kernel image ${1}
-+# ${2} output file
-+sdtinfo()
-+{
-+ info SDTINF ${2}
-+
-+ ${srctree}/scripts/dtrace_sdt.sh sdtinfo .tmp_sdtinfo.S ${1}
-+
-+ local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
-+ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
-+
-+ ${CC} ${aflags} -c -o ${2} .tmp_sdtinfo.S
-+}
-+
- # Link of vmlinux.o used for section mismatch analysis
- # ${1} output file
- modpost_link()
-@@ -84,17 +112,20 @@ objtool_link()
-
- # Link of vmlinux
- # ${1} - output file
--# ${2}, ${3}, ... - optional extra .o files
-+# ${2} - optional extra ld flag(s)
-+# ${3}, ${4}, ... - optional extra .o files
- vmlinux_link()
- {
- local lds="${objtree}/${KBUILD_LDS}"
- local output=${1}
-+ local flags="${2}"
- local objects
- local strip_debug
-
- info LD ${output}
-
-- # skip output file argument
-+ # skip output file and flags arguments
-+ shift
- shift
-
- # The kallsyms linking does not need debug symbols included.
-@@ -114,7 +145,7 @@ vmlinux_link()
-
- ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
- ${strip_debug#-Wl,} \
-- -o ${output} \
-+ ${flags} -o ${output} \
- -T ${lds} ${objects}
- else
- objects="-Wl,--whole-archive \
-@@ -128,7 +159,7 @@ vmlinux_link()
-
- ${CC} ${CFLAGS_vmlinux} \
- ${strip_debug} \
-- -o ${output} \
-+ ${flags} -o ${output} \
- -Wl,-T,${lds} \
- ${objects} \
- -lutil -lrt -lpthread
-@@ -219,7 +250,7 @@ kallsyms_step()
- kallsymso=${kallsyms_vmlinux}.o
- kallsyms_S=${kallsyms_vmlinux}.S
-
-- vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
-+ vmlinux_link ${kallsyms_vmlinux} "${2:-}" "${kallsymso_prev}" ${btf_vmlinux_bin_o} ${sdtstubo} ${sdtinfoo}
- kallsyms ${kallsyms_vmlinux} ${kallsyms_S}
-
- info AS ${kallsyms_S}
-@@ -245,6 +276,8 @@ cleanup()
- {
- rm -f .btf.*
- rm -f .tmp_System.map
-+ rm -f .tmp_sdtstub.*
-+ rm -f .tmp_sdtinfo.*
- rm -f .tmp_vmlinux*
- rm -f System.map
- rm -f vmlinux
-@@ -293,6 +326,14 @@ fi;
- # final build of init/
- ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
-
-+sdtstubo=""
-+sdtinfoo=""
-+if [ -n "${CONFIG_DTRACE}" ]; then
-+ sdtstubo=.tmp_sdtstub.o
-+ sdtinfoo=.tmp_sdtinfo.o
-+ sdtstub ${sdtstubo}
-+fi
-+
- #link vmlinux.o
- info LD vmlinux.o
- modpost_link vmlinux.o
-@@ -346,7 +387,23 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
- # a) Verify that the System.map from vmlinux matches the map from
- # ${kallsymso}.
-
-+ # step 1
-+ if [ -n "${CONFIG_DTRACE}" ]; then
-+ sdtinfo vmlinux.o ${sdtinfoo}
-+ fi
-+
- kallsyms_step 1
-+
-+ if [ -n "${CONFIG_DTRACE}" ]; then
-+ if [ -n "${CONFIG_ARM64}" ]; then
-+ kallsyms_step 1
-+ else
-+ kallsyms_step 1 -r
-+ fi
-+ sdtinfo ${kallsyms_vmlinux} ${sdtinfoo} vmlinux.o
-+ fi
-+
-+ # step 2
- kallsyms_step 2
-
- # step 3
-@@ -358,7 +415,7 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
- fi
- fi
-
--vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o}
-+vmlinux_link vmlinux "" "${kallsymso}" ${btf_vmlinux_bin_o} ${sdtstubo} ${sdtinfoo}
-
- # fill in BTF IDs
- if [ -n "${CONFIG_DEBUG_INFO_BTF}" -a -n "${CONFIG_BPF}" ]; then
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index f882ce0d9327..ceeb69afc209 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -2183,7 +2183,9 @@ static int check_exports(struct module *mod)
- const char *basename;
- exp = find_symbol(s->name);
- if (!exp || exp->module == mod) {
-- if (have_vmlinux && !s->weak) {
-+ if (have_vmlinux && !s->weak &&
-+ !strstarts(s->name, "__dtrace_probe_") &&
-+ !strstarts(s->name, "__dtrace_isenabled_")) {
- modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR,
- "\"%s\" [%s.ko] undefined!\n",
- s->name, mod->name);
-@@ -2238,6 +2240,13 @@ static int check_modname_len(struct module *mod)
- **/
- static void add_header(struct buffer *b, struct module *mod)
- {
-+ const char *modname;
-+
-+ modname = strrchr(mod->name, '/');
-+ if (modname != NULL)
-+ modname++;
-+ else
-+ modname = mod->name;
- buf_printf(b, "#include <linux/module.h>\n");
- /*
- * Include build-salt.h after module.h in order to
-@@ -2248,6 +2257,10 @@ static void add_header(struct buffer *b, struct module *mod)
- buf_printf(b, "#include <linux/vermagic.h>\n");
- buf_printf(b, "#include <linux/compiler.h>\n");
- buf_printf(b, "\n");
-+ buf_printf(b, "#ifdef CONFIG_DTRACE\n");
-+ buf_printf(b, "# include \"%s.sdtinfo.h\"\n", modname);
-+ buf_printf(b, "#endif\n");
-+ buf_printf(b, "\n");
- buf_printf(b, "BUILD_SALT;\n");
- buf_printf(b, "\n");
- buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
-@@ -2263,6 +2276,10 @@ static void add_header(struct buffer *b, struct module *mod)
- "\t.exit = cleanup_module,\n"
- "#endif\n");
- buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n");
-+ buf_printf(b, "#ifdef CONFIG_DTRACE\n");
-+ buf_printf(b, "\t.sdt_probes = _sdt_probes,\n");
-+ buf_printf(b, "\t.sdt_probec = _sdt_probec,\n");
-+ buf_printf(b, "#endif\n");
- buf_printf(b, "};\n");
- }
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0009-dtrace-sdt-provider-for-x86.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0009-dtrace-sdt-provider-for-x86.patch
deleted file mode 100644
index 12385fef2f4d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0009-dtrace-sdt-provider-for-x86.patch
+++ /dev/null
@@ -1,1076 +0,0 @@
-From 33bb9a2aab1f792110ebeebcc2a5a0b5e02cec6c Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 18:00:18 +0000
-Subject: [PATCH 09/19] dtrace: sdt provider for x86
-
-This implements the SDT provider itself. It is relatively
-straightforward except for the code needed to parse the argument strings
-ultimately derived from SDT DTRACE_PROBE invocations and perf-event
-prototype definitions.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/dtrace/Makefile.arch | 2 +
- arch/x86/dtrace/sdt_x86_64.c | 126 ++++++++
- dtrace/Makefile | 2 +
- dtrace/dt_test_dev.c | 33 ++
- dtrace/dt_test_mod.c | 5 +
- dtrace/sdt_dev.c | 562 ++++++++++++++++++++++++++++++++++
- dtrace/sdt_impl.h | 87 ++++++
- dtrace/sdt_mod.c | 154 ++++++++++
- 8 files changed, 971 insertions(+)
- create mode 100644 arch/x86/dtrace/sdt_x86_64.c
- create mode 100644 dtrace/sdt_dev.c
- create mode 100644 dtrace/sdt_impl.h
- create mode 100644 dtrace/sdt_mod.c
-
-diff --git a/arch/x86/dtrace/Makefile.arch b/arch/x86/dtrace/Makefile.arch
-index ffb9ef4d1722..8492eaee426d 100644
---- a/arch/x86/dtrace/Makefile.arch
-+++ b/arch/x86/dtrace/Makefile.arch
-@@ -7,5 +7,7 @@ DTARCHDIR = ../arch/x86/dtrace
- ccflags-y += -I$(srctree)/arch/x86/dtrace/include -Idtrace
-
- dtrace-obj += dtrace_asm_x86_64.o dtrace_isa_x86_64.o
-+sdt-obj += sdt_x86_64.o
-
- dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
-+sdt-y += $(addprefix $(DTARCHDIR)/, $(sdt-obj))
-diff --git a/arch/x86/dtrace/sdt_x86_64.c b/arch/x86/dtrace/sdt_x86_64.c
-new file mode 100644
-index 000000000000..e686634ff410
---- /dev/null
-+++ b/arch/x86/dtrace/sdt_x86_64.c
-@@ -0,0 +1,126 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: sdt_dev.c
-+ * DESCRIPTION: DTrace - SDT provider implementation for x86
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/sdt.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <asm/dtrace_util.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "sdt_impl.h"
-+
-+#define SDT_PATCHVAL 0xf0
-+
-+static uint8_t sdt_invop(struct pt_regs *regs)
-+{
-+ struct sdt_probe *sdt = sdt_probetab[SDT_ADDR2NDX(regs->ip)];
-+
-+ for (; sdt != NULL; sdt = sdt->sdp_hashnext) {
-+ if ((uintptr_t)sdt->sdp_patchpoint == regs->ip) {
-+ if (sdt->sdp_ptype == SDTPT_IS_ENABLED)
-+ regs->ax = 1;
-+ else {
-+ struct pt_regs *old_regs =
-+ this_cpu_core->cpu_dtrace_regs;
-+
-+ this_cpu_core->cpu_dtrace_regs = regs;
-+
-+ dtrace_probe(sdt->sdp_id, regs->di, regs->si,
-+ regs->dx, regs->cx, regs->r8,
-+ regs->r9, 0);
-+
-+ this_cpu_core->cpu_dtrace_regs = old_regs;
-+ }
-+
-+ return DTRACE_INVOP_NOPS;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+void sdt_provide_probe_arch(struct sdt_probe *sdp, struct module *mp, int idx)
-+{
-+ sdp->sdp_patchval = SDT_PATCHVAL;
-+ sdp->sdp_savedval = *sdp->sdp_patchpoint;
-+}
-+
-+int sdt_provide_module_arch(void *arg, struct module *mp)
-+{
-+ return 1;
-+}
-+
-+void sdt_destroy_module(void *arg, struct module *mp)
-+{
-+}
-+
-+void sdt_enable_arch(struct sdt_probe *sdp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_invop_enable(sdp->sdp_patchpoint, sdp->sdp_patchval);
-+}
-+
-+void sdt_disable_arch(struct sdt_probe *sdp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_invop_disable(sdp->sdp_patchpoint, sdp->sdp_savedval);
-+}
-+
-+uint64_t sdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ return 0;
-+
-+ switch (argno) {
-+ case 0:
-+ return regs->di;
-+ case 1:
-+ return regs->si;
-+ case 2:
-+ return regs->dx;
-+ case 3:
-+ return regs->cx;
-+ case 4:
-+ return regs->r8;
-+ case 5:
-+ return regs->r9;
-+ }
-+
-+ ASSERT(argno > 5);
-+
-+ st = (uint64_t *)regs->sp;
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ val = st[argno - 6];
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return val;
-+}
-+
-+int sdt_dev_init_arch(void)
-+{
-+ return dtrace_invop_add(sdt_invop);
-+}
-+
-+void sdt_dev_exit_arch(void)
-+{
-+ dtrace_invop_remove(sdt_invop);
-+}
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-index b91bc69d3802..126d4985967a 100644
---- a/dtrace/Makefile
-+++ b/dtrace/Makefile
-@@ -3,6 +3,7 @@
- #
-
- obj-$(CONFIG_DT_CORE) += dtrace.o
-+obj-$(CONFIG_DT_SDT) += sdt.o
- obj-$(CONFIG_DT_SYSTRACE) += systrace.o
- obj-$(CONFIG_DT_DT_TEST) += dt_test.o
-
-@@ -15,6 +16,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \
- dtrace_probe.o dtrace_probe_ctx.o \
- dtrace_ptofapi.o dtrace_predicate.o \
- dtrace_spec.o dtrace_state.o dtrace_util.o
-+sdt-y := sdt_mod.o sdt_dev.o
- systrace-y := systrace_mod.o systrace_dev.o
- dt_test-y := dt_test_mod.o dt_test_dev.o
-
-diff --git a/dtrace/dt_test_dev.c b/dtrace/dt_test_dev.c
-index 8e1f5bab8a12..b720d8091787 100644
---- a/dtrace/dt_test_dev.c
-+++ b/dtrace/dt_test_dev.c
-@@ -131,6 +131,39 @@ static long dt_test_ioctl(struct file *file,
- return 0;
- }
-
-+ if (DTRACE_PROBE_ENABLED(sdt__test))
-+ DTRACE_PROBE(sdt__test__is__enabled);
-+
-+ DTRACE_PROBE(sdt__test);
-+
-+ /*
-+ * Test translation-to-nothing.
-+ */
-+ DTRACE_PROBE(sdt__test__ioctl__file, int, cmd, int :, 666,
-+ char * : (), 0, struct file *, file, int, arg);
-+
-+ /*
-+ * Probes with every valid count of args.
-+ */
-+ DTRACE_PROBE(sdt__test__arg1, int, 1);
-+ DTRACE_PROBE(sdt__test__arg2, int, 1, int, 2);
-+ DTRACE_PROBE(sdt__test__arg3, int, 1, int, 2, int, 3);
-+ DTRACE_PROBE(sdt__test__arg4, int, 1, int, 2, int, 3, int, 4);
-+ DTRACE_PROBE(sdt__test__arg5, int, 1, int, 2, int, 3, int, 4, int, 5);
-+ DTRACE_PROBE(sdt__test__arg6, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6);
-+ DTRACE_PROBE(sdt__test__arg7, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7);
-+ DTRACE_PROBE(sdt__test__arg8, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8);
-+ DTRACE_PROBE(sdt__test__arg9, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9);
-+ DTRACE_PROBE(sdt__test__arga, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10);
-+ DTRACE_PROBE(sdt__test__argb, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11);
-+ DTRACE_PROBE(sdt__test__argc, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12);
-+ DTRACE_PROBE(sdt__test__argd, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13);
-+ DTRACE_PROBE(sdt__test__arge, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13, int, 14);
-+ DTRACE_PROBE(sdt__test__argf, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13, int, 14, int, 15);
-+ DTRACE_PROBE(sdt__test__argg, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13, int, 14, int, 15, int, 16);
-+ DTRACE_PROBE(sdt__test__argh, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13, int, 14, int, 15, int, 16, int, 17);
-+ DTRACE_PROBE(sdt__test__argi, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13, int, 14, int, 15, int, 16, int, 17, int, 18);
-+
- return -EAGAIN;
- }
-
-diff --git a/dtrace/dt_test_mod.c b/dtrace/dt_test_mod.c
-index d8af71665a37..a86c8bc02ae9 100644
---- a/dtrace/dt_test_mod.c
-+++ b/dtrace/dt_test_mod.c
-@@ -50,3 +50,8 @@ static struct dtrace_pops dt_test_pops = {
- };
-
- DT_PROVIDER_MODULE(dt_test, DTRACE_PRIV_USER)
-+
-+void foo(void)
-+{
-+ DTRACE_PROBE(sdt__test2);
-+}
-diff --git a/dtrace/sdt_dev.c b/dtrace/sdt_dev.c
-new file mode 100644
-index 000000000000..78457dad8773
---- /dev/null
-+++ b/dtrace/sdt_dev.c
-@@ -0,0 +1,562 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: sdt_dev.c
-+ * DESCRIPTION: DTrace - SDT provider device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/ctype.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/sdt.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "sdt_impl.h"
-+
-+#define SDT_PROBETAB_SIZE 0x1000 /* 4k entries -- 16K total */
-+
-+struct sdt_probe **sdt_probetab;
-+int sdt_probetab_size;
-+int sdt_probetab_mask;
-+
-+/*
-+ * Return, in newly-allocated space, a version of the passed-in type 'vartype'
-+ * which has been cleaned up suitably for CTF: leading and trailing spaces (if
-+ * any) removed, and optionally a trailing argument removed as well.
-+ *
-+ * Type strings look like either
-+ *
-+ * type (for SDT, as in function prototypes), or
-+ *
-+ * type argname (for perf: as in function declarations).
-+ *
-+ * Translator components ": (foo, foo)", if any, have been removed by this
-+ * stage.
-+ */
-+static char *cleanup_type(const char *vartype, int arg_strip)
-+{
-+ const char *cleaned;
-+ const char *p;
-+
-+ cleaned = vartype + strspn(vartype, " \t");
-+ for (p = cleaned + strlen(cleaned) - 1; p > cleaned && isspace(*p);
-+ p--);
-+ if (arg_strip) {
-+ for (; p > cleaned && (isalnum(*p) || *p == '_'); p--);
-+ for (; p > cleaned && isspace(*p); p--);
-+ }
-+ p++;
-+
-+ return kstrndup(cleaned, p - cleaned, GFP_KERNEL);
-+}
-+
-+/*
-+ * Set up the args lists, extracting them from their sdpd entry and parsing them
-+ * into an sdt_argdesc array for each probe.
-+ */
-+static struct sdt_argdesc *
-+sdt_setup_args(struct sdt_probedesc *sdpd,
-+ size_t *sdp_nargdesc)
-+{
-+ struct sdt_argdesc *args;
-+ char *argstr;
-+ char *p;
-+ int arg_strip = 0;
-+ char *next_arg = NULL;
-+ size_t arg = 0, sarg = 0, i;
-+
-+ *sdp_nargdesc = 0;
-+
-+ if ((sdpd->sdpd_args == NULL) || (sdpd->sdpd_args[0] == '\0'))
-+ return NULL;
-+
-+ /*
-+ * Take a copy of the string so we can mutate it without causing trouble
-+ * on module reload.
-+ */
-+ argstr = kstrdup(sdpd->sdpd_args, GFP_KERNEL);
-+ if (argstr == NULL)
-+ goto oom;
-+
-+ /*
-+ * Handle the common case of a trailing comma before we allocate space,
-+ * and elide it.
-+ */
-+ p = argstr + strlen(argstr) - 1;
-+ if (p[0] == ',' && p[1] == '\0')
-+ *p = '\0';
-+
-+ /*
-+ * This works for counting the number of args even though translator
-+ * strings can contain commas, because each comma denotes a new probe
-+ * argument. It may overcount in the case of elided arguments
-+ * ("foo : ,"): we compensate for that further down, and ignore the tiny
-+ * memory leak that results.
-+ */
-+ for (p = argstr; p != NULL; p = strchr(p + 1, ','))
-+ (*sdp_nargdesc)++;
-+
-+ args = kzalloc(*sdp_nargdesc * sizeof(struct sdt_argdesc),
-+ GFP_KERNEL);
-+ if (args == NULL)
-+ goto oom_argstr;
-+
-+ /*
-+ * We need to transform each arg (stripping off a terminal argument
-+ * name) if this is a perf probe.
-+ */
-+ if (strncmp(sdpd->sdpd_name, "__perf_", strlen("__perf_")) == 0)
-+ arg_strip = 1;
-+
-+ next_arg = argstr;
-+ do {
-+ char *tok;
-+ char *xlator = NULL, *p;
-+ char *native;
-+ int parens = 0;
-+ int empty_xlation;
-+
-+ /*
-+ * Find the end of this arg, and figure out if it has any
-+ * translators. Clean up the type of the arg (or native type,
-+ * if this is a translated type).
-+ */
-+ tok = next_arg;
-+ next_arg = NULL;
-+ p = strpbrk(tok, "():,");
-+ while (p && !next_arg) {
-+ switch (*p) {
-+ case '(':
-+ parens++;
-+ break;
-+ case ')':
-+ if (parens > 0)
-+ parens--;
-+ break;
-+ case ':':
-+ *p = '\0';
-+ xlator = p + 1;
-+ break;
-+ case ',':
-+ if (parens == 0) {
-+ *p = '\0';
-+ next_arg = p + 1;
-+ }
-+ break;
-+ }
-+ p = strpbrk(p + 1, "():,");
-+ }
-+
-+ native = cleanup_type(tok, arg_strip);
-+ if (native == NULL) {
-+ args[arg].sda_native = args[arg].sda_xlate = NULL;
-+ goto full_oom;
-+ }
-+
-+ /*
-+ * Special case: perf's DECLARE_TRACE_NOARGS passes a single arg
-+ * 'void'. Spot and skip it.
-+ */
-+ if (!xlator && arg_strip && strcmp(native, "void") == 0) {
-+ kfree(native);
-+ (*sdp_nargdesc)--;
-+ sarg++;
-+ continue;
-+ }
-+
-+ /*
-+ * No translator: straight mapping.
-+ */
-+ if (xlator == NULL) {
-+ ASSERT(arg < *sdp_nargdesc);
-+ args[arg].sda_mapping = sarg;
-+ args[arg].sda_native = native;
-+ args[arg].sda_xlate = NULL;
-+ arg++;
-+ sarg++;
-+ continue;
-+ }
-+
-+ /*
-+ * If this is a perf probe, warn: translations cannot exist for
-+ * these, and have no defined format yet in any case. We can
-+ * struggle on by assuming they look like SDT translations.
-+ */
-+ if (arg_strip)
-+ pr_warn("Perf probe %s has at least one SDT translation, "
-+ "which should be impossible.", sdpd->sdpd_name);
-+
-+ /*
-+ * Zero or more translations. (If there are zero, i.e. a pair
-+ * of empty parentheses or a colon with nothing after it, we
-+ * have to decrement the nargdesc.)
-+ */
-+
-+ empty_xlation = 1;
-+ while ((p = strsep(&xlator, "(,)")) != NULL) {
-+ /*
-+ * Skip the empty space before the ( or after the ).
-+ */
-+ if (strspn(p, " \t") == strlen(p))
-+ continue;
-+
-+ ASSERT(arg < *sdp_nargdesc);
-+
-+ empty_xlation = 0;
-+ args[arg].sda_mapping = sarg;
-+ args[arg].sda_native = kstrdup(native, GFP_KERNEL);
-+ args[arg].sda_xlate = cleanup_type(p, 0);
-+ if ((args[arg].sda_native == NULL) ||
-+ (args[arg].sda_xlate == NULL)) {
-+ pr_warn("Unable to create argdesc list for "
-+ "probe %s: out of memory\n",
-+ sdpd->sdpd_name);
-+ kfree(native);
-+ goto full_oom;
-+ }
-+ arg++;
-+ }
-+ if (empty_xlation)
-+ (*sdp_nargdesc)--;
-+
-+ kfree(native);
-+ sarg++;
-+ } while (next_arg != NULL);
-+
-+ kfree(argstr);
-+ return args;
-+
-+full_oom:
-+ for (i = 0; i < arg; i++) {
-+ kfree(args[i].sda_native);
-+ kfree(args[i].sda_xlate);
-+ }
-+ kfree(args);
-+oom_argstr:
-+ kfree(argstr);
-+oom:
-+ *sdp_nargdesc = 0;
-+ pr_warn("Unable to create argdesc list for probe %s: "
-+ "out of memory\n", sdpd->sdpd_name);
-+ return NULL;
-+}
-+
-+void sdt_provide_module(void *arg, struct module *mp)
-+{
-+ char *modname = mp->name;
-+ struct dtrace_mprovider *prov;
-+ struct sdt_probedesc *sdpd;
-+ struct sdt_probe *sdp, *prv;
-+ int idx, len;
-+ int probes_skipped = 0;
-+
-+ /* If module setup has failed then do not provide anything. */
-+ if (PDATA(mp) == NULL)
-+ return;
-+
-+ /*
-+ * Nothing to do if the module SDT probes were already created.
-+ */
-+ if (PDATA(mp)->sdt_probe_cnt != 0)
-+ return;
-+
-+ /*
-+ * Nothing to do if there are no SDT probes.
-+ */
-+ if (mp->sdt_probec == 0)
-+ return;
-+
-+ /*
-+ * Nothing if arch specific module setup fails.
-+ */
-+ if (!sdt_provide_module_arch(NULL, mp))
-+ return;
-+
-+ /*
-+ * Do not provide any probes unless all SDT providers have been created
-+ * for this meta-provider.
-+ */
-+ for (prov = sdt_providers; prov->dtmp_name != NULL; prov++) {
-+ if (prov->dtmp_id == DTRACE_PROVNONE)
-+ return;
-+ }
-+
-+ for (idx = 0, sdpd = mp->sdt_probes; idx < mp->sdt_probec;
-+ idx++, sdpd++) {
-+ char *name = sdpd->sdpd_name, *nname;
-+ int i, j;
-+ struct dtrace_mprovider *prov;
-+ dtrace_id_t id;
-+ enum fasttrap_probe_type ptype;
-+
-+ if (name[0] == '?') {
-+ ptype = SDTPT_IS_ENABLED;
-+ name++;
-+ } else
-+ ptype = SDTPT_OFFSETS;
-+
-+ for (prov = sdt_providers; prov->dtmp_pref != NULL; prov++) {
-+ char *prefix = prov->dtmp_pref;
-+ int len = strlen(prefix);
-+
-+ if (strncmp(name, prefix, len) == 0) {
-+ name += len;
-+ break;
-+ }
-+ }
-+
-+ nname = kmalloc(len = strlen(name) + 1, GFP_KERNEL);
-+ if (nname == NULL) {
-+ probes_skipped++;
-+ continue;
-+ }
-+
-+ for (i = j = 0; name[j] != '\0'; i++) {
-+ if (name[j] == '_' && name[j + 1] == '_') {
-+ nname[i] = '-';
-+ j += 2;
-+ } else
-+ nname[i] = name[j++];
-+ }
-+
-+ nname[i] = '\0';
-+
-+ sdp = kzalloc(sizeof(struct sdt_probe), GFP_KERNEL);
-+ if (sdp == NULL) {
-+ probes_skipped++;
-+ continue;
-+ }
-+
-+ sdp->sdp_loadcnt = 1; /* FIXME */
-+ sdp->sdp_module = mp;
-+ sdp->sdp_name = nname;
-+ sdp->sdp_namelen = len;
-+ sdp->sdp_provider = prov;
-+ sdp->sdp_ptype = ptype;
-+
-+ sdp->sdp_argdesc = sdt_setup_args(sdpd, &sdp->sdp_nargdesc);
-+
-+ id = dtrace_probe_lookup(prov->dtmp_id, modname,
-+ sdpd->sdpd_func, nname);
-+ if (id != DTRACE_IDNONE) {
-+ prv = dtrace_probe_arg(prov->dtmp_id, id);
-+ ASSERT(prv != NULL);
-+
-+ sdp->sdp_next = prv->sdp_next;
-+ sdp->sdp_id = id;
-+ prv->sdp_next = sdp;
-+ } else {
-+ sdp->sdp_id = dtrace_probe_create(prov->dtmp_id,
-+ modname,
-+ sdpd->sdpd_func,
-+ nname, SDT_AFRAMES,
-+ sdp);
-+
-+ /*
-+ * If we failed to create the probe just skip it.
-+ */
-+ if (sdp->sdp_id == DTRACE_IDNONE) {
-+ kfree(sdp);
-+ probes_skipped++;
-+ continue;
-+ }
-+
-+ PDATA(mp)->sdt_probe_cnt++;
-+ }
-+
-+ sdp->sdp_patchpoint = (asm_instr_t *)sdpd->sdpd_offset;
-+
-+ sdt_provide_probe_arch(sdp, mp, idx);
-+
-+ sdp->sdp_hashnext = sdt_probetab[
-+ SDT_ADDR2NDX(sdp->sdp_patchpoint)];
-+ sdt_probetab[SDT_ADDR2NDX(sdp->sdp_patchpoint)] = sdp;
-+ }
-+
-+ if (probes_skipped != 0)
-+ pr_warn("sdt: Failed to provide %d probes in %s (out of memory)\n",
-+ probes_skipped, mp->name);
-+}
-+
-+int sdt_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct sdt_probe *sdp = parg;
-+ struct sdt_probe *curr;
-+
-+ /*
-+ * Ensure that we have a reference to the module.
-+ */
-+ if (!try_module_get(sdp->sdp_module))
-+ return -EAGAIN;
-+
-+ /*
-+ * If at least one other enabled probe exists for this module, drop the
-+ * reference we took above, because we only need one to prevent the
-+ * module from being unloaded.
-+ */
-+ PDATA(sdp->sdp_module)->enabled_cnt++;
-+ if (PDATA(sdp->sdp_module)->enabled_cnt > 1)
-+ module_put(sdp->sdp_module);
-+
-+ for (curr = sdp; curr != NULL; curr = curr->sdp_next)
-+ sdt_enable_arch(curr, id, arg);
-+
-+ return 0;
-+}
-+
-+void sdt_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct sdt_probe *sdp = parg;
-+ struct sdt_probe *curr;
-+
-+ for (curr = sdp; curr != NULL; curr = curr->sdp_next)
-+ sdt_disable_arch(curr, id, arg);
-+
-+ /*
-+ * If we are disabling a probe, we know it was enabled, and therefore
-+ * we know that we have a reference on the module to prevent it from
-+ * being unloaded. If we disable the last probe on the module, we can
-+ * drop the reference.
-+ */
-+ PDATA(sdp->sdp_module)->enabled_cnt--;
-+ if (PDATA(sdp->sdp_module)->enabled_cnt == 0)
-+ module_put(sdp->sdp_module);
-+}
-+
-+void sdt_getargdesc(void *arg, dtrace_id_t id, void *parg,
-+ struct dtrace_argdesc *desc)
-+{
-+ struct sdt_probe *sdp = parg;
-+
-+ desc->dtargd_native[0] = '\0';
-+ desc->dtargd_xlate[0] = '\0';
-+
-+ while ((sdp->sdp_ptype == SDTPT_IS_ENABLED) &&
-+ (sdp->sdp_next != NULL))
-+ sdp = sdp->sdp_next;
-+
-+ if (sdp->sdp_nargdesc <= desc->dtargd_ndx) {
-+ desc->dtargd_ndx = DTRACE_ARGNONE;
-+ return;
-+ }
-+
-+ if (sdp->sdp_argdesc[desc->dtargd_ndx].sda_native != NULL)
-+ strlcpy(desc->dtargd_native,
-+ sdp->sdp_argdesc[desc->dtargd_ndx].sda_native,
-+ sizeof(desc->dtargd_native));
-+
-+ if (sdp->sdp_argdesc[desc->dtargd_ndx].sda_xlate != NULL)
-+ strlcpy(desc->dtargd_xlate,
-+ sdp->sdp_argdesc[desc->dtargd_ndx].sda_xlate,
-+ sizeof(desc->dtargd_xlate));
-+
-+ desc->dtargd_mapping = sdp->sdp_argdesc[desc->dtargd_ndx].sda_mapping;
-+}
-+
-+void sdt_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct sdt_probe *sdp = parg;
-+
-+ PDATA(sdp->sdp_module)->sdt_probe_cnt--;
-+
-+ while (sdp != NULL) {
-+ struct sdt_probe *old = sdp, *last, *hash;
-+ int ndx;
-+ size_t i;
-+
-+ ndx = SDT_ADDR2NDX(sdp->sdp_patchpoint);
-+ last = NULL;
-+ hash = sdt_probetab[ndx];
-+
-+ while (hash != sdp) {
-+ ASSERT(hash != NULL);
-+ last = hash;
-+ hash = hash->sdp_hashnext;
-+ }
-+
-+ if (last != NULL)
-+ last->sdp_hashnext = sdp->sdp_hashnext;
-+ else
-+ sdt_probetab[ndx] = sdp->sdp_hashnext;
-+
-+ for (i = 0; i < sdp->sdp_nargdesc; i++) {
-+ kfree(sdp->sdp_argdesc[i].sda_native);
-+ kfree(sdp->sdp_argdesc[i].sda_xlate);
-+ }
-+ kfree(sdp->sdp_argdesc);
-+ kfree(sdp->sdp_name);
-+ sdp = sdp->sdp_next;
-+ kfree(old);
-+ }
-+}
-+
-+static int sdt_open(struct inode *inode, struct file *file)
-+{
-+ return -EAGAIN;
-+}
-+
-+static int sdt_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations sdt_fops = {
-+ .owner = THIS_MODULE,
-+ .open = sdt_open,
-+ .release = sdt_close,
-+};
-+
-+static struct miscdevice sdt_dev = {
-+ .minor = DT_DEV_SDT_MINOR,
-+ .name = "sdt",
-+ .nodename = "dtrace/provider/sdt",
-+ .fops = &sdt_fops,
-+};
-+
-+int sdt_dev_init(void)
-+{
-+ int ret = 0;
-+
-+ ret = misc_register(&sdt_dev);
-+ if (ret) {
-+ pr_err("%s: Can't register misc device %d\n",
-+ sdt_dev.name, sdt_dev.minor);
-+ return ret;
-+ }
-+
-+ if (sdt_probetab_size == 0)
-+ sdt_probetab_size = SDT_PROBETAB_SIZE;
-+
-+ sdt_probetab_mask = sdt_probetab_size - 1;
-+ sdt_probetab = vzalloc(sdt_probetab_size * sizeof(struct sdt_probe *));
-+ if (sdt_probetab == NULL)
-+ return -ENOMEM;
-+
-+ sdt_dev_init_arch();
-+
-+ return ret;
-+}
-+
-+void sdt_dev_exit(void)
-+{
-+ sdt_dev_exit_arch();
-+
-+ vfree(sdt_probetab);
-+
-+ misc_deregister(&sdt_dev);
-+}
-diff --git a/dtrace/sdt_impl.h b/dtrace/sdt_impl.h
-new file mode 100644
-index 000000000000..e5b7f4f80270
---- /dev/null
-+++ b/dtrace/sdt_impl.h
-@@ -0,0 +1,87 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Statically Defined Tracing provider
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _SDT_IMPL_H_
-+#define _SDT_IMPL_H_
-+
-+#include <linux/sdt.h>
-+#include <asm/dtrace_arch.h>
-+#include <dtrace/sdt_arch.h>
-+
-+extern struct module *dtrace_kmod;
-+
-+struct sdt_argdesc;
-+
-+enum fasttrap_probe_type {
-+ SDTPT_NONE = 0,
-+ SDTPT_OFFSETS,
-+ SDTPT_IS_ENABLED
-+};
-+
-+struct sdt_probe {
-+ struct dtrace_mprovider *sdp_provider; /* provider */
-+ char *sdp_name; /* name of probe */
-+ int sdp_namelen; /* length of allocated name */
-+ dtrace_id_t sdp_id; /* probe ID */
-+ struct module *sdp_module; /* modctl for module */
-+ int sdp_loadcnt; /* load count for module */
-+ int sdp_primary; /* non-zero if primary mod */
-+ enum fasttrap_probe_type sdp_ptype; /* probe type */
-+ asm_instr_t *sdp_patchpoint;/* patch point */
-+ asm_instr_t sdp_patchval; /* instruction to patch */
-+ asm_instr_t sdp_savedval; /* saved instruction value */
-+ struct sdt_argdesc *sdp_argdesc; /* arguments for this probe */
-+ size_t sdp_nargdesc; /* number of arguments */
-+ struct sdt_probe *sdp_next; /* next probe */
-+ struct sdt_probe *sdp_hashnext; /* next on hash */
-+};
-+
-+struct sdt_argdesc {
-+ int sda_mapping;
-+ char *sda_native;
-+ char *sda_xlate;
-+};
-+
-+extern struct dtrace_mprovider sdt_providers[];
-+extern struct sdt_probe **sdt_probetab;
-+extern int sdt_probetab_size;
-+extern int sdt_probetab_mask;
-+
-+#define SDT_ADDR2NDX(addr) ((((uintptr_t)(addr)) >> 4) & \
-+ sdt_probetab_mask)
-+
-+extern void sdt_provide_probe_arch(struct sdt_probe *, struct module *, int);
-+extern int sdt_provide_module_arch(void *, struct module *);
-+extern void sdt_enable_arch(struct sdt_probe *, dtrace_id_t, void *);
-+extern void sdt_disable_arch(struct sdt_probe *, dtrace_id_t, void *);
-+
-+extern void sdt_provide_module(void *, struct module *);
-+extern void sdt_destroy_module(void *, struct module *);
-+extern int sdt_enable(void *, dtrace_id_t, void *);
-+extern void sdt_disable(void *, dtrace_id_t, void *);
-+extern void sdt_getargdesc(void *, dtrace_id_t, void *,
-+ struct dtrace_argdesc *);
-+extern uint64_t sdt_getarg(void *, dtrace_id_t, void *, int, int);
-+extern void sdt_destroy(void *, dtrace_id_t, void *);
-+
-+extern int sdt_dev_init(void);
-+extern void sdt_dev_exit(void);
-+
-+extern int sdt_dev_init_arch(void);
-+extern void sdt_dev_exit_arch(void);
-+
-+#endif /* _SDT_IMPL_H_ */
-diff --git a/dtrace/sdt_mod.c b/dtrace/sdt_mod.c
-new file mode 100644
-index 000000000000..1de9e72396aa
---- /dev/null
-+++ b/dtrace/sdt_mod.c
-@@ -0,0 +1,154 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: sdt_mod.c
-+ * DESCRIPTION: DTrace - SDT provider kernel module
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "sdt_impl.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("Profile Interrupt Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+static struct dtrace_pattr vtrace_attr = {
-+{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr info_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr fc_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr fpu_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_CPU },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr fsinfo_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr stab_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr sdt_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr xpv_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_PLATFORM },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
-+};
-+
-+static struct dtrace_pattr iscsi_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr perf_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pops sdt_pops = {
-+ .dtps_provide = NULL,
-+ .dtps_provide_module = sdt_provide_module,
-+ .dtps_destroy_module = sdt_destroy_module,
-+ .dtps_enable = sdt_enable,
-+ .dtps_disable = sdt_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = sdt_getargdesc,
-+#ifdef CONFIG_SPARC64
-+ .dtps_getargval = NULL,
-+#else
-+ .dtps_getargval = sdt_getarg,
-+#endif
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = sdt_destroy,
-+};
-+
-+struct dtrace_mprovider sdt_providers[] = {
-+ { "vtrace", "__vtrace_", &vtrace_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "sysinfo", "__cpu_sysinfo_", &info_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "vminfo", "__cpu_vminfo_", &info_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "fpuinfo", "__fpuinfo_", &fpu_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "sched", "__sched_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "proc", "__proc_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "io", "__io_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "ip", "__ip_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "lockstat", "__lockstat_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "tcp", "__tcp_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "udp", "__udp_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "mib", "__mib_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "fsinfo", "__fsinfo_", &fsinfo_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "iscsi", "__iscsi_", &iscsi_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "nfsv3", "__nfsv3_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "nfsv4", "__nfsv4_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "xpv", "__xpv_", &xpv_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "fc", "__fc_", &fc_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "srp", "__srp_", &fc_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "sysevent", "__sysevent_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "perf", "__perf_", &perf_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "sdt", NULL, &sdt_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { NULL }
-+};
-+
-+DT_MULTI_PROVIDER_MODULE(sdt, sdt_providers)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0010-dtrace-profile-provider-and-test-probe-core-componen.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0010-dtrace-profile-provider-and-test-probe-core-componen.patch
deleted file mode 100644
index 0ce39bf8db94..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0010-dtrace-profile-provider-and-test-probe-core-componen.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From 59b5eca72202d66370501cd651aef50b19ceb918 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 17:18:23 +0000
-Subject: [PATCH 10/19] dtrace: profile provider and test probe core components
-
-Only Kconfig changes are needed here: everything else is purely modular.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- kernel/dtrace/Kconfig | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-index c1ec55d8750e..7b88206fe835 100644
---- a/kernel/dtrace/Kconfig
-+++ b/kernel/dtrace/Kconfig
-@@ -23,6 +23,12 @@ config DT_CORE
-
- if DT_CORE
-
-+config DT_PROFILE
-+ tristate "Profile Interrupt Tracing"
-+ default m
-+ help
-+ The profile and tick providers, firing probes at specific intervals.
-+
- config DT_SDT
- tristate "Statically Defined Tracing"
- default m
-@@ -54,6 +60,12 @@ config DT_DT_TEST
- help
- A test provider used by the testsuite.
-
-+config DT_DT_PERF
-+ tristate "DTrace Performance Test Probe"
-+ default m
-+ help
-+ A test provider used for performance testing.
-+
- config DT_DEBUG
- bool "DTrace debugging"
- default m
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch
deleted file mode 100644
index d7d96d0bc613..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch
+++ /dev/null
@@ -1,641 +0,0 @@
-From f7a0d3e1af253e7887d41af5f199fc2561372448 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 18:05:13 +0000
-Subject: [PATCH 11/19] dtrace: profile and tick providers built on cyclics
-
-Probes are constructed dynamically as called upon by the user: some
-default commonly-used probes for common timing frequencies are provided
-whether or not called upon.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- dtrace/Makefile | 2 +
- dtrace/profile.h | 32 +++
- dtrace/profile_dev.c | 491 +++++++++++++++++++++++++++++++++++++++++++
- dtrace/profile_mod.c | 52 +++++
- 4 files changed, 577 insertions(+)
- create mode 100644 dtrace/profile.h
- create mode 100644 dtrace/profile_dev.c
- create mode 100644 dtrace/profile_mod.c
-
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-index 126d4985967a..5e6fb362a4e9 100644
---- a/dtrace/Makefile
-+++ b/dtrace/Makefile
-@@ -3,6 +3,7 @@
- #
-
- obj-$(CONFIG_DT_CORE) += dtrace.o
-+obj-$(CONFIG_DT_PROFILE) += profile.o
- obj-$(CONFIG_DT_SDT) += sdt.o
- obj-$(CONFIG_DT_SYSTRACE) += systrace.o
- obj-$(CONFIG_DT_DT_TEST) += dt_test.o
-@@ -16,6 +17,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \
- dtrace_probe.o dtrace_probe_ctx.o \
- dtrace_ptofapi.o dtrace_predicate.o \
- dtrace_spec.o dtrace_state.o dtrace_util.o
-+profile-y := profile_mod.o profile_dev.o
- sdt-y := sdt_mod.o sdt_dev.o
- systrace-y := systrace_mod.o systrace_dev.o
- dt_test-y := dt_test_mod.o dt_test_dev.o
-diff --git a/dtrace/profile.h b/dtrace/profile.h
-new file mode 100644
-index 000000000000..713886d1d8e8
---- /dev/null
-+++ b/dtrace/profile.h
-@@ -0,0 +1,32 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - profile provider
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _PROFILE_H_
-+#define _PROFILE_H_
-+
-+extern void profile_provide(void *, const struct dtrace_probedesc *);
-+extern int profile_enable(void *, dtrace_id_t, void *);
-+extern void profile_disable(void *, dtrace_id_t, void *);
-+extern int profile_usermode(void *, dtrace_id_t, void *);
-+extern void profile_destroy(void *, dtrace_id_t, void *);
-+
-+extern dtrace_provider_id_t profile_id;
-+
-+extern int profile_dev_init(void);
-+extern void profile_dev_exit(void);
-+
-+#endif /* _PROFILE_H_ */
-diff --git a/dtrace/profile_dev.c b/dtrace/profile_dev.c
-new file mode 100644
-index 000000000000..ce7261fcc911
---- /dev/null
-+++ b/dtrace/profile_dev.c
-@@ -0,0 +1,491 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: profile_dev.c
-+ * DESCRIPTION: DTrace - profile provider device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/ktime.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <asm/irq_regs.h>
-+#include <asm/ptrace.h>
-+
-+#include <linux/hardirq.h>
-+#include <linux/profile.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "profile.h"
-+
-+#define PROF_NAMELEN 15
-+#define PROF_PROFILE 0
-+#define PROF_TICK 1
-+#define PROF_PREFIX_PROFILE "profile-"
-+#define PROF_PREFIX_TICK "tick-"
-+
-+struct profile_probe {
-+ char prof_name[PROF_NAMELEN];
-+ dtrace_id_t prof_id;
-+ int prof_kind;
-+ ktime_t prof_interval;
-+ cyclic_id_t prof_cyclic;
-+};
-+
-+struct profile_probe_percpu {
-+ ktime_t profc_expected;
-+ ktime_t profc_interval;
-+ struct profile_probe *profc_probe;
-+};
-+
-+static ktime_t profile_interval_min = KTIME_INIT(0, NANOSEC / 5000);
-+static int profile_aframes;
-+
-+static int profile_rates[] = {
-+ 97, 199, 499, 997, 1999,
-+ 4001, 4999, 0, 0, 0,
-+ 0, 0, 0, 0, 0,
-+ 0, 0, 0, 0, 0,
-+ };
-+static int profile_ticks[] = {
-+ 1, 10, 100, 500, 1000,
-+ 5000, 0, 0, 0, 0,
-+ 0, 0, 0, 0, 0,
-+ };
-+
-+/*
-+ * profile_max defines the upper bound on the number of profile probes that
-+ * can exist (this is to prevent malicious or clumsy users from exhausing
-+ * system resources by creating a slew of profile probes). At mod load time,
-+ * this gets its value from PROFILE_MAX_DEFAULT or profile-max-probes if it's
-+ * present as module parameter.
-+ * FIXME: module parameter yet to be implemented.
-+ */
-+#define PROFILE_MAX_DEFAULT 1000 /* default max. number of probes */
-+
-+static int profile_max; /* maximum number of profile probes */
-+static atomic_t profile_total; /* current number of profile probes */
-+
-+static void profile_tick_fn(uintptr_t arg)
-+{
-+ struct profile_probe *prof = (struct profile_probe *)arg;
-+ unsigned long pc = 0, upc = 0;
-+ struct pt_regs *regs = get_irq_regs();
-+
-+ /*
-+ * If regs == NULL, then we were called from from softirq context which
-+ * also means that we didn't actually interrupt any processing (kernel
-+ * or user space).
-+ * If regs != NULL, then we did actually get called from hardirq
-+ * because the timer interrupt did really interrupt something that was
-+ * going on on the CPU (could be user mode or kernel mode).
-+ */
-+ if (regs == NULL) {
-+ uint64_t stack[8];
-+
-+ dtrace_getpcstack(stack, 8, 0, NULL);
-+ pc = stack[7];
-+ } else if (user_mode(regs))
-+ upc = instruction_pointer(regs);
-+ else
-+ pc = instruction_pointer(regs);
-+
-+ dtrace_probe(prof->prof_id, pc, upc, 0, 0, 0, 0, 0);
-+}
-+
-+static void profile_prof_fn(uintptr_t arg)
-+{
-+ struct profile_probe_percpu *pcpu = (struct profile_probe_percpu *)arg;
-+ struct profile_probe *prof = pcpu->profc_probe;
-+ ktime_t late;
-+ struct pt_regs *regs = get_irq_regs();
-+ unsigned long pc = 0, upc = 0;
-+
-+ late = ktime_sub(dtrace_gethrtime(), pcpu->profc_expected);
-+ pcpu->profc_expected = ktime_add(pcpu->profc_expected,
-+ pcpu->profc_interval);
-+
-+ /*
-+ * If regs == NULL, then we were called from from softirq context which
-+ * also means that we didn't actually interrupt any processing (kernel
-+ * or user space).
-+ * If regs != NULL, then we did actually get called from hardirq
-+ * because the timer interrupt did really interrupt something that was
-+ * going on on the CPU (could be user mode or kernel mode).
-+ */
-+ if (regs == NULL) {
-+ uint64_t stack[8];
-+
-+ dtrace_getpcstack(stack, 8, 0, NULL);
-+ pc = stack[7];
-+ } else if (user_mode(regs))
-+ upc = instruction_pointer(regs);
-+ else
-+ pc = instruction_pointer(regs);
-+
-+ dtrace_probe(prof->prof_id, pc, upc, ktime_to_ns(late), 0, 0, 0, 0);
-+}
-+
-+static void profile_online(void *arg, processorid_t cpu,
-+ struct cyc_handler *hdlr,
-+ struct cyc_time *when)
-+{
-+ struct profile_probe *prof = arg;
-+ struct profile_probe_percpu *pcpu;
-+
-+ pcpu = kzalloc(sizeof(struct profile_probe_percpu), GFP_KERNEL);
-+ pcpu->profc_probe = prof;
-+
-+ hdlr->cyh_func = profile_prof_fn;
-+ hdlr->cyh_arg = (uintptr_t)pcpu;
-+ hdlr->cyh_level = CY_HIGH_LEVEL;
-+
-+ when->cyt_interval = prof->prof_interval;
-+ when->cyt_when = ktime_add(dtrace_gethrtime(), when->cyt_interval);
-+
-+ pcpu->profc_expected = when->cyt_when;
-+ pcpu->profc_interval = when->cyt_interval;
-+}
-+
-+static void profile_offline(void *arg, processorid_t cpu, void *oarg)
-+{
-+ struct profile_probe_percpu *pcpu = oarg;
-+
-+ if (pcpu->profc_probe == arg) {
-+ kfree(pcpu);
-+ return;
-+ }
-+
-+ WARN_ONCE(1, "%s: called with mismatched probe info (%p vs %p)"
-+ " - leaking %lu bytes\n", __func__, pcpu->profc_probe, arg,
-+ sizeof(struct profile_probe_percpu));
-+
-+}
-+
-+static void profile_create(ktime_t interval, const char *name, int kind)
-+{
-+ struct profile_probe *prof;
-+ int nr_frames = 0; /* FIXME */
-+
-+ if (profile_aframes)
-+ nr_frames = profile_aframes;
-+
-+ if (ktime_lt(interval, profile_interval_min))
-+ return;
-+
-+ if (dtrace_probe_lookup(profile_id, NULL, NULL, name) != 0)
-+ return;
-+
-+ prof = kzalloc(sizeof(struct profile_probe), GFP_KERNEL);
-+ if (prof == NULL) {
-+ pr_warn("Unable to create probe %s: out of memory\n", name);
-+ return;
-+ }
-+
-+ atomic_inc(&profile_total);
-+ if (atomic_read(&profile_total) > profile_max)
-+ goto errout;
-+
-+ strcpy(prof->prof_name, name);
-+ prof->prof_interval = interval;
-+ prof->prof_cyclic = CYCLIC_NONE;
-+ prof->prof_kind = kind;
-+ prof->prof_id = dtrace_probe_create(profile_id, NULL, NULL, name,
-+ nr_frames, prof);
-+
-+ if (prof->prof_id == DTRACE_IDNONE) {
-+ pr_warn("Unable to create probe %s: out of memory\n", name);
-+ goto errout;
-+ }
-+
-+ return;
-+
-+errout:
-+ kfree(prof);
-+ atomic_dec(&profile_total);
-+ return;
-+}
-+
-+void profile_provide(void *arg, const struct dtrace_probedesc *desc)
-+{
-+ int i, j, rate, kind;
-+ long val = 0, mult = 1, mult_s = 0, mult_ns = 0, len;
-+ ktime_t interval;
-+ const char *name, *suffix = NULL;
-+ const struct {
-+ char *prefix;
-+ int kind;
-+ } types[] = {
-+ { PROF_PREFIX_PROFILE, PROF_PROFILE },
-+ { PROF_PREFIX_TICK, PROF_TICK },
-+ { NULL, 0 },
-+ };
-+
-+ const struct {
-+ char *name;
-+ long mult_s;
-+ long mult_ns;
-+ } suffixes[] = {
-+ { "ns", 0, 1 },
-+ { "nsec", 0, 1 },
-+ { "us", 0, NANOSEC / MICROSEC },
-+ { "usec", 0, NANOSEC / MICROSEC },
-+ { "ms", 0, NANOSEC / MILLISEC },
-+ { "msec", 0, NANOSEC / MILLISEC },
-+ { "s", 1, 0 },
-+ { "sec", 1, 0 },
-+ { "m", 60, 0 },
-+ { "min", 60, 0 },
-+ { "h", 60 * 60, 0 },
-+ { "hour", 60 * 60, 0 },
-+ { "d", 24 * 60 * 60, 0 },
-+ { "day", 24 * 60 * 60, 0 },
-+ { "hz", 0, 0 },
-+ { NULL, },
-+ };
-+
-+ if (desc == NULL) {
-+ char n[PROF_NAMELEN];
-+
-+ /*
-+ * If no description was provided, provide all of our probes.
-+ */
-+ for (i = 0; i < sizeof(profile_rates) / sizeof(int); i++) {
-+ rate = profile_rates[i];
-+ if (rate == 0)
-+ continue;
-+
-+ snprintf(n, PROF_NAMELEN, "%s%d",
-+ PROF_PREFIX_PROFILE, rate);
-+ profile_create(ktime_set(0, NANOSEC / rate),
-+ n, PROF_PROFILE);
-+ }
-+
-+ for (i = 0; i < sizeof(profile_ticks) / sizeof(int); i++) {
-+ rate = profile_ticks[i];
-+ if (rate == 0)
-+ continue;
-+
-+ snprintf(n, PROF_NAMELEN, "%s%d",
-+ PROF_PREFIX_TICK, rate);
-+ profile_create(ktime_set(0, NANOSEC / rate),
-+ n, PROF_TICK);
-+ }
-+
-+ return;
-+ }
-+
-+ name = desc->dtpd_name;
-+
-+ for (i = 0; types[i].prefix != NULL; i++) {
-+ len = strlen(types[i].prefix);
-+
-+ if (strncmp(name, types[i].prefix, len) != 0)
-+ continue;
-+
-+ break;
-+ }
-+
-+ if (types[i].prefix == NULL)
-+ return;
-+
-+ kind = types[i].kind;
-+
-+ /*
-+ * We need to start before any time suffix.
-+ */
-+ for (j = strlen(name); j >= len; j--) {
-+ if (name[j] >= '0' && name[j] <= '9')
-+ break;
-+
-+ suffix = &name[j];
-+ }
-+
-+ if (suffix == NULL) {
-+ WARN_ONCE(1, "%s: missing time suffix in %s\n", __func__, name);
-+ return;
-+ }
-+
-+ /*
-+ * Now determine the numerical value present in the probe name.
-+ */
-+ for (; j >= len; j--) {
-+ if (name[j] < '0' || name[j] > '9')
-+ return;
-+
-+ val += (name[j] - '0') * mult;
-+ mult *= 10;
-+ }
-+
-+ if (val == 0)
-+ return;
-+
-+ /*
-+ * Look up the suffix to determine the multiplier.
-+ */
-+ for (i = 0; suffixes[i].name != NULL; i++) {
-+ if (strcasecmp(suffixes[i].name, suffix) == 0) {
-+ mult_s = suffixes[i].mult_s;
-+ mult_ns = suffixes[i].mult_ns;
-+ break;
-+ }
-+ }
-+
-+ if (suffixes[i].name == NULL && *suffix != '\0')
-+ return;
-+
-+ if (mult_s == 0 && mult_ns == 0) {
-+ /*
-+ * The default is frequency (per-second).
-+ */
-+ interval = ns_to_ktime((int64_t)NANOSEC / val);
-+ } else {
-+ long sec;
-+ long nsec = val * mult_ns;
-+
-+ sec = nsec / NANOSEC;
-+ nsec %= NANOSEC;
-+
-+ interval = ktime_set(val * mult_s + sec, nsec);
-+ }
-+
-+
-+ profile_create(interval, name, kind);
-+}
-+
-+int profile_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct profile_probe *prof = parg;
-+ struct cyc_time when;
-+
-+ if (!ktime_nz(prof->prof_interval)) {
-+ WARN_ONCE(1, "%s: trying to enable 0-interval probe %s\n",
-+ __func__, prof->prof_name);
-+ return 1;
-+ }
-+ if (!MUTEX_HELD(&cpu_lock)) {
-+ WARN_ONCE(1, "%s: not holding cpu_lock\n", __func__);
-+ return 1;
-+ }
-+
-+ if (prof->prof_kind == PROF_TICK) {
-+ struct cyc_handler hdlr;
-+
-+ hdlr.cyh_func = profile_tick_fn;
-+ hdlr.cyh_arg = (uintptr_t)prof;
-+ hdlr.cyh_level = CY_HIGH_LEVEL;
-+
-+ when.cyt_interval = prof->prof_interval;
-+ when.cyt_when = ktime_set(0, 0);
-+
-+ prof->prof_cyclic = cyclic_add(&hdlr, &when);
-+ } else if (prof->prof_kind == PROF_PROFILE) {
-+ struct cyc_omni_handler omni;
-+
-+ omni.cyo_online = profile_online;
-+ omni.cyo_offline = profile_offline;
-+ omni.cyo_arg = prof;
-+
-+ prof->prof_cyclic = cyclic_add_omni(&omni);
-+ } else
-+ pr_warn_once("%s: Invalid profile type %d\n",
-+ __func__, prof->prof_kind);
-+
-+ return 0;
-+}
-+
-+void profile_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct profile_probe *prof = parg;
-+
-+ if (prof->prof_cyclic == CYCLIC_NONE) {
-+ WARN_ONCE(1, "%s: trying to disable probe %s without cyclic\n",
-+ __func__, prof->prof_name);
-+ return;
-+ }
-+ if (!MUTEX_HELD(&cpu_lock)) {
-+ WARN_ONCE(1, "%s: not holding cpu_lock\n", __func__);
-+ return;
-+ }
-+
-+ cyclic_remove(prof->prof_cyclic);
-+ prof->prof_cyclic = CYCLIC_NONE;
-+}
-+
-+int profile_usermode(void *arg, dtrace_id_t id, void *parg)
-+{
-+ return 1; /* FIXME: awaiting unprivileged tracing */
-+}
-+
-+void profile_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct profile_probe *prof = parg;
-+
-+ if (prof->prof_cyclic == CYCLIC_NONE) {
-+ kfree(prof);
-+
-+ if (atomic_read(&profile_total) >= 1) {
-+ atomic_dec(&profile_total);
-+ return;
-+ }
-+
-+ WARN_ONCE(1, "%s: profile_total refcount is 0!\n", __func__);
-+ }
-+
-+ WARN_ONCE(1, "%s: %s still assigned to cyclic\n",
-+ __func__, prof->prof_name);
-+}
-+
-+static int profile_open(struct inode *inode, struct file *file)
-+{
-+ return -EAGAIN;
-+}
-+
-+static int profile_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations profile_fops = {
-+ .owner = THIS_MODULE,
-+ .open = profile_open,
-+ .release = profile_close,
-+};
-+
-+static struct miscdevice profile_dev = {
-+ .minor = DT_DEV_PROFILE_MINOR,
-+ .name = "profile",
-+ .nodename = "dtrace/provider/profile",
-+ .fops = &profile_fops,
-+};
-+
-+int profile_dev_init(void)
-+{
-+ int ret = 0;
-+
-+ ret = misc_register(&profile_dev);
-+ if (ret)
-+ pr_err("%s: Can't register misc device %d\n",
-+ profile_dev.name, profile_dev.minor);
-+
-+ profile_max = PROFILE_MAX_DEFAULT;
-+
-+ return ret;
-+}
-+
-+void profile_dev_exit(void)
-+{
-+ misc_deregister(&profile_dev);
-+}
-diff --git a/dtrace/profile_mod.c b/dtrace/profile_mod.c
-new file mode 100644
-index 000000000000..1fb54a29e57e
---- /dev/null
-+++ b/dtrace/profile_mod.c
-@@ -0,0 +1,52 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: profile_mod.c
-+ * DESCRIPTION: DTrace - Profile provider kernel module
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "profile.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("Profile Interrupt Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+static const struct dtrace_pattr profile_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+};
-+
-+static struct dtrace_pops profile_pops = {
-+ .dtps_provide = profile_provide,
-+ .dtps_provide_module = NULL,
-+ .dtps_destroy_module = NULL,
-+ .dtps_enable = profile_enable,
-+ .dtps_disable = profile_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = NULL,
-+ .dtps_getargval = NULL,
-+ .dtps_usermode = profile_usermode,
-+ .dtps_destroy = profile_destroy,
-+};
-+
-+DT_PROVIDER_MODULE(profile, DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch
deleted file mode 100644
index dfe577d6ae57..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch
+++ /dev/null
@@ -1,412 +0,0 @@
-From 18dbf51fb9a2c43ac740c698ecbe91b48050e259 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 18:58:27 +0000
-Subject: [PATCH 12/19] dtrace: USDT and pid provider core and x86 components
-
-This implements the core (linked-in) machinery needed for userspace
-statically-defined tracepoints (for historical reasons, known as
-'fasttrap' by DTrace) and for the pid provider, which allows USDT
-probes to be dropped at addresses that do not correspond to symbols,
-at locations named as a symbol plus an offset. Both are implemented in
-terms of kprobes.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- include/linux/dtrace_os.h | 23 +++
- kernel/dtrace/Kconfig | 10 ++
- kernel/dtrace/dtrace_os.c | 272 ++++++++++++++++++++++++++++++++++++
- kernel/dtrace/dtrace_task.c | 15 ++
- 4 files changed, 320 insertions(+)
-
-diff --git a/include/linux/dtrace_os.h b/include/linux/dtrace_os.h
-index f2921ce039a7..836825b1c7be 100644
---- a/include/linux/dtrace_os.h
-+++ b/include/linux/dtrace_os.h
-@@ -14,6 +14,9 @@
- #include <linux/mm.h>
- #include <linux/notifier.h>
- #include <linux/timekeeper_internal.h>
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+#include <linux/uprobes.h>
-+#endif
- #include <asm/unistd.h>
- #include <linux/dtrace_cpu.h>
- #include <linux/dtrace_task.h>
-@@ -94,8 +97,28 @@ static inline int dtrace_no_pf(struct pt_regs *regs)
- }
-
- extern void (*dtrace_helpers_cleanup)(struct task_struct *);
-+extern void (*dtrace_fasttrap_probes_cleanup)(struct task_struct *);
- extern void (*dtrace_helpers_fork)(struct task_struct *, struct task_struct *);
-
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+struct fasttrap_machtp {
-+ struct inode *fmtp_ino;
-+ loff_t fmtp_off;
-+ struct uprobe_consumer fmtp_cns;
-+};
-+
-+extern int (*dtrace_tracepoint_hit)(struct fasttrap_machtp *,
-+ struct pt_regs *, int);
-+
-+extern struct task_struct *register_pid_provider(pid_t);
-+extern void unregister_pid_provider(pid_t);
-+
-+extern int dtrace_copy_code(pid_t, uint8_t *, uintptr_t, size_t);
-+extern int dtrace_tracepoint_enable(pid_t, uintptr_t, int,
-+ struct fasttrap_machtp *);
-+extern int dtrace_tracepoint_disable(pid_t, struct fasttrap_machtp *);
-+#endif /* CONFIG_DT_FASTTRAP || CONFIG_DT_FASTTRAP_MODULE */
-+
- #else
-
- /*
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-index 7b88206fe835..6bf6620981cd 100644
---- a/kernel/dtrace/Kconfig
-+++ b/kernel/dtrace/Kconfig
-@@ -23,6 +23,16 @@ config DT_CORE
-
- if DT_CORE
-
-+config DT_FASTTRAP
-+ tristate "Fasttrap Tracing"
-+ default m
-+ depends on ARCH_SUPPORTS_UPROBES
-+ select UPROBE_EVENT
-+ help
-+ Userspace tracing, providing the kernel support needed for tracing
-+ userspace programs. Currently, only statically defined probes
-+ (USDT) are supported.
-+
- config DT_PROFILE
- tristate "Profile Interrupt Tracing"
- default m
-diff --git a/kernel/dtrace/dtrace_os.c b/kernel/dtrace/dtrace_os.c
-index 931cfd0d0fbf..874e097b84fd 100644
---- a/kernel/dtrace/dtrace_os.c
-+++ b/kernel/dtrace/dtrace_os.c
-@@ -40,6 +40,10 @@
- #include <linux/shmem_fs.h>
- #include <linux/dtrace_task_impl.h>
-
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+# include <linux/uprobes.h>
-+#endif /* CONFIG_DT_FASTTRAP || CONFIG_DT_FASTTRAP_MODULE */
-+
- /*
- * OS SPECIFIC DTRACE SETUP
- */
-@@ -413,3 +417,271 @@ void dtrace_disable(void)
- dtrace_enabled = 0;
- }
- EXPORT_SYMBOL(dtrace_disable);
-+
-+/*
-+ * USER SPACE TRACING (FASTTRAP) SUPPORT
-+ */
-+
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+int (*dtrace_tracepoint_hit)(struct fasttrap_machtp *, struct pt_regs *, int);
-+EXPORT_SYMBOL(dtrace_tracepoint_hit);
-+
-+struct task_struct *register_pid_provider(pid_t pid)
-+{
-+ struct task_struct *p;
-+
-+ /*
-+ * Make sure the process exists, (FIXME: isn't a child created as the
-+ * result of a vfork(2)), and isn't a zombie (but may be in fork).
-+ */
-+ rcu_read_lock();
-+ p = find_task_by_vpid(pid);
-+ if (p == NULL) {
-+ rcu_read_unlock();
-+ return NULL;
-+ }
-+
-+ get_task_struct(p);
-+ rcu_read_unlock();
-+
-+ if (p->state & TASK_DEAD || p->dt_task == NULL ||
-+ p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) {
-+ put_task_struct(p);
-+ return NULL;
-+ }
-+
-+ /*
-+ * Increment dtrace_probes so that the process knows to inform us
-+ * when it exits or execs. fasttrap_provider_free() decrements this
-+ * when we're done with this provider.
-+ */
-+ if (p->dt_task != NULL)
-+ p->dt_task->dt_probes++;
-+ put_task_struct(p);
-+
-+ return p;
-+}
-+EXPORT_SYMBOL(register_pid_provider);
-+
-+void unregister_pid_provider(pid_t pid)
-+{
-+ struct task_struct *p;
-+
-+ /*
-+ * Decrement dtrace_probes on the process whose provider we're
-+ * freeing. We don't have to worry about clobbering somone else's
-+ * modifications to it because we have locked the bucket that
-+ * corresponds to this process's hash chain in the provider hash
-+ * table. Don't sweat it if we can't find the process.
-+ */
-+ rcu_read_lock();
-+ read_lock(&tasklist_lock);
-+ if ((p = find_task_by_vpid(pid)) == NULL) {
-+ read_unlock(&tasklist_lock);
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ get_task_struct(p);
-+ read_unlock(&tasklist_lock);
-+ rcu_read_unlock();
-+
-+ if (p->dt_task != NULL)
-+ p->dt_task->dt_probes--;
-+ put_task_struct(p);
-+}
-+EXPORT_SYMBOL(unregister_pid_provider);
-+
-+int dtrace_copy_code(pid_t pid, uint8_t *buf, uintptr_t addr, size_t size)
-+{
-+ struct task_struct *p;
-+ struct inode *ino;
-+ struct vm_area_struct *vma;
-+ struct address_space *map;
-+ loff_t off;
-+ int rc = 0;
-+
-+ /*
-+ * First we determine the inode and offset that 'addr' refers to in the
-+ * task referenced by 'pid'.
-+ */
-+ rcu_read_lock();
-+ p = find_task_by_vpid(pid);
-+ if (!p) {
-+ rcu_read_unlock();
-+ pr_warn("PID %d not found\n", pid);
-+ return -ESRCH;
-+ }
-+ get_task_struct(p);
-+ rcu_read_unlock();
-+
-+ mmap_write_lock(p->mm);
-+ vma = find_vma(p->mm, addr);
-+ if (vma == NULL || vma->vm_file == NULL) {
-+ rc = -EFAULT;
-+ goto out;
-+ }
-+
-+ ino = vma->vm_file->f_mapping->host;
-+ map = ino->i_mapping;
-+ off = ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (addr - vma->vm_start);
-+
-+ if (map->a_ops->readpage == NULL && !shmem_mapping(ino->i_mapping)) {
-+ rc = -EIO;
-+ goto out;
-+ }
-+
-+ /*
-+ * Armed with inode and offset, we can start reading pages...
-+ */
-+ do {
-+ int len;
-+ struct page *page;
-+ void *kaddr;
-+
-+ /*
-+ * We cannot read beyond the end of the inode content.
-+ */
-+ if (off >= i_size_read(ino))
-+ break;
-+
-+ len = min_t(int, size, PAGE_SIZE - (off & ~PAGE_MASK));
-+
-+ /*
-+ * Make sure that the page we're tring to read is populated and
-+ * in page cache.
-+ */
-+ if (map->a_ops->readpage)
-+ page = read_mapping_page(map, off >> PAGE_SHIFT,
-+ vma->vm_file);
-+ else
-+ page = shmem_read_mapping_page(map, off >> PAGE_SHIFT);
-+
-+ if (IS_ERR(page)) {
-+ rc = PTR_ERR(page);
-+ break;
-+ }
-+
-+ kaddr = kmap_atomic(page);
-+ memcpy(buf, kaddr + (off & ~PAGE_MASK), len);
-+ kunmap_atomic(kaddr);
-+ put_page(page);
-+
-+ buf += len;
-+ off += len;
-+ size -= len;
-+ } while (size > 0);
-+
-+out:
-+ mmap_write_unlock(p->mm);
-+ put_task_struct(p);
-+
-+ return rc;
-+}
-+EXPORT_SYMBOL(dtrace_copy_code);
-+
-+static int handler(struct uprobe_consumer *self, struct pt_regs *regs,
-+ int is_ret)
-+{
-+ struct fasttrap_machtp *mtp;
-+ int rc = 0;
-+
-+ mtp = container_of(self, struct fasttrap_machtp, fmtp_cns);
-+
-+ read_lock(&this_cpu_core->cpu_ft_lock);
-+ if (dtrace_tracepoint_hit == NULL)
-+ pr_warn("Fasttrap probes, but no handler\n");
-+ else
-+ rc = (*dtrace_tracepoint_hit)(mtp, regs, is_ret);
-+ read_unlock(&this_cpu_core->cpu_ft_lock);
-+
-+ return rc;
-+}
-+
-+static int prb_handler(struct uprobe_consumer *self, struct pt_regs *regs)
-+{
-+ return handler(self, regs, 0);
-+}
-+
-+static int ret_handler(struct uprobe_consumer *self, unsigned long func,
-+ struct pt_regs *regs)
-+{
-+ return handler(self, regs, 1);
-+}
-+
-+int dtrace_tracepoint_enable(pid_t pid, uintptr_t addr, int is_ret,
-+ struct fasttrap_machtp *mtp)
-+{
-+ struct task_struct *p;
-+ struct inode *ino;
-+ struct vm_area_struct *vma;
-+ loff_t off;
-+ int rc = 0;
-+
-+ mtp->fmtp_ino = NULL;
-+ mtp->fmtp_off = 0;
-+
-+ p = find_task_by_vpid(pid);
-+ if (!p) {
-+ pr_warn("PID %d not found\n", pid);
-+ return -ESRCH;
-+ }
-+
-+ if (p->dt_task == NULL) {
-+ pr_warn("PID %d no dtrace_task\n", pid);
-+ return -EFAULT;
-+ }
-+
-+ vma = find_vma(p->mm, addr);
-+ if (vma == NULL || vma->vm_file == NULL)
-+ return -EFAULT;
-+
-+ ino = vma->vm_file->f_mapping->host;
-+ off = ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (addr - vma->vm_start);
-+
-+ if (is_ret)
-+ mtp->fmtp_cns.ret_handler = ret_handler;
-+ else
-+ mtp->fmtp_cns.handler = prb_handler;
-+
-+ rc = uprobe_register(ino, off, &mtp->fmtp_cns);
-+
-+ /*
-+ * If successful, increment the count of the number of
-+ * tracepoints active in the victim process.
-+ */
-+ if (rc == 0) {
-+ mtp->fmtp_ino = ino;
-+ mtp->fmtp_off = off;
-+
-+ p->dt_task->dt_tp_count++;
-+ }
-+
-+ return rc;
-+}
-+EXPORT_SYMBOL(dtrace_tracepoint_enable);
-+
-+int dtrace_tracepoint_disable(pid_t pid, struct fasttrap_machtp *mtp)
-+{
-+ struct task_struct *p;
-+
-+ if (!mtp || !mtp->fmtp_ino)
-+ return -ENOENT;
-+
-+ uprobe_unregister(mtp->fmtp_ino, mtp->fmtp_off, &mtp->fmtp_cns);
-+
-+ mtp->fmtp_ino = NULL;
-+ mtp->fmtp_off = 0;
-+
-+ /*
-+ * Decrement the count of the number of tracepoints active in
-+ * the victim process (if it still exists).
-+ */
-+ p = find_task_by_vpid(pid);
-+ if (p != NULL && p->dt_task != NULL)
-+ p->dt_task->dt_tp_count--;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_tracepoint_disable);
-+#endif /* CONFIG_DT_FASTTRAP || CONFIG_DT_FASTTRAP_MODULE */
-diff --git a/kernel/dtrace/dtrace_task.c b/kernel/dtrace/dtrace_task.c
-index 02bcc6b7e0a2..8bae6e79c7f1 100644
---- a/kernel/dtrace/dtrace_task.c
-+++ b/kernel/dtrace/dtrace_task.c
-@@ -22,6 +22,14 @@
-
- struct kmem_cache *dtrace_task_cachep;
-
-+/*
-+ * Fasttrap hooks that need to be called when a fasttrap meta provider
-+ * is loaded and registered with the framework.
-+ */
-+void (*dtrace_helpers_cleanup)(struct task_struct *);
-+EXPORT_SYMBOL(dtrace_helpers_cleanup);
-+void (*dtrace_fasttrap_probes_cleanup)(struct task_struct *);
-+EXPORT_SYMBOL(dtrace_fasttrap_probes_cleanup);
- void (*dtrace_helpers_fork)(struct task_struct *, struct task_struct *);
- EXPORT_SYMBOL(dtrace_helpers_fork);
-
-@@ -76,6 +84,13 @@ static void dtrace_task_cleanup(struct task_struct *tsk)
- if (tsk->dt_task == NULL)
- return;
-
-+ /* Handle fasttrap provider cleanups. */
-+ if (tsk->dt_task->dt_helpers != NULL && dtrace_helpers_cleanup != NULL)
-+ (*dtrace_helpers_cleanup)(tsk);
-+
-+ if (tsk->dt_task->dt_probes && dtrace_fasttrap_probes_cleanup != NULL)
-+ (*dtrace_fasttrap_probes_cleanup)(tsk);
-+
- /* Release psinfo if any. */
- psinfo = tsk->dt_task->dt_psinfo;
- if (psinfo != NULL) {
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0013-dtrace-USDT-and-pid-providers.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0013-dtrace-USDT-and-pid-providers.patch
deleted file mode 100644
index 441bf139d28d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0013-dtrace-USDT-and-pid-providers.patch
+++ /dev/null
@@ -1,2691 +0,0 @@
-From 209f98383b9139b7d50f91f8433e50bf00c61236 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 18:08:41 +0000
-Subject: [PATCH 13/19] dtrace: USDT and pid providers
-
-For historical reasons, these are provided in a module named
-fasttrap.ko.
-
-Much of this is arch-dependent code for jump-table detection and
-implementation of globbed pid probes ("probe everything you can in this
-function"), as well as arch-dependent code to look up arguments and code
-to ensure that dropping a kprobe in a single process does not affect
-other processes running from the same binary.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/dtrace/Makefile.arch | 2 +
- arch/x86/dtrace/fasttrap_x86_64.c | 364 +++
- .../x86/dtrace/include/dtrace/fasttrap_arch.h | 29 +
- dtrace/Makefile | 2 +
- dtrace/fasttrap_dev.c | 1986 +++++++++++++++++
- dtrace/fasttrap_impl.h | 172 ++
- dtrace/fasttrap_mod.c | 38 +
- 7 files changed, 2593 insertions(+)
- create mode 100644 arch/x86/dtrace/fasttrap_x86_64.c
- create mode 100644 arch/x86/dtrace/include/dtrace/fasttrap_arch.h
- create mode 100644 dtrace/fasttrap_dev.c
- create mode 100644 dtrace/fasttrap_impl.h
- create mode 100644 dtrace/fasttrap_mod.c
-
-diff --git a/arch/x86/dtrace/Makefile.arch b/arch/x86/dtrace/Makefile.arch
-index 8492eaee426d..e4655557e06a 100644
---- a/arch/x86/dtrace/Makefile.arch
-+++ b/arch/x86/dtrace/Makefile.arch
-@@ -7,7 +7,9 @@ DTARCHDIR = ../arch/x86/dtrace
- ccflags-y += -I$(srctree)/arch/x86/dtrace/include -Idtrace
-
- dtrace-obj += dtrace_asm_x86_64.o dtrace_isa_x86_64.o
-+fasttrap-obj += fasttrap_x86_64.o
- sdt-obj += sdt_x86_64.o
-
- dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
-+fasttrap-y += $(addprefix $(DTARCHDIR)/, $(fasttrap-obj))
- sdt-y += $(addprefix $(DTARCHDIR)/, $(sdt-obj))
-diff --git a/arch/x86/dtrace/fasttrap_x86_64.c b/arch/x86/dtrace/fasttrap_x86_64.c
-new file mode 100644
-index 000000000000..012b2a50a46a
---- /dev/null
-+++ b/arch/x86/dtrace/fasttrap_x86_64.c
-@@ -0,0 +1,364 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fasttrap_x86_64.c
-+ * DESCRIPTION: DTrace - fasttrap provider implementation for x86
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <asm/insn.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fasttrap_impl.h"
-+
-+#define DISASM_REX_PREFIX(pfx) (((pfx) & 0xf0) == 0x40)
-+#define DISASM_MODRM_REG(modrm) (((modrm) >> 3) & 0x07)
-+
-+static int has_jump_table(const asm_instr_t *addr, size_t size)
-+{
-+ const asm_instr_t *end = addr + size;
-+
-+ while (addr < end) {
-+ int len;
-+
-+ /*
-+ * Register-dependent jump instructions start with a 0xff byte
-+ * and have the modrm.reg field set to 4. Such instructions
-+ * tend to be used for jump tables.
-+ */
-+ if ((addr[0] == 0xff && DISASM_MODRM_REG(addr[1]) == 4) ||
-+ (DISASM_REX_PREFIX(addr[0]) && addr[1] == 0xff &&
-+ DISASM_MODRM_REG(addr[2]) == 4))
-+ return 1;
-+
-+ len = dtrace_instr_size(addr);
-+
-+ /*
-+ * If we encounter a problem decoding an instruction, we will
-+ * assume that there might be a jump table. Better safe than
-+ * sorry...
-+ */
-+ if (len < 0)
-+ return 1;
-+
-+ addr += len;
-+ }
-+
-+ return 0;
-+}
-+
-+static uint64_t *fasttrap_all_offsets(asm_instr_t *text, size_t size,
-+ uint64_t *np)
-+{
-+ uint64_t *offs = NULL;
-+ uint64_t noffs;
-+ asm_instr_t *instr;
-+ asm_instr_t *end;
-+
-+ /*
-+ * Two passes are taken through this section of code. The first time
-+ * around we merely count the number of probe points. The second time,
-+ * we actually record their locations.
-+ */
-+again:
-+ noffs = 0;
-+ instr = text;
-+ end = text + size;
-+
-+ while (instr < end) {
-+ int len;
-+
-+ /*
-+ * If we fail to decode an instruction, it is time to give up.
-+ */
-+ len = dtrace_instr_size(instr);
-+ if (len < 0)
-+ goto fail;
-+
-+ if (offs)
-+ offs[noffs] = (uint64_t)(instr - text);
-+ noffs++;
-+
-+ instr += len;
-+ }
-+
-+ if (offs == NULL) {
-+ /*
-+ * No matching offsets found - we are done.
-+ */
-+ if (noffs == 0)
-+ goto fail;
-+
-+ /*
-+ * We know how many tracepoint locations there are for this
-+ * probe, so allocate member to record them, and kick off the
-+ * second pass.
-+ */
-+ offs = kmalloc(sizeof(uint64_t) * noffs, GFP_KERNEL);
-+ if (!offs)
-+ goto fail;
-+
-+ goto again;
-+ }
-+
-+ *np = noffs;
-+
-+ return offs;
-+
-+fail:
-+ *np = 0;
-+ kfree(offs);
-+
-+ return NULL;
-+}
-+
-+uint64_t *fasttrap_glob_offsets(struct fasttrap_probe_spec *probe,
-+ uint64_t *np)
-+{
-+ size_t size = probe->ftps_size;
-+ asm_instr_t *text = NULL;
-+ asm_instr_t *instr;
-+ asm_instr_t *end;
-+ uint64_t *offs = NULL;
-+ uint64_t noffs;
-+ int ret = 0;
-+ char ostr[sizeof(instr) * 2 + 1];
-+
-+ text = kmalloc(size, GFP_KERNEL);
-+ if (!text)
-+ goto fail;
-+
-+ ret = dtrace_copy_code(probe->ftps_pid, (uint8_t *)text,
-+ probe->ftps_pc, size);
-+ if (ret != 0)
-+ goto fail;
-+
-+ if (has_jump_table(text, size))
-+ goto fail;
-+
-+ if (probe->ftps_glen == 1 && probe->ftps_gstr[0] == '*') {
-+ offs = fasttrap_all_offsets(text, size, &noffs);
-+ goto out;
-+ }
-+
-+ /*
-+ * Two passes are taken through this section of code. The first time
-+ * around we merely count the number of probe points. The second time,
-+ * we actually record their locations.
-+ */
-+again:
-+ noffs = 0;
-+ instr = text;
-+ end = text + size;
-+
-+ while (instr < end) {
-+ int len;
-+ uint64_t off = (uint64_t)(instr - text);
-+
-+ /*
-+ * If we fail to decode an instruction, it is time to give up.
-+ */
-+ len = dtrace_instr_size(instr);
-+ if (len < 0)
-+ goto fail;
-+
-+ snprintf(ostr, sizeof(ostr), "%llx", off);
-+ if (dtrace_gmatch(ostr, probe->ftps_gstr)) {
-+ if (offs)
-+ offs[noffs] = off;
-+ noffs++;
-+ }
-+
-+ instr += len;
-+ }
-+
-+ if (offs == NULL) {
-+ /*
-+ * No matching offsets found - we are done.
-+ */
-+ if (noffs == 0)
-+ goto fail;
-+
-+ /*
-+ * We know how many tracepoint locations there are for this
-+ * probe, so allocate member to record them, and kick off the
-+ * second pass.
-+ */
-+ offs = kmalloc(sizeof(uint64_t) * noffs, GFP_KERNEL);
-+ if (!offs)
-+ goto fail;
-+
-+ goto again;
-+ }
-+
-+out:
-+ kfree(text);
-+
-+ *np = noffs;
-+
-+ return offs;
-+
-+fail:
-+ kfree(offs);
-+ kfree(text);
-+
-+ *np = 0;
-+ return NULL;
-+}
-+
-+uint64_t fasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ return 0;
-+
-+ switch (argno) {
-+ case 0:
-+ return regs->di;
-+ case 1:
-+ return regs->si;
-+ case 2:
-+ return regs->dx;
-+ case 3:
-+ return regs->cx;
-+ case 4:
-+ return regs->r8;
-+ case 5:
-+ return regs->r9;
-+ }
-+
-+ ASSERT(argno > 5);
-+
-+ pagefault_disable();
-+ st = (uint64_t *)regs->sp;
-+ __copy_from_user_inatomic_nocache(&val, (void *)&st[argno - 6 + 1],
-+ sizeof(st[0]));
-+ pagefault_enable();
-+
-+ return val;
-+}
-+
-+uint64_t fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg,
-+ int argno, int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ return 0;
-+
-+ switch (argno) {
-+ case 0:
-+ return regs->di;
-+ case 1:
-+ return regs->si;
-+ case 2:
-+ return regs->dx;
-+ case 3:
-+ return regs->cx;
-+ case 4:
-+ return regs->r8;
-+ case 5:
-+ return regs->r9;
-+ }
-+
-+ ASSERT(argno > 5);
-+
-+ pagefault_disable();
-+ st = (uint64_t *)regs->sp;
-+ __copy_from_user_inatomic_nocache(&val, (void *)&st[argno - 6],
-+ sizeof(st[0]));
-+ pagefault_enable();
-+
-+ return val;
-+}
-+
-+static void fasttrap_map_args(struct fasttrap_probe *probe,
-+ struct pt_regs *regs,
-+ int argc, uintptr_t *argv)
-+{
-+ int i, x, cap = min(argc, (int)probe->ftp_nargs);
-+ uintptr_t *st = (uintptr_t *)regs->sp;
-+
-+ for (i = 0; i < cap; i++) {
-+ switch (x = probe->ftp_argmap[i]) {
-+ case 0:
-+ argv[i] = regs->di;
-+ break;
-+ case 1:
-+ argv[i] = regs->si;
-+ break;
-+ case 2:
-+ argv[i] = regs->dx;
-+ break;
-+ case 3:
-+ argv[i] = regs->cx;
-+ break;
-+ case 4:
-+ argv[i] = regs->r8;
-+ break;
-+ case 5:
-+ argv[i] = regs->r9;
-+ break;
-+ default:
-+ ASSERT(x > 5);
-+
-+ __copy_from_user_inatomic_nocache(&argv[i],
-+ (void *)&st[x - 6],
-+ sizeof(st[0]));
-+ }
-+ }
-+
-+ while (i < argc)
-+ argv[i++] = 0;
-+}
-+
-+void fasttrap_pid_probe_arch(struct fasttrap_probe *ftp, struct pt_regs *regs)
-+{
-+ if (ftp->ftp_argmap == NULL) {
-+ dtrace_probe(ftp->ftp_id, regs->di, regs->si, regs->dx,
-+ regs->cx, regs->r8, regs->r9, 0);
-+ } else {
-+ uintptr_t t[6];
-+
-+ fasttrap_map_args(ftp, regs, sizeof(t) / sizeof(t[0]), t);
-+ dtrace_probe(ftp->ftp_id, t[0], t[1], t[2], t[3],
-+ t[4], t[5], 0);
-+ }
-+}
-+
-+void fasttrap_pid_retprobe_arch(struct fasttrap_probe *ftp,
-+ struct pt_regs *regs)
-+{
-+ /*
-+ * FIXME: The first argument to the probe should be the offset in the
-+ * function that the return occured at, but uprobes doesn't give
-+ * us that information (or so it seems).
-+ */
-+ dtrace_probe(ftp->ftp_id, 0, regs->ax, regs->dx, 0, 0, 0, 0);
-+}
-+
-+void fasttrap_set_enabled(struct pt_regs *regs)
-+{
-+ regs->ax = 1;
-+}
-+
-diff --git a/arch/x86/dtrace/include/dtrace/fasttrap_arch.h b/arch/x86/dtrace/include/dtrace/fasttrap_arch.h
-new file mode 100644
-index 000000000000..abbe9cb2bf38
---- /dev/null
-+++ b/arch/x86/dtrace/include/dtrace/fasttrap_arch.h
-@@ -0,0 +1,29 @@
-+/*
-+ * Dynamic Tracing for Linux - Fasttrap provider implementation defines
-+ *
-+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _X86_64_FASTTRAP_ARCH_H
-+#define _X86_64_FASTTRAP_ARCH_H
-+
-+#define FASTTRAP_ENTRY_AFRAMES 8
-+#define FASTTRAP_RETURN_AFRAMES 8
-+#define FASTTRAP_OFFSET_AFRAMES 8
-+
-+#endif /* _X86_64_FASTTRAP_ARCH_H */
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-index 5e6fb362a4e9..c7e3fc512a6c 100644
---- a/dtrace/Makefile
-+++ b/dtrace/Makefile
-@@ -3,6 +3,7 @@
- #
-
- obj-$(CONFIG_DT_CORE) += dtrace.o
-+obj-$(CONFIG_DT_FASTTRAP) += fasttrap.o
- obj-$(CONFIG_DT_PROFILE) += profile.o
- obj-$(CONFIG_DT_SDT) += sdt.o
- obj-$(CONFIG_DT_SYSTRACE) += systrace.o
-@@ -17,6 +18,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \
- dtrace_probe.o dtrace_probe_ctx.o \
- dtrace_ptofapi.o dtrace_predicate.o \
- dtrace_spec.o dtrace_state.o dtrace_util.o
-+fasttrap-y := fasttrap_mod.o fasttrap_dev.o
- profile-y := profile_mod.o profile_dev.o
- sdt-y := sdt_mod.o sdt_dev.o
- systrace-y := systrace_mod.o systrace_dev.o
-diff --git a/dtrace/fasttrap_dev.c b/dtrace/fasttrap_dev.c
-new file mode 100644
-index 000000000000..f48581e00f4b
---- /dev/null
-+++ b/dtrace/fasttrap_dev.c
-@@ -0,0 +1,1986 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fasttrap_dev.c
-+ * DESCRIPTION: DTrace - fasttrap provider device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/atomic.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/sort.h>
-+#include <linux/uaccess.h>
-+#include <linux/vmalloc.h>
-+#include <linux/workqueue.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fasttrap_impl.h"
-+
-+#define FASTTRAP_MAX_DEFAULT 250000
-+static uint32_t fasttrap_max;
-+static uint64_t fasttrap_pid_count;
-+static atomic_t fasttrap_total;
-+
-+#define FASTTRAP_TPOINTS_DEFAULT_SIZE 0x4000
-+#define FASTTRAP_PROVIDERS_DEFAULT_SIZE 0x100
-+#define FASTTRAP_PROCS_DEFAULT_SIZE 0x100
-+
-+#define FASTTRAP_PID_NAME "pid"
-+#define FASTTRAP_ENABLE_FAIL 1
-+#define FASTTRAP_ENABLE_PARTIAL 2
-+
-+struct fasttrap_hash fasttrap_tpoints;
-+static struct fasttrap_hash fasttrap_provs;
-+static struct fasttrap_hash fasttrap_procs;
-+
-+#define FASTTRAP_PROVS_INDEX(pid, name) \
-+ ((fasttrap_hash_str(name) + (pid)) & fasttrap_provs.fth_mask)
-+#define FASTTRAP_PROCS_INDEX(pid) ((pid) & fasttrap_procs.fth_mask)
-+
-+#define FASTTRAP_TPOINTS_ELEM(pid, pc) \
-+ FASTTRAP_ELEM_BUCKET(&fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)])
-+#define FASTTRAP_PROVS_ELEM(pid, name) \
-+ FASTTRAP_ELEM_BUCKET(&fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)])
-+#define FASTTRAP_PROCS_ELEM(pid) \
-+ FASTTRAP_ELEM_BUCKET(&fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)])
-+
-+#define CLEANUP_NONE 0
-+#define CLEANUP_SCHEDULED 1
-+#define CLEANUP_DEFERRED 2
-+
-+DEFINE_MUTEX(fasttrap_cleanup_mtx);
-+DEFINE_MUTEX(fasttrap_count_mtx);
-+static uint_t fasttrap_cleanup_state;
-+static uint_t fasttrap_cleanup_work;
-+
-+static struct kmem_cache *tracepoint_cachep;
-+
-+/*
-+ * Generation count on modifications to the global tracepoint lookup table.
-+ */
-+static volatile uint64_t fasttrap_mod_gen;
-+
-+static void fasttrap_pid_cleanup(void);
-+static void fasttrap_probes_cleanup(struct task_struct *);
-+
-+static int fasttrap_pid_probe(struct fasttrap_machtp *mtp,
-+ struct pt_regs *regs, int is_ret)
-+{
-+ struct fasttrap_tracepoint *tp;
-+ struct fasttrap_id *id;
-+ int is_enabled = 0;
-+
-+ tp = container_of(mtp, struct fasttrap_tracepoint, ftt_mtp);
-+
-+ /*
-+ * Verify that this probe event is actually related to the current
-+ * process (task group). If not, ignore it.
-+ *
-+ * TODO: The underlying probe mechanism should register a single
-+ * handler for the (inode, offset) combination. When the handler
-+ * is called, it should run through a list of fasttrap
-+ * tracepoints associated with the OS-level probe, looking for
-+ * one that is related to the current task.
-+ */
-+ if (tp->ftt_pid != current->tgid)
-+ return 0;
-+
-+ if (atomic64_read(&tp->ftt_proc->ftpc_acount) == 0)
-+ return 0;
-+
-+ this_cpu_core->cpu_dtrace_regs = regs;
-+
-+ if (!is_ret) {
-+ for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {
-+ struct fasttrap_probe *ftp = id->fti_probe;
-+
-+ if (id->fti_ptype == DTFTP_IS_ENABLED)
-+ is_enabled = 1;
-+ else
-+ fasttrap_pid_probe_arch(ftp, regs);
-+ }
-+ } else {
-+ for (id = tp->ftt_retids; id != NULL; id = id->fti_next) {
-+ struct fasttrap_probe *ftp = id->fti_probe;
-+
-+ fasttrap_pid_retprobe_arch(ftp, regs);
-+ }
-+ }
-+
-+ this_cpu_core->cpu_dtrace_regs = NULL;
-+
-+ if (is_enabled)
-+ fasttrap_set_enabled(regs);
-+
-+ return 0;
-+}
-+
-+static void fasttrap_pid_provide(void *arg,
-+ const struct dtrace_probedesc *desc)
-+{
-+ /*
-+ * There are no "default" pid probes.
-+ */
-+}
-+
-+static void fasttrap_enable_callbacks(void)
-+{
-+ /*
-+ * We don't have to play the RW lock game here because we're providing
-+ * something rather than taking something away -- we can be sure that
-+ * no threads have tried to follow these function pointers yet.
-+ */
-+ mutex_lock(&fasttrap_count_mtx);
-+ if (fasttrap_pid_count == 0) {
-+ ASSERT(dtrace_tracepoint_hit == NULL);
-+
-+ dtrace_fasttrap_probes_cleanup = &fasttrap_probes_cleanup;
-+ dtrace_tracepoint_hit = &fasttrap_pid_probe;
-+ }
-+
-+ ASSERT(dtrace_fasttrap_probes_cleanup == &fasttrap_probes_cleanup);
-+ ASSERT(dtrace_tracepoint_hit == &fasttrap_pid_probe);
-+
-+ fasttrap_pid_count++;
-+ mutex_unlock(&fasttrap_count_mtx);
-+}
-+
-+static void fasttrap_disable_callbacks(void)
-+{
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+ mutex_lock(&fasttrap_count_mtx);
-+ ASSERT(fasttrap_pid_count > 0);
-+ fasttrap_pid_count--;
-+
-+ if (fasttrap_pid_count == 0) {
-+ int cpu;
-+
-+ for_each_present_cpu(cpu) {
-+ struct cpu_core *cpuc = per_cpu_core(cpu);
-+
-+ write_lock(&cpuc->cpu_ft_lock);
-+ }
-+
-+ dtrace_tracepoint_hit = NULL;
-+ dtrace_fasttrap_probes_cleanup = NULL;
-+
-+ for_each_present_cpu(cpu) {
-+ struct cpu_core *cpuc = per_cpu_core(cpu);
-+
-+ write_unlock(&cpuc->cpu_ft_lock);
-+ }
-+ }
-+
-+ mutex_unlock(&fasttrap_count_mtx);
-+}
-+
-+/*
-+ * This function ensures that no threads are actively using the memory
-+ * associated with probes that were formerly live.
-+ */
-+static void fasttrap_mod_barrier(uint64_t gen)
-+{
-+ int cpu;
-+
-+ if (gen < fasttrap_mod_gen)
-+ return;
-+
-+ fasttrap_mod_gen++;
-+
-+ for_each_present_cpu(cpu) {
-+ struct cpu_core *cpuc = per_cpu_core(cpu);
-+
-+ mutex_lock(&cpuc->cpuc_pid_lock);
-+ mutex_unlock(&cpuc->cpuc_pid_lock);
-+ }
-+}
-+
-+static int fasttrap_tracepoint_enable(struct fasttrap_probe *probe,
-+ uint_t index)
-+{
-+ struct fasttrap_tracepoint *tp, *new_tp = NULL;
-+ struct fasttrap_bucket *bucket;
-+ struct fasttrap_id *id;
-+ pid_t pid;
-+ uintptr_t pc;
-+
-+ ASSERT(index < probe->ftp_ntps);
-+
-+ pid = probe->ftp_pid;
-+ pc = probe->ftp_tps[index].fit_tp->ftt_pc;
-+ id = &probe->ftp_tps[index].fit_id;
-+
-+ ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid);
-+
-+ /*
-+ * Before we make any modifications, make sure we've imposed a barrier
-+ * on the generation in which this probe was last modified.
-+ */
-+ fasttrap_mod_barrier(probe->ftp_gen);
-+
-+ bucket = FASTTRAP_TPOINTS_ELEM(pid, pc);
-+
-+ /*
-+ * If the tracepoint has already been enabled, just add our id to the
-+ * list of interested probes. This may be our second time through
-+ * this path in which case we'll have constructed the tracepoint we'd
-+ * like to install. If we can't find a match, and have an allocated
-+ * tracepoint ready to go, enable that one now.
-+ *
-+ * A tracepoint whose process is defunct is also considered defunct.
-+ */
-+again:
-+ mutex_lock(&bucket->ftb_mtx);
-+ for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
-+ /*
-+ * Note that it's safe to access the active count on the
-+ * associated proc structure because we know that at least one
-+ * provider (this one) will still be around throughout this
-+ * operation.
-+ */
-+ if (tp->ftt_pid != pid || tp->ftt_pc != pc ||
-+ atomic64_read(&tp->ftt_proc->ftpc_acount) == 0)
-+ continue;
-+
-+ /*
-+ * Now that we've found a matching tracepoint, it would be
-+ * a decent idea to confirm that the tracepoint is still
-+ * enabled and the trap instruction hasn't been overwritten.
-+ * Since this is a little hairy, we'll punt for now.
-+ */
-+
-+ /*
-+ * This can't be the first interested probe. We don't have
-+ * to worry about another thread being in the midst of
-+ * deleting this tracepoint (which would be the only valid
-+ * reason for a tracepoint to have no interested probes)
-+ * since we're holding P_PR_LOCK for this process.
-+ */
-+ ASSERT(tp->ftt_ids != NULL || tp->ftt_retids != NULL);
-+
-+ switch (id->fti_ptype) {
-+ case DTFTP_ENTRY:
-+ case DTFTP_OFFSETS:
-+ case DTFTP_IS_ENABLED:
-+ if (tp->ftt_ids == NULL) /* return tp */
-+ continue;
-+
-+ ASSERT(tp->ftt_retids == NULL);
-+
-+ id->fti_next = tp->ftt_ids;
-+ dtrace_membar_producer();
-+ tp->ftt_ids = id;
-+ dtrace_membar_producer();
-+ break;
-+
-+ case DTFTP_RETURN:
-+ case DTFTP_POST_OFFSETS:
-+ if (tp->ftt_retids == NULL) /* non-return tp */
-+ continue;
-+
-+ ASSERT(tp->ftt_ids == NULL);
-+
-+ id->fti_next = tp->ftt_retids;
-+ dtrace_membar_producer();
-+ tp->ftt_retids = id;
-+ dtrace_membar_producer();
-+ break;
-+
-+ default:
-+ ASSERT(0); /* FIXME */
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ if (new_tp != NULL) {
-+ new_tp->ftt_ids = NULL;
-+ new_tp->ftt_retids = NULL;
-+ }
-+
-+ return 0;
-+ }
-+
-+ /*
-+ * If we have a good tracepoint ready to go, install it now while
-+ * we have the lock held and no one can screw with us.
-+ */
-+ if (new_tp != NULL) {
-+ int rc = 0;
-+
-+ new_tp->ftt_next = bucket->ftb_data;
-+ dtrace_membar_producer();
-+ bucket->ftb_data = new_tp;
-+ dtrace_membar_producer();
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Activate the tracepoint in the ISA-specific manner.
-+ * If this fails, we need to report the failure, but
-+ * indicate that this tracepoint must still be disabled
-+ * by calling fasttrap_tracepoint_disable().
-+ */
-+ rc = dtrace_tracepoint_enable(pid, pc,
-+ id->fti_ptype == DTFTP_RETURN,
-+ &new_tp->ftt_mtp);
-+
-+ return rc ? FASTTRAP_ENABLE_PARTIAL : 0;
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Initialize the tracepoint that's been preallocated with the probe.
-+ */
-+ new_tp = probe->ftp_tps[index].fit_tp;
-+
-+ ASSERT(new_tp->ftt_pid == pid);
-+ ASSERT(new_tp->ftt_pc == pc);
-+ ASSERT(new_tp->ftt_proc == probe->ftp_prov->ftp_proc);
-+ ASSERT(new_tp->ftt_ids == NULL);
-+ ASSERT(new_tp->ftt_retids == NULL);
-+
-+ switch (id->fti_ptype) {
-+ case DTFTP_ENTRY:
-+ case DTFTP_OFFSETS:
-+ case DTFTP_IS_ENABLED:
-+ id->fti_next = NULL;
-+ new_tp->ftt_ids = id;
-+ break;
-+
-+ case DTFTP_RETURN:
-+ case DTFTP_POST_OFFSETS:
-+ id->fti_next = NULL;
-+ new_tp->ftt_retids = id;
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ }
-+
-+ goto again;
-+}
-+
-+static void fasttrap_tracepoint_disable(struct fasttrap_probe *probe,
-+ uint_t index)
-+{
-+ struct fasttrap_bucket *bucket;
-+ struct fasttrap_provider *prov = probe->ftp_prov;
-+ struct fasttrap_tracepoint **pp, *tp;
-+ struct fasttrap_id *id, **idp = NULL;
-+ pid_t pid;
-+ uintptr_t pc;
-+
-+ ASSERT(index < probe->ftp_ntps);
-+
-+ pid = probe->ftp_pid;
-+ pc = probe->ftp_tps[index].fit_tp->ftt_pc;
-+ id = &probe->ftp_tps[index].fit_id;
-+
-+ ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid);
-+
-+ /*
-+ * Find the tracepoint and make sure that our id is one of the
-+ * ones registered with it. Return probes are linked in their
-+ * own tracepoint, even though they share the (pi, pc) pair with
-+ * entry probes.
-+ */
-+ bucket = FASTTRAP_TPOINTS_ELEM(pid, pc);
-+ mutex_lock(&bucket->ftb_mtx);
-+ for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
-+ if (tp->ftt_pid != pid || tp->ftt_pc != pc ||
-+ tp->ftt_proc != prov->ftp_proc)
-+ continue;
-+
-+ if (id->fti_ptype == DTFTP_RETURN && tp->ftt_retids == NULL)
-+ continue;
-+
-+ if (id->fti_ptype != DTFTP_RETURN && tp->ftt_ids == NULL)
-+ continue;
-+
-+ break;
-+ }
-+
-+ /*
-+ * If we somehow lost this tracepoint, we are in trouble.
-+ */
-+ ASSERT(tp != NULL);
-+
-+ switch (id->fti_ptype) {
-+ case DTFTP_ENTRY:
-+ case DTFTP_OFFSETS:
-+ case DTFTP_IS_ENABLED:
-+ ASSERT(tp->ftt_ids != NULL);
-+ idp = &tp->ftt_ids;
-+ break;
-+
-+ case DTFTP_RETURN:
-+ case DTFTP_POST_OFFSETS:
-+ ASSERT(tp->ftt_retids != NULL);
-+ idp = &tp->ftt_retids;
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ }
-+
-+ while ((*idp)->fti_probe != probe) {
-+ idp = &(*idp)->fti_next;
-+ ASSERT(*idp != NULL);
-+ }
-+
-+ id = *idp;
-+ *idp = id->fti_next;
-+ dtrace_membar_producer();
-+
-+ ASSERT(id->fti_probe == probe);
-+
-+ /*
-+ * If there are other registered enablings of this tracepoint, we're
-+ * all done, but if this was the last probe assocated with this
-+ * this tracepoint, we need to remove and free it.
-+ */
-+ if (tp->ftt_ids != NULL || tp->ftt_retids != NULL) {
-+ /*
-+ * If the current probe's tracepoint is in use, swap it
-+ * for an unused tracepoint.
-+ */
-+ if (tp == probe->ftp_tps[index].fit_tp) {
-+ struct fasttrap_probe *tmp_probe;
-+ struct fasttrap_tracepoint **tmp_tp;
-+ uint_t tmp_index;
-+
-+ if (tp->ftt_ids != NULL) {
-+ tmp_probe = tp->ftt_ids->fti_probe;
-+ tmp_index = FASTTRAP_ID_INDEX(tp->ftt_ids);
-+ tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp;
-+ } else {
-+ tmp_probe = tp->ftt_retids->fti_probe;
-+ tmp_index = FASTTRAP_ID_INDEX(tp->ftt_retids);
-+ tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp;
-+ }
-+
-+ ASSERT(*tmp_tp != NULL);
-+ ASSERT(*tmp_tp != probe->ftp_tps[index].fit_tp);
-+ ASSERT((*tmp_tp)->ftt_ids == NULL);
-+ ASSERT((*tmp_tp)->ftt_retids == NULL);
-+
-+ probe->ftp_tps[index].fit_tp = *tmp_tp;
-+ *tmp_tp = tp;
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Tag the modified probe with the generation in which it was
-+ * changed.
-+ */
-+ probe->ftp_gen = fasttrap_mod_gen;
-+ return;
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ dtrace_tracepoint_disable(pid, &tp->ftt_mtp);
-+
-+ /*
-+ * Remove the probe from the hash table of active tracepoints.
-+ */
-+ mutex_lock(&bucket->ftb_mtx);
-+ pp = (struct fasttrap_tracepoint **)&bucket->ftb_data;
-+ ASSERT(*pp != NULL);
-+ while (*pp != tp) {
-+ pp = &(*pp)->ftt_next;
-+ ASSERT(*pp != NULL);
-+ }
-+
-+ *pp = tp->ftt_next;
-+ dtrace_membar_producer();
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Tag the modified probe with the generation in which it was changed.
-+ */
-+ probe->ftp_gen = fasttrap_mod_gen;
-+}
-+
-+static int fasttrap_pid_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fasttrap_probe *probe = parg;
-+ int i, rc;
-+
-+ ASSERT(probe != NULL);
-+ ASSERT(!probe->ftp_enabled);
-+ ASSERT(id == probe->ftp_id);
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+ /*
-+ * Increment the count of enabled probes on this probe's provider;
-+ * the provider can't go away while the probe still exists. We
-+ * must increment this even if we aren't able to properly enable
-+ * this probe.
-+ */
-+ mutex_lock(&probe->ftp_prov->ftp_mtx);
-+ probe->ftp_prov->ftp_rcount++;
-+ mutex_unlock(&probe->ftp_prov->ftp_mtx);
-+
-+ /*
-+ * If this probe's provider is retired (meaning it was valid in a
-+ * previously exec'ed incarnation of this address space), bail out. The
-+ * provider can't go away while we're in this code path.
-+ */
-+ if (probe->ftp_prov->ftp_retired)
-+ return 0;
-+
-+#ifdef FIXME
-+ /*
-+ * If we can't find the process, it may be that we're in the context of
-+ * a fork in which the traced process is being born and we're copying
-+ * USDT probes. Otherwise, the process is gone so bail.
-+ */
-+ p = sprlock(probe->ftp_pid);
-+ if (p == NULL) {
-+ if ((curproc->p_flag & SFORKING) == 0)
-+ return 0;
-+
-+ mutex_enter(&pidlock);
-+ p = prfind(probe->ftp_pid);
-+
-+ /*
-+ * Confirm that curproc is indeed forking the process in which
-+ * we're trying to enable probes.
-+ */
-+ ASSERT(p != NULL);
-+ ASSERT(p->p_parent == curproc);
-+ ASSERT(p->p_stat == SIDL);
-+
-+ mutex_enter(&p->p_lock);
-+ mutex_exit(&pidlock);
-+
-+ sprlock_proc(p);
-+ }
-+
-+ ASSERT(!(p->p_flag & SVFORK));
-+ mutex_exit(&p->p_lock);
-+#endif
-+
-+ /*
-+ * We have to enable the trap entry point before any user threads have
-+ * the chance to execute the trap instruction we're about to place
-+ * in their process's text.
-+ */
-+ fasttrap_enable_callbacks();
-+
-+ /*
-+ * Enable all the tracepoints and add this probe's id to each
-+ * tracepoint's list of active probes.
-+ */
-+ for (i = 0; i < probe->ftp_ntps; i++) {
-+ rc = fasttrap_tracepoint_enable(probe, i);
-+ if (rc != 0) {
-+ /*
-+ * If enabling the tracepoint failed completely,
-+ * we don't have to disable it; if the failure
-+ * was only partial we must disable it.
-+ */
-+ if (rc == FASTTRAP_ENABLE_FAIL)
-+ i--;
-+ else
-+ ASSERT(rc == FASTTRAP_ENABLE_PARTIAL);
-+
-+ /*
-+ * Back up and pull out all the tracepoints we've
-+ * created so far for this probe.
-+ */
-+ while (i >= 0) {
-+ fasttrap_tracepoint_disable(probe, i);
-+ i--;
-+ }
-+
-+#ifdef FIXME
-+ mutex_enter(&p->p_lock);
-+ sprunlock(p);
-+#endif
-+
-+ /*
-+ * Since we're not actually enabling this probe,
-+ * drop our reference on the trap table entry.
-+ */
-+ fasttrap_disable_callbacks();
-+ return 0;
-+ }
-+ }
-+
-+#ifdef FIXME
-+ mutex_enter(&p->p_lock);
-+ sprunlock(p);
-+#endif
-+
-+ probe->ftp_enabled = 1;
-+ return 0;
-+}
-+
-+static void fasttrap_pid_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fasttrap_probe *probe = parg;
-+ struct fasttrap_provider *prov = probe->ftp_prov;
-+ int i, whack = 0;
-+
-+ ASSERT(id == probe->ftp_id);
-+
-+ mutex_lock(&prov->ftp_mtx);
-+
-+ /*
-+ * Disable all the associated tracepoints (for fully enabled probes).
-+ */
-+ if (probe->ftp_enabled) {
-+ for (i = 0; i < probe->ftp_ntps; i++)
-+ fasttrap_tracepoint_disable(probe, i);
-+ }
-+
-+ ASSERT(prov->ftp_rcount > 0);
-+ prov->ftp_rcount--;
-+
-+ if ((prov->ftp_retired || prov->ftp_rcount == 0) && !prov->ftp_marked)
-+ whack = prov->ftp_marked = 1;
-+
-+ mutex_unlock(&prov->ftp_mtx);
-+
-+ if (whack)
-+ fasttrap_pid_cleanup();
-+
-+ if (!probe->ftp_enabled)
-+ return;
-+
-+ probe->ftp_enabled = 0;
-+
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+ fasttrap_disable_callbacks();
-+}
-+
-+static void fasttrap_pid_getargdesc(void *arg, dtrace_id_t id, void *parg,
-+ struct dtrace_argdesc *desc)
-+{
-+ struct fasttrap_probe *probe = parg;
-+ char *str;
-+ int i, ndx;
-+
-+ desc->dtargd_native[0] = '\0';
-+ desc->dtargd_xlate[0] = '\0';
-+
-+ if (probe->ftp_prov->ftp_retired != 0 ||
-+ desc->dtargd_ndx >= probe->ftp_nargs) {
-+ desc->dtargd_ndx = DTRACE_ARGNONE;
-+ return;
-+ }
-+
-+ ndx = (probe->ftp_argmap != NULL) ? probe->ftp_argmap[desc->dtargd_ndx]
-+ : desc->dtargd_ndx;
-+
-+ str = probe->ftp_ntypes;
-+ for (i = 0; i < ndx; i++)
-+ str += strlen(str) + 1;
-+
-+ ASSERT(strlen(str + 1) < sizeof(desc->dtargd_native));
-+ strcpy(desc->dtargd_native, str);
-+
-+ if (probe->ftp_xtypes == NULL)
-+ return;
-+
-+ str = probe->ftp_xtypes;
-+ for (i = 0; i < desc->dtargd_ndx; i++)
-+ str += strlen(str) + 1;
-+
-+ ASSERT(strlen(str + 1) < sizeof(desc->dtargd_xlate));
-+ strcpy(desc->dtargd_xlate, str);
-+}
-+
-+static void fasttrap_pid_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fasttrap_probe *probe = parg;
-+ int i;
-+
-+ ASSERT(probe != NULL);
-+ ASSERT(!probe->ftp_enabled);
-+ ASSERT(atomic_read(&fasttrap_total) >= probe->ftp_ntps);
-+
-+ atomic_add(-probe->ftp_ntps, &fasttrap_total);
-+
-+ if (probe->ftp_gen + 1 >= fasttrap_mod_gen)
-+ fasttrap_mod_barrier(probe->ftp_gen);
-+
-+ for (i = 0; i < probe->ftp_ntps; i++)
-+ kmem_cache_free(tracepoint_cachep, probe->ftp_tps[i].fit_tp);
-+
-+ kfree(probe);
-+}
-+
-+static const struct dtrace_pattr pid_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+};
-+
-+static struct dtrace_pops pid_pops = {
-+ .dtps_provide = fasttrap_pid_provide,
-+ .dtps_provide_module = NULL,
-+ .dtps_destroy_module = NULL,
-+ .dtps_enable = fasttrap_pid_enable,
-+ .dtps_disable = fasttrap_pid_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = fasttrap_pid_getargdesc,
-+ .dtps_getargval = fasttrap_pid_getarg,
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = fasttrap_pid_destroy
-+};
-+
-+static struct dtrace_pops usdt_pops = {
-+ .dtps_provide = fasttrap_pid_provide,
-+ .dtps_provide_module = NULL,
-+ .dtps_destroy_module = NULL,
-+ .dtps_enable = fasttrap_pid_enable,
-+ .dtps_disable = fasttrap_pid_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = fasttrap_pid_getargdesc,
-+ .dtps_getargval = fasttrap_usdt_getarg,
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = fasttrap_pid_destroy
-+};
-+
-+static uint_t fasttrap_hash_str(const char *p)
-+{
-+ unsigned int g;
-+ uint_t hval = 0;
-+
-+ while (*p) {
-+ hval = (hval << 4) + *p++;
-+ g = hval & 0xf0000000;
-+ if (g != 0)
-+ hval ^= g >> 24;
-+ hval &= ~g;
-+ }
-+
-+ return hval;
-+}
-+
-+static int fasttrap_uint32_cmp(const void *ap, const void *bp)
-+{
-+ return (*(const uint32_t *)ap - *(const uint32_t *)bp);
-+}
-+
-+void fasttrap_meta_create_probe(void *arg, void *parg,
-+ struct dtrace_helper_probedesc *dhpb)
-+{
-+ struct fasttrap_provider *provider = parg;
-+ struct fasttrap_probe *pp;
-+ struct fasttrap_tracepoint *tp;
-+ int i, j;
-+ uint32_t ntps;
-+
-+ /*
-+ * Since the meta provider count is non-zero we don't have to worry
-+ * about this provider disappearing.
-+ */
-+ ASSERT(provider->ftp_mcount > 0);
-+
-+ /*
-+ * The offsets must be unique.
-+ */
-+ sort(dhpb->dthpb_offs, dhpb->dthpb_noffs, sizeof(uint32_t),
-+ fasttrap_uint32_cmp, NULL);
-+ for (i = 1; i < dhpb->dthpb_noffs; i++) {
-+ if (dhpb->dthpb_base + dhpb->dthpb_offs[i] <=
-+ dhpb->dthpb_base + dhpb->dthpb_offs[i - 1])
-+ return;
-+ }
-+
-+ sort(dhpb->dthpb_enoffs, dhpb->dthpb_nenoffs, sizeof(uint32_t),
-+ fasttrap_uint32_cmp, NULL);
-+ for (i = 1; i < dhpb->dthpb_nenoffs; i++) {
-+ if (dhpb->dthpb_base + dhpb->dthpb_enoffs[i] <=
-+ dhpb->dthpb_base + dhpb->dthpb_enoffs[i - 1])
-+ return;
-+ }
-+
-+ /*
-+ * Grab the creation lock to ensure consistency between calls to
-+ * dtrace_probe_lookup() and dtrace_probe_create() in the face of
-+ * other threads creating probes.
-+ */
-+ mutex_lock(&provider->ftp_cmtx);
-+
-+ if (dtrace_probe_lookup(provider->ftp_provid, dhpb->dthpb_mod,
-+ dhpb->dthpb_func, dhpb->dthpb_name) != DTRACE_IDNONE) {
-+ mutex_unlock(&provider->ftp_cmtx);
-+ return;
-+ }
-+
-+ ntps = dhpb->dthpb_noffs + dhpb->dthpb_nenoffs;
-+ ASSERT(ntps > 0);
-+
-+ pp = kzalloc(offsetof(struct fasttrap_probe, ftp_tps[ntps]),
-+ GFP_KERNEL);
-+ if (pp == NULL) {
-+ pr_warn("Unable to create probe %s: out of memory\n",
-+ dhpb->dthpb_name);
-+ mutex_unlock(&provider->ftp_cmtx);
-+ return;
-+ }
-+
-+ atomic_add(ntps, &fasttrap_total);
-+ if (atomic_read(&fasttrap_total) > fasttrap_max) {
-+ kfree(pp);
-+ atomic_add(-ntps, &fasttrap_total);
-+ mutex_unlock(&provider->ftp_cmtx);
-+ return;
-+ }
-+
-+ pp->ftp_prov = provider;
-+ pp->ftp_pid = provider->ftp_pid;
-+ pp->ftp_ntps = ntps;
-+ pp->ftp_nargs = dhpb->dthpb_xargc;
-+ pp->ftp_xtypes = dhpb->dthpb_xtypes;
-+ pp->ftp_ntypes = dhpb->dthpb_ntypes;
-+
-+ /*
-+ * First create a tracepoint for each actual point of interest.
-+ */
-+ for (i = 0; i < dhpb->dthpb_noffs; i++) {
-+ tp = kmem_cache_alloc(tracepoint_cachep, GFP_KERNEL);
-+ if (tp == NULL)
-+ goto fail;
-+
-+ tp->ftt_proc = provider->ftp_proc;
-+ tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_offs[i];
-+ tp->ftt_pid = provider->ftp_pid;
-+ memset(&tp->ftt_mtp, 0, sizeof(struct fasttrap_machtp));
-+ tp->ftt_ids = NULL;
-+ tp->ftt_retids = NULL;
-+ tp->ftt_next = NULL;
-+
-+ dt_dbg_dof(" Tracepoint at 0x%lx (0x%llx + 0x%x)\n",
-+ tp->ftt_pc, dhpb->dthpb_base, dhpb->dthpb_offs[i]);
-+
-+ pp->ftp_tps[i].fit_tp = tp;
-+ pp->ftp_tps[i].fit_id.fti_probe = pp;
-+ pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_OFFSETS;
-+ }
-+
-+ /*
-+ * Then create a tracepoint for each is-enabled point.
-+ */
-+ for (j = 0; i < ntps; i++, j++) {
-+ tp = kmem_cache_alloc(tracepoint_cachep, GFP_KERNEL);
-+ if (tp == NULL)
-+ goto fail;
-+
-+ tp->ftt_proc = provider->ftp_proc;
-+ tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_enoffs[j];
-+ tp->ftt_pid = provider->ftp_pid;
-+ memset(&tp->ftt_mtp, 0, sizeof(struct fasttrap_machtp));
-+ tp->ftt_ids = NULL;
-+ tp->ftt_retids = NULL;
-+ tp->ftt_next = NULL;
-+
-+ pp->ftp_tps[i].fit_tp = tp;
-+ pp->ftp_tps[i].fit_id.fti_probe = pp;
-+ pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_IS_ENABLED;
-+ }
-+
-+ /*
-+ * If the arguments are shuffled around we set the argument remapping
-+ * table. Later, when the probe fires, we only remap the arguments
-+ * if the table is non-NULL.
-+ */
-+ for (i = 0; i < dhpb->dthpb_xargc; i++) {
-+ if (dhpb->dthpb_args[i] != i) {
-+ pp->ftp_argmap = dhpb->dthpb_args;
-+ break;
-+ }
-+ }
-+
-+ /*
-+ * The probe is fully constructed -- register it with DTrace.
-+ */
-+ pp->ftp_id = dtrace_probe_create(provider->ftp_provid, dhpb->dthpb_mod,
-+ dhpb->dthpb_func, dhpb->dthpb_name,
-+ FASTTRAP_OFFSET_AFRAMES, pp);
-+ if (pp->ftp_id == DTRACE_IDNONE)
-+ goto fail;
-+
-+ mutex_unlock(&provider->ftp_cmtx);
-+ return;
-+
-+fail:
-+ pr_warn("Unable to create probe %s: out of memory\n",
-+ dhpb->dthpb_name);
-+
-+ for (i = 0; i < ntps; i++)
-+ kmem_cache_free(tracepoint_cachep, pp->ftp_tps[i].fit_tp);
-+
-+ kfree(pp);
-+ atomic_add(-ntps, &fasttrap_total);
-+ mutex_unlock(&provider->ftp_cmtx);
-+}
-+
-+static void fasttrap_proc_release(struct fasttrap_proc *proc)
-+{
-+ struct fasttrap_bucket *bucket;
-+ struct fasttrap_proc *fprc, **fprcp;
-+ pid_t pid = proc->ftpc_pid;
-+
-+ mutex_lock(&proc->ftpc_mtx);
-+
-+ ASSERT(proc->ftpc_rcount != 0);
-+ ASSERT(atomic64_read(&proc->ftpc_acount) <= proc->ftpc_rcount);
-+
-+ if (--proc->ftpc_rcount != 0) {
-+ mutex_unlock(&proc->ftpc_mtx);
-+ return;
-+ }
-+
-+ mutex_unlock(&proc->ftpc_mtx);
-+
-+ /*
-+ * There should definitely be no live providers associated with this
-+ * process at this point.
-+ */
-+ ASSERT(atomic64_read(&proc->ftpc_acount) == 0);
-+
-+ bucket = FASTTRAP_PROCS_ELEM(pid);
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ fprcp = (struct fasttrap_proc **)&bucket->ftb_data;
-+ while ((fprc = *fprcp) != NULL) {
-+ if (fprc == proc)
-+ break;
-+
-+ fprcp = &fprc->ftpc_next;
-+ }
-+
-+ /*
-+ * Something strange has happened if we can't find the proc.
-+ */
-+ ASSERT(fprc != NULL);
-+
-+ *fprcp = fprc->ftpc_next;
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ kfree(fprc);
-+}
-+
-+static void fasttrap_provider_free(struct fasttrap_provider *provider)
-+{
-+ pid_t pid = provider->ftp_pid;
-+
-+ /*
-+ * There need to be no associated enabled probes, no consumers
-+ * creating probes, and no meta providers referencing this provider.
-+ */
-+ ASSERT(provider->ftp_rcount == 0);
-+ ASSERT(provider->ftp_ccount == 0);
-+ ASSERT(provider->ftp_mcount == 0);
-+
-+ /*
-+ * If this provider hasn't been retired, we need to explicitly drop the
-+ * count of active providers on the associated process structure.
-+ */
-+ if (!provider->ftp_retired) {
-+ atomic64_add(-1, &provider->ftp_proc->ftpc_acount);
-+ ASSERT(atomic64_read(&provider->ftp_proc->ftpc_acount) <
-+ provider->ftp_proc->ftpc_rcount);
-+ }
-+
-+ fasttrap_proc_release(provider->ftp_proc);
-+
-+ kfree(provider);
-+
-+ unregister_pid_provider(pid);
-+}
-+
-+static struct fasttrap_proc *fasttrap_proc_lookup(pid_t pid)
-+{
-+ struct fasttrap_bucket *bucket;
-+ struct fasttrap_proc *fprc, *new_fprc;
-+
-+ bucket = FASTTRAP_PROCS_ELEM(pid);
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) {
-+ if (fprc->ftpc_pid == pid &&
-+ atomic64_read(&fprc->ftpc_acount) != 0) {
-+ mutex_lock(&fprc->ftpc_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+ fprc->ftpc_rcount++;
-+ atomic64_inc(&fprc->ftpc_acount);
-+ ASSERT(atomic64_read(&fprc->ftpc_acount) <=
-+ fprc->ftpc_rcount);
-+ mutex_unlock(&fprc->ftpc_mtx);
-+
-+ return fprc;
-+ }
-+ }
-+
-+ /*
-+ * Drop the bucket lock so we don't try to perform a sleeping
-+ * allocation under it.
-+ */
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ new_fprc = kzalloc(sizeof(struct fasttrap_proc), GFP_KERNEL);
-+ if (new_fprc == NULL)
-+ return NULL;
-+
-+ new_fprc->ftpc_pid = pid;
-+ new_fprc->ftpc_rcount = 1;
-+ atomic64_set(&new_fprc->ftpc_acount, 1);
-+ mutex_init(&new_fprc->ftpc_mtx);
-+
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Take another lap through the list to make sure a proc hasn't
-+ * been created for this pid while we weren't under the bucket lock.
-+ */
-+ for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) {
-+ if (fprc->ftpc_pid == pid &&
-+ atomic64_read(&fprc->ftpc_acount) != 0) {
-+ mutex_lock(&fprc->ftpc_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+ fprc->ftpc_rcount++;
-+ atomic64_inc(&fprc->ftpc_acount);
-+ ASSERT(atomic64_read(&fprc->ftpc_acount) <=
-+ fprc->ftpc_rcount);
-+ mutex_unlock(&fprc->ftpc_mtx);
-+
-+ kfree(new_fprc);
-+
-+ return fprc;
-+ }
-+ }
-+
-+ new_fprc->ftpc_next = bucket->ftb_data;
-+ bucket->ftb_data = new_fprc;
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ return new_fprc;
-+}
-+
-+/*
-+ * Lookup a fasttrap-managed provider based on its name and associated pid.
-+ * If the pattr argument is non-NULL, this function instantiates the provider
-+ * if it doesn't exist otherwise it returns NULL. The provider is returned
-+ * with its lock held.
-+ */
-+static struct fasttrap_provider *
-+fasttrap_provider_lookup(pid_t pid, const char *name,
-+ const struct dtrace_pattr *pa)
-+{
-+ struct fasttrap_provider *fp, *new_fp = NULL;
-+ struct fasttrap_proc *proc = NULL;
-+ struct fasttrap_bucket *bucket;
-+ char provname[DTRACE_PROVNAMELEN];
-+ struct task_struct *p;
-+ const struct cred *cred = NULL;
-+
-+ ASSERT(strlen(name) < sizeof(fp->ftp_name));
-+ ASSERT(pa != NULL);
-+
-+ bucket = FASTTRAP_PROVS_ELEM(pid, name);
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Take a lap through the list and return the match if we find it.
-+ */
-+ for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
-+ if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
-+ !fp->ftp_retired) {
-+ mutex_lock(&fp->ftp_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ return fp;
-+ }
-+ }
-+
-+ /*
-+ * Drop the bucket lock so we don't try to perform a sleeping
-+ * allocation under it.
-+ */
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ p = register_pid_provider(pid);
-+ if (p == NULL)
-+ goto fail;
-+
-+ /*
-+ * Grab the credentials for this process so we have
-+ * something to pass to dtrace_register().
-+ */
-+ cred = get_cred(p->cred);
-+
-+ proc = fasttrap_proc_lookup(pid);
-+ if (proc == NULL)
-+ goto fail;
-+
-+ new_fp = kzalloc(sizeof(struct fasttrap_provider), GFP_KERNEL);
-+ if (new_fp == NULL)
-+ goto fail;
-+
-+ new_fp->ftp_pid = pid;
-+ new_fp->ftp_proc = proc;
-+ mutex_init(&new_fp->ftp_mtx);
-+ mutex_init(&new_fp->ftp_cmtx);
-+
-+ ASSERT(new_fp->ftp_proc != NULL);
-+
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Take another lap through the list to make sure a provider hasn't
-+ * been created for this pid while we weren't under the bucket lock.
-+ */
-+ for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
-+ if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
-+ !fp->ftp_retired) {
-+ mutex_lock(&fp->ftp_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+ fasttrap_provider_free(new_fp);
-+ put_cred(cred);
-+
-+ return fp;
-+ }
-+ }
-+
-+ strcpy(new_fp->ftp_name, name);
-+
-+ /*
-+ * Fail and return NULL if either the provider name is too long
-+ * or we fail to register this new provider with the DTrace
-+ * framework. Note that this is the only place we ever construct
-+ * the full provider name -- we keep it in pieces in the provider
-+ * structure.
-+ */
-+ if (snprintf(provname, sizeof(provname), "%s%u", name, (uint_t)pid) >=
-+ sizeof(provname) ||
-+ dtrace_register(provname, pa,
-+ DTRACE_PRIV_PROC | DTRACE_PRIV_OWNER, cred,
-+ pa == &pid_attr ? &pid_pops : &usdt_pops,
-+ new_fp, &new_fp->ftp_provid) != 0) {
-+ mutex_unlock(&bucket->ftb_mtx);
-+ fasttrap_provider_free(new_fp);
-+ put_cred(cred);
-+ return NULL;
-+ }
-+
-+ new_fp->ftp_next = bucket->ftb_data;
-+ bucket->ftb_data = new_fp;
-+
-+ mutex_lock(&new_fp->ftp_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ put_cred(cred);
-+
-+ return new_fp;
-+
-+fail:
-+ if (proc)
-+ fasttrap_proc_release(proc);
-+ if (cred)
-+ put_cred(cred);
-+ if (p)
-+ unregister_pid_provider(pid);
-+
-+ return NULL;
-+}
-+
-+void *fasttrap_meta_provide(void *arg, struct dtrace_helper_provdesc *dhpv,
-+ pid_t pid)
-+{
-+ struct fasttrap_provider *provider;
-+
-+ if (strlen(dhpv->dthpv_provname) + 10 >= sizeof(provider->ftp_name)) {
-+ pr_warn("Failed to instantiate provider %s: name too long "
-+ "to accommodate pid\n", dhpv->dthpv_provname);
-+ return NULL;
-+ }
-+
-+ /*
-+ * Don't let folks spoof the true pid provider.
-+ */
-+ if (strcmp(dhpv->dthpv_provname, FASTTRAP_PID_NAME) == 0) {
-+ pr_warn("Failed to instantiate provider %s: %s is an invalid "
-+ "name\n", dhpv->dthpv_provname, FASTTRAP_PID_NAME);
-+ return NULL;
-+ }
-+
-+ /*
-+ * The highest stability class that fasttrap supports is ISA; cap
-+ * the stability of the new provider accordingly.
-+ */
-+ if (dhpv->dthpv_pattr.dtpa_provider.dtat_class > DTRACE_CLASS_ISA)
-+ dhpv->dthpv_pattr.dtpa_provider.dtat_class = DTRACE_CLASS_ISA;
-+ if (dhpv->dthpv_pattr.dtpa_mod.dtat_class > DTRACE_CLASS_ISA)
-+ dhpv->dthpv_pattr.dtpa_mod.dtat_class = DTRACE_CLASS_ISA;
-+ if (dhpv->dthpv_pattr.dtpa_func.dtat_class > DTRACE_CLASS_ISA)
-+ dhpv->dthpv_pattr.dtpa_func.dtat_class = DTRACE_CLASS_ISA;
-+ if (dhpv->dthpv_pattr.dtpa_name.dtat_class > DTRACE_CLASS_ISA)
-+ dhpv->dthpv_pattr.dtpa_name.dtat_class = DTRACE_CLASS_ISA;
-+ if (dhpv->dthpv_pattr.dtpa_args.dtat_class > DTRACE_CLASS_ISA)
-+ dhpv->dthpv_pattr.dtpa_args.dtat_class = DTRACE_CLASS_ISA;
-+
-+ provider = fasttrap_provider_lookup(pid, dhpv->dthpv_provname,
-+ &dhpv->dthpv_pattr);
-+ if (provider == NULL) {
-+ pr_warn("Failed to instantiate provider %s for process %u\n",
-+ dhpv->dthpv_provname, (uint_t)pid);
-+ return NULL;
-+ }
-+
-+ /*
-+ * Up the meta provider count so this provider isn't removed until the
-+ * meta provider has been told to remove it.
-+ */
-+ provider->ftp_mcount++;
-+
-+ mutex_unlock(&provider->ftp_mtx);
-+
-+ return provider;
-+}
-+
-+static void fasttrap_pid_cleanup_cb(struct work_struct *work)
-+{
-+ struct fasttrap_provider **fpp, *fp;
-+ struct fasttrap_bucket *bucket;
-+ dtrace_provider_id_t provid;
-+ int i, later = 0;
-+
-+ static volatile int in;
-+
-+ ASSERT(in == 0);
-+ in = 1;
-+
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ if (!fasttrap_cleanup_work && fasttrap_cleanup_state == CLEANUP_NONE) {
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+ in = 0;
-+ return;
-+ }
-+
-+ dt_dbg_prov("Fasttrap provider cleanup callback processing...\n");
-+ while (fasttrap_cleanup_work) {
-+ fasttrap_cleanup_work = 0;
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+
-+ later = 0;
-+
-+ /*
-+ * Iterate over all the providers trying to remove the marked
-+ * ones. If a provider is marked but not retired, we just
-+ * have to take a crack at removing it -- it's no big deal if
-+ * we can't.
-+ */
-+ for (i = 0; i < fasttrap_provs.fth_nent; i++) {
-+ bucket = FASTTRAP_ELEM_BUCKET(&fasttrap_provs.fth_table[i]);
-+ mutex_lock(&bucket->ftb_mtx);
-+ fpp = (struct fasttrap_provider **)&bucket->ftb_data;
-+
-+ while ((fp = *fpp) != NULL) {
-+ dt_dbg_prov(" Trying to unregister %s%d "
-+ "(%smarked)\n",
-+ fp->ftp_name, fp->ftp_pid,
-+ fp->ftp_marked ? "not " : "");
-+ if (!fp->ftp_marked) {
-+ fpp = &fp->ftp_next;
-+ continue;
-+ }
-+
-+ dt_dbg_prov(" ccount %llu, mcount %llu "
-+ "rcount %llu, %sretired, "
-+ "%smarked\n",
-+ fp->ftp_ccount, fp->ftp_mcount,
-+ fp->ftp_rcount,
-+ fp->ftp_retired ? "" : "not ",
-+ fp->ftp_marked ? "" : "not ");
-+
-+ mutex_lock(&fp->ftp_mtx);
-+
-+ /*
-+ * If this provider has consumers actively
-+ * creating probes (ftp_ccount) or is a USDT
-+ * provider (ftp_mcount), we can't unregister
-+ * or even condense.
-+ */
-+ if (fp->ftp_ccount != 0 ||
-+ fp->ftp_mcount != 0) {
-+ mutex_unlock(&fp->ftp_mtx);
-+ fp->ftp_marked = 0;
-+ continue;
-+ }
-+
-+ if (!fp->ftp_retired || fp->ftp_rcount != 0)
-+ fp->ftp_marked = 0;
-+
-+ mutex_unlock(&fp->ftp_mtx);
-+
-+ /*
-+ * If we successfully unregister this
-+ * provider we can remove it from the hash
-+ * chain and free the memory. If our attempt
-+ * to unregister fails and this is a retired
-+ * provider, increment our flag to try again
-+ * pretty soon. If we've consumed more than
-+ * half of our total permitted number of
-+ * probes call dtrace_condense() to try to
-+ * clean out the unenabled probes.
-+ */
-+ provid = fp->ftp_provid;
-+ mutex_lock(&module_mutex);
-+ if (dtrace_unregister(provid) != 0) {
-+ if (atomic_read(&fasttrap_total) >
-+ fasttrap_max / 2)
-+ dtrace_condense(provid);
-+
-+ later += fp->ftp_marked;
-+ fpp = &fp->ftp_next;
-+ } else {
-+ *fpp = fp->ftp_next;
-+ fasttrap_provider_free(fp);
-+ }
-+ mutex_unlock(&module_mutex);
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+ }
-+
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ }
-+
-+ ASSERT(fasttrap_cleanup_state != CLEANUP_NONE);
-+
-+ /*
-+ * If we were unable to remove a retired provider, try again after
-+ * a second. This situation can occur in certain circumstances where
-+ * providers cannot be unregistered even though they have no probes
-+ * enabled because of an execution of dtrace -l or something similar.
-+ * If the timeout has been disabled (set to 1 because we're trying
-+ * to detach), we set fasttrap_cleanup_work to ensure that we'll
-+ * get a chance to do that work if and when the timeout is reenabled
-+ * (if detach fails).
-+ */
-+ if (later > 0) {
-+ dt_dbg_prov(" Some providers were not removed "
-+ " (state %d, later = %d)\n",
-+ fasttrap_cleanup_state, later);
-+ if (fasttrap_cleanup_state == CLEANUP_DEFERRED)
-+ fasttrap_cleanup_work = 1;
-+ else {
-+ struct delayed_work *dw = container_of(
-+ work,
-+ struct delayed_work,
-+ work);
-+
-+ fasttrap_cleanup_state = CLEANUP_SCHEDULED;
-+ schedule_delayed_work(dw, HZ);
-+ }
-+ } else
-+ fasttrap_cleanup_state = CLEANUP_NONE;
-+
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+ in = 0;
-+
-+ dt_dbg_prov("Fasttrap provider cleanup callback done\n");
-+}
-+
-+static DECLARE_DELAYED_WORK(fasttrap_cleanup, fasttrap_pid_cleanup_cb);
-+
-+/*
-+ * Activate the asynchronous cleanup mechanism.
-+ */
-+static void fasttrap_pid_cleanup(void)
-+{
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ fasttrap_cleanup_work = 1;
-+ fasttrap_cleanup_state = CLEANUP_SCHEDULED;
-+ schedule_delayed_work(&fasttrap_cleanup, 3);
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+}
-+
-+void fasttrap_provider_retire(pid_t pid, const char *name, int mprov)
-+{
-+ struct fasttrap_provider *fp;
-+ struct fasttrap_bucket *bucket;
-+ dtrace_provider_id_t provid;
-+
-+ ASSERT(strlen(name) < sizeof(fp->ftp_name));
-+
-+ dt_dbg_prov("Retiring %s %sprovider for PID %d\n",
-+ name, mprov ? "meta-" : "", pid);
-+
-+ bucket = FASTTRAP_PROVS_ELEM(pid, name);
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
-+ if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
-+ !fp->ftp_retired)
-+ break;
-+ }
-+
-+ if (fp == NULL) {
-+ mutex_unlock(&bucket->ftb_mtx);
-+ return;
-+ }
-+
-+ mutex_lock(&fp->ftp_mtx);
-+ ASSERT(!mprov || fp->ftp_mcount > 0);
-+ if (mprov && --fp->ftp_mcount != 0) {
-+ mutex_unlock(&fp->ftp_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+ return;
-+ }
-+
-+ /*
-+ * Mark the provider to be removed in our post-processing step, mark it
-+ * retired, and drop the active count on its proc. Marking it indicates
-+ * that we should try to remove it; setting the retired flag indicates
-+ * that we're done with this provider; dropping the active count on the
-+ * proc releases our hold, and when this reaches zero (as it will
-+ * during exit or exec) the proc and associated providers become
-+ * defunct.
-+ *
-+ * We obviously need to take the bucket lock before the provider lock
-+ * to perform the lookup, but we need to drop the provider lock
-+ * before calling into the DTrace framework since we acquire the
-+ * provider lock in callbacks invoked from the DTrace framework. The
-+ * bucket lock therefore protects the integrity of the provider hash
-+ * table.
-+ */
-+ atomic64_dec(&fp->ftp_proc->ftpc_acount);
-+ ASSERT(atomic64_read(&fp->ftp_proc->ftpc_acount) <
-+ fp->ftp_proc->ftpc_rcount);
-+
-+ fp->ftp_retired = 1;
-+ fp->ftp_marked = 1;
-+ provid = fp->ftp_provid;
-+ mutex_unlock(&fp->ftp_mtx);
-+
-+ /*
-+ * We don't have to worry about invalidating the same provider twice
-+ * since fasttrap_provider_lookup() will ignore provider that have
-+ * been marked as retired.
-+ */
-+ dtrace_invalidate(provid);
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ fasttrap_pid_cleanup();
-+}
-+
-+static void fasttrap_probes_cleanup(struct task_struct *tsk)
-+{
-+ fasttrap_provider_retire(tsk->pid, FASTTRAP_PID_NAME, 0);
-+}
-+
-+void fasttrap_meta_remove(void *arg, struct dtrace_helper_provdesc *dhpv,
-+ pid_t pid)
-+{
-+ /*
-+ * Clean up the USDT provider. There may be active consumers of the
-+ * provider busy adding probes, no damage will actually befall the
-+ * provider until that count has dropped to zero. This just puts
-+ * the provider on death row.
-+ */
-+ fasttrap_provider_retire(pid, dhpv->dthpv_provname, 1);
-+}
-+
-+static int fasttrap_add_probe(struct fasttrap_probe_spec *probe)
-+{
-+ struct fasttrap_provider *provider;
-+ struct fasttrap_probe *pp;
-+ struct fasttrap_tracepoint *tp;
-+ uint64_t *offs = NULL;
-+ uint64_t noffs;
-+ char *name;
-+ int aframes, retired;
-+
-+ switch (probe->ftps_type) {
-+ case DTFTP_ENTRY:
-+ name = "entry";
-+ aframes = FASTTRAP_ENTRY_AFRAMES;
-+ break;
-+ case DTFTP_RETURN:
-+ name = "return";
-+ aframes = FASTTRAP_RETURN_AFRAMES;
-+ break;
-+ case DTFTP_OFFSETS:
-+ if (probe->ftps_glen <= 0)
-+ return -EINVAL;
-+
-+ name = "<offsets>";
-+ aframes = FASTTRAP_OFFSET_AFRAMES;
-+ offs = fasttrap_glob_offsets(probe, &noffs);
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ provider = fasttrap_provider_lookup(probe->ftps_pid, FASTTRAP_PID_NAME,
-+ &pid_attr);
-+ if (provider == NULL)
-+ return -ESRCH;
-+
-+ /*
-+ * Increment the consumer reference count on the provider to indicate
-+ * that a new probe is being associated with the provider. This makes
-+ * sure that the provider will not be removed while we are working with
-+ * it.
-+ *
-+ * This also means that we can drop the provider lock.
-+ */
-+ provider->ftp_ccount++;
-+ mutex_unlock(&provider->ftp_mtx);
-+
-+ /*
-+ * Grab the probe creation lock for this provider to ensure consistency
-+ * between dtrace_probe_lookup() and dtrace_probe_create() because
-+ * other threads might be creating probes also.
-+ */
-+ mutex_lock(&provider->ftp_cmtx);
-+
-+ if (probe->ftps_type == DTFTP_OFFSETS) {
-+ int i;
-+
-+ for (i = 0; i < noffs; i++) {
-+ char ostr[sizeof(*offs) + 1];
-+
-+ snprintf(ostr, sizeof(ostr), "%llx", offs[i]);
-+ if (dtrace_probe_lookup(provider->ftp_provid,
-+ probe->ftps_mod,
-+ probe->ftps_func, ostr) != 0)
-+ continue;
-+
-+ atomic_add(1, &fasttrap_total);
-+ if (atomic_read(&fasttrap_total) > fasttrap_max)
-+ goto fail_reset;
-+
-+ pp = kzalloc(sizeof(struct fasttrap_probe), GFP_KERNEL);
-+ if (pp == NULL)
-+ goto fail_reset;
-+
-+ pp->ftp_prov = provider;
-+ pp->ftp_pid = provider->ftp_pid;
-+ pp->ftp_ntps = 1;
-+
-+ tp = kmem_cache_alloc(tracepoint_cachep, GFP_KERNEL);
-+ if (tp == NULL)
-+ goto fail_reset;
-+
-+ tp->ftt_proc = provider->ftp_proc;
-+ tp->ftt_pc = probe->ftps_pc + offs[i];
-+ tp->ftt_pid = provider->ftp_pid;
-+ memset(&tp->ftt_mtp, 0,
-+ sizeof(struct fasttrap_machtp));
-+ tp->ftt_ids = NULL;
-+ tp->ftt_retids = NULL;
-+ tp->ftt_next = NULL;
-+
-+ pp->ftp_tps[0].fit_tp = tp;
-+ pp->ftp_tps[0].fit_id.fti_probe = pp;
-+ pp->ftp_tps[0].fit_id.fti_ptype = probe->ftps_type;
-+
-+ pp->ftp_id = dtrace_probe_create(provider->ftp_provid,
-+ probe->ftps_mod,
-+ probe->ftps_func, ostr,
-+ aframes, pp);
-+ if (pp->ftp_id == DTRACE_IDNONE) {
-+ kmem_cache_free(tracepoint_cachep, tp);
-+ kfree(pp);
-+
-+ goto fail_reset;
-+ }
-+ }
-+ } else if (dtrace_probe_lookup(provider->ftp_provid, probe->ftps_mod,
-+ probe->ftps_func, name) == 0) {
-+ atomic_add(1, &fasttrap_total);
-+ if (atomic_read(&fasttrap_total) > fasttrap_max)
-+ goto fail_reset;
-+
-+ pp = kzalloc(sizeof(struct fasttrap_probe), GFP_KERNEL);
-+ if (pp == NULL)
-+ goto fail_reset;
-+
-+ pp->ftp_prov = provider;
-+ pp->ftp_pid = provider->ftp_pid;
-+ pp->ftp_ntps = 1;
-+
-+ tp = kmem_cache_alloc(tracepoint_cachep, GFP_KERNEL);
-+ if (tp == NULL)
-+ goto fail_reset;
-+
-+ tp->ftt_proc = provider->ftp_proc;
-+ tp->ftt_pc = probe->ftps_pc;
-+ tp->ftt_pid = provider->ftp_pid;
-+ memset(&tp->ftt_mtp, 0, sizeof(struct fasttrap_machtp));
-+ tp->ftt_ids = NULL;
-+ tp->ftt_retids = NULL;
-+ tp->ftt_next = NULL;
-+
-+ pp->ftp_tps[0].fit_tp = tp;
-+ pp->ftp_tps[0].fit_id.fti_probe = pp;
-+ pp->ftp_tps[0].fit_id.fti_ptype = probe->ftps_type;
-+
-+ pp->ftp_id = dtrace_probe_create(provider->ftp_provid,
-+ probe->ftps_mod,
-+ probe->ftps_func, name,
-+ aframes, pp);
-+ if (pp->ftp_id == DTRACE_IDNONE) {
-+ kmem_cache_free(tracepoint_cachep, tp);
-+ kfree(pp);
-+
-+ goto fail_reset;
-+ }
-+ }
-+
-+ mutex_unlock(&provider->ftp_cmtx);
-+
-+ /*
-+ * The provider is still around because of the consumer reference
-+ * count that we incremented. If another thread tried to clean up the
-+ * provider while we were using it (because the process called exec or
-+ * exit), we'll trigger a cleanup.
-+ */
-+ mutex_lock(&provider->ftp_mtx);
-+ provider->ftp_ccount--;
-+ retired = provider->ftp_retired;
-+ mutex_unlock(&provider->ftp_mtx);
-+
-+ if (retired)
-+ fasttrap_pid_cleanup();
-+
-+ return 0;
-+
-+fail_reset:
-+ atomic_add(-1, &fasttrap_total);
-+
-+ /*
-+ * If we failed to create the probe, it usually means we ran out of
-+ * memory. We'll try to remove this provider to free some. This
-+ * usually happens when a user accidentally triggers the creation of
-+ * a very large amount of probes (e.g. pid587:::).
-+ */
-+ mutex_unlock(&provider->ftp_cmtx);
-+
-+ kfree(offs);
-+
-+ mutex_lock(&provider->ftp_mtx);
-+ provider->ftp_ccount--;
-+ provider->ftp_marked = 1;
-+ mutex_unlock(&provider->ftp_mtx);
-+
-+ fasttrap_pid_cleanup();
-+
-+ return -ENOMEM;
-+}
-+
-+static long fasttrap_ioctl(struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ void __user *argp = (void __user *)arg;
-+
-+ if (cmd == FASTTRAPIOC_MAKEPROBE) {
-+ struct fasttrap_probe_spec __user *uprobe = argp;
-+ struct fasttrap_probe_spec *probe;
-+ uint8_t glen;
-+ size_t size;
-+ int ret;
-+ char *c;
-+
-+ dt_dbg_ioctl("PID IOCTL MAKEPROBE (cmd %#x), argp %p\n",
-+ cmd, argp);
-+
-+ if (copy_from_user(&glen, &uprobe->ftps_glen,
-+ sizeof(uprobe->ftps_glen)))
-+ return -EFAULT;
-+
-+ size = sizeof(struct fasttrap_probe_spec) +
-+ sizeof(probe->ftps_gstr[0]) * (glen - 1);
-+
-+ if (size > 1024 * 1024)
-+ return -ENOMEM;
-+
-+ probe = kmalloc(size, GFP_KERNEL);
-+ if (!probe)
-+ return -ENOMEM;
-+
-+ if (copy_from_user(probe, uprobe, size) != 0) {
-+ ret = -EFAULT;
-+ goto err;
-+ }
-+
-+ for (c = &probe->ftps_func[0]; *c != '\0'; c++) {
-+ if (*c < 0x20 || 0x7f <= *c) {
-+ ret = -EINVAL;
-+ goto err;
-+ }
-+ }
-+
-+ for (c = &probe->ftps_mod[0]; *c != '\0'; c++) {
-+ if (*c < 0x20 || 0x7f <= *c) {
-+ ret = -EINVAL;
-+ goto err;
-+ }
-+ }
-+
-+ ret = fasttrap_add_probe(probe);
-+err:
-+ kfree(probe);
-+
-+ return ret;
-+ }
-+
-+ return -EAGAIN;
-+}
-+
-+static int fasttrap_open(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static int fasttrap_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations fasttrap_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = fasttrap_ioctl,
-+ .open = fasttrap_open,
-+ .release = fasttrap_close,
-+};
-+
-+static struct miscdevice fasttrap_dev = {
-+ .minor = DT_DEV_FASTTRAP_MINOR,
-+ .name = "fasttrap",
-+ .nodename = "dtrace/provider/fasttrap",
-+ .fops = &fasttrap_fops,
-+};
-+
-+static int fasttrap_init_htable(struct fasttrap_hash *fth, ulong_t nent)
-+{
-+ ulong_t i;
-+
-+ if ((nent & (nent - 1)) == 0)
-+ fth->fth_nent = nent;
-+ else
-+ fth->fth_nent = 1 << fls(nent);
-+
-+ ASSERT(fth->fth_nent > 0);
-+
-+ fth->fth_mask = fth->fth_nent - 1;
-+ fth->fth_table = vzalloc(fth->fth_nent *
-+ sizeof(struct fasttrap_bucket_elem));
-+
-+ if (fth->fth_table == NULL)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < fth->fth_nent; i++)
-+ mutex_init(&fth->fth_table[i].bucket.ftb_mtx);
-+
-+ return 0;
-+}
-+
-+int fasttrap_dev_init(void)
-+{
-+ int ret = 0;
-+ ulong_t nent;
-+
-+ ret = misc_register(&fasttrap_dev);
-+ if (ret) {
-+ pr_err("%s: Can't register misc device %d\n",
-+ fasttrap_dev.name, fasttrap_dev.minor);
-+ goto fail;
-+ }
-+
-+#ifdef FIXME
-+ dtrace_fasttrap_exit_ptr = &fasttrap_exec_exit;
-+ dtrace_fasttrap_exec_ptr = &fasttrap_exec_exit;
-+#endif
-+
-+ tracepoint_cachep = KMEM_CACHE(fasttrap_tracepoint, 0);
-+
-+ fasttrap_max = FASTTRAP_MAX_DEFAULT;
-+ atomic_set(&fasttrap_total, 0);
-+
-+ /*
-+ * Conjure up the tracepoints hashtable...
-+ */
-+ nent = FASTTRAP_TPOINTS_DEFAULT_SIZE;
-+
-+ if (nent == 0 || nent > 0x1000000)
-+ nent = FASTTRAP_TPOINTS_DEFAULT_SIZE;
-+
-+ if (fasttrap_init_htable(&fasttrap_tpoints, nent) != 0)
-+ return -ENOMEM;
-+
-+ /*
-+ * ... and the providers hash table...
-+ */
-+ nent = FASTTRAP_PROVIDERS_DEFAULT_SIZE;
-+ if (fasttrap_init_htable(&fasttrap_provs, nent) != 0)
-+ return -ENOMEM;
-+
-+ /*
-+ * ... and the procs hash table.
-+ */
-+ nent = FASTTRAP_PROCS_DEFAULT_SIZE;
-+ if (fasttrap_init_htable(&fasttrap_procs, nent) != 0)
-+ return -ENOMEM;
-+
-+fail:
-+ return ret;
-+}
-+
-+/*
-+ * This function is called with module_mutex held.
-+ */
-+int fasttrap_prov_exit(void)
-+{
-+ int fail = 0;
-+ ulong_t i;
-+
-+ if (dtrace_meta_unregister(fasttrap_id) != 0)
-+ return 0;
-+
-+ /*
-+ * Prevent any new timeouts from running by setting fasttrap_timeout
-+ * to a non-zero value, and wait for the current timeout to complete.
-+ */
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ fasttrap_cleanup_work = 0;
-+
-+ while (fasttrap_cleanup_state != CLEANUP_DEFERRED) {
-+ uint_t tmp;
-+
-+ tmp = fasttrap_cleanup_state;
-+ fasttrap_cleanup_state = CLEANUP_DEFERRED;
-+
-+ if (tmp != CLEANUP_NONE) {
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+ flush_delayed_work(&fasttrap_cleanup);
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ }
-+ }
-+
-+ fasttrap_cleanup_work = 0;
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+
-+ /*
-+ * Iterate over all of our providers. If there's still a process
-+ * that corresponds to that pid, fail to detach.
-+ */
-+ for (i = 0; i < fasttrap_provs.fth_nent; i++) {
-+ struct fasttrap_provider **fpp, *fp;
-+ struct fasttrap_bucket *bucket;
-+
-+ bucket = FASTTRAP_ELEM_BUCKET(&fasttrap_provs.fth_table[i]);
-+ mutex_lock(&bucket->ftb_mtx);
-+ fpp = (struct fasttrap_provider **)&bucket->ftb_data;
-+ while ((fp = *fpp) != NULL) {
-+ /*
-+ * Acquire and release the lock as a simple way of
-+ * waiting for any other consumer to finish with
-+ * this provider. A thread must first acquire the
-+ * bucket lock so there's no chance of another thread
-+ * blocking on the provider's lock.
-+ */
-+ mutex_lock(&fp->ftp_mtx);
-+ mutex_unlock(&fp->ftp_mtx);
-+
-+ if (dtrace_unregister(fp->ftp_provid) != 0) {
-+ fail = 1;
-+ fpp = &fp->ftp_next;
-+ } else {
-+ *fpp = fp->ftp_next;
-+ fasttrap_provider_free(fp);
-+ }
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+ }
-+
-+ if (fail) {
-+ uint_t work;
-+
-+ /*
-+ * If we're failing to detach, we need to unblock timeouts
-+ * and start a new timeout if any work has accumulated while
-+ * we've been unsuccessfully trying to detach.
-+ */
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ fasttrap_cleanup_state = CLEANUP_NONE;
-+ work = fasttrap_cleanup_work;
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+
-+ if (work)
-+ fasttrap_pid_cleanup();
-+
-+ dtrace_meta_register("fasttrap", &fasttrap_mops, NULL,
-+ &fasttrap_id);
-+
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+void fasttrap_dev_exit(void)
-+{
-+#ifdef DEBUG
-+ mutex_lock(&fasttrap_count_mtx);
-+ ASSERT(fasttrap_pid_count == 0);
-+ mutex_unlock(&fasttrap_count_mtx);
-+#endif
-+
-+ if (fasttrap_tpoints.fth_table)
-+ vfree(fasttrap_tpoints.fth_table);
-+ fasttrap_tpoints.fth_nent = 0;
-+
-+ if (fasttrap_provs.fth_table)
-+ vfree(fasttrap_provs.fth_table);
-+ fasttrap_provs.fth_nent = 0;
-+
-+ if (fasttrap_procs.fth_table)
-+ vfree(fasttrap_procs.fth_table);
-+ fasttrap_procs.fth_nent = 0;
-+
-+ kmem_cache_destroy(tracepoint_cachep);
-+
-+#ifdef FIXME
-+ ASSERT(dtrace_fasttrap_exec_ptr == &fasttrap_exec_exit);
-+ dtrace_fasttrap_exec_ptr = NULL;
-+
-+ ASSERT(dtrace_fasttrap_exit_ptr == &fasttrap_exec_exit);
-+ dtrace_fasttrap_exit_ptr = NULL;
-+#endif
-+
-+ misc_deregister(&fasttrap_dev);
-+}
-diff --git a/dtrace/fasttrap_impl.h b/dtrace/fasttrap_impl.h
-new file mode 100644
-index 000000000000..cd2c4a28871e
---- /dev/null
-+++ b/dtrace/fasttrap_impl.h
-@@ -0,0 +1,172 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - fasttrap provider
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _FASTTRAP_IMPL_H_
-+#define _FASTTRAP_IMPL_H_
-+
-+#include <linux/dtrace/fasttrap.h>
-+#include <dtrace/fasttrap_arch.h>
-+#include <linux/cache.h>
-+
-+/*
-+ * Fasttrap Providers, Probes and Tracepoints
-+ *
-+ * Each Solaris process can have multiple providers -- the pid provider as
-+ * well as any number of user-level statically defined tracing (USDT)
-+ * providers. Those providers are each represented by a fasttrap_provider.
-+ * All providers for a given process have a pointer to a shared
-+ * fasttrap_proc. The fasttrap_proc has two states: active or defunct.
-+ * When the count of active providers goes to zero it becomes defunct; a
-+ * provider drops its active count when it is removed individually or as part
-+ * of a mass removal when a process exits or performs an exec.
-+ *
-+ * Each probe is represented by a fasttrap_probe which has a pointer to
-+ * its associated provider as well as a list of fasttrap_id_tp structures
-+ * which are tuples combining a fasttrap_id and a fasttrap_tracepoint.
-+ * A fasttrap_tracepoint represents the actual point of instrumentation
-+ * and it contains two lists of fasttrap_id structures (to be fired pre-
-+ * and post-instruction emulation) that identify the probes attached to the
-+ * tracepoint. Tracepoints also have a pointer to the fasttrap_proc for the
-+ * process they trace which is used when looking up a tracepoint both when a
-+ * probe fires and when enabling and disabling probes.
-+ *
-+ * It's important to note that probes are preallocated with the necessary
-+ * number of tracepoints, but that tracepoints can be shared by probes and
-+ * swapped between probes. If a probe's preallocated tracepoint is enabled
-+ * (and, therefore, the associated probe is enabled), and that probe is
-+ * then disabled, ownership of that tracepoint may be exchanged for an
-+ * unused tracepoint belonging to another probe that was attached to the
-+ * enabled tracepoint.
-+ */
-+struct fasttrap_proc {
-+ pid_t ftpc_pid; /* process ID for this proc */
-+ atomic64_t ftpc_acount; /* count of active providers */
-+ uint64_t ftpc_rcount; /* count of extant providers */
-+ struct mutex ftpc_mtx; /* lock on all but acount */
-+ struct fasttrap_proc *ftpc_next; /* next proc in hash chain */
-+};
-+
-+struct fasttrap_provider {
-+ pid_t ftp_pid; /* process ID for this prov */
-+ char ftp_name[DTRACE_PROVNAMELEN]; /* prov name (w/o the pid) */
-+ dtrace_provider_id_t ftp_provid; /* DTrace provider handle */
-+ uint_t ftp_marked; /* mark for possible removal */
-+ uint_t ftp_retired; /* mark when retired */
-+ struct mutex ftp_mtx; /* provider lock */
-+ struct mutex ftp_cmtx; /* lock on creating probes */
-+ uint64_t ftp_rcount; /* enabled probes ref count */
-+ uint64_t ftp_ccount; /* consumers creating probes */
-+ uint64_t ftp_mcount; /* meta provider count */
-+ struct fasttrap_proc *ftp_proc; /* shared proc for all provs */
-+ struct fasttrap_provider *ftp_next; /* next prov in hash chain */
-+};
-+
-+struct fasttrap_id {
-+ struct fasttrap_probe *fti_probe; /* referrring probe */
-+ struct fasttrap_id *fti_next; /* enabled probe list on tp */
-+ enum fasttrap_probe_type fti_ptype; /* probe type */
-+};
-+
-+struct fasttrap_tracepoint {
-+ struct fasttrap_proc *ftt_proc; /* associated process struct */
-+ uintptr_t ftt_pc; /* address of tracepoint */
-+ pid_t ftt_pid; /* pid of tracepoint */
-+ struct fasttrap_machtp ftt_mtp; /* ISA-specific portion */
-+ struct fasttrap_id *ftt_ids; /* NULL-terminated list */
-+ struct fasttrap_id *ftt_retids; /* NULL-terminated list */
-+ struct fasttrap_tracepoint *ftt_next; /* link in global hash */
-+};
-+
-+struct fasttrap_id_tp {
-+ struct fasttrap_id fit_id;
-+ struct fasttrap_tracepoint *fit_tp;
-+};
-+
-+struct fasttrap_probe {
-+ dtrace_id_t ftp_id; /* DTrace probe identifier */
-+ pid_t ftp_pid; /* pid for this probe */
-+ struct fasttrap_provider *ftp_prov; /* this probe's provider */
-+ uint64_t ftp_gen; /* modification generation */
-+ uint64_t ftp_ntps; /* number of tracepoints */
-+ uint8_t *ftp_argmap; /* native to translated args */
-+ uint8_t ftp_nargs; /* translated argument count */
-+ uint8_t ftp_enabled; /* is this probe enabled */
-+ char *ftp_xtypes; /* translated types index */
-+ char *ftp_ntypes; /* native types index */
-+ struct fasttrap_id_tp ftp_tps[1]; /* flexible array */
-+};
-+
-+struct fasttrap_bucket_elem {
-+ union {
-+ struct fasttrap_bucket {
-+ struct mutex ftb_mtx; /* bucket lock */
-+ void *ftb_data; /* data payload */
-+ } bucket;
-+
-+ /*
-+ * Fill a cacheline, no matter how large struct mutex is.
-+ */
-+ uint8_t ftb_pad[(sizeof(struct fasttrap_bucket) +
-+ L1_CACHE_BYTES - 1) & ~(L1_CACHE_BYTES - 1)];
-+ };
-+};
-+typedef struct fasttrap_bucket fasttrap_bucket_t;
-+
-+#define FASTTRAP_ELEM_BUCKET(elem) ((fasttrap_bucket_t *) (elem))
-+
-+struct fasttrap_hash {
-+ ulong_t fth_nent; /* power-of-2 num. of entries */
-+ ulong_t fth_mask; /* fth_nent - 1 */
-+ struct fasttrap_bucket_elem *fth_table; /* array of buckets */
-+};
-+
-+extern struct fasttrap_hash fasttrap_tpoints;
-+
-+#define FASTTRAP_ID_INDEX(id) \
-+ ((struct fasttrap_id_tp *)(((char *)(id) - \
-+ offsetof(struct fasttrap_id_tp, fit_id))) - \
-+ &(id)->fti_probe->ftp_tps[0])
-+#define FASTTRAP_TPOINTS_INDEX(pid, pc) \
-+ (((pc) / sizeof(fasttrap_instr_t) + (pid)) & \
-+ fasttrap_tpoints.fth_mask)
-+
-+extern uint64_t *fasttrap_glob_offsets(struct fasttrap_probe_spec *probe,
-+ uint64_t *np);
-+extern uint64_t fasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg,
-+ int argno, int aframes);
-+extern uint64_t fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg,
-+ int argno, int aframes);
-+extern void fasttrap_pid_probe_arch(struct fasttrap_probe *ftp,
-+ struct pt_regs *regs);
-+extern void fasttrap_pid_retprobe_arch(struct fasttrap_probe *ftp,
-+ struct pt_regs *regs);
-+extern void fasttrap_set_enabled(struct pt_regs *regs);
-+
-+extern void fasttrap_meta_create_probe(void *, void *,
-+ struct dtrace_helper_probedesc *);
-+extern void *fasttrap_meta_provide(void *, struct dtrace_helper_provdesc *,
-+ pid_t);
-+extern void fasttrap_meta_remove(void *, struct dtrace_helper_provdesc *,
-+ pid_t);
-+
-+extern dtrace_meta_provider_id_t fasttrap_id;
-+extern struct dtrace_mops fasttrap_mops;
-+
-+extern int fasttrap_dev_init(void);
-+extern void fasttrap_dev_exit(void);
-+
-+#endif /* _FASTTRAP_IMPL_H_ */
-diff --git a/dtrace/fasttrap_mod.c b/dtrace/fasttrap_mod.c
-new file mode 100644
-index 000000000000..e9bd0eb065f1
---- /dev/null
-+++ b/dtrace/fasttrap_mod.c
-@@ -0,0 +1,38 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fasttrap_mod.c
-+ * DESCRIPTION: DTrace - fasttrap provider kernel module
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#define DTRACE_HAVE_PROV_EXIT
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fasttrap_impl.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("Fasttrap Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+struct dtrace_mops fasttrap_mops = {
-+ fasttrap_meta_create_probe,
-+ fasttrap_meta_provide,
-+ fasttrap_meta_remove
-+};
-+
-+DT_META_PROVIDER_MODULE(fasttrap)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch
deleted file mode 100644
index 8bee6b6fd438..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch
+++ /dev/null
@@ -1,1799 +0,0 @@
-From bc81b22d39f0332275cd6834fdffb749368e62a0 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 19:02:39 +0000
-Subject: [PATCH 14/19] dtrace: function boundary tracing (FBT) core and x86
- components
-
-This commit implements the core components needed for FBT tracing.
-Unlike ftrace we allow the tracing of very large numbers of functions at
-once: the intent is that the system should still be stable when every
-eligible function in the kernel is traced simultaneously. Functions
-that are not safe for this (because e.g. they are used in trap handling,
-or by functions called by the DTrace module itself during probe
-processing) are (semi-manually) blacklisted from being probed.
-
-As part of this, a treewide change to the prototype of traps is started:
-they all return 0 by default now, with a nonzero return value indicating
-that the trap happened as a result of an FBT probe: the return value is
-the opcode atop which the trap was originally placed for later emulation.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/entry/entry_64.S | 134 ++++++++++++++++++-
- arch/x86/hyperv/hv_init.c | 1 +
- arch/x86/include/asm/idtentry.h | 86 +++++++------
- arch/x86/include/asm/irq_stack.h | 36 +++---
- arch/x86/kernel/apic/apic.c | 4 +
- arch/x86/kernel/apic/vector.c | 1 +
- arch/x86/kernel/cpu/acrn.c | 1 +
- arch/x86/kernel/cpu/mce/amd.c | 1 +
- arch/x86/kernel/cpu/mce/core.c | 3 +
- arch/x86/kernel/cpu/mce/therm_throt.c | 1 +
- arch/x86/kernel/cpu/mce/threshold.c | 1 +
- arch/x86/kernel/cpu/mshyperv.c | 2 +
- arch/x86/kernel/dtrace_fbt.c | 177 ++++++++++++++++++++++++++
- arch/x86/kernel/fbt_blacklist.h | 95 ++++++++++++++
- arch/x86/kernel/irq.c | 5 +
- arch/x86/kernel/irq_work.c | 1 +
- arch/x86/kernel/kvm.c | 1 +
- arch/x86/kernel/nmi.c | 5 +-
- arch/x86/kernel/sev-es.c | 6 +-
- arch/x86/kernel/smp.c | 4 +
- arch/x86/kernel/traps.c | 91 ++++++++-----
- arch/x86/mm/fault.c | 3 +-
- arch/x86/xen/enlighten_hvm.c | 1 +
- arch/x86/xen/enlighten_pv.c | 8 +-
- include/linux/dtrace_fbt.h | 48 +++++++
- kernel/dtrace/Kconfig | 7 +
- kernel/dtrace/Makefile | 4 +-
- kernel/dtrace/dtrace_fbt_core.c | 125 ++++++++++++++++++
- kernel/dtrace/dtrace_os.c | 2 +
- kernel/kprobes.c | 8 ++
- 30 files changed, 764 insertions(+), 98 deletions(-)
- create mode 100644 arch/x86/kernel/dtrace_fbt.c
- create mode 100644 arch/x86/kernel/fbt_blacklist.h
- create mode 100644 include/linux/dtrace_fbt.h
- create mode 100644 kernel/dtrace/dtrace_fbt_core.c
-
-diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
-index cad08703c4ad..689b45e5b0c4 100644
---- a/arch/x86/entry/entry_64.S
-+++ b/arch/x86/entry/entry_64.S
-@@ -38,7 +38,7 @@
- #include <asm/frame.h>
- #include <asm/trapnr.h>
- #include <asm/nospec-branch.h>
--#include <asm/fsgsbase.h>
-+#include <asm/dtrace_util.h>
- #include <linux/err.h>
-
- #include "calling.h"
-@@ -335,6 +335,15 @@ SYM_CODE_END(ret_from_fork)
-
- call \cfunc
-
-+#ifdef CONFIG_DTRACE
-+ /*
-+ * Nonzero exit from a trap handler means we want to emulate
-+ * an instruction.
-+ */
-+ test %rax,%rax
-+ jnz dtrace_error_return
-+#endif
-+
- jmp error_return
- .endm
-
-@@ -1097,6 +1106,129 @@ SYM_CODE_START_LOCAL(error_return)
- jmp swapgs_restore_regs_and_return_to_usermode
- SYM_CODE_END(error_return)
-
-+#ifdef CONFIG_DTRACE
-+/*
-+ * Emulate an instruction (given by one of the DTRACE_INVOP constants) on exit
-+ * from a trap handler.
-+ */
-+SYM_CODE_START_LOCAL(dtrace_error_return)
-+ UNWIND_HINT_REGS
-+
-+ negq %rax
-+
-+ cmpl $DTRACE_INVOP_MOV_RSP_RBP,%eax
-+ je dtrace_emu_mov
-+ cmpl $DTRACE_INVOP_PUSH_BP,%eax
-+ je dtrace_emu_push
-+ cmpl $DTRACE_INVOP_LEAVE,%eax
-+ je dtrace_emu_leave
-+ cmpl $DTRACE_INVOP_NOP,%eax
-+ je dtrace_emu_nop
-+ cmpl $DTRACE_INVOP_RET,%eax
-+ je dtrace_emu_ret
-+
-+ leaq dtrace_error_msg(%rip),%rdi
-+ movq %rax,%rsi
-+ movq (%rsp),%rdx
-+ call printk
-+
-+ jmp error_return
-+
-+dtrace_emu_mov:
-+ POP_REGS
-+ addq $8, %rsp /* skip regs->orig_ax */
-+
-+ /* Emulate "mov %rsp, %rbp" instruction. */
-+ pushq %rax /* push temp */
-+ movq 8(%rsp),%rax /* load calling RIP */
-+ addq $3,%rax /* increment over trapping instr */
-+ movq %rax,8(%rsp) /* store calling RIP */
-+ movq 32(%rsp),%rbp /* load %rsp into %rbp */
-+ popq %rax /* pop off temp */
-+
-+ INTERRUPT_RETURN
-+
-+dtrace_emu_push:
-+ POP_REGS
-+ addq $8, %rsp /* skip regs->orig_ax */
-+
-+ /*
-+ * Emulate a "pushq %rbp" instruction. We need to move the stack down
-+ * to make room for the extra address getting pushed.
-+ */
-+ subq $16,%rsp /* make room for %rbp */
-+ pushq %rax /* push temp */
-+ movq 24(%rsp),%rax /* load calling RIP */
-+ addq $1,%rax /* increment over trapping instr */
-+ movq %rax,8(%rsp) /* store calling RIP */
-+ movq 32(%rsp),%rax /* load calling CS */
-+ movq %rax,16(%rsp) /* store calling CS */
-+ movq 40(%rsp),%rax /* load calling RFLAGS */
-+ movq %rax,24(%rsp) /* store calling RFLAGS */
-+ movq 48(%rsp),%rax /* load calling RSP */
-+ subq $8,%rax /* make room for %rbp */
-+ movq %rax,32(%rsp) /* store calling RSP */
-+ movq 56(%rsp),%rax /* load calling SS */
-+ movq %rax,40(%rsp) /* store calling SS */
-+ movq 32(%rsp),%rax /* reload calling RSP */
-+ movq %rbp,(%rax) /* store %rbp there */
-+ popq %rax /* pop off temp */
-+
-+ INTERRUPT_RETURN
-+
-+dtrace_emu_nop:
-+ POP_REGS
-+ addq $8, %rsp /* skip regs->orig_ax */
-+
-+ /* Emulate a "nop" instruction. */
-+ incq (%rsp)
-+
-+ INTERRUPT_RETURN
-+
-+dtrace_emu_leave:
-+ POP_REGS
-+ addq $8, %rsp /* skip regs->orig_ax */
-+
-+ /*
-+ * Emulate a "leave" instruction. This is equivalent to the sequence:
-+ * movq %rbp,%rsp
-+ * popq %rbp
-+ * We can use the fact that on x86_64 %rsp is saved explicitly, so we
-+ * do not need to move any data around.
-+ */
-+ pushq %rax /* push temp */
-+ movq 8(%rsp),%rax /* load calling RIP */
-+ addq $1,%rax /* increment over trapping instr */
-+ movq %rax,8(%rsp) /* store calling RIP */
-+ movq (%rbp),%rax /* get new %rbp */
-+ addq $8,%rbp /* adjust new %rsp */
-+ movq %rbp,32(%rsp) /* store new %rsp */
-+ movq %rax,%rbp /* set new %rbp */
-+ popq %rax /* pop off temp */
-+
-+ INTERRUPT_RETURN
-+
-+dtrace_emu_ret:
-+ POP_REGS
-+ addq $8, %rsp /* skip regs->orig_ax */
-+
-+ /* Emulate a "ret" instruction. */
-+ pushq %rax /* push temp */
-+ movq 32(%rsp),%rax /* load %rsp */
-+ movq (%rax),%rax /* load calling RIP */
-+ movq %rax,8(%rsp) /* store calling RIP */
-+ addq $8,32(%rsp) /* adjust new %rsp */
-+ popq %rax /* pop off temp */
-+
-+ INTERRUPT_RETURN
-+SYM_CODE_END(dtrace_error_return)
-+
-+.pushsection .rodata, "a"
-+dtrace_error_msg:
-+ .asciz "DTRACE: non-zero (%x) return from trap at %x\n"
-+.popsection
-+#endif
-+
- /*
- * Runs on exception stack. Xen PV does not go through this path at all,
- * so we can use real assembly here.
-diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
-index 6375967a8244..e22347681c03 100644
---- a/arch/x86/hyperv/hv_init.c
-+++ b/arch/x86/hyperv/hv_init.c
-@@ -161,6 +161,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_reenlightenment)
- ack_APIC_irq();
- inc_irq_stat(irq_hv_reenlightenment_count);
- schedule_delayed_work(&hv_reenlightenment_work, HZ/10);
-+ return 0;
- }
-
- void set_hv_tscchange_cb(void (*cb)(void))
-diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h
-index b2442eb0ac2f..2222870fb7ab 100644
---- a/arch/x86/include/asm/idtentry.h
-+++ b/arch/x86/include/asm/idtentry.h
-@@ -32,7 +32,7 @@ void idtentry_exit_nmi(struct pt_regs *regs, bool irq_state);
- #define DECLARE_IDTENTRY(vector, func) \
- asmlinkage void asm_##func(void); \
- asmlinkage void xen_asm_##func(void); \
-- __visible void func(struct pt_regs *regs)
-+ __visible int func(struct pt_regs *regs)
-
- /**
- * DEFINE_IDTENTRY - Emit code for simple IDT entry points
-@@ -48,19 +48,21 @@ void idtentry_exit_nmi(struct pt_regs *regs, bool irq_state);
- * which has to run before returning to the low level assembly code.
- */
- #define DEFINE_IDTENTRY(func) \
--static __always_inline void __##func(struct pt_regs *regs); \
-+static __always_inline int __##func(struct pt_regs *regs); \
- \
--__visible noinstr void func(struct pt_regs *regs) \
-+__visible noinstr int func(struct pt_regs *regs) \
- { \
- irqentry_state_t state = irqentry_enter(regs); \
-+ int ret; \
- \
- instrumentation_begin(); \
-- __##func (regs); \
-+ ret = __##func (regs); \
- instrumentation_end(); \
- irqentry_exit(regs, state); \
-+ return ret; \
- } \
- \
--static __always_inline void __##func(struct pt_regs *regs)
-+static __always_inline int __##func(struct pt_regs *regs)
-
- /* Special case for 32bit IRET 'trap' */
- #define DECLARE_IDTENTRY_SW DECLARE_IDTENTRY
-@@ -83,7 +85,7 @@ static __always_inline void __##func(struct pt_regs *regs)
- #define DECLARE_IDTENTRY_ERRORCODE(vector, func) \
- asmlinkage void asm_##func(void); \
- asmlinkage void xen_asm_##func(void); \
-- __visible void func(struct pt_regs *regs, unsigned long error_code)
-+ __visible int func(struct pt_regs *regs, unsigned long error_code)
-
- /**
- * DEFINE_IDTENTRY_ERRORCODE - Emit code for simple IDT entry points
-@@ -93,22 +95,24 @@ static __always_inline void __##func(struct pt_regs *regs)
- * Same as DEFINE_IDTENTRY, but has an extra error_code argument
- */
- #define DEFINE_IDTENTRY_ERRORCODE(func) \
--static __always_inline void __##func(struct pt_regs *regs, \
-- unsigned long error_code); \
-+static __always_inline int __##func(struct pt_regs *regs, \
-+ unsigned long error_code); \
- \
--__visible noinstr void func(struct pt_regs *regs, \
-- unsigned long error_code) \
-+__visible noinstr int func(struct pt_regs *regs, \
-+ unsigned long error_code) \
- { \
- irqentry_state_t state = irqentry_enter(regs); \
-+ int ret; \
- \
- instrumentation_begin(); \
-- __##func (regs, error_code); \
-+ ret = __##func (regs, error_code); \
- instrumentation_end(); \
- irqentry_exit(regs, state); \
-+ return ret; \
- } \
- \
--static __always_inline void __##func(struct pt_regs *regs, \
-- unsigned long error_code)
-+static __always_inline int __##func(struct pt_regs *regs, \
-+ unsigned long error_code)
-
- /**
- * DECLARE_IDTENTRY_RAW - Declare functions for raw IDT entry points
-@@ -136,7 +140,7 @@ static __always_inline void __##func(struct pt_regs *regs, \
- * is required before the enter/exit() helpers are invoked.
- */
- #define DEFINE_IDTENTRY_RAW(func) \
--__visible noinstr void func(struct pt_regs *regs)
-+__visible noinstr int func(struct pt_regs *regs)
-
- /**
- * DECLARE_IDTENTRY_RAW_ERRORCODE - Declare functions for raw IDT entry points
-@@ -164,7 +168,7 @@ __visible noinstr void func(struct pt_regs *regs)
- * is required before the enter/exit() helpers are invoked.
- */
- #define DEFINE_IDTENTRY_RAW_ERRORCODE(func) \
--__visible noinstr void func(struct pt_regs *regs, unsigned long error_code)
-+__visible noinstr int func(struct pt_regs *regs, unsigned long error_code)
-
- /**
- * DECLARE_IDTENTRY_IRQ - Declare functions for device interrupt IDT entry
-@@ -190,23 +194,25 @@ __visible noinstr void func(struct pt_regs *regs, unsigned long error_code)
- * has to be done in the function body if necessary.
- */
- #define DEFINE_IDTENTRY_IRQ(func) \
--static __always_inline void __##func(struct pt_regs *regs, u8 vector); \
-+static __always_inline int __##func(struct pt_regs *regs, u8 vector); \
- \
--__visible noinstr void func(struct pt_regs *regs, \
-- unsigned long error_code) \
-+__visible noinstr int func(struct pt_regs *regs, \
-+ unsigned long error_code) \
- { \
- irqentry_state_t state = irqentry_enter(regs); \
-+ int ret; \
- \
- instrumentation_begin(); \
- irq_enter_rcu(); \
- kvm_set_cpu_l1tf_flush_l1d(); \
-- __##func (regs, (u8)error_code); \
-+ ret = __##func (regs, (u8)error_code); \
- irq_exit_rcu(); \
- instrumentation_end(); \
- irqentry_exit(regs, state); \
-+ return ret; \
- } \
- \
--static __always_inline void __##func(struct pt_regs *regs, u8 vector)
-+static __always_inline int __##func(struct pt_regs *regs, u8 vector)
-
- /**
- * DECLARE_IDTENTRY_SYSVEC - Declare functions for system vector entry points
-@@ -233,22 +239,24 @@ static __always_inline void __##func(struct pt_regs *regs, u8 vector)
- * Runs the function on the interrupt stack if the entry hit kernel mode
- */
- #define DEFINE_IDTENTRY_SYSVEC(func) \
--static void __##func(struct pt_regs *regs); \
-+static int __##func(struct pt_regs *regs); \
- \
--__visible noinstr void func(struct pt_regs *regs) \
-+__visible noinstr int func(struct pt_regs *regs) \
- { \
- irqentry_state_t state = irqentry_enter(regs); \
-+ int ret; \
- \
- instrumentation_begin(); \
- irq_enter_rcu(); \
- kvm_set_cpu_l1tf_flush_l1d(); \
-- run_sysvec_on_irqstack_cond(__##func, regs); \
-+ ret = run_sysvec_on_irqstack_cond(__##func, regs); \
- irq_exit_rcu(); \
- instrumentation_end(); \
- irqentry_exit(regs, state); \
-+ return ret; \
- } \
- \
--static noinline void __##func(struct pt_regs *regs)
-+static noinline int __##func(struct pt_regs *regs)
-
- /**
- * DEFINE_IDTENTRY_SYSVEC_SIMPLE - Emit code for simple system vector IDT
-@@ -262,22 +270,24 @@ static noinline void __##func(struct pt_regs *regs)
- * interrupt vectors.
- */
- #define DEFINE_IDTENTRY_SYSVEC_SIMPLE(func) \
--static __always_inline void __##func(struct pt_regs *regs); \
-+static __always_inline int __##func(struct pt_regs *regs); \
- \
--__visible noinstr void func(struct pt_regs *regs) \
-+__visible noinstr int func(struct pt_regs *regs) \
- { \
- irqentry_state_t state = irqentry_enter(regs); \
-+ int ret; \
- \
- instrumentation_begin(); \
- __irq_enter_raw(); \
- kvm_set_cpu_l1tf_flush_l1d(); \
-- __##func (regs); \
-+ ret = __##func (regs); \
- __irq_exit_raw(); \
- instrumentation_end(); \
- irqentry_exit(regs, state); \
-+ return ret; \
- } \
- \
--static __always_inline void __##func(struct pt_regs *regs)
-+static __always_inline int __##func(struct pt_regs *regs)
-
- /**
- * DECLARE_IDTENTRY_XENCB - Declare functions for XEN HV callback entry point
-@@ -306,7 +316,7 @@ static __always_inline void __##func(struct pt_regs *regs)
- */
- #define DECLARE_IDTENTRY_IST(vector, func) \
- DECLARE_IDTENTRY_RAW(vector, func); \
-- __visible void noist_##func(struct pt_regs *regs)
-+ __visible int noist_##func(struct pt_regs *regs)
-
- /**
- * DECLARE_IDTENTRY_VC - Declare functions for the VC entry point
-@@ -318,8 +328,8 @@ static __always_inline void __##func(struct pt_regs *regs)
- */
- #define DECLARE_IDTENTRY_VC(vector, func) \
- DECLARE_IDTENTRY_RAW_ERRORCODE(vector, func); \
-- __visible noinstr void ist_##func(struct pt_regs *regs, unsigned long error_code); \
-- __visible noinstr void safe_stack_##func(struct pt_regs *regs, unsigned long error_code)
-+ __visible noinstr int ist_##func(struct pt_regs *regs, unsigned long error_code); \
-+ __visible noinstr int safe_stack_##func(struct pt_regs *regs, unsigned long error_code)
-
- /**
- * DEFINE_IDTENTRY_IST - Emit code for IST entry points
-@@ -401,10 +411,10 @@ static __always_inline void __##func(struct pt_regs *regs)
- * - The C handler called from the C shim
- */
- #define DECLARE_IDTENTRY_DF(vector, func) \
-- asmlinkage void asm_##func(void); \
-- __visible void func(struct pt_regs *regs, \
-- unsigned long error_code, \
-- unsigned long address)
-+ asmlinkage int asm_##func(void); \
-+ __visible int func(struct pt_regs *regs, \
-+ unsigned long error_code, \
-+ unsigned long address)
-
- /**
- * DEFINE_IDTENTRY_DF - Emit code for double fault on 32bit
-@@ -414,9 +424,9 @@ static __always_inline void __##func(struct pt_regs *regs)
- * cr2 in the address argument.
- */
- #define DEFINE_IDTENTRY_DF(func) \
--__visible noinstr void func(struct pt_regs *regs, \
-- unsigned long error_code, \
-- unsigned long address)
-+__visible noinstr int func(struct pt_regs *regs, \
-+ unsigned long error_code, \
-+ unsigned long address)
-
- #endif /* !CONFIG_X86_64 */
-
-diff --git a/arch/x86/include/asm/irq_stack.h b/arch/x86/include/asm/irq_stack.h
-index 775816965c6a..04f91986cee3 100644
---- a/arch/x86/include/asm/irq_stack.h
-+++ b/arch/x86/include/asm/irq_stack.h
-@@ -12,11 +12,11 @@ static __always_inline bool irqstack_active(void)
- return __this_cpu_read(irq_count) != -1;
- }
-
--void asm_call_on_stack(void *sp, void (*func)(void), void *arg);
--void asm_call_sysvec_on_stack(void *sp, void (*func)(struct pt_regs *regs),
-- struct pt_regs *regs);
--void asm_call_irq_on_stack(void *sp, void (*func)(struct irq_desc *desc),
-- struct irq_desc *desc);
-+int asm_call_on_stack(void *sp, void (*func)(void), void *arg);
-+int asm_call_sysvec_on_stack(void *sp, int (*func)(struct pt_regs *regs),
-+ struct pt_regs *regs);
-+int asm_call_irq_on_stack(void *sp, void (*func)(struct irq_desc *desc),
-+ struct irq_desc *desc);
-
- static __always_inline void __run_on_irqstack(void (*func)(void))
- {
-@@ -27,15 +27,17 @@ static __always_inline void __run_on_irqstack(void (*func)(void))
- __this_cpu_sub(irq_count, 1);
- }
-
--static __always_inline void
--__run_sysvec_on_irqstack(void (*func)(struct pt_regs *regs),
-+static __always_inline int
-+__run_sysvec_on_irqstack(int (*func)(struct pt_regs *regs),
- struct pt_regs *regs)
- {
- void *tos = __this_cpu_read(hardirq_stack_ptr);
-+ int ret;
-
- __this_cpu_add(irq_count, 1);
-- asm_call_sysvec_on_stack(tos - 8, func, regs);
-+ ret = asm_call_sysvec_on_stack(tos - 8, func, regs);
- __this_cpu_sub(irq_count, 1);
-+ return ret;
- }
-
- static __always_inline void
-@@ -51,11 +53,11 @@ __run_irq_on_irqstack(void (*func)(struct irq_desc *desc),
-
- #else /* CONFIG_X86_64 */
- static inline bool irqstack_active(void) { return false; }
--static inline void __run_on_irqstack(void (*func)(void)) { }
--static inline void __run_sysvec_on_irqstack(void (*func)(struct pt_regs *regs),
-- struct pt_regs *regs) { }
--static inline void __run_irq_on_irqstack(void (*func)(struct irq_desc *desc),
-- struct irq_desc *desc) { }
-+static inline int __run_on_irqstack(int (*func)(void)) { }
-+static inline int __run_sysvec_on_irqstack(int (*func)(struct pt_regs *regs),
-+ struct pt_regs *regs) { }
-+static inline int __run_irq_on_irqstack(int (*func)(struct irq_desc *desc),
-+ struct irq_desc *desc) { }
- #endif /* !CONFIG_X86_64 */
-
- static __always_inline bool irq_needs_irq_stack(struct pt_regs *regs)
-@@ -79,16 +81,16 @@ static __always_inline void run_on_irqstack_cond(void (*func)(void),
- func();
- }
-
--static __always_inline void
--run_sysvec_on_irqstack_cond(void (*func)(struct pt_regs *regs),
-+static __always_inline int
-+run_sysvec_on_irqstack_cond(int (*func)(struct pt_regs *regs),
- struct pt_regs *regs)
- {
- lockdep_assert_irqs_disabled();
-
- if (irq_needs_irq_stack(regs))
-- __run_sysvec_on_irqstack(func, regs);
-+ return __run_sysvec_on_irqstack(func, regs);
- else
-- func(regs);
-+ return func(regs);
- }
-
- static __always_inline void
-diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
-index 113f6ca7b828..06bd0bf3ae5a 100644
---- a/arch/x86/kernel/apic/apic.c
-+++ b/arch/x86/kernel/apic/apic.c
-@@ -1098,6 +1098,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_apic_timer_interrupt)
- trace_local_timer_exit(LOCAL_TIMER_VECTOR);
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- int setup_profiling_timer(unsigned int multiplier)
-@@ -2160,11 +2161,13 @@ DEFINE_IDTENTRY_IRQ(spurious_interrupt)
- }
- out:
- trace_spurious_apic_exit(vector);
-+ return 0;
- }
-
- DEFINE_IDTENTRY_SYSVEC(sysvec_spurious_apic_interrupt)
- {
- __spurious_interrupt(regs, SPURIOUS_APIC_VECTOR);
-+ return 0;
- }
-
- /*
-@@ -2207,6 +2210,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_error_interrupt)
- apic_printk(APIC_DEBUG, KERN_CONT "\n");
-
- trace_error_apic_exit(ERROR_APIC_VECTOR);
-+ return 0;
- }
-
- /**
-diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
-index 758bbf25ef74..a841e833f267 100644
---- a/arch/x86/kernel/apic/vector.c
-+++ b/arch/x86/kernel/apic/vector.c
-@@ -887,6 +887,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_irq_move_cleanup)
- }
-
- raw_spin_unlock(&vector_lock);
-+ return 0;
- }
-
- static void __send_cleanup_vector(struct apic_chip_data *apicd)
-diff --git a/arch/x86/kernel/cpu/acrn.c b/arch/x86/kernel/cpu/acrn.c
-index 0b2c03943ac6..b17c61c16e99 100644
---- a/arch/x86/kernel/cpu/acrn.c
-+++ b/arch/x86/kernel/cpu/acrn.c
-@@ -53,6 +53,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_acrn_hv_callback)
- acrn_intr_handler();
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- const __initconst struct hypervisor_x86 x86_hyper_acrn = {
-diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c
-index 0c6b02dd744c..8126b080d488 100644
---- a/arch/x86/kernel/cpu/mce/amd.c
-+++ b/arch/x86/kernel/cpu/mce/amd.c
-@@ -928,6 +928,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_deferred_error)
- deferred_error_int_vector();
- trace_deferred_error_apic_exit(DEFERRED_ERROR_VECTOR);
- ack_APIC_irq();
-+ return 0;
- }
-
- /*
-diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
-index 311688202ea5..e94cf10e05f7 100644
---- a/arch/x86/kernel/cpu/mce/core.c
-+++ b/arch/x86/kernel/cpu/mce/core.c
-@@ -2030,6 +2030,7 @@ DEFINE_IDTENTRY_MCE(exc_machine_check)
- dr7 = local_db_save();
- exc_machine_check_kernel(regs);
- local_db_restore(dr7);
-+ return 0;
- }
-
- /* The user mode variant. */
-@@ -2040,6 +2041,7 @@ DEFINE_IDTENTRY_MCE_USER(exc_machine_check)
- dr7 = local_db_save();
- exc_machine_check_user(regs);
- local_db_restore(dr7);
-+ return 0;
- }
- #else
- /* 32bit unified entry point */
-@@ -2053,6 +2055,7 @@ DEFINE_IDTENTRY_RAW(exc_machine_check)
- else
- exc_machine_check_kernel(regs);
- local_db_restore(dr7);
-+ return 0;
- }
- #endif
-
-diff --git a/arch/x86/kernel/cpu/mce/therm_throt.c b/arch/x86/kernel/cpu/mce/therm_throt.c
-index a7cd2d203ced..8e86a3baf32e 100644
---- a/arch/x86/kernel/cpu/mce/therm_throt.c
-+++ b/arch/x86/kernel/cpu/mce/therm_throt.c
-@@ -621,6 +621,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_thermal)
- smp_thermal_vector();
- trace_thermal_apic_exit(THERMAL_APIC_VECTOR);
- ack_APIC_irq();
-+ return 0;
- }
-
- /* Thermal monitoring depends on APIC, ACPI and clock modulation */
-diff --git a/arch/x86/kernel/cpu/mce/threshold.c b/arch/x86/kernel/cpu/mce/threshold.c
-index 6a059a035021..fa361a5b297a 100644
---- a/arch/x86/kernel/cpu/mce/threshold.c
-+++ b/arch/x86/kernel/cpu/mce/threshold.c
-@@ -28,4 +28,5 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_threshold)
- mce_threshold_vector();
- trace_threshold_apic_exit(THRESHOLD_APIC_VECTOR);
- ack_APIC_irq();
-+ return 0;
- }
-diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
-index 6cc50ab07bde..5146b1f713e0 100644
---- a/arch/x86/kernel/cpu/mshyperv.c
-+++ b/arch/x86/kernel/cpu/mshyperv.c
-@@ -53,6 +53,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
- ack_APIC_irq();
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- int hv_setup_vmbus_irq(int irq, void (*handler)(void))
-@@ -88,6 +89,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_stimer0)
- ack_APIC_irq();
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- int hv_setup_stimer0_irq(int *irq, int *vector, void (*handler)(void))
-diff --git a/arch/x86/kernel/dtrace_fbt.c b/arch/x86/kernel/dtrace_fbt.c
-new file mode 100644
-index 000000000000..52ff3f49d101
---- /dev/null
-+++ b/arch/x86/kernel/dtrace_fbt.c
-@@ -0,0 +1,177 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_fbt.c
-+ * DESCRIPTION: Dynamic Tracing: FBT registration code (arch-specific)
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/kallsyms.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_fbt.h>
-+#include <linux/slab.h>
-+#include <linux/sort.h>
-+#include <asm/insn.h>
-+#include <asm/sections.h>
-+
-+#define FBT_MOV_RSP_RBP_1 0x48
-+#define FBT_MOV_RSP_RBP_2 0x89
-+#define FBT_MOV_RSP_RBP_3 0xe5
-+#define FBT_PUSHL_EBP 0x55
-+#define FBT_NOP 0x90
-+#define FBT_RET_IMM16 0xc2
-+#define FBT_RET 0xc3
-+#define FBT_LEAVE 0xc9
-+
-+#define BL_SENTRY(tp, nm) extern tp nm;
-+#define BL_DENTRY(tp, nm)
-+#include "fbt_blacklist.h"
-+#undef BL_DENTRY
-+#undef BL_SENTRY
-+
-+static void
-+dtrace_fbt_populate_bl(void)
-+{
-+#define BL_SENTRY(tp, nm) dtrace_fbt_bl_add((unsigned long)&nm, \
-+ __stringify(nm));
-+#define BL_DENTRY(tp, nm) dtrace_fbt_bl_add(0, __stringify(nm));
-+#include "fbt_blacklist.h"
-+#undef BL_SENTRY
-+#undef BL_DENTRY
-+}
-+
-+void dtrace_fbt_init(fbt_add_probe_fn fbt_add_probe, struct module *mp,
-+ void *arg)
-+{
-+ loff_t pos;
-+ struct kallsym_iter sym;
-+ asm_instr_t *paddr = NULL;
-+ struct dt_fbt_bl_entry *blent = NULL;
-+
-+ /*
-+ * Look up any unresolved symbols in the blacklist, and sort the list
-+ * by ascending address.
-+ */
-+ dtrace_fbt_populate_bl();
-+ blent = dtrace_fbt_bl_first();
-+
-+ pos = 0;
-+ kallsyms_iter_reset(&sym, 0);
-+ while (kallsyms_iter_update(&sym, pos++)) {
-+ asm_instr_t *addr, *end;
-+ int state = 0, insc = 0;
-+ void *fbtp = NULL;
-+
-+ /*
-+ * There is no point considering non-function symbols for FBT,
-+ * or symbols that have a zero size. We could consider weak
-+ * symbols but that gets quite complicated and there is no
-+ * demands for that (so far).
-+ */
-+ if (sym.type != 'T' && sym.type != 't')
-+ continue;
-+ if (!sym.size)
-+ continue;
-+
-+ /*
-+ * Handle only symbols that belong to the module we have been
-+ * asked for.
-+ */
-+ if (mp == dtrace_kmod && !core_kernel_text(sym.value))
-+ continue;
-+
-+ /*
-+ * Ensure we have not been given .init symbol from kallsyms
-+ * interface. This could lead to memory corruption once DTrace
-+ * tries to enable probe in already freed memory.
-+ */
-+ if (mp != dtrace_kmod && !within_module_core(sym.value, mp))
-+ continue;
-+
-+ /*
-+ * See if the symbol is on the FBT's blacklist. Since both
-+ * iterators are workng in sort order by ascending address we
-+ * can use concurrent traversal.
-+ */
-+ while (blent != NULL &&
-+ dtrace_fbt_bl_entry_addr(blent) < sym.value) {
-+ blent = dtrace_fbt_bl_next(blent);
-+ }
-+ if (dtrace_fbt_bl_entry_addr(blent) == sym.value)
-+ continue;
-+
-+ /*
-+ * No FBT tracing for DTrace functions, and functions that are
-+ * crucial to probe processing.
-+ * Also weed out symbols that are not relevant here.
-+ */
-+ if (strncmp(sym.name, "dtrace_", 7) == 0)
-+ continue;
-+ if (strncmp(sym.name, "insn_", 5) == 0)
-+ continue;
-+ if (strncmp(sym.name, "inat_", 5) == 0)
-+ continue;
-+ if (strncmp(sym.name, "_GLOBAL_", 8) == 0)
-+ continue;
-+ if (strncmp(sym.name, "do_", 3) == 0)
-+ continue;
-+ if (strncmp(sym.name, "xen_", 4) == 0)
-+ continue;
-+
-+ addr = (asm_instr_t *)sym.value;
-+ end = (asm_instr_t *)(sym.value + sym.size);
-+
-+ /*
-+ * FIXME:
-+ * When there are multiple symbols for the same address, we
-+ * should link them together as probes associated with the
-+ * same function. When a probe for that function is triggered
-+ * all associated probes should fire.
-+ *
-+ * For now, we ignore duplicates.
-+ */
-+ if (addr == paddr)
-+ continue;
-+ paddr = addr;
-+
-+ while (addr < end) {
-+ struct insn insn;
-+
-+ insc++;
-+
-+ switch (state) {
-+ case 0: /* start of function */
-+ if (*addr == FBT_PUSHL_EBP) {
-+ fbt_add_probe(
-+ mp, sym.name,
-+ FBT_ENTRY, *addr, addr, 0,
-+ NULL, arg);
-+ state = 1;
-+ } else if (insc > 10)
-+ state = 2;
-+ break;
-+ case 1: /* look for ret */
-+ if (*addr == FBT_RET) {
-+ uintptr_t off;
-+
-+ off = addr - (asm_instr_t *)sym.value;
-+ fbtp = fbt_add_probe(
-+ mp, sym.name,
-+ FBT_RETURN, *addr, addr, off,
-+ fbtp, arg);
-+ }
-+ break;
-+ }
-+
-+ if (state == 2)
-+ break;
-+
-+ kernel_insn_init(&insn, addr, MAX_INSN_SIZE);
-+ insn_get_length(&insn);
-+
-+ addr += insn.length;
-+ }
-+ }
-+}
-+EXPORT_SYMBOL(dtrace_fbt_init);
-diff --git a/arch/x86/kernel/fbt_blacklist.h b/arch/x86/kernel/fbt_blacklist.h
-new file mode 100644
-index 000000000000..2e1ce2a90c86
---- /dev/null
-+++ b/arch/x86/kernel/fbt_blacklist.h
-@@ -0,0 +1,95 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Functions used in die notifier chain calling.
-+ */
-+BL_SENTRY(void *, notify_die)
-+BL_DENTRY(void *, notifier_call_chain)
-+BL_SENTRY(typeof(atomic_notifier_call_chain_robust), atomic_notifier_call_chain_robust)
-+BL_SENTRY(typeof(atomic_notifier_call_chain), atomic_notifier_call_chain)
-+BL_SENTRY(typeof(raw_notifier_call_chain_robust), raw_notifier_call_chain_robust)
-+BL_SENTRY(typeof(raw_notifier_call_chain), raw_notifier_call_chain)
-+BL_DENTRY(void *, hw_breakpoint_exceptions_notify)
-+BL_DENTRY(void *, kprobe_exceptions_notify)
-+
-+/*
-+ * Functions used to update vtime in probe context.
-+ */
-+BL_SENTRY(typeof(ktime_get_raw_fast_ns), ktime_get_raw_fast_ns)
-+BL_DENTRY(void *, raw_read_seqcount)
-+BL_DENTRY(void *, read_seqcount_retry)
-+BL_DENTRY(void *, __read_seqcount_retry)
-+
-+/* xen_clocksource */
-+BL_DENTRY(void *, xen_clocksource_get_cycles)
-+BL_DENTRY(void *, xen_clocksource_read)
-+BL_DENTRY(void *, pvclock_clocksource_read)
-+BL_DENTRY(void *, pvclock_touch_watchdogs)
-+BL_DENTRY(void *, touch_softlockup_watchdog_sync)
-+BL_DENTRY(void *, clocksource_touch_watchdog)
-+BL_DENTRY(void *, clocksource_resume_watchdog)
-+BL_DENTRY(void *, reset_hung_task_detector)
-+/* clocksource_tsc */
-+BL_DENTRY(void *, read_tsc)
-+BL_DENTRY(void *, get_cycles)
-+/* clocksource_hpet */
-+BL_DENTRY(void *, read_hpet)
-+BL_DENTRY(void *, hpet_readl)
-+/* kvm_clock */
-+BL_DENTRY(void *, kvm_clock_get_cycles)
-+BL_DENTRY(void *, kvm_clock_read)
-+
-+/*
-+ * Functions used in trap handling.
-+ */
-+BL_DENTRY(void *, fixup_exception)
-+BL_DENTRY(void *, paranoid_entry)
-+BL_DENTRY(void *, kgdb_ll_trap)
-+BL_DENTRY(void *, error_entry)
-+BL_DENTRY(void *, xen_int3)
-+BL_DENTRY(void *, ftrace_int3_handler)
-+BL_DENTRY(typeof(poke_int3_handler), poke_int3_handler)
-+BL_DENTRY(void *, fixup_bad_iret)
-+BL_DENTRY(void *, xen_adjust_exception_frame)
-+BL_DENTRY(void *, paravirt_nop)
-+BL_DENTRY(void *, ist_enter)
-+BL_DENTRY(void *, rcu_nmi_enter)
-+BL_DENTRY(void *, rcu_dynticks_curr_cpu_in_eqs)
-+BL_DENTRY(void *, rcu_dynticks_eqs_exit)
-+BL_DENTRY(void *, trace_rcu_dyntick)
-+BL_DENTRY(void *, rcu_nmi_exit)
-+BL_DENTRY(void *, rcu_irq_exit)
-+BL_DENTRY(void *, rcu_nmi_exit_common)
-+BL_DENTRY(void *, rcu_dynticks_eqs_enter)
-+BL_DENTRY(void *, ist_exit)
-+
-+/*
-+ * Functions used in page fault handling.
-+ */
-+BL_DENTRY(void *, do_kern_addr_fault)
-+BL_DENTRY(void *, do_kern_addr_fault)
-+BL_DENTRY(void *, handle_page_fault)
-+BL_DENTRY(void *, huge_page_mask)
-+BL_DENTRY(void *, mmap_address_hint_valid)
-+BL_DENTRY(void *, vm_start_gap)
-+BL_DENTRY(void *, hugetlb_get_unmapped_area_bottomup)
-+BL_DENTRY(void *, hugetlb_get_unmapped_area_topdown)
-+BL_DENTRY(void *, down_read_trylock)
-+BL_DENTRY(void *, __get_user_pages_fast)
-+BL_DENTRY(void *, gup_pud_range)
-+BL_DENTRY(void *, gup_huge_pud)
-+BL_DENTRY(void *, gup_pmd_range)
-+BL_DENTRY(void *, gup_huge_pmd)
-+BL_DENTRY(void *, gup_pte_range)
-+BL_DENTRY(void *, pte_mfn_to_pfn)
-+
-+/*
-+ * Functions used under 4.12 idr_find
-+ */
-+BL_DENTRY(void *, idr_find)
-+BL_DENTRY(void *, find_next_bit)
-+BL_DENTRY(void *, _find_next_bit)
-+BL_DENTRY(void *, radix_tree_lookup)
-+BL_DENTRY(void *, __radix_tree_lookup)
-+BL_DENTRY(void *, radix_tree_load_root)
-+BL_DENTRY(void *, radix_tree_descend)
-+BL_DENTRY(void *, is_sibling_entry)
-diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
-index c5dd50369e2f..b80211006fb2 100644
---- a/arch/x86/kernel/irq.c
-+++ b/arch/x86/kernel/irq.c
-@@ -260,6 +260,7 @@ DEFINE_IDTENTRY_IRQ(common_interrupt)
- }
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- #ifdef CONFIG_X86_LOCAL_APIC
-@@ -279,6 +280,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_x86_platform_ipi)
- x86_platform_ipi_callback();
- trace_x86_platform_ipi_exit(X86_PLATFORM_IPI_VECTOR);
- set_irq_regs(old_regs);
-+ return 0;
- }
- #endif
-
-@@ -302,6 +304,7 @@ DEFINE_IDTENTRY_SYSVEC_SIMPLE(sysvec_kvm_posted_intr_ipi)
- {
- ack_APIC_irq();
- inc_irq_stat(kvm_posted_intr_ipis);
-+ return 0;
- }
-
- /*
-@@ -312,6 +315,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_kvm_posted_intr_wakeup_ipi)
- ack_APIC_irq();
- inc_irq_stat(kvm_posted_intr_wakeup_ipis);
- kvm_posted_intr_wakeup_handler();
-+ return 0;
- }
-
- /*
-@@ -321,6 +325,7 @@ DEFINE_IDTENTRY_SYSVEC_SIMPLE(sysvec_kvm_posted_intr_nested_ipi)
- {
- ack_APIC_irq();
- inc_irq_stat(kvm_posted_intr_nested_ipis);
-+ return 0;
- }
- #endif
-
-diff --git a/arch/x86/kernel/irq_work.c b/arch/x86/kernel/irq_work.c
-index 890d4778cd35..ac74998e2faa 100644
---- a/arch/x86/kernel/irq_work.c
-+++ b/arch/x86/kernel/irq_work.c
-@@ -21,6 +21,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_irq_work)
- inc_irq_stat(apic_irq_work_irqs);
- irq_work_run();
- trace_irq_work_exit(IRQ_WORK_VECTOR);
-+ return 0;
- }
-
- void arch_irq_work_raise(void)
-diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
-index 7f57ede3cb8e..07ea0a6336e9 100644
---- a/arch/x86/kernel/kvm.c
-+++ b/arch/x86/kernel/kvm.c
-@@ -285,6 +285,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_kvm_asyncpf_interrupt)
- }
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- static void __init paravirt_ops_setup(void)
-diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
-index 4bc77aaf1303..c3c8eec1a597 100644
---- a/arch/x86/kernel/nmi.c
-+++ b/arch/x86/kernel/nmi.c
-@@ -484,11 +484,11 @@ DEFINE_IDTENTRY_RAW(exc_nmi)
- sev_es_nmi_complete();
-
- if (IS_ENABLED(CONFIG_SMP) && arch_cpu_is_offline(smp_processor_id()))
-- return;
-+ return 0;
-
- if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {
- this_cpu_write(nmi_state, NMI_LATCHED);
-- return;
-+ return 0;
- }
- this_cpu_write(nmi_state, NMI_EXECUTING);
- this_cpu_write(nmi_cr2, read_cr2());
-@@ -522,6 +522,7 @@ DEFINE_IDTENTRY_RAW(exc_nmi)
-
- if (user_mode(regs))
- mds_user_clear_cpu_buffers();
-+ return 0;
- }
-
- void stop_nmi(void)
-diff --git a/arch/x86/kernel/sev-es.c b/arch/x86/kernel/sev-es.c
-index 84c1821819af..536e85e4932d 100644
---- a/arch/x86/kernel/sev-es.c
-+++ b/arch/x86/kernel/sev-es.c
-@@ -1260,7 +1260,7 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication)
- */
- if (error_code == SVM_EXIT_EXCP_BASE + X86_TRAP_DB) {
- vc_handle_trap_db(regs);
-- return;
-+ return 0;
- }
-
- instrumentation_begin();
-@@ -1326,7 +1326,7 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication)
- out:
- instrumentation_end();
-
-- return;
-+ return 0;
-
- fail:
- if (user_mode(regs)) {
-@@ -1359,6 +1359,7 @@ DEFINE_IDTENTRY_VC_IST(exc_vmm_communication)
- instrumentation_begin();
- panic("Can't handle #VC exception from unsupported context\n");
- instrumentation_end();
-+ return 0;
- }
-
- DEFINE_IDTENTRY_VC(exc_vmm_communication)
-@@ -1367,6 +1368,7 @@ DEFINE_IDTENTRY_VC(exc_vmm_communication)
- safe_stack_exc_vmm_communication(regs, error_code);
- else
- ist_exc_vmm_communication(regs, error_code);
-+ return 0;
- }
-
- bool __init handle_vc_boot_ghcb(struct pt_regs *regs)
-diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
-index eff4ce3b10da..2b3046a5b07e 100644
---- a/arch/x86/kernel/smp.c
-+++ b/arch/x86/kernel/smp.c
-@@ -136,6 +136,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_reboot)
- ack_APIC_irq();
- cpu_emergency_vmxoff();
- stop_this_cpu(NULL);
-+ return 0;
- }
-
- static int register_stop_handler(void)
-@@ -229,6 +230,7 @@ DEFINE_IDTENTRY_SYSVEC_SIMPLE(sysvec_reschedule_ipi)
- inc_irq_stat(irq_resched_count);
- scheduler_ipi();
- trace_reschedule_exit(RESCHEDULE_VECTOR);
-+ return 0;
- }
-
- DEFINE_IDTENTRY_SYSVEC(sysvec_call_function)
-@@ -238,6 +240,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_call_function)
- inc_irq_stat(irq_call_count);
- generic_smp_call_function_interrupt();
- trace_call_function_exit(CALL_FUNCTION_VECTOR);
-+ return 0;
- }
-
- DEFINE_IDTENTRY_SYSVEC(sysvec_call_function_single)
-@@ -247,6 +250,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_call_function_single)
- inc_irq_stat(irq_call_count);
- generic_smp_call_function_single_interrupt();
- trace_call_function_single_exit(CALL_FUNCTION_SINGLE_VECTOR);
-+ return 0;
- }
-
- static int __init nonmi_ipi_setup(char *str)
-diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
-index 170c94ec0068..39f2ab128cc7 100644
---- a/arch/x86/kernel/traps.c
-+++ b/arch/x86/kernel/traps.c
-@@ -166,17 +166,20 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
- }
- NOKPROBE_SYMBOL(do_trap);
-
--static void do_error_trap(struct pt_regs *regs, long error_code, char *str,
-+static int do_error_trap(struct pt_regs *regs, long error_code, char *str,
- unsigned long trapnr, int signr, int sicode, void __user *addr)
- {
-+ int ret;
-+
- RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
-
-- if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) !=
-- NOTIFY_STOP) {
-+ ret = notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr);
-+ if ((ret & NOTIFY_STOP_MASK) != NOTIFY_STOP_MASK) {
- cond_local_irq_enable(regs);
- do_trap(trapnr, signr, str, regs, error_code, sicode, addr);
- cond_local_irq_disable(regs);
- }
-+ return notifier_to_errno(ret);
- }
-
- /*
-@@ -196,13 +199,14 @@ static __always_inline void __user *error_get_trap_addr(struct pt_regs *regs)
-
- DEFINE_IDTENTRY(exc_divide_error)
- {
-- do_error_trap(regs, 0, "divide error", X86_TRAP_DE, SIGFPE,
-- FPE_INTDIV, error_get_trap_addr(regs));
-+ return do_error_trap(regs, 0, "divide error", X86_TRAP_DE, SIGFPE,
-+ FPE_INTDIV, error_get_trap_addr(regs));
- }
-
- DEFINE_IDTENTRY(exc_overflow)
- {
-- do_error_trap(regs, 0, "overflow", X86_TRAP_OF, SIGSEGV, 0, NULL);
-+ return do_error_trap(regs, 0, "overflow", X86_TRAP_OF, SIGSEGV,
-+ 0, NULL);
- }
-
- #ifdef CONFIG_X86_F00F_BUG
-@@ -253,37 +257,38 @@ DEFINE_IDTENTRY_RAW(exc_invalid_op)
- * in case exception entry is the one triggering WARNs.
- */
- if (!user_mode(regs) && handle_bug(regs))
-- return;
-+ return 0;
-
- state = irqentry_enter(regs);
- instrumentation_begin();
- handle_invalid_op(regs);
- instrumentation_end();
- irqentry_exit(regs, state);
-+ return 0;
- }
-
- DEFINE_IDTENTRY(exc_coproc_segment_overrun)
- {
-- do_error_trap(regs, 0, "coprocessor segment overrun",
-- X86_TRAP_OLD_MF, SIGFPE, 0, NULL);
-+ return do_error_trap(regs, 0, "coprocessor segment overrun",
-+ X86_TRAP_OLD_MF, SIGFPE, 0, NULL);
- }
-
- DEFINE_IDTENTRY_ERRORCODE(exc_invalid_tss)
- {
-- do_error_trap(regs, error_code, "invalid TSS", X86_TRAP_TS, SIGSEGV,
-- 0, NULL);
-+ return do_error_trap(regs, error_code, "invalid TSS", X86_TRAP_TS,
-+ SIGSEGV, 0, NULL);
- }
-
- DEFINE_IDTENTRY_ERRORCODE(exc_segment_not_present)
- {
-- do_error_trap(regs, error_code, "segment not present", X86_TRAP_NP,
-- SIGBUS, 0, NULL);
-+ return do_error_trap(regs, error_code, "segment not present", X86_TRAP_NP,
-+ SIGBUS, 0, NULL);
- }
-
- DEFINE_IDTENTRY_ERRORCODE(exc_stack_segment)
- {
-- do_error_trap(regs, error_code, "stack segment", X86_TRAP_SS, SIGBUS,
-- 0, NULL);
-+ return do_error_trap(regs, error_code, "stack segment", X86_TRAP_SS,
-+ SIGBUS, 0, NULL);
- }
-
- DEFINE_IDTENTRY_ERRORCODE(exc_alignment_check)
-@@ -291,7 +296,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_alignment_check)
- char *str = "alignment check";
-
- if (notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_AC, SIGBUS) == NOTIFY_STOP)
-- return;
-+ return 0;
-
- if (!user_mode(regs))
- die("Split lock detected\n", regs, error_code);
-@@ -306,6 +311,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_alignment_check)
-
- out:
- local_irq_disable();
-+ return 0;
- }
-
- #ifdef CONFIG_VMAP_STACK
-@@ -402,7 +408,7 @@ DEFINE_IDTENTRY_DF(exc_double_fault)
- regs->ip = (unsigned long)asm_exc_general_protection;
- regs->sp = (unsigned long)&gpregs->orig_ax;
-
-- return;
-+ return 0;
- }
- #endif
-
-@@ -461,13 +467,14 @@ DEFINE_IDTENTRY_DF(exc_double_fault)
- die("double fault", regs, error_code);
- panic("Machine halted.");
- instrumentation_end();
-+ return 0;
- }
-
- DEFINE_IDTENTRY(exc_bounds)
- {
- if (notify_die(DIE_TRAP, "bounds", regs, 0,
- X86_TRAP_BR, SIGSEGV) == NOTIFY_STOP)
-- return;
-+ return 0;
- cond_local_irq_enable(regs);
-
- if (!user_mode(regs))
-@@ -476,6 +483,7 @@ DEFINE_IDTENTRY(exc_bounds)
- do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, 0, 0, NULL);
-
- cond_local_irq_disable(regs);
-+ return 0;
- }
-
- enum kernel_gp_hint {
-@@ -529,7 +537,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
- enum kernel_gp_hint hint = GP_NO_HINT;
- struct task_struct *tsk;
- unsigned long gp_addr;
-- int ret;
-+ int ret = 0;
-
- cond_local_irq_enable(regs);
-
-@@ -542,7 +550,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
- local_irq_enable();
- handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
- local_irq_disable();
-- return;
-+ return 0;
- }
-
- tsk = current;
-@@ -572,8 +580,10 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
- goto exit;
-
- ret = notify_die(DIE_GPF, desc, regs, error_code, X86_TRAP_GP, SIGSEGV);
-- if (ret == NOTIFY_STOP)
-+ if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK) {
-+ ret = notifier_to_errno(ret);
- goto exit;
-+ }
-
- if (error_code)
- snprintf(desc, sizeof(desc), "segment-related " GPFSTR);
-@@ -597,9 +607,10 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
-
- exit:
- cond_local_irq_disable(regs);
-+ return ret;
- }
-
--static bool do_int3(struct pt_regs *regs)
-+static bool do_int3(struct pt_regs *regs, int *error_code)
- {
- int res;
-
-@@ -615,28 +626,37 @@ static bool do_int3(struct pt_regs *regs)
- #endif
- res = notify_die(DIE_INT3, "int3", regs, 0, X86_TRAP_BP, SIGTRAP);
-
-- return res == NOTIFY_STOP;
-+ if ((res & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK) {
-+ *error_code = notifier_to_errno (res);
-+ return true;
-+ }
-+
-+ return false;
- }
-
--static void do_int3_user(struct pt_regs *regs)
-+static int do_int3_user(struct pt_regs *regs)
- {
-- if (do_int3(regs))
-- return;
-+ int ret = 0;
-+ if (do_int3(regs, &ret))
-+ return ret;
-
- cond_local_irq_enable(regs);
- do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, 0, 0, NULL);
- cond_local_irq_disable(regs);
-+ return 0;
- }
-
- DEFINE_IDTENTRY_RAW(exc_int3)
- {
-+ int ret = 0;
-+
- /*
- * poke_int3_handler() is completely self contained code; it does (and
- * must) *NOT* call out to anything, lest it hits upon yet another
- * INT3.
- */
- if (poke_int3_handler(regs))
-- return;
-+ return 0;
-
- /*
- * irqentry_enter_from_user_mode() uses static_branch_{,un}likely()
-@@ -648,17 +668,18 @@ DEFINE_IDTENTRY_RAW(exc_int3)
- if (user_mode(regs)) {
- irqentry_enter_from_user_mode(regs);
- instrumentation_begin();
-- do_int3_user(regs);
-+ ret = do_int3_user(regs);
- instrumentation_end();
- irqentry_exit_to_user_mode(regs);
- } else {
- bool irq_state = idtentry_enter_nmi(regs);
- instrumentation_begin();
-- if (!do_int3(regs))
-+ if (!do_int3(regs, &ret))
- die("int3", regs, 0);
- instrumentation_end();
- idtentry_exit_nmi(regs, irq_state);
- }
-+ return ret;
- }
-
- #ifdef CONFIG_X86_64
-@@ -988,12 +1009,14 @@ static __always_inline void exc_debug_user(struct pt_regs *regs,
- DEFINE_IDTENTRY_DEBUG(exc_debug)
- {
- exc_debug_kernel(regs, debug_read_clear_dr6());
-+ return 0;
- }
-
- /* User entry, runs on regular task stack */
- DEFINE_IDTENTRY_DEBUG_USER(exc_debug)
- {
- exc_debug_user(regs, debug_read_clear_dr6());
-+ return 0;
- }
- #else
- /* 32 bit does not have separate entry points. */
-@@ -1005,6 +1028,7 @@ DEFINE_IDTENTRY_RAW(exc_debug)
- exc_debug_user(regs, dr6);
- else
- exc_debug_kernel(regs, dr6);
-+ return 0;
- }
- #endif
-
-@@ -1058,6 +1082,7 @@ static void math_error(struct pt_regs *regs, int trapnr)
- DEFINE_IDTENTRY(exc_coprocessor_error)
- {
- math_error(regs, X86_TRAP_MF);
-+ return 0;
- }
-
- DEFINE_IDTENTRY(exc_simd_coprocessor_error)
-@@ -1066,10 +1091,11 @@ DEFINE_IDTENTRY(exc_simd_coprocessor_error)
- /* AMD 486 bug: INVD in CPL 0 raises #XF instead of #GP */
- if (!static_cpu_has(X86_FEATURE_XMM)) {
- __exc_general_protection(regs, 0);
-- return;
-+ return 0;
- }
- }
- math_error(regs, X86_TRAP_XF);
-+ return 0;
- }
-
- DEFINE_IDTENTRY(exc_spurious_interrupt_bug)
-@@ -1093,6 +1119,7 @@ DEFINE_IDTENTRY(exc_spurious_interrupt_bug)
- * In theory this could be limited to 32bit, but the handler is not
- * hurting and who knows which other CPUs suffer from this.
- */
-+ return 0;
- }
-
- DEFINE_IDTENTRY(exc_device_not_available)
-@@ -1109,7 +1136,7 @@ DEFINE_IDTENTRY(exc_device_not_available)
- math_emulate(&info);
-
- cond_local_irq_disable(regs);
-- return;
-+ return 0;
- }
- #endif
-
-@@ -1125,6 +1152,7 @@ DEFINE_IDTENTRY(exc_device_not_available)
- */
- die("unexpected #NM exception", regs, 0);
- }
-+ return 0;
- }
-
- #ifdef CONFIG_X86_32
-@@ -1137,6 +1165,7 @@ DEFINE_IDTENTRY_SW(iret_error)
- ILL_BADSTK, (void __user *)NULL);
- }
- local_irq_disable();
-+ return 0;
- }
- #endif
-
-diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
-index 5b16183100d0..d5b9734946c3 100644
---- a/arch/x86/mm/fault.c
-+++ b/arch/x86/mm/fault.c
-@@ -1493,7 +1493,7 @@ DEFINE_IDTENTRY_RAW_ERRORCODE(exc_page_fault)
- * itself.
- */
- if (kvm_handle_async_pf(regs, (u32)address))
-- return;
-+ return 0;
-
- /*
- * Entry handling for valid #PF from kernel mode is slightly
-@@ -1512,4 +1512,5 @@ DEFINE_IDTENTRY_RAW_ERRORCODE(exc_page_fault)
- instrumentation_end();
-
- irqentry_exit(regs, state);
-+ return 0;
- }
-diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
-index ec50b7423a4c..1c4b08f2dc3b 100644
---- a/arch/x86/xen/enlighten_hvm.c
-+++ b/arch/x86/xen/enlighten_hvm.c
-@@ -129,6 +129,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_xen_hvm_callback)
- xen_hvm_evtchn_do_upcall();
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- #ifdef CONFIG_KEXEC_CORE
-diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
-index 4409306364dc..080702bf757b 100644
---- a/arch/x86/xen/enlighten_pv.c
-+++ b/arch/x86/xen/enlighten_pv.c
-@@ -563,12 +563,12 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
- preempt_enable();
- }
-
--void noist_exc_debug(struct pt_regs *regs);
-+int noist_exc_debug(struct pt_regs *regs);
-
- DEFINE_IDTENTRY_RAW(xenpv_exc_nmi)
- {
- /* On Xen PV, NMI doesn't use IST. The C part is the sane as native. */
-- exc_nmi(regs);
-+ return exc_nmi(regs);
- }
-
- DEFINE_IDTENTRY_RAW(xenpv_exc_debug)
-@@ -578,9 +578,9 @@ DEFINE_IDTENTRY_RAW(xenpv_exc_debug)
- * to the correct handler.
- */
- if (user_mode(regs))
-- noist_exc_debug(regs);
-+ return noist_exc_debug(regs);
- else
-- exc_debug(regs);
-+ return exc_debug(regs);
- }
-
- struct trap_array_entry {
-diff --git a/include/linux/dtrace_fbt.h b/include/linux/dtrace_fbt.h
-new file mode 100644
-index 000000000000..d11e273cee31
---- /dev/null
-+++ b/include/linux/dtrace_fbt.h
-@@ -0,0 +1,48 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ *Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FBT_H
-+#define _LINUX_DTRACE_FBT_H
-+
-+#include <linux/module.h>
-+#include <asm/dtrace_arch.h>
-+
-+extern unsigned long dtrace_fbt_nfuncs __attribute__((weak));
-+
-+/*
-+ * Prototype for callback function that handles the actual creation of FBT
-+ * probes.
-+ *
-+ * Arguments to pass:
-+ * - Pointer to module the probe will belong to
-+ * - function name
-+ * - probe type (FBT_ENTRY or FBT_RETURN)
-+ * - probe subtype (arch-specific)
-+ * - address (location of the probe)
-+ * - offset from the function start
-+ * - return value from previous callback invocation
-+ * - cookie passed to dtrace_fbt_init
-+ * Returns:
-+ * - generic pointer (only to be used to pass back in)
-+ */
-+#define FBT_ENTRY 0
-+#define FBT_RETURN 1
-+
-+typedef void *(*fbt_add_probe_fn)(struct module *, char *, int, int,
-+ asm_instr_t *, uintptr_t, void *, void *);
-+extern void dtrace_fbt_init(fbt_add_probe_fn, struct module *, void *);
-+
-+/*
-+ * Dynamic blacklist routines.
-+ */
-+struct dt_fbt_bl_entry;
-+
-+extern struct dt_fbt_bl_entry *dtrace_fbt_bl_add(unsigned long, const char *);
-+extern struct dt_fbt_bl_entry *dtrace_fbt_bl_first(void);
-+extern struct dt_fbt_bl_entry *dtrace_fbt_bl_next(struct dt_fbt_bl_entry *);
-+extern unsigned long dtrace_fbt_bl_entry_addr(struct dt_fbt_bl_entry *);
-+extern const char *dtrace_fbt_bl_entry_name(struct dt_fbt_bl_entry *);
-+
-+#endif /* _LINUX_DTRACE_FBT_H */
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-index 6bf6620981cd..1f070e49c69f 100644
---- a/kernel/dtrace/Kconfig
-+++ b/kernel/dtrace/Kconfig
-@@ -55,6 +55,13 @@ config DT_SDT_PERF
- Provides the perf provider, containing a DTrace probe for each
- perf-events tracepoint in the system.
-
-+config DT_FBT
-+ tristate "Function boundary tracing"
-+ default m
-+ select FTRACE
-+ help
-+ Provides function boundary tracing for functions in the kernel.
-+
- config DT_SYSTRACE
- tristate "System Call Tracing"
- default m
-diff --git a/kernel/dtrace/Makefile b/kernel/dtrace/Makefile
-index 06329cbe52cb..0e5fb34b7b47 100644
---- a/kernel/dtrace/Makefile
-+++ b/kernel/dtrace/Makefile
-@@ -4,11 +4,11 @@
-
- DT_CORE_ARCH_OBJS = $(addprefix ../../arch/$(SRCARCH)/kernel/, \
- dtrace_syscall.o dtrace_syscall_stubs.o \
-- dtrace_sdt.o dtrace_util.o)
-+ dtrace_fbt.o dtrace_sdt.o dtrace_util.o)
-
- ifdef CONFIG_DT_CORE
- obj-y += cyclic.o dtrace_os.o dtrace_cpu.o \
-- dtrace_sdt_core.o \
-+ dtrace_sdt_core.o dtrace_fbt_core.o \
- dtrace_task.o dtrace_psinfo.o \
- $(DT_CORE_ARCH_OBJS)
- endif
-diff --git a/kernel/dtrace/dtrace_fbt_core.c b/kernel/dtrace/dtrace_fbt_core.c
-new file mode 100644
-index 000000000000..67182a3b13fc
---- /dev/null
-+++ b/kernel/dtrace/dtrace_fbt_core.c
-@@ -0,0 +1,125 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_fbt_core.c
-+ * DESCRIPTION: DTrace - FBT common code
-+ *
-+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/kallsyms.h>
-+#include <linux/rbtree.h>
-+#include <linux/slab.h>
-+#include <linux/dtrace_fbt.h>
-+
-+struct dt_fbt_bl_entry {
-+ struct rb_node dfbe_node;
-+ unsigned long dfbe_addr;
-+ const char *dfbe_name;
-+};
-+
-+static struct rb_root dt_fbt_root = RB_ROOT;
-+
-+struct dt_fbt_bl_entry *
-+dtrace_fbt_bl_add(unsigned long addr, const char *name)
-+{
-+ struct rb_node **p = &dt_fbt_root.rb_node;
-+ struct rb_node *parent = NULL;
-+ struct dt_fbt_bl_entry *entry;
-+
-+ /*
-+ * If no address was given, we need to do a symbol name lookup:
-+ * - If no symbol name was given, we cannot add anything.
-+ * - If the lookup failed, we cannot add anything.
-+ */
-+ if (addr == 0) {
-+ if (name == NULL)
-+ return NULL;
-+
-+ addr = kallsyms_lookup_name(name);
-+
-+ if (addr == 0)
-+ return NULL;
-+ }
-+
-+ /* Find place in the tree. */
-+ while (*p) {
-+ parent = *p;
-+ entry = rb_entry(parent, struct dt_fbt_bl_entry, dfbe_node);
-+
-+ if (addr > entry->dfbe_addr)
-+ p = &parent->rb_right;
-+ else if (addr < entry->dfbe_addr)
-+ p = &parent->rb_left;
-+ else
-+ return NULL; /* no duplicates please */
-+ }
-+
-+ /* Create a new blacklist entry. */
-+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-+ if (entry == NULL)
-+ return NULL;
-+
-+ entry->dfbe_name = name;
-+ entry->dfbe_addr = addr;
-+
-+ /* Update the tree. */
-+ rb_link_node(&entry->dfbe_node, parent, p);
-+ rb_insert_color(&entry->dfbe_node, &dt_fbt_root);
-+
-+ return entry;
-+}
-+
-+/*
-+ * Iterators for blacklisted symbols. The iteration happens in sort order by
-+ * virtual memory address. Symbols with pending resolution are inored.
-+ */
-+struct dt_fbt_bl_entry *
-+dtrace_fbt_bl_first(void)
-+{
-+ struct rb_node *node = rb_first(&dt_fbt_root);
-+
-+ if (node == NULL)
-+ return (NULL);
-+
-+ return rb_entry(node, struct dt_fbt_bl_entry, dfbe_node);
-+}
-+
-+struct dt_fbt_bl_entry *
-+dtrace_fbt_bl_next(struct dt_fbt_bl_entry *entry)
-+{
-+ struct rb_node *node = rb_next(&entry->dfbe_node);
-+
-+ if (node == NULL)
-+ return (NULL);
-+
-+ return rb_entry(node, struct dt_fbt_bl_entry, dfbe_node);
-+}
-+
-+unsigned long
-+dtrace_fbt_bl_entry_addr(struct dt_fbt_bl_entry *entry)
-+{
-+ if (entry == NULL)
-+ return (0);
-+
-+ return entry->dfbe_addr;
-+}
-+
-+const char *
-+dtrace_fbt_bl_entry_name(struct dt_fbt_bl_entry *entry)
-+{
-+ if (entry == NULL)
-+ return (NULL);
-+
-+ return entry->dfbe_name;
-+}
-diff --git a/kernel/dtrace/dtrace_os.c b/kernel/dtrace/dtrace_os.c
-index 874e097b84fd..bb5650cf72eb 100644
---- a/kernel/dtrace/dtrace_os.c
-+++ b/kernel/dtrace/dtrace_os.c
-@@ -18,6 +18,7 @@
-
- #include <linux/binfmts.h>
- #include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_fbt.h>
- #include <linux/dtrace_os.h>
- #include <linux/dtrace_sdt.h>
- #include <linux/fs.h>
-@@ -103,6 +104,7 @@ void __init dtrace_os_init(void)
- dtrace_kmod->core_layout.size = 0x2000000;
- #endif
-
-+ dtrace_kmod->num_ftrace_callsites = dtrace_fbt_nfuncs;
- dtrace_kmod->state = MODULE_STATE_LIVE;
- atomic_inc(&dtrace_kmod->refcnt);
-
-diff --git a/kernel/kprobes.c b/kernel/kprobes.c
-index 41fdbb7953c6..b702c7c484e7 100644
---- a/kernel/kprobes.c
-+++ b/kernel/kprobes.c
-@@ -38,6 +38,10 @@
- #include <linux/perf_event.h>
- #include <linux/static_call.h>
-
-+#ifdef CONFIG_DTRACE
-+#include <linux/dtrace_fbt.h>
-+#endif
-+
- #include <asm/sections.h>
- #include <asm/cacheflush.h>
- #include <asm/errno.h>
-@@ -2336,6 +2340,10 @@ int kprobe_add_ksym_blacklist(unsigned long entry)
- !kallsyms_lookup_size_offset(entry, &size, &offset))
- return -EINVAL;
-
-+#ifdef CONFIG_DTRACE
-+ dtrace_fbt_bl_add(entry, NULL);
-+#endif
-+
- ent = kmalloc(sizeof(*ent), GFP_KERNEL);
- if (!ent)
- return -ENOMEM;
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0015-dtrace-fbt-provider-modular-components.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0015-dtrace-fbt-provider-modular-components.patch
deleted file mode 100644
index 700f494ff26d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0015-dtrace-fbt-provider-modular-components.patch
+++ /dev/null
@@ -1,683 +0,0 @@
-From b3955b4ec46d8139665fc881dd088e9fcb67ff36 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 18:12:44 +0000
-Subject: [PATCH 15/19] dtrace: fbt provider, modular components
-
-This uses the fbt machinery added in the previous commit.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/dtrace/Makefile.arch | 2 +
- arch/x86/dtrace/fbt_x86_64.c | 156 ++++++++++++
- arch/x86/dtrace/include/dtrace/fbt_arch.h | 42 ++++
- dtrace/Makefile | 2 +
- dtrace/fbt_dev.c | 281 ++++++++++++++++++++++
- dtrace/fbt_impl.h | 52 ++++
- dtrace/fbt_mod.c | 56 +++++
- 7 files changed, 591 insertions(+)
- create mode 100644 arch/x86/dtrace/fbt_x86_64.c
- create mode 100644 arch/x86/dtrace/include/dtrace/fbt_arch.h
- create mode 100644 dtrace/fbt_dev.c
- create mode 100644 dtrace/fbt_impl.h
- create mode 100644 dtrace/fbt_mod.c
-
-diff --git a/arch/x86/dtrace/Makefile.arch b/arch/x86/dtrace/Makefile.arch
-index e4655557e06a..906fa8c7e17c 100644
---- a/arch/x86/dtrace/Makefile.arch
-+++ b/arch/x86/dtrace/Makefile.arch
-@@ -8,8 +8,10 @@ ccflags-y += -I$(srctree)/arch/x86/dtrace/include -Idtrace
-
- dtrace-obj += dtrace_asm_x86_64.o dtrace_isa_x86_64.o
- fasttrap-obj += fasttrap_x86_64.o
-+fbt-obj += fbt_x86_64.o
- sdt-obj += sdt_x86_64.o
-
- dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
- fasttrap-y += $(addprefix $(DTARCHDIR)/, $(fasttrap-obj))
-+fbt-y += $(addprefix $(DTARCHDIR)/, $(fbt-obj))
- sdt-y += $(addprefix $(DTARCHDIR)/, $(sdt-obj))
-diff --git a/arch/x86/dtrace/fbt_x86_64.c b/arch/x86/dtrace/fbt_x86_64.c
-new file mode 100644
-index 000000000000..a8a05292be7e
---- /dev/null
-+++ b/arch/x86/dtrace/fbt_x86_64.c
-@@ -0,0 +1,156 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fbt_x86_64.c
-+ * DESCRIPTION: DTrace - FBT provider implementation for x86
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_fbt.h>
-+#include <linux/vmalloc.h>
-+#include <asm/dtrace_util.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fbt_impl.h"
-+
-+/*
-+ * Use 0xf0 (LOCK Prefix) and X86_TRAP_UD for Invalid Opcode traps to be used.
-+ * Use 0xcc (INT 3) and X86_TRAP_BP for Breakpoint traps to be used.
-+ */
-+#define FBT_ENTRY_PATCHVAL 0xcc
-+#define FBT_ENTRY_TRAP X86_TRAP_BP
-+#define FBT_RETURN_PATCHVAL 0xcc
-+#define FBT_RETURN_TRAP X86_TRAP_BP
-+
-+static uint8_t fbt_invop(struct pt_regs *regs)
-+{
-+ struct fbt_probe *fbp = fbt_probetab[FBT_ADDR2NDX(regs->ip)];
-+
-+ for (; fbp != NULL; fbp = fbp->fbp_hashnext) {
-+ if ((uintptr_t)fbp->fbp_patchpoint == regs->ip) {
-+ struct pt_regs *old = this_cpu_core->cpu_dtrace_regs;
-+
-+ this_cpu_core->cpu_dtrace_regs = regs;
-+ if (fbp->fbp_roffset == 0) {
-+ dtrace_probe(fbp->fbp_id, regs->di, regs->si,
-+ regs->dx, regs->cx, regs->r8,
-+ regs->r9, 0);
-+ } else {
-+ dtrace_probe(fbp->fbp_id, fbp->fbp_roffset,
-+ regs->ax, 0, 0, 0, 0, 0);
-+ }
-+
-+ this_cpu_core->cpu_dtrace_regs = old;
-+
-+ return fbp->fbp_rval;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+uint64_t fbt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ return 0;
-+
-+ switch (argno) {
-+ case 0:
-+ return regs->di;
-+ case 1:
-+ return regs->si;
-+ case 2:
-+ return regs->dx;
-+ case 3:
-+ return regs->cx;
-+ case 4:
-+ return regs->r8;
-+ case 5:
-+ return regs->r9;
-+ }
-+
-+ ASSERT(argno > 5);
-+
-+ st = (uint64_t *)regs->sp;
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ /*
-+ * Skip the topmost slot of the stack because that holds the return
-+ * address for the call to the function we are entering. At this point
-+ * the BP has not been pushed yet, so we are still working within the
-+ * caller's stack frame.
-+ */
-+ val = st[1 + argno - 6];
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return val;
-+}
-+
-+void fbt_provide_probe_arch(struct fbt_probe *fbp, int probetype, int stype)
-+{
-+ fbp->fbp_patchval = probetype == FBT_ENTRY ? FBT_ENTRY_PATCHVAL
-+ : FBT_RETURN_PATCHVAL;
-+ fbp->fbp_savedval = *fbp->fbp_patchpoint;
-+ fbp->fbp_rval = probetype == FBT_ENTRY ? DTRACE_INVOP_PUSH_BP
-+ : DTRACE_INVOP_RET;
-+}
-+
-+int fbt_can_patch_return_arch(asm_instr_t *addr)
-+{
-+ return 1;
-+}
-+
-+int fbt_provide_module_arch(void *arg, struct module *mp)
-+{
-+ return 1;
-+}
-+
-+void fbt_destroy_module(void *arg, struct module *mp)
-+{
-+}
-+
-+void fbt_enable_arch(struct fbt_probe *fbp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_invop_enable(fbp->fbp_patchpoint, fbp->fbp_patchval);
-+}
-+
-+void fbt_disable_arch(struct fbt_probe *fbp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_invop_disable(fbp->fbp_patchpoint, fbp->fbp_savedval);
-+}
-+
-+int fbt_dev_init_arch(void)
-+{
-+ fbt_probetab_mask = fbt_probetab_size - 1;
-+ fbt_probetab = dtrace_vzalloc_try(fbt_probetab_size *
-+ sizeof(struct fbt_probe *));
-+
-+ if (fbt_probetab == NULL)
-+ return -ENOMEM;
-+
-+ return dtrace_invop_add(fbt_invop);
-+}
-+
-+void fbt_dev_exit_arch(void)
-+{
-+ vfree(fbt_probetab);
-+ fbt_probetab_mask = 0;
-+ fbt_probetab_size = 0;
-+
-+ dtrace_invop_remove(fbt_invop);
-+}
-diff --git a/arch/x86/dtrace/include/dtrace/fbt_arch.h b/arch/x86/dtrace/include/dtrace/fbt_arch.h
-new file mode 100644
-index 000000000000..7e90b2b75bba
---- /dev/null
-+++ b/arch/x86/dtrace/include/dtrace/fbt_arch.h
-@@ -0,0 +1,42 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - FBT Implementation defines
-+ *
-+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _X86_64_FBT_ARCH_H
-+#define _X86_64_FBT_ARCH_H
-+
-+#define FBT_AFRAMES 7
-+
-+struct fbt_probe {
-+ char *fbp_name; /* name of probe */
-+ dtrace_id_t fbp_id; /* probe ID */
-+ struct module *fbp_module; /* defining module */
-+ int fbp_primary; /* non-zero if primary mod */
-+ asm_instr_t *fbp_patchpoint;/* patch point */
-+ asm_instr_t fbp_patchval; /* instruction to patch */
-+ asm_instr_t fbp_savedval; /* saved instruction value */
-+ uintptr_t fbp_roffset; /* relative offset */
-+ int fbp_rval;
-+ struct fbt_probe *fbp_next; /* next probe */
-+ struct fbt_probe *fbp_hashnext; /* next on hash */
-+};
-+
-+#endif /* _X86_64_FBT_ARCH_H */
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-index c7e3fc512a6c..35b8b098123f 100644
---- a/dtrace/Makefile
-+++ b/dtrace/Makefile
-@@ -4,6 +4,7 @@
-
- obj-$(CONFIG_DT_CORE) += dtrace.o
- obj-$(CONFIG_DT_FASTTRAP) += fasttrap.o
-+obj-$(CONFIG_DT_FBT) += fbt.o
- obj-$(CONFIG_DT_PROFILE) += profile.o
- obj-$(CONFIG_DT_SDT) += sdt.o
- obj-$(CONFIG_DT_SYSTRACE) += systrace.o
-@@ -19,6 +20,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \
- dtrace_ptofapi.o dtrace_predicate.o \
- dtrace_spec.o dtrace_state.o dtrace_util.o
- fasttrap-y := fasttrap_mod.o fasttrap_dev.o
-+fbt-y := fbt_mod.o fbt_dev.o
- profile-y := profile_mod.o profile_dev.o
- sdt-y := sdt_mod.o sdt_dev.o
- systrace-y := systrace_mod.o systrace_dev.o
-diff --git a/dtrace/fbt_dev.c b/dtrace/fbt_dev.c
-new file mode 100644
-index 000000000000..281fd749aae7
---- /dev/null
-+++ b/dtrace/fbt_dev.c
-@@ -0,0 +1,281 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fbt_dev.c
-+ * DESCRIPTION: DTrace - FBT provider device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/kallsyms.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <linux/dtrace_fbt.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fbt_impl.h"
-+
-+#define FBT_PROBETAB_SIZE 0x8000 /* 32k entries -- 128K total */
-+
-+struct fbt_probe **fbt_probetab;
-+int fbt_probetab_size = FBT_PROBETAB_SIZE;
-+int fbt_probetab_mask;
-+
-+static void *fbt_provide_probe(struct module *mp, char *func, int probetype,
-+ int stype, asm_instr_t *addr, uintptr_t off,
-+ void *pfbt, void *arg)
-+{
-+ struct fbt_probe *fbp;
-+ struct fbt_probe *prev;
-+ int *skipped = arg;
-+
-+ switch (probetype) {
-+ case FBT_ENTRY:
-+ fbp = kzalloc(sizeof(struct fbt_probe), GFP_KERNEL);
-+ fbp->fbp_name = kstrdup(func, GFP_KERNEL);
-+ if (fbp->fbp_name == NULL)
-+ goto err_probe;
-+
-+ fbp->fbp_id = dtrace_probe_create(fbt_id, mp->name, func,
-+ "entry", FBT_AFRAMES, fbp);
-+ if (fbp->fbp_id == DTRACE_IDNONE)
-+ goto err_name;
-+
-+ fbp->fbp_module = mp;
-+ fbp->fbp_primary = 1; /* FIXME */
-+ fbp->fbp_roffset = off;
-+ fbp->fbp_patchpoint = addr;
-+ fbt_provide_probe_arch(fbp, probetype, stype);
-+
-+ fbp->fbp_hashnext = fbt_probetab[FBT_ADDR2NDX(fbp->fbp_patchpoint)];
-+ fbt_probetab[FBT_ADDR2NDX(fbp->fbp_patchpoint)] = fbp;
-+
-+ PDATA(mp)->fbt_probe_cnt++;
-+
-+ return fbp;
-+ case FBT_RETURN:
-+
-+ /* Check if we are able to patch this return probe. */
-+ if (!fbt_can_patch_return_arch(addr))
-+ return pfbt;
-+
-+ fbp = kzalloc(sizeof(struct fbt_probe), GFP_KERNEL);
-+ fbp->fbp_name = kstrdup(func, GFP_KERNEL);
-+ if (fbp->fbp_name == NULL)
-+ goto err_probe;
-+
-+ prev = (struct fbt_probe *)pfbt;
-+ if (prev != NULL) {
-+ prev->fbp_next = fbp;
-+ fbp->fbp_id = prev->fbp_id;
-+ } else {
-+ fbp->fbp_id = dtrace_probe_create(fbt_id, mp->name,
-+ func, "return",
-+ FBT_AFRAMES, fbp);
-+ if (fbp->fbp_id == DTRACE_IDNONE)
-+ goto err_name;
-+ }
-+
-+ fbp->fbp_module = mp;
-+ fbp->fbp_primary = 1; /* FIXME */
-+ fbp->fbp_roffset = off;
-+ fbp->fbp_patchpoint = addr;
-+ fbt_provide_probe_arch(fbp, probetype, stype);
-+
-+ fbp->fbp_hashnext = fbt_probetab[FBT_ADDR2NDX(fbp->fbp_patchpoint)];
-+ fbt_probetab[FBT_ADDR2NDX(fbp->fbp_patchpoint)] = fbp;
-+
-+ PDATA(mp)->fbt_probe_cnt++;
-+
-+ return fbp;
-+ default:
-+ pr_info("FBT: Invalid probe type %d (%d) for %s\n",
-+ probetype, stype, func);
-+
-+ return NULL;
-+ }
-+
-+err_name:
-+ kfree(fbp->fbp_name);
-+err_probe:
-+ kfree(fbp);
-+ (*skipped)++;
-+
-+ return NULL;
-+}
-+
-+void fbt_provide_module(void *arg, struct module *mp)
-+{
-+ struct module_use *use;
-+ int probes_skipped = 0;
-+
-+ /* If module setup has failed then do not provide anything. */
-+ if (PDATA(mp) == NULL)
-+ return;
-+
-+ /*
-+ * Nothing to do if the module FBT probes were already created.
-+ */
-+ if (PDATA(mp)->fbt_probe_cnt != 0)
-+ return;
-+
-+ /*
-+ * Do not try to instrument DTrace itself and its modules:
-+ * - dtrace module
-+ * - all modules depending on dtrace
-+ */
-+ if (!strncmp(mp->name, "dtrace", 7))
-+ return;
-+
-+ list_for_each_entry(use, &mp->target_list, target_list) {
-+ if (!strncmp(use->target->name, "dtrace", 7))
-+ return;
-+ }
-+
-+ /*
-+ * Provide probes.
-+ */
-+ if (!fbt_provide_module_arch(arg, mp))
-+ return;
-+
-+ dtrace_fbt_init((fbt_add_probe_fn)fbt_provide_probe, mp,
-+ &probes_skipped);
-+
-+ if (probes_skipped != 0)
-+ pr_warn("fbt: Failed to provide %d probes in %s (out of memory)\n",
-+ probes_skipped, mp->name);
-+}
-+
-+int fbt_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fbt_probe *fbp = parg;
-+ struct fbt_probe *curr;
-+
-+ /*
-+ * Ensure that we have a reference to the module.
-+ */
-+ if (!try_module_get(fbp->fbp_module))
-+ return -EAGAIN;
-+
-+ /*
-+ * If at least one other enabled probe exists for this module, drop the
-+ * reference we took above, because we only need one to prevent the
-+ * module from being unloaded.
-+ */
-+ PDATA(fbp->fbp_module)->enabled_cnt++;
-+ if (PDATA(fbp->fbp_module)->enabled_cnt > 1)
-+ module_put(fbp->fbp_module);
-+
-+ for (curr = fbp; curr != NULL; curr = curr->fbp_next)
-+ fbt_enable_arch(curr, id, arg);
-+
-+ return 0;
-+}
-+
-+void fbt_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fbt_probe *fbp = parg;
-+ struct fbt_probe *curr;
-+
-+ for (curr = fbp; curr != NULL; curr = curr->fbp_next)
-+ fbt_disable_arch(curr, id, arg);
-+
-+ /*
-+ * If we are disabling a probe, we know it was enabled, and therefore
-+ * we know that we have a reference on the module to prevent it from
-+ * being unloaded. If we disable the last probe on the module, we can
-+ * drop the reference.
-+ */
-+ PDATA(fbp->fbp_module)->enabled_cnt--;
-+ if (PDATA(fbp->fbp_module)->enabled_cnt == 0)
-+ module_put(fbp->fbp_module);
-+}
-+
-+void fbt_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fbt_probe *fbp = parg;
-+ struct fbt_probe *hbp, *lst, *nxt;
-+ int ndx;
-+ struct module *mp = fbp->fbp_module;
-+
-+ do {
-+ nxt = fbp->fbp_next;
-+
-+ ndx = FBT_ADDR2NDX(fbp->fbp_patchpoint);
-+ lst = NULL;
-+ hbp = fbt_probetab[ndx];
-+
-+ while (hbp != fbp) {
-+ ASSERT(hbp != NULL);
-+
-+ lst = hbp;
-+ hbp = hbp->fbp_hashnext;
-+ }
-+
-+ if (lst != NULL)
-+ lst->fbp_hashnext = fbp->fbp_hashnext;
-+ else
-+ fbt_probetab[ndx] = fbp->fbp_hashnext;
-+
-+ kfree(fbp->fbp_name);
-+ kfree(fbp);
-+
-+ PDATA(mp)->fbt_probe_cnt--;
-+
-+ fbp = nxt;
-+ } while (fbp != NULL);
-+}
-+
-+static int fbt_open(struct inode *inode, struct file *file)
-+{
-+ return -EAGAIN;
-+}
-+
-+static int fbt_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations fbt_fops = {
-+ .owner = THIS_MODULE,
-+ .open = fbt_open,
-+ .release = fbt_close,
-+};
-+
-+static struct miscdevice fbt_dev = {
-+ .minor = DT_DEV_FBT_MINOR,
-+ .name = "fbt",
-+ .nodename = "dtrace/provider/fbt",
-+ .fops = &fbt_fops,
-+};
-+
-+int fbt_dev_init(void)
-+{
-+ int ret = 0;
-+
-+ ret = misc_register(&fbt_dev);
-+ if (ret)
-+ pr_err("%s: Can't register misc device %d\n",
-+ fbt_dev.name, fbt_dev.minor);
-+
-+ return fbt_dev_init_arch();
-+}
-+
-+void fbt_dev_exit(void)
-+{
-+ fbt_dev_exit_arch();
-+
-+ misc_deregister(&fbt_dev);
-+}
-diff --git a/dtrace/fbt_impl.h b/dtrace/fbt_impl.h
-new file mode 100644
-index 000000000000..85f83e704988
---- /dev/null
-+++ b/dtrace/fbt_impl.h
-@@ -0,0 +1,52 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Function Boundary Tracing provider
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _FBT_H_
-+#define _FBT_H_
-+
-+#include <asm/dtrace_arch.h>
-+#include <dtrace/fbt_arch.h>
-+
-+#define FBT_ADDR2NDX(addr) ((((uintptr_t)(addr)) >> 4) & \
-+ fbt_probetab_mask)
-+
-+extern struct fbt_probe **fbt_probetab;
-+extern int fbt_probetab_size;
-+extern int fbt_probetab_mask;
-+
-+extern void fbt_provide_probe_arch(struct fbt_probe *, int, int);
-+extern void fbt_enable_arch(struct fbt_probe *, dtrace_id_t, void *);
-+extern void fbt_disable_arch(struct fbt_probe *, dtrace_id_t, void *);
-+extern int fbt_can_patch_return_arch(asm_instr_t *);
-+
-+extern int fbt_provide_module_arch(void *, struct module *);
-+extern void fbt_provide_module(void *, struct module *);
-+extern void fbt_destroy_module(void *, struct module *);
-+extern int fbt_enable(void *, dtrace_id_t, void *);
-+extern void fbt_disable(void *, dtrace_id_t, void *);
-+extern uint64_t fbt_getarg(void *, dtrace_id_t, void *, int, int);
-+extern void fbt_destroy(void *, dtrace_id_t, void *);
-+
-+extern dtrace_provider_id_t fbt_id;
-+
-+extern int fbt_dev_init_arch(void);
-+extern void fbt_dev_exit_arch(void);
-+
-+extern int fbt_dev_init(void);
-+extern void fbt_dev_exit(void);
-+
-+#endif /* _FBT_H_ */
-diff --git a/dtrace/fbt_mod.c b/dtrace/fbt_mod.c
-new file mode 100644
-index 000000000000..3da13d71809d
---- /dev/null
-+++ b/dtrace/fbt_mod.c
-@@ -0,0 +1,56 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fbt_mod.c
-+ * DESCRIPTION: DTrace - FBT provider kernel module
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fbt_impl.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("Function Boundary Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+static const struct dtrace_pattr fbt_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pops fbt_pops = {
-+ .dtps_provide = NULL,
-+ .dtps_provide_module = fbt_provide_module,
-+ .dtps_destroy_module = fbt_destroy_module,
-+ .dtps_enable = fbt_enable,
-+ .dtps_disable = fbt_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = NULL,
-+#ifdef CONFIG_X86_64
-+ .dtps_getargval = fbt_getarg,
-+#else
-+ .dtps_getargval = NULL,
-+#endif
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = fbt_destroy
-+};
-+
-+DT_PROVIDER_MODULE(fbt, DTRACE_PRIV_KERNEL)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0016-dtrace-arm-arm64-port.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0016-dtrace-arm-arm64-port.patch
deleted file mode 100644
index a0e8ded1a459..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0016-dtrace-arm-arm64-port.patch
+++ /dev/null
@@ -1,2667 +0,0 @@
-From 7448665d4354efd9fafea1149cc2adc31dc98c64 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Thu, 8 Nov 2018 18:57:33 +0000
-Subject: [PATCH 16/19] dtrace, arm: arm64 port
-
-This provides an arm64 implementation of DTrace.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/arm64/Kconfig | 3 +
- arch/arm64/dtrace/Makefile.arch | 17 +
- arch/arm64/dtrace/dtrace_asm_arm64.S | 51 +++
- arch/arm64/dtrace/dtrace_isa_arm64.c | 164 +++++++
- arch/arm64/dtrace/fasttrap_arm64.c | 282 ++++++++++++
- arch/arm64/dtrace/fbt_arm64.c | 152 +++++++
- .../dtrace/include/dtrace/fasttrap_arch.h | 30 ++
- arch/arm64/dtrace/include/dtrace/fbt_arch.h | 53 +++
- arch/arm64/dtrace/include/dtrace/sdt_arch.h | 28 ++
- arch/arm64/dtrace/sdt_arm64.c | 122 +++++
- arch/arm64/include/asm/brk-imm.h | 6 +
- arch/arm64/include/asm/cpu.h | 1 +
- arch/arm64/include/asm/debug-monitors.h | 4 +
- arch/arm64/include/asm/dtrace_arch.h | 31 ++
- arch/arm64/include/asm/dtrace_cpuinfo.h | 13 +
- arch/arm64/include/asm/dtrace_sdt_arch.h | 15 +
- arch/arm64/include/asm/dtrace_syscall.h | 3 +
- arch/arm64/include/asm/dtrace_syscall_types.h | 11 +
- arch/arm64/include/asm/dtrace_util.h | 14 +
- arch/arm64/include/asm/kdebug.h | 11 +
- arch/arm64/include/asm/syscall.h | 8 +-
- arch/arm64/kernel/dtrace_fbt.c | 187 ++++++++
- arch/arm64/kernel/dtrace_sdt.c | 25 ++
- arch/arm64/kernel/dtrace_syscall.c | 89 ++++
- arch/arm64/kernel/dtrace_syscall_stubs.S | 0
- arch/arm64/kernel/dtrace_util.c | 292 ++++++++++++
- arch/arm64/kernel/entry-common.c | 6 +-
- arch/arm64/kernel/entry.S | 53 ++-
- arch/arm64/kernel/fbt_blacklist.h | 91 ++++
- arch/arm64/kernel/probes/uprobes.c | 3 +-
- arch/arm64/kernel/sys.c | 2 +-
- arch/arm64/mm/fault.c | 18 +
- include/linux/uprobes.h | 1 +
- kernel/events/uprobes.c | 10 +
- scripts/dtrace_sdt_arm64.sh | 425 ++++++++++++++++++
- scripts/link-vmlinux.sh | 15 +-
- 36 files changed, 2221 insertions(+), 15 deletions(-)
- create mode 100644 arch/arm64/dtrace/Makefile.arch
- create mode 100644 arch/arm64/dtrace/dtrace_asm_arm64.S
- create mode 100644 arch/arm64/dtrace/dtrace_isa_arm64.c
- create mode 100644 arch/arm64/dtrace/fasttrap_arm64.c
- create mode 100644 arch/arm64/dtrace/fbt_arm64.c
- create mode 100644 arch/arm64/dtrace/include/dtrace/fasttrap_arch.h
- create mode 100644 arch/arm64/dtrace/include/dtrace/fbt_arch.h
- create mode 100644 arch/arm64/dtrace/include/dtrace/sdt_arch.h
- create mode 100644 arch/arm64/dtrace/sdt_arm64.c
- create mode 100644 arch/arm64/include/asm/dtrace_arch.h
- create mode 100644 arch/arm64/include/asm/dtrace_cpuinfo.h
- create mode 100644 arch/arm64/include/asm/dtrace_sdt_arch.h
- create mode 100644 arch/arm64/include/asm/dtrace_syscall.h
- create mode 100644 arch/arm64/include/asm/dtrace_syscall_types.h
- create mode 100644 arch/arm64/include/asm/dtrace_util.h
- create mode 100644 arch/arm64/include/asm/kdebug.h
- create mode 100644 arch/arm64/kernel/dtrace_fbt.c
- create mode 100644 arch/arm64/kernel/dtrace_sdt.c
- create mode 100644 arch/arm64/kernel/dtrace_syscall.c
- create mode 100644 arch/arm64/kernel/dtrace_syscall_stubs.S
- create mode 100644 arch/arm64/kernel/dtrace_util.c
- create mode 100644 arch/arm64/kernel/fbt_blacklist.h
- create mode 100755 scripts/dtrace_sdt_arm64.sh
-
-diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index a6b5b7ef40ae..72a0be5f1717 100644
---- a/arch/arm64/Kconfig
-+++ b/arch/arm64/Kconfig
-@@ -323,6 +323,9 @@ config PGTABLE_LEVELS
- config ARCH_SUPPORTS_UPROBES
- def_bool y
-
-+config ARCH_SUPPORTS_DTRACE
-+ def_bool y
-+
- config ARCH_PROC_KCORE_TEXT
- def_bool y
-
-diff --git a/arch/arm64/dtrace/Makefile.arch b/arch/arm64/dtrace/Makefile.arch
-new file mode 100644
-index 000000000000..393b5cea3f7c
---- /dev/null
-+++ b/arch/arm64/dtrace/Makefile.arch
-@@ -0,0 +1,17 @@
-+#
-+# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+#
-+
-+DTARCHDIR = ../arch/arm64/dtrace
-+
-+ccflags-y += -I$(srctree)/arch/arm64/dtrace/include -Idtrace
-+
-+dtrace-obj += dtrace_asm_arm64.o dtrace_isa_arm64.o
-+fasttrap-obj += fasttrap_arm64.o
-+fbt-obj += fbt_arm64.o
-+sdt-obj += sdt_arm64.o
-+
-+dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
-+fasttrap-y += $(addprefix $(DTARCHDIR)/, $(fasttrap-obj))
-+fbt-y += $(addprefix $(DTARCHDIR)/, $(fbt-obj))
-+sdt-y += $(addprefix $(DTARCHDIR)/, $(sdt-obj))
-diff --git a/arch/arm64/dtrace/dtrace_asm_arm64.S b/arch/arm64/dtrace/dtrace_asm_arm64.S
-new file mode 100644
-index 000000000000..d0f7bad5fb0b
---- /dev/null
-+++ b/arch/arm64/dtrace/dtrace_asm_arm64.S
-@@ -0,0 +1,51 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - ARM64 specific assembly
-+ *
-+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/linkage.h>
-+
-+SYM_CODE_START(dtrace_caller)
-+ mov x0, #-1
-+ ret
-+SYM_CODE_END(dtrace_caller)
-+
-+SYM_CODE_START(dtrace_copy)
-+ ret
-+SYM_CODE_END(dtrace_copy)
-+
-+SYM_CODE_START(dtrace_copystr)
-+ ret
-+SYM_CODE_END(dtrace_copystr)
-+
-+SYM_CODE_START(dtrace_fuword8_nocheck)
-+ ldrb w0, [x0]
-+ ret
-+SYM_CODE_END(dtrace_fuword8_nocheck)
-+
-+SYM_CODE_START(dtrace_fuword16_nocheck)
-+ ldrh w0, [x0]
-+ ret
-+SYM_CODE_END(dtrace_fuword16_nocheck)
-+
-+SYM_CODE_START(dtrace_fuword32_nocheck)
-+ ldr w0, [x0]
-+ ret
-+SYM_CODE_END(dtrace_fuword32_nocheck)
-+
-+SYM_CODE_START(dtrace_fuword64_nocheck)
-+ ldr x0, [x0]
-+ ret
-+SYM_CODE_END(dtrace_fuword64_nocheck)
-diff --git a/arch/arm64/dtrace/dtrace_isa_arm64.c b/arch/arm64/dtrace/dtrace_isa_arm64.c
-new file mode 100644
-index 000000000000..2eb530149c5b
---- /dev/null
-+++ b/arch/arm64/dtrace/dtrace_isa_arm64.c
-@@ -0,0 +1,164 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_isa_arm64.c
-+ * DESCRIPTION: DTrace - arm64 architecture specific support functions
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <asm/stacktrace.h>
-+#include <linux/ptrace.h>
-+
-+#include "dtrace.h"
-+
-+uintptr_t _userlimit = 0x0000ffffffffffffLL;
-+
-+void dtrace_copyin_arch(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+}
-+
-+void dtrace_copyinstr_arch(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+}
-+
-+void dtrace_copyout(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+}
-+
-+void dtrace_copyoutstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+}
-+
-+#define DTRACE_FUWORD(bits) \
-+ uint##bits##_t dtrace_fuword##bits(void *uaddr) \
-+ { \
-+ extern uint##bits##_t dtrace_fuword##bits##_nocheck(void *);\
-+ \
-+ if ((uintptr_t)uaddr > _userlimit) { \
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); \
-+ this_cpu_core->cpuc_dtrace_illval = (uintptr_t)uaddr; \
-+ } \
-+ \
-+ return dtrace_fuword##bits##_nocheck(uaddr); \
-+ }
-+
-+DTRACE_FUWORD(8)
-+DTRACE_FUWORD(16)
-+DTRACE_FUWORD(32)
-+DTRACE_FUWORD(64)
-+
-+static int dtrace_unwind_frame(struct task_struct *task,
-+ struct stackframe *frame)
-+{
-+ unsigned long fp = frame->fp;
-+
-+ if (fp & 0xf)
-+ return -EINVAL;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp));
-+ frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8));
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ if (!frame->fp && !frame->pc)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+uint64_t dtrace_getarg(int argno, int aframes)
-+{
-+ uint64_t *st;
-+ uint64_t val;
-+ int i;
-+ struct stackframe frame;
-+ struct task_struct *task = current;
-+
-+ if (argno < 7)
-+ return 0;
-+
-+ if (this_cpu_core->cpu_dtrace_regs)
-+ st = (uint64_t *)this_cpu_core->cpu_dtrace_regs->regs[29];
-+ else {
-+ frame.fp = (unsigned long)__builtin_frame_address(0);
-+ frame.pc = (unsigned long)dtrace_getarg;
-+
-+ aframes += 1; /* Count this function. */
-+ for (i = 0; i < aframes; i++) {
-+ if (dtrace_unwind_frame(task, &frame) < 0)
-+ break;
-+ }
-+
-+ /*
-+ * If we cannot traverse the expected number of stack frames,
-+ * there is something wrong with the stack.
-+ */
-+ if (i < aframes) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADSTACK);
-+
-+ return 0;
-+ }
-+
-+ st = (uint64_t *)frame.fp;
-+ }
-+
-+ /*
-+ * The first 7 arguments (arg0 through arg6) are passed in registers
-+ * to dtrace_probe(). The remaining arguments (arg7 through arg9) are
-+ * passed on the stack.
-+ *
-+ * Stack layout:
-+ * bp[0] = pushed fp from caller
-+ * bp[1] = return address
-+ * bp[2] = 8th argument (arg7 -> argno = 7)
-+ * bp[3] = 9th argument (arg8 -> argno = 8)
-+ * ...
-+ */
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ val = READ_ONCE_NOCHECK(st[2 + (argno - 7)]);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return val;
-+}
-+
-+ulong_t dtrace_getreg(struct task_struct *task, uint_t reg)
-+{
-+ struct pt_regs *rp = task_pt_regs(task);
-+
-+ return regs_get_register(rp, reg * sizeof(uint64_t));
-+}
-+
-+void pdata_init(struct dtrace_module *pdata, struct module *mp)
-+{
-+ /*
-+ * Throw away existing data as we don't support reusal at
-+ * the moment.
-+ */
-+ if (mp->pdata != NULL)
-+ pdata_cleanup(pdata, mp);
-+
-+ pdata->sdt_tab = NULL;
-+ pdata->fbt_tab = NULL;
-+}
-+
-+void pdata_cleanup(struct dtrace_module *pdata, struct module *mp)
-+{
-+ if (pdata->sdt_tab != NULL)
-+ dtrace_free_text(pdata->sdt_tab);
-+ if (pdata->fbt_tab != NULL)
-+ dtrace_free_text(pdata->fbt_tab);
-+}
-diff --git a/arch/arm64/dtrace/fasttrap_arm64.c b/arch/arm64/dtrace/fasttrap_arm64.c
-new file mode 100644
-index 000000000000..cc970a11412c
---- /dev/null
-+++ b/arch/arm64/dtrace/fasttrap_arm64.c
-@@ -0,0 +1,282 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fasttrap_arm64.c
-+ * DESCRIPTION: DTrace - fasttrap provider implementation for arm64
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <asm/insn.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fasttrap_impl.h"
-+
-+static int has_jump_table(const asm_instr_t *addr, size_t size)
-+{
-+ const asm_instr_t *end = addr + size;
-+
-+ while (addr < end) {
-+ /*
-+ * If we encounter a branch-to-register instruction, we assume
-+ * it is part of a jump table implementation.
-+ */
-+ if (aarch64_insn_is_br(addr[0]))
-+ return 1;
-+
-+ addr++;
-+ }
-+
-+ return 0;
-+}
-+
-+static uint64_t *fasttrap_all_offsets(asm_instr_t *text, size_t size,
-+ uint64_t *np)
-+{
-+ uint64_t *offs = NULL;
-+ uint64_t noffs;
-+ asm_instr_t *instr;
-+ asm_instr_t *end;
-+
-+ /*
-+ * Two passes are taken through this section of code. The first time
-+ * around we merely count the number of probe points. The second time,
-+ * we actually record their locations.
-+ */
-+again:
-+ noffs = 0;
-+ instr = text;
-+ end = text + size;
-+
-+ while (instr < end) {
-+ if (offs)
-+ offs[noffs] = (uint64_t)
-+ ((uintptr_t)instr - (uintptr_t)text);
-+ noffs++;
-+
-+ instr++;
-+ }
-+
-+ if (offs == NULL) {
-+ /*
-+ * No matching offsets found - we are done.
-+ */
-+ if (noffs == 0)
-+ goto fail;
-+
-+ /*
-+ * We know how many tracepoint locations there are for this
-+ * probe, so allocate a member to record them, and kick off the
-+ * second pass.
-+ */
-+ offs = kmalloc(sizeof(uint64_t) * noffs, GFP_KERNEL);
-+ if (!offs)
-+ goto fail;
-+
-+ goto again;
-+ }
-+
-+ *np = noffs;
-+
-+ return offs;
-+
-+fail:
-+ *np = 0;
-+ kfree(offs);
-+
-+ return NULL;
-+}
-+
-+uint64_t *fasttrap_glob_offsets(struct fasttrap_probe_spec *probe,
-+ uint64_t *np)
-+{
-+ size_t size = probe->ftps_size;
-+ asm_instr_t *text = NULL;
-+ asm_instr_t *instr;
-+ asm_instr_t *end;
-+ uint64_t *offs = NULL;
-+ uint64_t noffs;
-+ int ret = 0;
-+ char ostr[sizeof(instr) * 2 + 1]; /* 2 chars / byte + 1 */
-+
-+ if (!IS_ALIGNED(size, sizeof(instr[0])))
-+ goto fail;
-+
-+ text = kmalloc(size, GFP_KERNEL);
-+ if (!text)
-+ goto fail;
-+
-+ ret = dtrace_copy_code(probe->ftps_pid, (uint8_t *)text,
-+ probe->ftps_pc, size);
-+ if (ret != 0)
-+ goto fail;
-+
-+ /*
-+ * From this point on, size will be a count of instructions rather than
-+ * a byte count. We already verified earlier on that it is a multiple
-+ * of the instruction size.
-+ */
-+ size /= sizeof(instr[0]);
-+
-+ if (has_jump_table(text, size))
-+ goto fail;
-+
-+ if (probe->ftps_glen == 1 && probe->ftps_gstr[0] == '*') {
-+ offs = fasttrap_all_offsets(text, size, &noffs);
-+ goto out;
-+ }
-+
-+ /*
-+ * Two passes are taken through this section of code. The first time
-+ * around we merely count the number of probe points. The second time,
-+ * we actually record their locations.
-+ */
-+again:
-+ noffs = 0;
-+ instr = text;
-+ end = text + size;
-+
-+ while (instr < end) {
-+ uint64_t off = (uint64_t)
-+ ((uintptr_t)instr - (uintptr_t)text);
-+
-+ snprintf(ostr, sizeof(ostr), "%llx", off);
-+ if (dtrace_gmatch(ostr, probe->ftps_gstr)) {
-+ if (offs)
-+ offs[noffs] = off;
-+ noffs++;
-+ }
-+
-+ instr++;
-+ }
-+
-+ if (offs == NULL) {
-+ /*
-+ * No matching offsets found - we are done.
-+ */
-+ if (noffs == 0)
-+ goto fail;
-+
-+ /*
-+ * We know how many tracepoint locations there are for this
-+ * probe, so allocate member to record them, and kick off the
-+ * second pass.
-+ */
-+ offs = kmalloc(sizeof(uint64_t) * noffs, GFP_KERNEL);
-+ if (!offs)
-+ goto fail;
-+
-+ goto again;
-+ }
-+
-+out:
-+ kfree(text);
-+
-+ *np = noffs;
-+
-+ return offs;
-+
-+fail:
-+ kfree(offs);
-+ kfree(text);
-+
-+ *np = 0;
-+ return NULL;
-+}
-+
-+uint64_t fasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ return 0;
-+
-+ if (argno < 8)
-+ return regs->regs[argno];
-+
-+ pagefault_disable();
-+ st = (uint64_t *)regs->sp;
-+ __copy_from_user_inatomic_nocache(&val, (void *)&st[argno - 8],
-+ sizeof(st[0]));
-+ pagefault_enable();
-+
-+ return val;
-+}
-+
-+uint64_t fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg,
-+ int argno, int aframes)
-+{
-+ return fasttrap_pid_getarg(arg, id, parg, argno, aframes);
-+}
-+
-+static void fasttrap_map_args(struct fasttrap_probe *probe,
-+ struct pt_regs *regs, int argc, uintptr_t *argv)
-+{
-+ int i, x, cap = min(argc, (int)probe->ftp_nargs);
-+ uintptr_t *st = (uintptr_t *)regs->sp;
-+
-+ for (i = 0; i < cap; i++) {
-+ x = probe->ftp_argmap[i];
-+
-+ if (x < 8)
-+ argv[i] = regs->regs[x];
-+ else {
-+ pagefault_disable();
-+ __copy_from_user_inatomic_nocache(&argv[i],
-+ (void *)&st[x - 8],
-+ sizeof(st[0]));
-+ pagefault_enable();
-+ }
-+ }
-+
-+ while (i < argc)
-+ argv[i++] = 0;
-+}
-+
-+void fasttrap_pid_probe_arch(struct fasttrap_probe *ftp, struct pt_regs *regs)
-+{
-+ if (ftp->ftp_argmap == NULL) {
-+ dtrace_probe(ftp->ftp_id, regs->regs[0], regs->regs[1],
-+ regs->regs[2], regs->regs[3],
-+ regs->regs[4], regs->regs[5],
-+ regs->regs[6]);
-+ } else {
-+ uintptr_t t[7];
-+
-+ fasttrap_map_args(ftp, regs, sizeof(t) / sizeof(t[0]), t);
-+ dtrace_probe(ftp->ftp_id, t[0], t[1], t[2], t[3],
-+ t[4], t[5], t[6]);
-+ }
-+}
-+
-+void fasttrap_pid_retprobe_arch(struct fasttrap_probe *ftp,
-+ struct pt_regs *regs)
-+{
-+ /*
-+ * FIXME: The first argument to the probe should be the offset in the
-+ * function that the return occurred at, but uprobes doesn't give
-+ * us that information (or so it seems).
-+ */
-+ dtrace_probe(ftp->ftp_id, 0, regs->regs[0], regs->regs[1], 0, 0, 0, 0);
-+}
-+
-+void fasttrap_set_enabled(struct pt_regs *regs)
-+{
-+ regs->regs[0] = 1;
-+}
-diff --git a/arch/arm64/dtrace/fbt_arm64.c b/arch/arm64/dtrace/fbt_arm64.c
-new file mode 100644
-index 000000000000..be9dcaf8db28
---- /dev/null
-+++ b/arch/arm64/dtrace/fbt_arm64.c
-@@ -0,0 +1,152 @@
-+/*
-+ * FILE: fbt_arm64.c
-+ * DESCRIPTION: DTrace - FBT provider implementation for arm64
-+ *
-+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_fbt.h>
-+#include <linux/ptrace.h>
-+#include <linux/vmalloc.h>
-+#include <asm/dtrace_util.h>
-+#include <asm/debug-monitors.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fbt_impl.h"
-+
-+static int fbt_brk_hook(struct pt_regs *regs, unsigned int esr)
-+{
-+ uintptr_t ip = instruction_pointer(regs);
-+ struct fbt_probe *fbp = fbt_probetab[FBT_ADDR2NDX(ip)];
-+
-+ for (; fbp != NULL; fbp = fbp->fbp_hashnext) {
-+ if ((uintptr_t)fbp->fbp_patchpoint == ip) {
-+ struct pt_regs *oregs;
-+
-+ oregs = this_cpu_core->cpu_dtrace_regs;
-+ this_cpu_core->cpu_dtrace_regs = regs;
-+
-+ if (fbp->fbp_roffset == 0) {
-+ dtrace_probe(fbp->fbp_id, regs->regs[0],
-+ regs->regs[1], regs->regs[2],
-+ regs->regs[3], regs->regs[4],
-+ regs->regs[5], regs->regs[6]);
-+ } else {
-+ dtrace_probe(fbp->fbp_id, fbp->fbp_roffset,
-+ regs->regs[0], 0, 0, 0, 0, 0);
-+ }
-+
-+ this_cpu_core->cpu_dtrace_regs = oregs;
-+
-+ return DBG_HOOK_HANDLED;
-+ }
-+ }
-+
-+ return DBG_HOOK_ERROR;
-+}
-+
-+uint64_t fbt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ regs = current_pt_regs();
-+
-+ if (argno < 8)
-+ return regs->regs[argno];
-+
-+ /*
-+ * Arguments are passed by register for the first 8 arguments, and the
-+ * rest is placed on the stack. The frame pointer (fp) points at the
-+ * beginning of the current frame, and the stack pointer (sp) will
-+ * point to the end of the frame. Arguments passed by stack are placed
-+ * in stack slots at the end of the frame, so at (sp), (sp + 1), etc...
-+ */
-+ st = (uint64_t *)regs->sp;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ val = READ_ONCE_NOCHECK(st[argno - 8]);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return 0;
-+}
-+
-+void fbt_provide_probe_arch(struct fbt_probe *fbp, int type, int stype)
-+{
-+ fbp->fbp_patchval = type == FBT_ENTRY ? BRK64_OPCODE_DPROBE_FBE
-+ : BRK64_OPCODE_DPROBE_FBR;
-+ fbp->fbp_savedval = dtrace_text_peek(fbp->fbp_patchpoint);
-+}
-+
-+int fbt_can_patch_return_arch(asm_instr_t *addr)
-+{
-+ return 1;
-+}
-+
-+int fbt_provide_module_arch(void *arg, struct module *mp)
-+{
-+ return 1;
-+}
-+
-+void fbt_destroy_module(void *arg, struct module *mp)
-+{
-+}
-+
-+void fbt_enable_arch(struct fbt_probe *fbp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_text_poke(fbp->fbp_patchpoint, fbp->fbp_patchval);
-+}
-+
-+void fbt_disable_arch(struct fbt_probe *fbp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_text_poke(fbp->fbp_patchpoint, fbp->fbp_savedval);
-+}
-+
-+static struct break_hook dtrace_fbe_break_hook = {
-+ .imm = DPROBES_FBE_BRK_IMM,
-+ .fn = fbt_brk_hook,
-+};
-+
-+static struct break_hook dtrace_fbr_break_hook = {
-+ .imm = DPROBES_FBR_BRK_IMM,
-+ .fn = fbt_brk_hook,
-+};
-+
-+int fbt_dev_init_arch(void)
-+{
-+ fbt_probetab_mask = fbt_probetab_size - 1;
-+ fbt_probetab = dtrace_vzalloc_try(fbt_probetab_size *
-+ sizeof(struct fbt_probe *));
-+
-+ if (fbt_probetab == NULL)
-+ return -ENOMEM;
-+
-+ dtrace_kernel_brk_start(&dtrace_fbe_break_hook);
-+ dtrace_kernel_brk_start(&dtrace_fbr_break_hook);
-+
-+ return 0;
-+}
-+
-+void fbt_dev_exit_arch(void)
-+{
-+ dtrace_kernel_brk_stop(&dtrace_fbr_break_hook);
-+ dtrace_kernel_brk_stop(&dtrace_fbe_break_hook);
-+
-+ vfree(fbt_probetab);
-+ fbt_probetab_mask = 0;
-+ fbt_probetab_size = 0;
-+}
-diff --git a/arch/arm64/dtrace/include/dtrace/fasttrap_arch.h b/arch/arm64/dtrace/include/dtrace/fasttrap_arch.h
-new file mode 100644
-index 000000000000..d5ffa6e711db
---- /dev/null
-+++ b/arch/arm64/dtrace/include/dtrace/fasttrap_arch.h
-@@ -0,0 +1,30 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Fasttrap provider implementation defines
-+ *
-+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _ARM64_FASTTRAP_ARCH_H
-+#define _ARM64_FASTTRAP_ARCH_H
-+
-+#define FASTTRAP_ENTRY_AFRAMES 8
-+#define FASTTRAP_RETURN_AFRAMES 8
-+#define FASTTRAP_OFFSET_AFRAMES 8
-+
-+#endif /* _ARM64_FASTTRAP_ARCH_H */
-diff --git a/arch/arm64/dtrace/include/dtrace/fbt_arch.h b/arch/arm64/dtrace/include/dtrace/fbt_arch.h
-new file mode 100644
-index 000000000000..ed1cd785b3ba
---- /dev/null
-+++ b/arch/arm64/dtrace/include/dtrace/fbt_arch.h
-@@ -0,0 +1,53 @@
-+/*
-+ * Dynamic Tracing for Linux - FBT Implementation defines
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _ARM64_FBT_ARCH_H
-+#define _ARM64_FBT_ARCH_H
-+
-+/*
-+ * FBT entry probes are triggered from a breakpoint. The following stack trace
-+ * illustrates the frames that are involved in the call sequence prior to the
-+ * actual FBT provider handler.
-+ *
-+ * vmlinux`brk_handler+0x70 <- to be skipped
-+ * vmlinux`do_debug_exception+0x9c <- to be skipped
-+ * vmlinux`el1_sync+0x1d8 <- to be skipped
-+ * vmlinux`SyS_read+0x4
-+ *
-+ * Therefore, 3 frames need to be skipped.
-+ */
-+#define FBT_AFRAMES 3
-+
-+struct fbt_probe {
-+ char *fbp_name; /* name of probe */
-+ dtrace_id_t fbp_id; /* probe ID */
-+ struct module *fbp_module; /* defining module */
-+ int fbp_primary; /* non-zero if primary mod */
-+ asm_instr_t *fbp_patchpoint;/* patch point */
-+ asm_instr_t fbp_patchval; /* instruction to patch */
-+ asm_instr_t fbp_savedval; /* saved instruction value */
-+ uint64_t fbp_roffset; /* relative offset */
-+ struct fbt_probe *fbp_next; /* next probe */
-+ struct fbt_probe *fbp_hashnext; /* next on hash */
-+ int fbp_isret;
-+};
-+
-+#endif /* _ARM64_FBT_ARCH_H */
-diff --git a/arch/arm64/dtrace/include/dtrace/sdt_arch.h b/arch/arm64/dtrace/include/dtrace/sdt_arch.h
-new file mode 100644
-index 000000000000..237922a77495
---- /dev/null
-+++ b/arch/arm64/dtrace/include/dtrace/sdt_arch.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - SDT Implementation defines
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _ARM64_SDT_ARCH_H
-+#define _ARM64_SDT_ARCH_H
-+
-+#define SDT_AFRAMES 1
-+
-+#endif /* _ARM64_SDT_ARCH_H */
-diff --git a/arch/arm64/dtrace/sdt_arm64.c b/arch/arm64/dtrace/sdt_arm64.c
-new file mode 100644
-index 000000000000..ba25824e413e
---- /dev/null
-+++ b/arch/arm64/dtrace/sdt_arm64.c
-@@ -0,0 +1,122 @@
-+/*
-+ * FILE: sdt_arm64.c
-+ * DESCRIPTION: DTrace - SDT provider implementation for arm64
-+ *
-+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/ptrace.h>
-+#include <linux/sdt.h>
-+#include <asm/debug-monitors.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "sdt_impl.h"
-+
-+static int sdt_brk_hook(struct pt_regs *regs, unsigned int esr)
-+{
-+ uintptr_t ip = instruction_pointer(regs);
-+ struct sdt_probe *sdt = sdt_probetab[SDT_ADDR2NDX(ip)];
-+
-+ for (; sdt != NULL; sdt = sdt->sdp_hashnext) {
-+ if ((uintptr_t)sdt->sdp_patchpoint == ip) {
-+ if (sdt->sdp_ptype == SDTPT_IS_ENABLED)
-+ regs->regs[0] = 1;
-+ else {
-+ this_cpu_core->cpu_dtrace_regs = regs;
-+ dtrace_probe(sdt->sdp_id, regs->regs[0],
-+ regs->regs[1], regs->regs[2],
-+ regs->regs[3], regs->regs[4],
-+ regs->regs[5], regs->regs[6]);
-+ this_cpu_core->cpu_dtrace_regs = NULL;
-+ }
-+
-+ instruction_pointer_set(regs,
-+ instruction_pointer(regs) + 4);
-+
-+ return DBG_HOOK_HANDLED;
-+ }
-+ }
-+
-+ return DBG_HOOK_ERROR;
-+}
-+
-+void sdt_provide_probe_arch(struct sdt_probe *sdp, struct module *mp, int idx)
-+{
-+ sdp->sdp_patchval = BRK64_OPCODE_DPROBE_SDT;
-+ sdp->sdp_savedval = dtrace_text_peek(sdp->sdp_patchpoint);
-+}
-+
-+int sdt_provide_module_arch(void *arg, struct module *mp)
-+{
-+ return 1;
-+}
-+
-+void sdt_destroy_module(void *arg, struct module *mp)
-+{
-+}
-+
-+void sdt_enable_arch(struct sdt_probe *sdp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_text_poke(sdp->sdp_patchpoint, sdp->sdp_patchval);
-+}
-+
-+void sdt_disable_arch(struct sdt_probe *sdp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_text_poke(sdp->sdp_patchpoint, sdp->sdp_savedval);
-+}
-+
-+static struct break_hook dtrace_sdt_break_hook = {
-+ .imm = DPROBES_SDT_BRK_IMM,
-+ .fn = sdt_brk_hook,
-+};
-+
-+int sdt_dev_init_arch(void)
-+{
-+ dtrace_kernel_brk_start(&dtrace_sdt_break_hook);
-+ return 0;
-+}
-+
-+void sdt_dev_exit_arch(void)
-+{
-+ dtrace_kernel_brk_stop(&dtrace_sdt_break_hook);
-+}
-+
-+uint64_t sdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ regs = current_pt_regs();
-+
-+ if (argno < 8)
-+ return regs->regs[argno];
-+
-+ /*
-+ * Arguments are passed by register for the first 8 arguments, and the
-+ * rest is placed on the stack. The frame pointer (fp) points at the
-+ * beginning of the current frame, and the stack pointer (sp) will
-+ * point to the end of the frame. Arguments passed by stack are placed
-+ * in stack slots at the end of the frame, so at (sp), (sp + 1), etc...
-+ */
-+ st = (uint64_t *)regs->sp;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ val = READ_ONCE_NOCHECK(st[argno - 8]);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return val;
-+}
-diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h
-index ec7720dbe2c8..405cfb7da5ea 100644
---- a/arch/arm64/include/asm/brk-imm.h
-+++ b/arch/arm64/include/asm/brk-imm.h
-@@ -11,6 +11,9 @@
- * 0x004: for installing kprobes
- * 0x005: for installing uprobes
- * 0x006: for kprobe software single-step
-+ * 0x007: for installing DTrace SDT probes
-+ * 0x008: for installing DTrace function-boundary tracing entry probes
-+ * 0x009: for installing DTrace function-boundary tracing return probes
- * Allowed values for kgdb are 0x400 - 0x7ff
- * 0x100: for triggering a fault on purpose (reserved)
- * 0x400: for dynamic BRK instruction
-@@ -21,6 +24,9 @@
- #define KPROBES_BRK_IMM 0x004
- #define UPROBES_BRK_IMM 0x005
- #define KPROBES_BRK_SS_IMM 0x006
-+#define DPROBES_SDT_BRK_IMM 0x007
-+#define DPROBES_FBE_BRK_IMM 0x008
-+#define DPROBES_FBR_BRK_IMM 0x009
- #define FAULT_BRK_IMM 0x100
- #define KGDB_DYN_DBG_BRK_IMM 0x400
- #define KGDB_COMPILED_DBG_BRK_IMM 0x401
-diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h
-index 7faae6ff3ab4..496e8df36b56 100644
---- a/arch/arm64/include/asm/cpu.h
-+++ b/arch/arm64/include/asm/cpu.h
-@@ -60,6 +60,7 @@ struct cpuinfo_arm64 {
- };
-
- DECLARE_PER_CPU(struct cpuinfo_arm64, cpu_data);
-+#define cpu_data(cpu) per_cpu(cpu_data, (cpu))
-
- void cpuinfo_store_cpu(void);
- void __init cpuinfo_store_boot_cpu(void);
-diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
-index 657c921fd784..030756b7e008 100644
---- a/arch/arm64/include/asm/debug-monitors.h
-+++ b/arch/arm64/include/asm/debug-monitors.h
-@@ -56,6 +56,10 @@
- #define BRK64_OPCODE_KPROBES_SS (AARCH64_BREAK_MON | (KPROBES_BRK_SS_IMM << 5))
- /* uprobes BRK opcodes with ESR encoding */
- #define BRK64_OPCODE_UPROBES (AARCH64_BREAK_MON | (UPROBES_BRK_IMM << 5))
-+/* DTrace probes BRK opcodes with ESR encoding */
-+#define BRK64_OPCODE_DPROBE_SDT (AARCH64_BREAK_MON | (DPROBES_SDT_BRK_IMM << 5))
-+#define BRK64_OPCODE_DPROBE_FBE (AARCH64_BREAK_MON | (DPROBES_FBE_BRK_IMM << 5))
-+#define BRK64_OPCODE_DPROBE_FBR (AARCH64_BREAK_MON | (DPROBES_FBR_BRK_IMM << 5))
-
- /* AArch32 */
- #define DBG_ESR_EVT_BKPT 0x4
-diff --git a/arch/arm64/include/asm/dtrace_arch.h b/arch/arm64/include/asm/dtrace_arch.h
-new file mode 100644
-index 000000000000..89f883e20aa7
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_arch.h
-@@ -0,0 +1,31 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. */
-+
-+#ifndef _ASM_ARM64_DTRACE_ARCH_H
-+#define _ASM_ARM64_DTRACE_ARCH_H
-+
-+/* Number of argumens stored inside the mstate. */
-+#define DTRACE_MSTATE_ARGS_MAX 7
-+
-+typedef uint32_t asm_instr_t;
-+
-+typedef int (*prov_exit_f)(void);
-+
-+/*
-+ * Structure to hold DTrace specific information about modules (including the
-+ * core kernel module). Note that each module (and the main kernel) already
-+ * has three fields that relate to probing:
-+ * - sdt_probes: description of SDT probes in the module
-+ * - sdt_probec: number of SDT probes in the module
-+ * - pdata: pointer to a dtrace_module struct (for DTrace)
-+ */
-+struct dtrace_module {
-+ int enabled_cnt;
-+ size_t sdt_probe_cnt;
-+ asm_instr_t *sdt_tab;
-+ size_t fbt_probe_cnt;
-+ asm_instr_t *fbt_tab;
-+ prov_exit_f prov_exit; /* Called with module_mutex held */
-+};
-+
-+#endif /* _ASM_ARM64_DTRACE_ARCH_H */
-diff --git a/arch/arm64/include/asm/dtrace_cpuinfo.h b/arch/arm64/include/asm/dtrace_cpuinfo.h
-new file mode 100644
-index 000000000000..4e0ab793c92c
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_cpuinfo.h
-@@ -0,0 +1,13 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/* Copyright (C) 2018 Oracle, Inc. */
-+
-+#ifndef _ASM_ARM64_DTRACE_CPUINFO_H_
-+#define _ASM_ARM64_DTRACE_CPUINFO_H_
-+
-+#include <asm/cpu.h>
-+
-+typedef struct cpuinfo_arm64 cpuinfo_arch_t;
-+
-+#define dtrace_cpuinfo_chip(ci) ((ci)->cpu.node_id)
-+
-+#endif /* _ASM_ARM64_DTRACE_CPUINFO_H_ */
-diff --git a/arch/arm64/include/asm/dtrace_sdt_arch.h b/arch/arm64/include/asm/dtrace_sdt_arch.h
-new file mode 100644
-index 000000000000..b93a03c215b3
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_sdt_arch.h
-@@ -0,0 +1,15 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/* Copyright (C) 2018 Oracle, Inc. */
-+
-+#ifndef _ASM_ARM64_DTRACE_SDT_ARCH_H
-+#define _ASM_ARM64_DTRACE_SDT_ARCH_H
-+
-+#include <asm/dtrace_arch.h>
-+
-+#define NOP_INSTR 0xd503201f
-+#define MOV_INSTR 0xd2800000 /* mov x0, #0x0 - default = false */
-+
-+#define __DTRACE_SDT_ISENABLED_PROTO void
-+#define __DTRACE_SDT_ISENABLED_ARGS
-+
-+#endif /* _ASM_ARM64_DTRACE_SDT_ARCH_H */
-diff --git a/arch/arm64/include/asm/dtrace_syscall.h b/arch/arm64/include/asm/dtrace_syscall.h
-new file mode 100644
-index 000000000000..402826562478
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_syscall.h
-@@ -0,0 +1,3 @@
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-diff --git a/arch/arm64/include/asm/dtrace_syscall_types.h b/arch/arm64/include/asm/dtrace_syscall_types.h
-new file mode 100644
-index 000000000000..88e6eca6e169
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_syscall_types.h
-@@ -0,0 +1,11 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/dtrace_types.h>
-+
-+typedef asmlinkage long (*dt_sys_call_t)(const struct pt_regs *regs);
-+
-+#define DTRACE_SYSCALL_WRAP_PREFIX "__arm64_"
-diff --git a/arch/arm64/include/asm/dtrace_util.h b/arch/arm64/include/asm/dtrace_util.h
-new file mode 100644
-index 000000000000..003bd34524d6
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_util.h
-@@ -0,0 +1,14 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/* Copyright (C) 2019, Oracle and/or its affiliates. All rights reserved. */
-+
-+#ifndef _ASM_ARM64_DTRACE_UTIL_H
-+#define _ASM_ARM64_DTRACE_UTIL_H
-+
-+#include <asm/dtrace_arch.h>
-+
-+extern asm_instr_t dtrace_text_peek(asm_instr_t *addr);
-+extern void dtrace_text_poke(asm_instr_t *addr, asm_instr_t opcode);
-+extern void dtrace_kernel_brk_start(void *arg);
-+extern void dtrace_kernel_brk_stop(void *arg);
-+
-+#endif /* _ASM_ARM64_DTRACE_UTIL_H */
-diff --git a/arch/arm64/include/asm/kdebug.h b/arch/arm64/include/asm/kdebug.h
-new file mode 100644
-index 000000000000..66c884086d04
---- /dev/null
-+++ b/arch/arm64/include/asm/kdebug.h
-@@ -0,0 +1,11 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+#ifndef _ARM64_KDEBUG_H
-+#define _ARM64_KDEBUG_H
-+
-+/* Grossly misnamed. */
-+enum die_val {
-+ DIE_OOPS = 1,
-+ DIE_PAGE_FAULT,
-+};
-+
-+#endif /* _ARM64_KDEBUG_H */
-diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
-index cfc0672013f6..1ab1fc22cb8b 100644
---- a/arch/arm64/include/asm/syscall.h
-+++ b/arch/arm64/include/asm/syscall.h
-@@ -11,7 +11,13 @@
-
- typedef long (*syscall_fn_t)(const struct pt_regs *regs);
-
--extern const syscall_fn_t sys_call_table[];
-+#if IS_ENABLED(CONFIG_DT_SYSTRACE)
-+#define CONST_SYS_CALL_TABLE
-+#else
-+#define CONST_SYS_CALL_TABLE const
-+#endif
-+
-+extern CONST_SYS_CALL_TABLE syscall_fn_t sys_call_table[];
-
- #ifdef CONFIG_COMPAT
- extern const syscall_fn_t compat_sys_call_table[];
-diff --git a/arch/arm64/kernel/dtrace_fbt.c b/arch/arm64/kernel/dtrace_fbt.c
-new file mode 100644
-index 000000000000..3761e8aa4550
---- /dev/null
-+++ b/arch/arm64/kernel/dtrace_fbt.c
-@@ -0,0 +1,187 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_fbt.c
-+ * DESCRIPTION: Dynamic Tracing: FBT registration code (arch-specific)
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/kallsyms.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_fbt.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/slab.h>
-+#include <linux/sort.h>
-+#include <asm/insn.h>
-+#include <asm/sections.h>
-+
-+#define FBT_REG_FP 0x1d /* fp is regiater 29 */
-+#define FBT_REG_LR 0x1e /* lr is regiater 30 */
-+#define FBT_REG_SP 0x1f /* sp is register 31 */
-+#define FBT_MOV_FP_SP 0x910003fd /* "mov x29, sp" */
-+
-+#define BL_SENTRY(tp, nm) extern tp nm;
-+#define BL_DENTRY(tp, nm)
-+#include "fbt_blacklist.h"
-+#undef BL_DENTRY
-+#undef BL_SENTRY
-+
-+static void
-+dtrace_fbt_populate_bl(void)
-+{
-+#define BL_SENTRY(tp, nm) dtrace_fbt_bl_add((unsigned long)&nm, \
-+ __stringify(nm));
-+#define BL_DENTRY(tp, nm) dtrace_fbt_bl_add(0, __stringify(nm));
-+#include "fbt_blacklist.h"
-+#undef BL_SENTRY
-+#undef BL_DENTRY
-+}
-+
-+void dtrace_fbt_init(fbt_add_probe_fn fbt_add_probe, struct module *mp,
-+ void *arg)
-+{
-+ loff_t pos;
-+ struct kallsym_iter sym;
-+ asm_instr_t *paddr = NULL;
-+ struct dt_fbt_bl_entry *blent = NULL;
-+
-+ /*
-+ * Look up any unresolved symbols in the blacklist, and sort the list
-+ * by ascending address.
-+ */
-+ dtrace_fbt_populate_bl();
-+
-+ blent = dtrace_fbt_bl_first();
-+
-+ pos = 0;
-+ kallsyms_iter_reset(&sym, 0);
-+ while (kallsyms_iter_update(&sym, pos++)) {
-+ asm_instr_t *addr, *end;
-+ asm_instr_t instr;
-+ void *fbtp = NULL;
-+
-+ /*
-+ * There is no point considering non-function symbols for FBT,
-+ * or symbols that have a zero size. We could consider weak
-+ * symbols but that gets quite complicated and there is no
-+ * demands for that (so far).
-+ */
-+ if (sym.type != 'T' && sym.type != 't')
-+ continue;
-+ if (!sym.size)
-+ continue;
-+
-+ /*
-+ * The symbol must be at a properly aligned text address.
-+ */
-+ if (!IS_ALIGNED(sym.value, sizeof(asm_instr_t)))
-+ continue;
-+
-+ /*
-+ * Handle only symbols that belong to the module we have been
-+ * asked for.
-+ */
-+ if (mp == dtrace_kmod && !core_kernel_text(sym.value))
-+ continue;
-+
-+ /*
-+ * Ensure we have not been given .init symbol from kallsyms
-+ * interface. This could lead to memory corruption once DTrace
-+ * tries to enable probe in already freed memory.
-+ */
-+ if (mp != dtrace_kmod && !within_module_core(sym.value, mp))
-+ continue;
-+
-+ /*
-+ * See if the symbol is on the FBT's blacklist. Since both
-+ * iterators are workng in sort order by ascending address we
-+ * can use concurrent traversal.
-+ */
-+ while (blent != NULL &&
-+ dtrace_fbt_bl_entry_addr(blent) < sym.value) {
-+ blent = dtrace_fbt_bl_next(blent);
-+ }
-+ if (dtrace_fbt_bl_entry_addr(blent) == sym.value)
-+ continue;
-+
-+ /*
-+ * No FBT tracing for DTrace functions, and functions that are
-+ * crucial to probe processing.
-+ * Also weed out symbols that are not relevant here.
-+ */
-+ if (strncmp(sym.name, "dtrace_", 7) == 0)
-+ continue;
-+ if (strncmp(sym.name, "insn_", 5) == 0)
-+ continue;
-+ if (strncmp(sym.name, "inat_", 5) == 0)
-+ continue;
-+ if (strncmp(sym.name, "_GLOBAL_", 8) == 0)
-+ continue;
-+ if (strncmp(sym.name, "do_", 3) == 0)
-+ continue;
-+ if (strncmp(sym.name, "xen_", 4) == 0)
-+ continue;
-+
-+ addr = (asm_instr_t *)sym.value;
-+ end = (asm_instr_t *)(sym.value + sym.size);
-+
-+ /*
-+ * FIXME:
-+ * When there are multiple symbols for the same address, we
-+ * should link them together as probes associated with the
-+ * same function. When a probe for that function is triggered
-+ * all associated probes should fire.
-+ *
-+ * For now, we ignore duplicates.
-+ */
-+ if (addr == paddr)
-+ continue;
-+ paddr = addr;
-+
-+ instr = le32_to_cpu(*addr);
-+
-+ /*
-+ * We can only instrument functions that begin with a proper
-+ * frame set-up sequence:
-+ * stp x29, x30, [sp,#-80]!
-+ * mov x29, sp
-+ * So, a STP instruction storing the FP (x29) and LR (x30)
-+ * registers as a pair in a location relative to the SP
-+ * register value. And then a MOV instruction that sets the
-+ * FP (x29) register to the current SP value (effectively
-+ * establishing the new stack frame).
-+ *
-+ * We will place our breakpoint on the MOV instruction.
-+ */
-+ if (!aarch64_insn_is_stp_pre(instr) ||
-+ aarch64_insn_decode_register(
-+ AARCH64_INSN_REGTYPE_RN, instr) != FBT_REG_SP ||
-+ aarch64_insn_decode_register(
-+ AARCH64_INSN_REGTYPE_RT, instr) != FBT_REG_FP ||
-+ aarch64_insn_decode_register(
-+ AARCH64_INSN_REGTYPE_RT2, instr) != FBT_REG_LR)
-+ continue;
-+
-+ addr++;
-+ instr = le32_to_cpu(*addr);
-+ if (instr != FBT_MOV_FP_SP)
-+ continue;
-+
-+ fbt_add_probe(mp, sym.name, FBT_ENTRY, instr, addr, 0, NULL,
-+ arg);
-+
-+ while (++addr < end) {
-+ uintptr_t off;
-+
-+ instr = le32_to_cpu(*addr);
-+ if (!aarch64_insn_is_ret(instr))
-+ continue;
-+
-+ off = (uintptr_t)addr - sym.value;
-+ fbtp = fbt_add_probe(mp, sym.name, FBT_RETURN, instr,
-+ addr, off, fbtp, arg);
-+ }
-+ }
-+}
-+EXPORT_SYMBOL(dtrace_fbt_init);
-diff --git a/arch/arm64/kernel/dtrace_sdt.c b/arch/arm64/kernel/dtrace_sdt.c
-new file mode 100644
-index 000000000000..d5a6a9d398b3
---- /dev/null
-+++ b/arch/arm64/kernel/dtrace_sdt.c
-@@ -0,0 +1,25 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_sdt.c
-+ * DESCRIPTION: Dynamic Tracing: SDT registration code (arch-specific)
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/module.h>
-+#include <asm/insn.h>
-+#include <asm/dtrace_arch.h>
-+#include <asm/dtrace_sdt_arch.h>
-+
-+void __init_or_module dtrace_sdt_nop_multi(asm_instr_t **addrs,
-+ int *is_enabled, int cnt)
-+{
-+ int i;
-+
-+ for (i = 0; i < cnt; i++) {
-+ if (likely(!is_enabled[i]))
-+ aarch64_insn_patch_text_nosync(addrs[i], NOP_INSTR);
-+ else
-+ aarch64_insn_patch_text_nosync(addrs[i], MOV_INSTR);
-+ }
-+}
-diff --git a/arch/arm64/kernel/dtrace_syscall.c b/arch/arm64/kernel/dtrace_syscall.c
-new file mode 100644
-index 000000000000..73730e42f3b8
---- /dev/null
-+++ b/arch/arm64/kernel/dtrace_syscall.c
-@@ -0,0 +1,89 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_syscall.c
-+ * DESCRIPTION: Dynamic Tracing: system call tracing support (arch-specific)
-+ *
-+ * Copyright (C) 2010, 2018 Oracle Corporation
-+ */
-+
-+#include <linux/dtrace_syscall.h>
-+#include <linux/ptrace.h>
-+#include <asm/syscall.h>
-+
-+void (*systrace_probe)(dtrace_id_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t);
-+
-+void systrace_stub(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
-+ uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
-+ uintptr_t arg5, uintptr_t arg6)
-+{
-+}
-+
-+asmlinkage long systrace_syscall(const struct pt_regs *regs);
-+
-+static struct systrace_info systrace_info = {
-+ &systrace_probe,
-+ systrace_stub,
-+ systrace_syscall,
-+ {},
-+ {
-+#undef __SYSCALL
-+#define __SYSCALL(nr, sym) [nr] { .name = __stringify(sym), },
-+#include <asm/unistd.h>
-+#undef __SYSCALL
-+ }
-+ };
-+
-+
-+asmlinkage long systrace_syscall(const struct pt_regs *regs)
-+{
-+ long rc = 0;
-+ unsigned long sysnum;
-+ dtrace_id_t id;
-+ struct dtrace_syscalls *sc;
-+
-+ sysnum = syscall_get_nr(current, (struct pt_regs *) regs);
-+ sc = &systrace_info.sysent[sysnum];
-+
-+ id = sc->stsy_entry;
-+ /* TODO: arg 6. */
-+ if (id != DTRACE_IDNONE)
-+ (*systrace_probe)(id, regs->regs[0], regs->regs[1],
-+ regs->regs[2], regs->regs[3], regs->regs[4],
-+ regs->regs[5], 0);
-+
-+ /*
-+ * FIXME: Add stop functionality for DTrace.
-+ */
-+
-+ if (sc->stsy_underlying != NULL)
-+ rc = (*sc->stsy_underlying)(regs);
-+
-+ id = sc->stsy_return;
-+ if (id != DTRACE_IDNONE)
-+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
-+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0, 0);
-+
-+ return rc;
-+}
-+
-+struct systrace_info *dtrace_syscalls_init()
-+{
-+ int i;
-+
-+ /*
-+ * Only initialize this stuff once...
-+ */
-+ if (systrace_info.sysent[0].stsy_tblent != NULL)
-+ return &systrace_info;
-+
-+ for (i = 0; i < NR_syscalls; i++) {
-+ systrace_info.sysent[i].stsy_tblent =
-+ (dt_sys_call_t *)&sys_call_table[i];
-+ systrace_info.sysent[i].stsy_underlying =
-+ (dt_sys_call_t)sys_call_table[i];
-+ }
-+
-+ return &systrace_info;
-+}
-+EXPORT_SYMBOL(dtrace_syscalls_init);
-diff --git a/arch/arm64/kernel/dtrace_syscall_stubs.S b/arch/arm64/kernel/dtrace_syscall_stubs.S
-new file mode 100644
-index 000000000000..e69de29bb2d1
-diff --git a/arch/arm64/kernel/dtrace_util.c b/arch/arm64/kernel/dtrace_util.c
-new file mode 100644
-index 000000000000..8142cf0459c2
---- /dev/null
-+++ b/arch/arm64/kernel/dtrace_util.c
-@@ -0,0 +1,292 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_util.c
-+ * DESCRIPTION: Dynamic Tracing: Architecture utility functions
-+ *
-+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/kdebug.h>
-+#include <linux/notifier.h>
-+#include <linux/ptrace.h>
-+#include <linux/uaccess.h>
-+#include <linux/uprobes.h>
-+#include <asm/debug-monitors.h>
-+#include <asm/insn.h>
-+
-+void dtrace_skip_instruction(struct pt_regs *regs)
-+{
-+ instruction_pointer_set(regs, instruction_pointer(regs) + 4);
-+}
-+
-+void dtrace_handle_badaddr(struct pt_regs *regs)
-+{
-+ unsigned long addr = current->thread.fault_address;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = addr;
-+
-+ dtrace_skip_instruction(regs);
-+}
-+
-+int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
-+ void *args)
-+{
-+ struct die_args *dargs = args;
-+
-+ switch (val) {
-+ case DIE_PAGE_FAULT: {
-+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
-+ return NOTIFY_DONE;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = dargs->err;
-+
-+ dtrace_skip_instruction(dargs->regs);
-+
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ }
-+ case DIE_OOPS: {
-+ pr_info("DTrace: last probe %u\n",
-+ this_cpu_core->cpuc_current_probe);
-+ return NOTIFY_DONE;
-+ }
-+ default:
-+ return NOTIFY_DONE;
-+ }
-+}
-+
-+struct user_stackframe {
-+ struct user_stackframe __user *fp;
-+ unsigned long lr;
-+} __packed;
-+
-+static int dtrace_unwind_frame(struct user_stackframe *frame)
-+{
-+ struct user_stackframe __user *ofp = frame->fp;
-+ unsigned long ret;
-+
-+ /* Verify alignment. */
-+ if ((unsigned long)ofp & 0xf)
-+ return -EINVAL;
-+
-+ /* Verify read access. */
-+ if (!access_ok(ofp, sizeof(struct user_stackframe)))
-+ return -EINVAL;
-+
-+ pagefault_disable();
-+ ret = __copy_from_user_inatomic(frame, ofp,
-+ sizeof(struct user_stackframe));
-+ pagefault_enable();
-+
-+ /* Make sure the read worked. */
-+ if (ret) {
-+ frame->fp = ofp;
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * If the frame pointer in the current frame is NULL, we have reached
-+ * the end of the call chain.
-+ */
-+ if (frame->fp == NULL)
-+ return 0;
-+
-+ /*
-+ * In older glibc versions, the call chain did not end with an initial
-+ * frame with NULL frame pointer. Instead, the initial frame stored
-+ * the beginning of the stack as frame pointer. We look for that here
-+ * as a special case, and return a frame where the frame pointer is
-+ * set to NULL (as it ought to be).
-+ *
-+ * If we do not know the beginning of the stack, we are out of luck.
-+ */
-+ if (current->dt_task && current->dt_task->dt_ustack == frame->fp) {
-+ frame->fp = NULL;
-+ return 0;
-+ }
-+
-+ /*
-+ * Verify strictly increasing consecutive values. Since the stack
-+ * grows downward, walking the call chain in reverse must yield ever
-+ * increasing frame pointers.
-+ */
-+ if (ofp >= frame->fp)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+void dtrace_user_stacktrace(struct stacktrace_state *st)
-+{
-+ struct pt_regs *regs = current_pt_regs();
-+ uint64_t *pcs = st->pcs;
-+ int limit = st->limit;
-+ int fixups, patches, skip;
-+ struct user_stackframe frame0, frame;
-+ struct user_stackframe *bos = current->dt_task
-+ ? current->dt_task->dt_ustack
-+ : NULL;
-+ struct return_instance *rilist = current->utask
-+ ? current->utask->return_instances
-+ : NULL;
-+ struct return_instance *ri;
-+
-+ /*
-+ * If we do not have user-mode registers, or if there is no known
-+ * bottom of stack, we cannot collect a call chain.
-+ */
-+ if (!user_mode(regs))
-+ goto out;
-+ if (!bos)
-+ goto out;
-+ if (!limit)
-+ goto out;
-+
-+ frame0.fp = (struct user_stackframe __user *)regs->regs[29];
-+ frame0.lr = regs->regs[30];
-+
-+ /*
-+ * The first special situation we need to deal with here is the rare
-+ * case of tracing the instruction after a call, when the current
-+ * program counter just got loaded from the link register, i.e. they
-+ * will be the same. In that case, we don't want to record both pc
-+ * and lr in the trace.
-+ *
-+ * Uretprobes are also tricky because if we are asked to provide a
-+ * ustack() while processing a uretprobe firing, we are still in the
-+ * middle of handling the probe. Things are not back to normal yet.
-+ */
-+ if (regs->pc != frame0.lr) {
-+ ri = rilist;
-+ if (pcs) {
-+ if (uprobe_return_addr_is_hijacked(frame0.lr) &&
-+ ri && ri->orig_ret_vaddr == regs->pc)
-+ *pcs++ = ri->func;
-+ else
-+ *pcs++ = regs->pc;
-+ }
-+
-+ limit--;
-+ st->depth++;
-+
-+ if (!limit)
-+ goto out;
-+ }
-+
-+ /*
-+ * First pass: determine how many return addresses need to be fixed up,
-+ * and how many return instances we have.
-+ */
-+ frame = frame0;
-+ fixups = 0;
-+ do {
-+ if (uprobe_return_addr_is_hijacked(frame.lr))
-+ fixups++;
-+
-+ if (frame.fp == NULL)
-+ break;
-+
-+ if (dtrace_unwind_frame(&frame) < 0) {
-+ this_cpu_core->cpuc_dtrace_illval = (uintptr_t)frame.fp;
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADSTACK);
-+ break;
-+ }
-+ } while (frame.lr);
-+
-+ patches = 0;
-+ for (ri = rilist; ri != NULL; ri = ri->next)
-+ patches++;
-+
-+ /*
-+ * It is possible that we think we need one more fixup than we can
-+ * satisfy with the return instances. This is because we cannot quite
-+ * determine whether the first one is actually needed or not (due to
-+ * lack of proper state when the uretprobe implementation interferes
-+ * with frame chain walking).
-+ */
-+ skip = fixups - patches;
-+ if (skip > 1) {
-+ this_cpu_core->cpuc_dtrace_illval = 0;
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADSTACK);
-+ goto out;
-+ }
-+
-+ /*
-+ * Second pass: fill in the actual stack trace.
-+ */
-+ frame = frame0;
-+ ri = rilist;
-+ do {
-+ if (uprobe_return_addr_is_hijacked(frame.lr)) {
-+ if (skip) {
-+ skip = 0;
-+ goto skip_frame;
-+ }
-+
-+ frame.lr = ri->orig_ret_vaddr;
-+ ri = ri->next;
-+ }
-+
-+ if (pcs)
-+ *pcs++ = frame.lr;
-+
-+ limit--;
-+ st->depth++;
-+
-+skip_frame:
-+ if (frame.fp == NULL)
-+ break;
-+
-+ if (dtrace_unwind_frame(&frame) < 0) {
-+ this_cpu_core->cpuc_dtrace_illval = (uintptr_t)frame.fp;
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADSTACK);
-+ break;
-+ }
-+ } while (limit);
-+
-+out:
-+ if (pcs) {
-+ while (limit--)
-+ *pcs++ = 0;
-+ }
-+}
-+
-+asm_instr_t dtrace_text_peek(asm_instr_t *addr)
-+{
-+ asm_instr_t opcode;
-+
-+ aarch64_insn_read(addr, &opcode);
-+
-+ return opcode;
-+}
-+EXPORT_SYMBOL(dtrace_text_peek);
-+
-+void dtrace_text_poke(asm_instr_t *addr, asm_instr_t opcode)
-+{
-+ aarch64_insn_patch_text_nosync(addr, opcode);
-+}
-+EXPORT_SYMBOL(dtrace_text_poke);
-+
-+void dtrace_kernel_brk_start(void *arg)
-+{
-+ register_kernel_break_hook((struct break_hook *)arg);
-+}
-+EXPORT_SYMBOL(dtrace_kernel_brk_start);
-+
-+void dtrace_kernel_brk_stop(void *arg)
-+{
-+ unregister_kernel_break_hook((struct break_hook *)arg);
-+}
-+EXPORT_SYMBOL(dtrace_kernel_brk_stop);
-+
-+void dtrace_mod_pdata_init(struct dtrace_module *pdata)
-+{
-+}
-+
-+void dtrace_mod_pdata_cleanup(struct dtrace_module *pdata)
-+{
-+}
-diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
-index 70e0a7591245..b4f8280d9ce3 100644
---- a/arch/arm64/kernel/entry-common.c
-+++ b/arch/arm64/kernel/entry-common.c
-@@ -199,8 +199,7 @@ static void noinstr el1_fpac(struct pt_regs *regs, unsigned long esr)
- local_daif_mask();
- exit_to_kernel_mode(regs);
- }
--
--asmlinkage void noinstr el1_sync_handler(struct pt_regs *regs)
-+asmlinkage int noinstr el1_sync_handler(struct pt_regs *regs)
- {
- unsigned long esr = read_sysreg(esr_el1);
-
-@@ -225,13 +224,14 @@ asmlinkage void noinstr el1_sync_handler(struct pt_regs *regs)
- case ESR_ELx_EC_WATCHPT_CUR:
- case ESR_ELx_EC_BRK64:
- el1_dbg(regs, esr);
-- break;
-+ return 1;
- case ESR_ELx_EC_FPAC:
- el1_fpac(regs, esr);
- break;
- default:
- el1_inv(regs, esr);
- }
-+ return 0;
- }
-
- asmlinkage void noinstr enter_from_user_mode(void)
-diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
-index d72c818b019c..6ac1846a645e 100644
---- a/arch/arm64/kernel/entry.S
-+++ b/arch/arm64/kernel/entry.S
-@@ -28,6 +28,7 @@
- #include <asm/thread_info.h>
- #include <asm/asm-uaccess.h>
- #include <asm/unistd.h>
-+#include <asm/debug-monitors.h>
-
- /*
- * Context tracking and irqflag tracing need to instrument transitions between
-@@ -276,7 +277,7 @@ alternative_else_nop_endif
- */
- .endm
-
-- .macro kernel_exit, el
-+ .macro kernel_exit, el, fbt_emu = 0
- .if \el != 0
- disable_daif
-
-@@ -332,7 +333,11 @@ alternative_else_nop_endif
-
- msr elr_el1, x21 // set up the return data
- msr spsr_el1, x22
-- ldp x0, x1, [sp, #16 * 0]
-+
-+ /*
-+ * No need to restore x0 and x1 - we may still clobber them. We will
-+ * restore them right before we return.
-+ */
- ldp x2, x3, [sp, #16 * 1]
- ldp x4, x5, [sp, #16 * 2]
- ldp x6, x7, [sp, #16 * 3]
-@@ -348,7 +353,44 @@ alternative_else_nop_endif
- ldp x26, x27, [sp, #16 * 13]
- ldp x28, x29, [sp, #16 * 14]
- ldr lr, [sp, #S_LR]
-+
-+ .if \fbt_emu != 0 // FBT emulation needed?
-+ mrs x0, esr_el1 // check if ESR is FBT probe
-+ and x0, x0, #0x1f // ... mask code
-+ cmp x0, #DPROBES_FBE_BRK_IMM // ... compare with FBE code
-+ beq 6f // FBT entry -> emulate instr.
-+ cmp x0, #DPROBES_FBR_BRK_IMM // ... compare with FBR code
-+ beq 7f // FBT return -> emulate instr.
-+ b 8f // not FBT -> skip next section
-+
-+6:
-+ mrs x0, elr_el1 // retrieve xeceptionx link reg
-+ add x0, x0, #0x4 // advance to next instr
-+ msr elr_el1, x0 // set exception link reg
-+
-+ ldp x0, x1, [sp, #16 * 0] // done with x0, restore orig
- add sp, sp, #S_FRAME_SIZE // restore sp
-+ mov x29, sp // instr we put probe on
-+ b 9f // FBT done -> branch to eret
-+
-+7:
-+ msr elr_el1, lr // set exception link reg to
-+ // link register value, to
-+ // simulate the 'ret' instr.
-+
-+ ldp x0, x1, [sp, #16 * 0] // done with x0, restore orig
-+ add sp, sp, #S_FRAME_SIZE // restore sp
-+ b 9f // FBT done -> branch to eret
-+
-+8:
-+ ldp x0, x1, [sp, #16 * 0] // done with x0, restore orig
-+ add sp, sp, #S_FRAME_SIZE // restore sp
-+9:
-+ .else
-+ ldp x0, x1, [sp, #16 * 0] // done with x0, restore orig
-+ add sp, sp, #S_FRAME_SIZE // restore sp
-+
-+ .endif
-
- .if \el == 0
- alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
-@@ -625,7 +667,12 @@ SYM_CODE_START_LOCAL_NOALIGN(el1_sync)
- kernel_entry 1
- mov x0, sp
- bl el1_sync_handler
-- kernel_exit 1
-+#if IS_ENABLED(CONFIG_DT_FBT)
-+ cmp x0, 1
-+ b.ne 1020f
-+ kernel_exit 1, 1
-+#endif
-+1020: kernel_exit 1
- SYM_CODE_END(el1_sync)
-
- .align 6
-diff --git a/arch/arm64/kernel/fbt_blacklist.h b/arch/arm64/kernel/fbt_blacklist.h
-new file mode 100644
-index 000000000000..7ad327515c8f
---- /dev/null
-+++ b/arch/arm64/kernel/fbt_blacklist.h
-@@ -0,0 +1,91 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Functions used in die notifier chain calling.
-+ */
-+BL_SENTRY(void *, notify_die)
-+BL_DENTRY(void *, notifier_call_chain)
-+BL_SENTRY(typeof(atomic_notifier_call_chain_robust), atomic_notifier_call_chain_robust)
-+BL_SENTRY(typeof(atomic_notifier_call_chain), atomic_notifier_call_chain)
-+BL_SENTRY(typeof(raw_notifier_call_chain_robust), raw_notifier_call_chain_robust)
-+BL_SENTRY(typeof(raw_notifier_call_chain), raw_notifier_call_chain)
-+BL_DENTRY(void *, hw_breakpoint_exceptions_notify)
-+BL_DENTRY(void *, kprobe_exceptions_notify)
-+
-+/*
-+ * Functions used to update vtime in probe context.
-+ */
-+BL_SENTRY(typeof(ktime_get_raw_fast_ns), ktime_get_raw_fast_ns)
-+BL_DENTRY(void *, raw_read_seqcount)
-+BL_DENTRY(void *, read_seqcount_retry)
-+BL_DENTRY(void *, __read_seqcount_retry)
-+
-+/* xen_clocksource */
-+BL_DENTRY(void *, xen_clocksource_get_cycles)
-+BL_DENTRY(void *, xen_clocksource_read)
-+BL_DENTRY(void *, pvclock_clocksource_read)
-+BL_DENTRY(void *, pvclock_touch_watchdogs)
-+BL_DENTRY(void *, touch_softlockup_watchdog_sync)
-+BL_DENTRY(void *, clocksource_touch_watchdog)
-+BL_DENTRY(void *, clocksource_resume_watchdog)
-+BL_DENTRY(void *, reset_hung_task_detector)
-+/* clocksource_tsc */
-+BL_DENTRY(void *, read_tsc)
-+BL_DENTRY(void *, get_cycles)
-+/* clocksource_hpet */
-+BL_DENTRY(void *, read_hpet)
-+BL_DENTRY(void *, hpet_readl)
-+/* kvm_clock */
-+BL_DENTRY(void *, kvm_clock_get_cycles)
-+BL_DENTRY(void *, kvm_clock_read)
-+/* arm_arch */
-+BL_DENTRY(void *, arch_counter_get_cntvct);
-+BL_DENTRY(void *, arch_counter_get_cntvct_mem);
-+BL_DENTRY(void *, arch_counter_get_cntpct);
-+BL_DENTRY(void *, arch_counter_read);
-+
-+/*
-+ * Functions used in trap handling.
-+ */
-+BL_DENTRY(void *, fixup_exception)
-+BL_DENTRY(void *, paranoid_entry)
-+BL_DENTRY(void *, kgdb_ll_trap)
-+BL_DENTRY(void *, error_entry)
-+BL_DENTRY(void *, xen_int3)
-+BL_DENTRY(void *, ftrace_int3_handler)
-+BL_DENTRY(typeof(poke_int3_handler), poke_int3_handler)
-+BL_DENTRY(void *, fixup_bad_iret)
-+BL_DENTRY(void *, xen_adjust_exception_frame)
-+BL_DENTRY(void *, paravirt_nop)
-+BL_DENTRY(void *, ist_enter)
-+BL_DENTRY(void *, rcu_nmi_enter)
-+BL_DENTRY(void *, rcu_dynticks_curr_cpu_in_eqs)
-+BL_DENTRY(void *, rcu_dynticks_eqs_exit)
-+BL_DENTRY(void *, rcu_nmi_exit)
-+BL_DENTRY(void *, rcu_dynticks_eqs_enter)
-+BL_DENTRY(void *, ist_exit)
-+
-+/*
-+ * Functions used in page fault handling.
-+ */
-+BL_DENTRY(void *, do_page_fault)
-+BL_DENTRY(void *, __do_page_fault)
-+BL_DENTRY(void *, down_read_trylock)
-+BL_DENTRY(void *, __get_user_pages_fast)
-+BL_DENTRY(void *, gup_pud_range)
-+BL_DENTRY(void *, gup_huge_pud)
-+BL_DENTRY(void *, gup_pmd_range)
-+BL_DENTRY(void *, gup_huge_pmd)
-+BL_DENTRY(void *, gup_pte_range)
-+BL_DENTRY(void *, pte_mfn_to_pfn)
-+
-+/*
-+ * Functions used under 4.19 idr_find
-+ */
-+BL_DENTRY(void *, idr_find)
-+BL_DENTRY(void *, find_next_bit)
-+BL_DENTRY(void *, _find_next_bit)
-+BL_DENTRY(void *, radix_tree_lookup)
-+BL_DENTRY(void *, __radix_tree_lookup)
-+BL_DENTRY(void *, radix_tree_load_root)
-+BL_DENTRY(void *, radix_tree_descend)
-+BL_DENTRY(void *, is_sibling_entry)
-diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
-index a412d8edbcd2..49482af77b9f 100644
---- a/arch/arm64/kernel/probes/uprobes.c
-+++ b/arch/arm64/kernel/probes/uprobes.c
-@@ -179,7 +179,8 @@ static int uprobe_single_step_handler(struct pt_regs *regs,
- {
- struct uprobe_task *utask = current->utask;
-
-- WARN_ON(utask && (instruction_pointer(regs) != utask->xol_vaddr + 4));
-+ WARN_ON(utask && utask->active_uprobe &&
-+ (instruction_pointer(regs) != utask->xol_vaddr + 4));
- if (uprobe_post_sstep_notifier(regs))
- return DBG_HOOK_HANDLED;
-
-diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c
-index d5ffaaab31a7..4563f0a4d0db 100644
---- a/arch/arm64/kernel/sys.c
-+++ b/arch/arm64/kernel/sys.c
-@@ -55,7 +55,7 @@ asmlinkage long __arm64_sys_ni_syscall(const struct pt_regs *__unused)
- #undef __SYSCALL
- #define __SYSCALL(nr, sym) [nr] = __arm64_##sym,
-
--const syscall_fn_t sys_call_table[__NR_syscalls] = {
-+CONST_SYS_CALL_TABLE syscall_fn_t sys_call_table[__NR_syscalls] = {
- [0 ... __NR_syscalls - 1] = __arm64_sys_ni_syscall,
- #include <asm/unistd.h>
- };
-diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
-index 795d224f184f..d2725a8ac9f3 100644
---- a/arch/arm64/mm/fault.c
-+++ b/arch/arm64/mm/fault.c
-@@ -14,6 +14,7 @@
- #include <linux/mm.h>
- #include <linux/hardirq.h>
- #include <linux/init.h>
-+#include <linux/kdebug.h>
- #include <linux/kprobes.h>
- #include <linux/uaccess.h>
- #include <linux/page-flags.h>
-@@ -60,6 +61,19 @@ static inline const struct fault_info *esr_to_debug_fault_info(unsigned int esr)
- return debug_fault_info + DBG_ESR_EVT(esr);
- }
-
-+#ifdef CONFIG_DTRACE
-+static int dtrace_fault(struct pt_regs *regs, unsigned long addr)
-+{
-+ preempt_disable();
-+ if (notify_die(DIE_PAGE_FAULT, "page fault", regs, addr, 14,
-+ SIGKILL) == NOTIFY_STOP)
-+ return 1;
-+ preempt_enable();
-+
-+ return 0;
-+}
-+#endif
-+
- static void data_abort_decode(unsigned int esr)
- {
- pr_alert("Data abort info:\n");
-@@ -459,6 +473,10 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
-
- if (kprobe_page_fault(regs, esr))
- return 0;
-+#ifdef CONFIG_DTRACE
-+ if (dtrace_fault(regs, addr))
-+ return 0;
-+#endif
-
- /*
- * If we're in an interrupt or have no user context, we must not take
-diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
-index f46e0ca0169c..b27885982066 100644
---- a/include/linux/uprobes.h
-+++ b/include/linux/uprobes.h
-@@ -124,6 +124,7 @@ extern void uprobe_copy_process(struct task_struct *t, unsigned long flags);
- extern int uprobe_post_sstep_notifier(struct pt_regs *regs);
- extern int uprobe_pre_sstep_notifier(struct pt_regs *regs);
- extern void uprobe_notify_resume(struct pt_regs *regs);
-+extern bool uprobe_return_addr_is_hijacked(unsigned long addr);
- extern bool uprobe_deny_signal(void);
- extern bool arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs);
- extern void uprobe_clear_state(struct mm_struct *mm);
-diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
-index 00b0358739ab..5a7a1c019870 100644
---- a/kernel/events/uprobes.c
-+++ b/kernel/events/uprobes.c
-@@ -1845,6 +1845,16 @@ static unsigned long get_trampoline_vaddr(void)
- return trampoline_vaddr;
- }
-
-+/*
-+ * Verify whether a return address is a trampoline address or a regular return
-+ * address. This is used by stack unwinders to determine whether a return
-+ * address in a stack trace needs to be adjusted.
-+ */
-+bool uprobe_return_addr_is_hijacked(unsigned long addr)
-+{
-+ return addr == get_trampoline_vaddr();
-+}
-+
- static void cleanup_return_instances(struct uprobe_task *utask, bool chained,
- struct pt_regs *regs)
- {
-diff --git a/scripts/dtrace_sdt_arm64.sh b/scripts/dtrace_sdt_arm64.sh
-new file mode 100755
-index 000000000000..a8fdc4ae0bc4
---- /dev/null
-+++ b/scripts/dtrace_sdt_arm64.sh
-@@ -0,0 +1,425 @@
-+#!/bin/sh
-+
-+LANG=C
-+export LANG
-+
-+#
-+# Syntax:
-+# dtrace_sdt_arm64.sh sdtinfo <S-file> <l-file> <o-file>
-+# This is used to generate DTrace SDT probe definitions for a
-+# linked kernel image file <l-file>, based on relocation info
-+# from the kernel object file <o-file>. The output is written
-+# to <S-file>.
-+#
-+
-+opr="$1"
-+shift
-+if [ -z "$opr" ]; then
-+ echo "ERROR: Missing operation" > /dev/stderr
-+ exit 1
-+elif [ "$opr" != "sdtinfo" ]; then
-+ echo "ERROR: Invalid operation: ${opr}" > /dev/stderr
-+ exit 1
-+fi
-+
-+tfn="$1"
-+shift
-+if [ -z "$tfn" ]; then
-+ echo "ERROR: Missing target filename" > /dev/stderr
-+ exit 1
-+fi
-+
-+lfn="$1"
-+ofn="$2"
-+
-+if [ -z "$lfn" ]; then
-+ echo "ERROR: Missing linked kernel file argument" > /dev/stderr
-+ exit 1
-+elif [ -z "$ofn" ]; then
-+ echo "ERROR: Missing kernel object file argument" > /dev/stderr
-+ exit 1
-+fi
-+
-+# For arm64, the kernel is built using "-ffunction-sections -fdata-sections"
-+# which due to the linked bug conflicts with "--emit-relocs". Probe discovery
-+# therefore is a bit more complicated.
-+#
-+# First we collect the VMA address of all the code sections in the linked
-+# kernel image.
-+#
-+# Subsequently, we go through the list of symbols in the linked kernel image,
-+# and write out records for some select symbols that are used in the processing
-+# of probe locations:
-+#
-+# <section> <address> B <name>
-+# Named identifier at a specific address (global variable).
-+#
-+# We also process any function symbols, and build a lookup map for section-name
-+# pairs and just name. Due to the possibility of having symbols with identical
-+# names (in the same section, e.g. global and/or one or more local), we append
-+# -<n> to every 2nd and later copy of the same symbol name in the current
-+# section.
-+# section and name
-+# name
-+# (If multiple symbols map to any of the above combinations, that specific
-+# combination is omitted from the mapping.)
-+#
-+# Next, we process the list of function symbols, and for any function that
-+# is not located in a section that starts with .exit.text, .init.text, or
-+# .meminit.text) we determine its in-section offset and output a record:
-+#
-+# <section> <offset> F <name> <address> <section-base-address>
-+# Named function at a specific address.
-+#
-+# Finally, each relocation record from a non-init or exit section that relates
-+# to SDT probes is written to the output stream:
-+#
-+# <section> <address> R <value>
-+# Relocation within a section at a specific address
-+#
-+# Probes are identified in the relocation records as symbols with either a
-+# __dtrace_probe_ or __dtrace_isenabled_ prefix.
-+#
-+# All these records are sorted by section and offset, and any SDT probe
-+# location relocation records (R) result in writing out an entry that records
-+# its offset relative to the _stext symbol, along with the name of the function
-+# it was found in, and the probe name.
-+
-+(
-+ objdump -ht ${lfn}
-+ objdump -tr ${ofn}
-+) | \
-+ gawk 'function subl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ if (v0l >= v1l) {
-+ if (v0h >= v1h) {
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "ERROR: [stage 1.a] Invalid addresses: %s - %s\n", v0, v1;
-+ d = 0;
-+ errc++;
-+ }
-+ } else {
-+ if (v0h > v1h) {
-+ v0h--;
-+ v0l += 4294967296;
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "ERROR: [stage 1.b] Invalid addresses: %s - %s\n", v0, v1;
-+ d = 0;
-+ errc++;
-+ }
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 - v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ BEGIN {
-+ phase = 0;
-+ }
-+
-+ /^SYMBOL / {
-+ phase++;
-+ delete scnt;
-+ next;
-+ }
-+
-+ phase == 0 && /^ *[1-9][0-9]* / {
-+ snam = $2;
-+ addr = $4;
-+ getline;
-+ if (/CODE/)
-+ secs[snam] = addr;
-+
-+ next;
-+ }
-+
-+ phase == 1 && $NF ~ /_(stext|_init_(begin|end))$/ {
-+ print ". " $1 " B " $NF;
-+ next;
-+ }
-+
-+ phase == 1 && / F / {
-+ if ($4 ~ /^\.(exit|init|meminit)\.text/)
-+ next;
-+
-+ off = subl($1, secs[$4]);
-+
-+ sym = $NF;
-+ scnt[sym]++;
-+ if (scnt[sym] > 1)
-+ sym = sym"-"(scnt[sym] - 1);
-+
-+ # section and name
-+ id = $4 " " sym;
-+ if (id in smap) {
-+ if (smap[id] != $1)
-+ smap[id] = 0;
-+ } else
-+ smap[id] = $1;
-+
-+ # name
-+ id = sym;
-+ if (id in smap) {
-+ if (smap[id] != $1)
-+ smap[id] = 0;
-+ } else
-+ smap[id] = $1;
-+
-+ next;
-+ }
-+
-+ phase == 2 && / F / {
-+ if ($4 ~ /^\.(exit|init|meminit)\.text/)
-+ next;
-+
-+ sym = $NF;
-+ scnt[sym]++;
-+ if (scnt[sym] > 1)
-+ sym = sym"-"(scnt[sym] - 1);
-+
-+ # section and name
-+ id = $4 " " sym;
-+ if (!(id in smap))
-+ id = sym;
-+ # name
-+ if (id in smap) {
-+ addr = smap[id];
-+ if (!addr)
-+ print "ERROR: Non-unique symbol: " $4 " " $6 " " $1 " ["sym"]";
-+ } else {
-+ print "ERROR: Could not find " $4 " " $6 " " $1 " ["sym"]";
-+ addr = 0;
-+ }
-+
-+ print $4 " " $1 " F " $6 " " addr " " secs[$4];
-+ next;
-+ }
-+
-+ /^RELOC/ {
-+ sect = substr($4, 2, length($4) - 3);
-+ next;
-+ }
-+
-+ sect ~ /^\.(exit|init|meminit)\.text/ {
-+ next;
-+ }
-+
-+ sect && /__dtrace_probe_/ {
-+ $3 = substr($3, 16);
-+ sub(/[\-+].*$/, "", $3);
-+ print sect " " $1 " R " $3;
-+ next;
-+ }
-+
-+ sect && /__dtrace_isenabled_/ {
-+ $3 = substr($3, 20);
-+ sub(/[\-+].*$/, "", $3);
-+ print sect " " $1 " R ?" $3;
-+ next;
-+ }' | \
-+ sort -u | \
-+ gawk 'function addl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8 || length(v1) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ v0l += v1l;
-+ v0h += v1h;
-+ d = sprintf("%x", v0l);
-+ if (length(d) > 8) {
-+ v0h++;
-+ v0l -= 4294967296;
-+ }
-+ d = sprintf("%x", v0h);
-+ if (length(d) <= 8) {
-+ d = sprintf("%08x%08x", v0h, v0l);
-+ } else {
-+ printf "#error [stage 2.a] Invalid addresses: %s + %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 + v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ function subl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ if (v0l >= v1l) {
-+ if (v0h >= v1h) {
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error [stage 2.b] Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ if (v0h > v1h) {
-+ v0h--;
-+ v0l += 4294967296;
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error [stage 2.c] Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 - v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ function map_string(str, off) {
-+ if (str in strmap)
-+ off = strmap[str];
-+ else {
-+ off = strsz;
-+ strmap[str] = strsz;
-+ strv[strc++] = str;
-+ strsz += length(str) + 1;
-+ }
-+
-+ return off;
-+ }
-+
-+ BEGIN {
-+ print "#include <asm/types.h>";
-+ print "#if BITS_PER_LONG == 64";
-+ print "# define PTR .quad";
-+ if (arch == "aarch64")
-+ print "# define ALGN .align 3";
-+ else
-+ print "# define ALGN .align 8";
-+ print "#else";
-+ print "# define PTR .long";
-+ if (arch == "aarch64")
-+ print "# define ALGN .align 2";
-+ else
-+ print "# define ALGN .align 4";
-+ print "#endif";
-+
-+ print "\t.section .rodata, \042a\042";
-+ print "";
-+
-+ print ".globl dtrace_sdt_probes";
-+ print "\tALGN";
-+ print "dtrace_sdt_probes:";
-+
-+ probec = 0;
-+ stroff = 0;
-+ strc = 0;
-+ }
-+
-+ $1 == "ERROR:" {
-+ next;
-+ }
-+
-+ $4 == "_stext" {
-+ stext = $2;
-+ next;
-+ }
-+
-+ $4 == "__init_begin" {
-+ init_beg = $2;
-+ next;
-+ }
-+
-+ $4 == "__init_end" {
-+ init_end = $2;
-+ next;
-+ }
-+
-+ $3 == "F" {
-+ fnam = $4;
-+ sub(/\..*$/, "", fnam);
-+ foff = $2;
-+ fadr = $5;
-+
-+ if (fadr != padr)
-+ funcc++;
-+ padr = fadr;
-+
-+ next;
-+ }
-+
-+ $3 == "R" {
-+ addr = addl(fadr, subl($2, foff));
-+ if (addr >= init_beg && addr <= init_end)
-+ next;
-+ addr = subl(addr, stext);
-+
-+ print "/*";
-+ print " * " $1 " " foff " F " fnam " " fadr;
-+ print " * " $0;
-+ print " * (" fadr " + (" $2 " - " foff ")) - " stext;
-+ print " */";
-+ printf "\tPTR\t_stext + 0x%s\n", addr;
-+ printf "\tPTR\t%d\n", map_string($4);
-+ printf "\tPTR\t%d\n", map_string(fnam);
-+
-+ probec++;
-+
-+ next;
-+ }
-+
-+ END {
-+ print "";
-+ print ".globl dtrace_sdt_strings";
-+ print "\tALGN";
-+ print "dtrace_sdt_strings:";
-+
-+
-+ for (i = 0; i < strc; i++)
-+ printf "\t.asciz\t\042%s\042\n", strv[i];
-+
-+ print "";
-+ print ".globl dtrace_sdt_nprobes";
-+ print ".globl dtrace_fbt_nfuncs";
-+ print "\tALGN";
-+ print "dtrace_sdt_nprobes:";
-+ printf "\tPTR\t%d\n", probec;
-+ print "dtrace_fbt_nfuncs:";
-+ printf "\tPTR\t%d\n", funcc;
-+
-+ exit(errc == 0 ? 0 : 1);
-+ }' > ${tfn}
-+
-+exit $?
-diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
-index 0b2f3bb60936..aa4c70504d8c 100755
---- a/scripts/link-vmlinux.sh
-+++ b/scripts/link-vmlinux.sh
-@@ -63,7 +63,12 @@ sdtinfo()
- {
- info SDTINF ${2}
-
-- ${srctree}/scripts/dtrace_sdt.sh sdtinfo .tmp_sdtinfo.S ${1}
-+ if [ -n "${CONFIG_ARM64}" ]; then
-+ ${srctree}/scripts/dtrace_sdt_arm64.sh sdtinfo .tmp_sdtinfo.S \
-+ ${1} ${3}
-+ else
-+ ${srctree}/scripts/dtrace_sdt.sh sdtinfo .tmp_sdtinfo.S ${1}
-+ fi
-
- local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
- ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
-@@ -389,16 +394,14 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
-
- # step 1
- if [ -n "${CONFIG_DTRACE}" ]; then
-- sdtinfo vmlinux.o ${sdtinfoo}
-+ sdtinfo vmlinux.o ${sdtinfoo} vmlinux.o
- fi
-
- kallsyms_step 1
-
- if [ -n "${CONFIG_DTRACE}" ]; then
-- if [ -n "${CONFIG_ARM64}" ]; then
-- kallsyms_step 1
-- else
-- kallsyms_step 1 -r
-+ if [ -n "${CONFIG_X86_64}" ]; then
-+ kallsyms_step 1 --emit-relocs
- fi
- sdtinfo ${kallsyms_vmlinux} ${sdtinfoo} vmlinux.o
- fi
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0017-dtrace-add-SDT-probes.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0017-dtrace-add-SDT-probes.patch
deleted file mode 100644
index c0d71f7e0b63..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0017-dtrace-add-SDT-probes.patch
+++ /dev/null
@@ -1,3306 +0,0 @@
-From 5694e5386d32e8fe708a76177b44244d18bd8f7b Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Thu, 8 Nov 2018 18:59:39 +0000
-Subject: [PATCH 17/19] dtrace: add SDT probes
-
-This adds a variety of SDT probes.
-
-XXX add documentation here from the commit messages
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- block/bio.c | 7 ++
- block/blk-core.c | 4 +
- fs/exec.c | 8 ++
- fs/nfs/internal.h | 13 +++
- fs/nfs/read.c | 3 +
- fs/nfs/write.c | 2 +
- fs/xfs/xfs_buf.c | 19 ++++
- include/linux/rwlock_api_smp.h | 38 +++++++
- include/linux/spinlock_api_smp.h | 12 ++
- kernel/exit.c | 5 +
- kernel/fork.c | 3 +
- kernel/locking/mutex.c | 52 ++++++++-
- kernel/locking/qrwlock.c | 24 +++-
- kernel/locking/qspinlock.c | 20 +++-
- kernel/sched/core.c | 31 +++++-
- kernel/signal.c | 31 +++++-
- kernel/time/timer.c | 3 +
- net/ipv4/ip_input.c | 66 +++++++++--
- net/ipv4/ip_output.c | 71 +++++++++++-
- net/ipv4/raw.c | 49 ++++++--
- net/ipv4/tcp.c | 26 +++++
- net/ipv4/tcp_input.c | 43 +++++++
- net/ipv4/tcp_ipv4.c | 114 ++++++++++++++++++-
- net/ipv4/tcp_minisocks.c | 15 +++
- net/ipv4/tcp_output.c | 29 +++++
- net/ipv4/udp.c | 26 ++++-
- net/ipv6/ip6_input.c | 103 ++++++++++++++---
- net/ipv6/ip6_output.c | 186 ++++++++++++++++++++++++++-----
- net/ipv6/mcast.c | 72 +++++++++---
- net/ipv6/ndisc.c | 9 ++
- net/ipv6/output_core.c | 9 ++
- net/ipv6/raw.c | 38 ++++++-
- net/ipv6/tcp_ipv6.c | 107 +++++++++++++++++-
- net/ipv6/udp.c | 26 ++++-
- 34 files changed, 1153 insertions(+), 111 deletions(-)
-
-diff --git a/block/bio.c b/block/bio.c
-index fa01bef35bb1..f2cde8dc402c 100644
---- a/block/bio.c
-+++ b/block/bio.c
-@@ -1153,6 +1153,8 @@ int submit_bio_wait(struct bio *bio)
- bio->bi_opf |= REQ_SYNC;
- submit_bio(bio);
-
-+ DTRACE_IO(wait__start, struct bio * : (bufinfo_t *, devinfo_t *), bio,
-+ struct file * : fileinfo_t *, NULL);
- /* Prevent hang_check timer from firing at us during very long I/O */
- hang_check = sysctl_hung_task_timeout_secs;
- if (hang_check)
-@@ -1161,6 +1163,8 @@ int submit_bio_wait(struct bio *bio)
- ;
- else
- wait_for_completion_io(&done);
-+ DTRACE_IO(wait__done, struct bio * : (bufinfo_t *, devinfo_t *), bio,
-+ struct file * : fileinfo_t *, NULL);
-
- return blk_status_to_errno(bio->bi_status);
- }
-@@ -1444,6 +1448,9 @@ void bio_endio(struct bio *bio)
- }
-
- blk_throtl_bio_endio(bio);
-+ DTRACE_IO(done, struct bio * :
-+ (bufinfo_t *, devinfo_t *), bio,
-+ struct file * : fileinfo_t *, NULL);
- /* release cgroup info */
- bio_uninit(bio);
- if (bio->bi_end_io)
-diff --git a/block/blk-core.c b/block/blk-core.c
-index 2d53e2ff48ff..67523a6729fb 100644
---- a/block/blk-core.c
-+++ b/block/blk-core.c
-@@ -913,11 +913,15 @@ static noinline_for_stack bool submit_bio_checks(struct bio *bio)
- */
- bio_set_flag(bio, BIO_TRACE_COMPLETION);
- }
-+ DTRACE_IO(start, struct bio * : (bufinfo_t *, devinfo_t *), bio,
-+ struct file * : fileinfo_t *, NULL);
- return true;
-
- not_supported:
- status = BLK_STS_NOTSUPP;
- end_io:
-+ DTRACE_IO(start, struct bio * : (bufinfo_t *, devinfo_t *), bio,
-+ struct file * : fileinfo_t *, NULL);
- bio->bi_status = status;
- bio_endio(bio);
- return false;
-diff --git a/fs/exec.c b/fs/exec.c
-index 4340b2803004..acd96c0e0e5f 100644
---- a/fs/exec.c
-+++ b/fs/exec.c
-@@ -64,6 +64,7 @@
- #include <linux/compat.h>
- #include <linux/vmalloc.h>
- #include <linux/io_uring.h>
-+#include <linux/sdt.h>
- #include <linux/dtrace_os.h>
-
- #include <linux/uaccess.h>
-@@ -1797,6 +1798,7 @@ static int bprm_execve(struct linux_binprm *bprm,
- current->in_execve = 1;
-
- file = do_open_execat(fd, filename, flags);
-+ DTRACE_PROC(exec, char *, filename->name);
- retval = PTR_ERR(file);
- if (IS_ERR(file))
- goto out_unmark;
-@@ -1834,6 +1836,8 @@ static int bprm_execve(struct linux_binprm *bprm,
- task_numa_free(current, false);
- if (displaced)
- put_files_struct(displaced);
-+
-+ DTRACE_PROC(exec__success);
- return retval;
-
- out:
-@@ -1923,6 +1927,8 @@ static int do_execveat_common(int fd, struct filename *filename,
-
- out_ret:
- putname(filename);
-+ if (retval < 0)
-+ DTRACE_PROC(exec__failure, int, retval);
- return retval;
- }
-
-@@ -1976,6 +1982,8 @@ int kernel_execve(const char *kernel_filename,
- free_bprm(bprm);
- out_ret:
- putname(filename);
-+ if (retval < 0)
-+ DTRACE_PROC(exec__failure, int, retval);
- return retval;
- }
-
-diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
-index 98554dd18a71..1e13fb97d642 100644
---- a/fs/nfs/internal.h
-+++ b/fs/nfs/internal.h
-@@ -10,6 +10,7 @@
- #include <linux/sunrpc/addr.h>
- #include <linux/nfs_page.h>
- #include <linux/wait_bit.h>
-+#include <linux/sdt.h>
-
- #define NFS_SB_MASK (SB_RDONLY|SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS)
-
-@@ -832,3 +833,15 @@ static inline void nfs_set_port(struct sockaddr *sap, int *port,
-
- rpc_set_port(sap, *port);
- }
-+
-+#define DTRACE_IO_NFS(name, rw, size, inode) \
-+ if (DTRACE_IO_ENABLED(name)) { \
-+ struct bio bio __maybe_unused = { \
-+ .bi_opf = rw, \
-+ .bi_iter.bi_size = size, \
-+ .bi_iter.bi_sector = NFS_FILEID(inode), \
-+ }; \
-+ DTRACE_IO(name, struct bio * : (bufinfo_t *, \
-+ devinfo_t *), &bio, \
-+ struct file * : fileinfo_t *, NULL); \
-+}
-diff --git a/fs/nfs/read.c b/fs/nfs/read.c
-index eb854f1f86e2..7049b4540f94 100644
---- a/fs/nfs/read.c
-+++ b/fs/nfs/read.c
-@@ -212,6 +212,8 @@ static void nfs_initiate_read(struct nfs_pgio_header *hdr,
- struct inode *inode = hdr->inode;
- int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0;
-
-+ DTRACE_IO_NFS(start, REQ_OP_READ, hdr->args.count, hdr->inode);
-+
- task_setup_data->flags |= swap_flags;
- rpc_ops->read_setup(hdr, msg);
- trace_nfs_initiate_read(hdr);
-@@ -243,6 +245,7 @@ static int nfs_readpage_done(struct rpc_task *task,
- struct inode *inode)
- {
- int status = NFS_PROTO(inode)->read_done(task, hdr);
-+ DTRACE_IO_NFS(done, REQ_OP_READ, hdr->res.count, hdr->inode);
- if (status != 0)
- return status;
-
-diff --git a/fs/nfs/write.c b/fs/nfs/write.c
-index 639c34fec04a..8bd0bd4e5b76 100644
---- a/fs/nfs/write.c
-+++ b/fs/nfs/write.c
-@@ -1403,6 +1403,7 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
- task_setup_data->priority = priority;
- rpc_ops->write_setup(hdr, msg, &task_setup_data->rpc_client);
- trace_nfs_initiate_write(hdr);
-+ DTRACE_IO_NFS(start, REQ_OP_WRITE, hdr->args.count, hdr->inode);
- }
-
- /* If a nfs_flush_* function fails, it should remove reqs from @head and
-@@ -1562,6 +1563,7 @@ static int nfs_writeback_done(struct rpc_task *task,
- * depend on tighter cache coherency when writing.
- */
- status = NFS_PROTO(inode)->write_done(task, hdr);
-+ DTRACE_IO_NFS(done, REQ_OP_WRITE, hdr->res.count, hdr->inode);
- if (status != 0)
- return status;
-
-diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
-index 4e4cf91f4f9f..6550a3447816 100644
---- a/fs/xfs/xfs_buf.c
-+++ b/fs/xfs/xfs_buf.c
-@@ -52,6 +52,21 @@ static kmem_zone_t *xfs_buf_zone;
- * b_lock (trylock due to inversion)
- */
-
-+#define DTRACE_IO_XFS_WAIT(name, bp, is_write) \
-+ if (DTRACE_IO_ENABLED(name)) { \
-+ struct bio bio __maybe_unused = { \
-+ .bi_iter.bi_sector = (bp)->b_bn, \
-+ .bi_iter.bi_size = (bp)->b_length, \
-+ .bi_opf = is_write ? \
-+ REQ_OP_WRITE : REQ_OP_READ, \
-+ .bi_disk = (bp)->b_target->bt_bdev->bd_disk, \
-+ .bi_partno = (bp)->b_target->bt_bdev->bd_partno,\
-+ }; \
-+ DTRACE_IO(name, struct bio * : (bufinfo_t *, \
-+ devinfo_t *), &bio, \
-+ struct file * : fileinfo_t *, NULL); \
-+ }
-+
- static int __xfs_buf_submit(struct xfs_buf *bp, bool wait);
-
- static inline int
-@@ -1633,10 +1648,14 @@ static int
- xfs_buf_iowait(
- struct xfs_buf *bp)
- {
-+ int orig_flags __attribute__((unused)) = bp->b_flags;
-+
- ASSERT(!(bp->b_flags & XBF_ASYNC));
-
- trace_xfs_buf_iowait(bp, _RET_IP_);
-+ DTRACE_IO_XFS_WAIT(wait__start, bp, orig_flags & XBF_WRITE);
- wait_for_completion(&bp->b_iowait);
-+ DTRACE_IO_XFS_WAIT(wait__done, bp, orig_flags & XBF_WRITE);
- trace_xfs_buf_iowait_done(bp, _RET_IP_);
-
- return bp->b_error;
-diff --git a/include/linux/rwlock_api_smp.h b/include/linux/rwlock_api_smp.h
-index abfb53ab11be..2531929ccb58 100644
---- a/include/linux/rwlock_api_smp.h
-+++ b/include/linux/rwlock_api_smp.h
-@@ -5,6 +5,8 @@
- # error "please don't include this file directly"
- #endif
-
-+#include <linux/sdt.h>
-+
- /*
- * include/linux/rwlock_api_smp.h
- *
-@@ -119,6 +121,8 @@ static inline int __raw_read_trylock(rwlock_t *lock)
- preempt_disable();
- if (do_raw_read_trylock(lock)) {
- rwlock_acquire_read(&lock->dep_map, 0, 1, _RET_IP_);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- return 1;
- }
- preempt_enable();
-@@ -130,6 +134,8 @@ static inline int __raw_write_trylock(rwlock_t *lock)
- preempt_disable();
- if (do_raw_write_trylock(lock)) {
- rwlock_acquire(&lock->dep_map, 0, 1, _RET_IP_);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- return 1;
- }
- preempt_enable();
-@@ -148,6 +154,8 @@ static inline void __raw_read_lock(rwlock_t *lock)
- preempt_disable();
- rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- }
-
- static inline unsigned long __raw_read_lock_irqsave(rwlock_t *lock)
-@@ -159,6 +167,8 @@ static inline unsigned long __raw_read_lock_irqsave(rwlock_t *lock)
- rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED_FLAGS(lock, do_raw_read_trylock, do_raw_read_lock,
- do_raw_read_lock_flags, &flags);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- return flags;
- }
-
-@@ -168,6 +178,8 @@ static inline void __raw_read_lock_irq(rwlock_t *lock)
- preempt_disable();
- rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- }
-
- static inline void __raw_read_lock_bh(rwlock_t *lock)
-@@ -175,6 +187,8 @@ static inline void __raw_read_lock_bh(rwlock_t *lock)
- __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- }
-
- static inline unsigned long __raw_write_lock_irqsave(rwlock_t *lock)
-@@ -186,6 +200,8 @@ static inline unsigned long __raw_write_lock_irqsave(rwlock_t *lock)
- rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED_FLAGS(lock, do_raw_write_trylock, do_raw_write_lock,
- do_raw_write_lock_flags, &flags);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- return flags;
- }
-
-@@ -195,6 +211,8 @@ static inline void __raw_write_lock_irq(rwlock_t *lock)
- preempt_disable();
- rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- }
-
- static inline void __raw_write_lock_bh(rwlock_t *lock)
-@@ -202,6 +220,8 @@ static inline void __raw_write_lock_bh(rwlock_t *lock)
- __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- }
-
- static inline void __raw_write_lock(rwlock_t *lock)
-@@ -209,6 +229,8 @@ static inline void __raw_write_lock(rwlock_t *lock)
- preempt_disable();
- rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- }
-
- #endif /* !CONFIG_GENERIC_LOCKBREAK || CONFIG_DEBUG_LOCK_ALLOC */
-@@ -217,6 +239,8 @@ static inline void __raw_write_unlock(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_write_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- preempt_enable();
- }
-
-@@ -224,6 +248,8 @@ static inline void __raw_read_unlock(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_read_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- preempt_enable();
- }
-
-@@ -232,6 +258,8 @@ __raw_read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_read_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- local_irq_restore(flags);
- preempt_enable();
- }
-@@ -240,6 +268,8 @@ static inline void __raw_read_unlock_irq(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_read_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- local_irq_enable();
- preempt_enable();
- }
-@@ -248,6 +278,8 @@ static inline void __raw_read_unlock_bh(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_read_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- }
-
-@@ -256,6 +288,8 @@ static inline void __raw_write_unlock_irqrestore(rwlock_t *lock,
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_write_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- local_irq_restore(flags);
- preempt_enable();
- }
-@@ -264,6 +298,8 @@ static inline void __raw_write_unlock_irq(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_write_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- local_irq_enable();
- preempt_enable();
- }
-@@ -272,6 +308,8 @@ static inline void __raw_write_unlock_bh(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_write_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- }
-
-diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h
-index 19a9be9d97ee..e7601d01b87d 100644
---- a/include/linux/spinlock_api_smp.h
-+++ b/include/linux/spinlock_api_smp.h
-@@ -5,6 +5,8 @@
- # error "please don't include this file directly"
- #endif
-
-+#include <linux/sdt.h>
-+
- /*
- * include/linux/spinlock_api_smp.h
- *
-@@ -88,6 +90,7 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock)
- preempt_disable();
- if (do_raw_spin_trylock(lock)) {
- spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- return 1;
- }
- preempt_enable();
-@@ -118,6 +121,7 @@ static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)
- #else
- do_raw_spin_lock_flags(lock, &flags);
- #endif
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- return flags;
- }
-
-@@ -127,6 +131,7 @@ static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)
- preempt_disable();
- spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- }
-
- static inline void __raw_spin_lock_bh(raw_spinlock_t *lock)
-@@ -134,6 +139,7 @@ static inline void __raw_spin_lock_bh(raw_spinlock_t *lock)
- __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- }
-
- static inline void __raw_spin_lock(raw_spinlock_t *lock)
-@@ -141,6 +147,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
- preempt_disable();
- spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- }
-
- #endif /* !CONFIG_GENERIC_LOCKBREAK || CONFIG_DEBUG_LOCK_ALLOC */
-@@ -149,6 +156,7 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
- {
- spin_release(&lock->dep_map, _RET_IP_);
- do_raw_spin_unlock(lock);
-+ DTRACE_LOCKSTAT(spin__release, spinlock_t *, lock);
- preempt_enable();
- }
-
-@@ -157,6 +165,7 @@ static inline void __raw_spin_unlock_irqrestore(raw_spinlock_t *lock,
- {
- spin_release(&lock->dep_map, _RET_IP_);
- do_raw_spin_unlock(lock);
-+ DTRACE_LOCKSTAT(spin__release, spinlock_t *, lock);
- local_irq_restore(flags);
- preempt_enable();
- }
-@@ -165,6 +174,7 @@ static inline void __raw_spin_unlock_irq(raw_spinlock_t *lock)
- {
- spin_release(&lock->dep_map, _RET_IP_);
- do_raw_spin_unlock(lock);
-+ DTRACE_LOCKSTAT(spin__release, spinlock_t *, lock);
- local_irq_enable();
- preempt_enable();
- }
-@@ -173,6 +183,7 @@ static inline void __raw_spin_unlock_bh(raw_spinlock_t *lock)
- {
- spin_release(&lock->dep_map, _RET_IP_);
- do_raw_spin_unlock(lock);
-+ DTRACE_LOCKSTAT(spin__release, spinlock_t *, lock);
- __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- }
-
-@@ -181,6 +192,7 @@ static inline int __raw_spin_trylock_bh(raw_spinlock_t *lock)
- __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- if (do_raw_spin_trylock(lock)) {
- spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- return 1;
- }
- __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
-diff --git a/kernel/exit.c b/kernel/exit.c
-index da498c5f029c..285b0c0ff00d 100644
---- a/kernel/exit.c
-+++ b/kernel/exit.c
-@@ -64,6 +64,7 @@
- #include <linux/rcuwait.h>
- #include <linux/compat.h>
- #include <linux/io_uring.h>
-+#include <linux/sdt.h>
- #include <linux/dtrace_os.h>
-
- #include <linux/uaccess.h>
-@@ -796,6 +797,10 @@ void __noreturn do_exit(long code)
- tsk->exit_code = code;
- taskstats_exit(tsk, group_dead);
-
-+ DTRACE_PROC(lwp__exit);
-+ if (group_dead)
-+ DTRACE_PROC(exit, int, code & 0x80 ? 3 : code & 0x7f ? 2 : 1);
-+
- /* Remove DTrace state for this task */
- dtrace_task_free(tsk);
-
-diff --git a/kernel/fork.c b/kernel/fork.c
-index 0d8a2b12fd90..0729e80e4ad8 100644
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -96,6 +96,7 @@
- #include <linux/kasan.h>
- #include <linux/scs.h>
- #include <linux/io_uring.h>
-+#include <linux/sdt.h>
- #include <linux/dtrace_task_impl.h>
-
- #include <asm/pgalloc.h>
-@@ -2513,6 +2514,8 @@ pid_t kernel_clone(struct kernel_clone_args *args)
- }
-
- put_pid(pid);
-+ DTRACE_PROC(lwp__create, struct task_struct * : (lwpsinfo_t *, psinfo_t *), p);
-+ DTRACE_PROC(create, struct task_struct * : psinfo_t *, p);
- return nr;
- }
-
-diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
-index 5352ce50a97e..e784dd89d924 100644
---- a/kernel/locking/mutex.c
-+++ b/kernel/locking/mutex.c
-@@ -29,6 +29,7 @@
- #include <linux/interrupt.h>
- #include <linux/debug_locks.h>
- #include <linux/osq_lock.h>
-+#include <linux/sdt.h>
-
- #ifdef CONFIG_DEBUG_MUTEXES
- # include "mutex-debug.h"
-@@ -282,6 +283,7 @@ void __sched mutex_lock(struct mutex *lock)
-
- if (!__mutex_trylock_fast(lock))
- __mutex_lock_slowpath(lock);
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
- }
- EXPORT_SYMBOL(mutex_lock);
- #endif
-@@ -734,10 +736,14 @@ static noinline void __sched __mutex_unlock_slowpath(struct mutex *lock, unsigne
- void __sched mutex_unlock(struct mutex *lock)
- {
- #ifndef CONFIG_DEBUG_LOCK_ALLOC
-- if (__mutex_unlock_fast(lock))
-+ if (__mutex_unlock_fast(lock)) {
-+ DTRACE_LOCKSTAT(adaptive__release, struct mutex *, lock);
- return;
-+ }
- #endif
-+
- __mutex_unlock_slowpath(lock, _RET_IP_);
-+ DTRACE_LOCKSTAT(adaptive__release, struct mutex *, lock);
- }
- EXPORT_SYMBOL(mutex_unlock);
-
-@@ -927,6 +933,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- struct lockdep_map *nest_lock, unsigned long ip,
- struct ww_acquire_ctx *ww_ctx, const bool use_ww_ctx)
- {
-+ u64 spinstart = 0, spinend, spintotal = 0;
-+ u64 waitstart, waitend, waittotal = 0;
- struct mutex_waiter waiter;
- bool first = false;
- struct ww_mutex *ww;
-@@ -958,9 +966,11 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- if (__mutex_trylock(lock) ||
- mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx, NULL)) {
- /* got the lock, yay! */
-+
- lock_acquired(&lock->dep_map, ip);
- if (use_ww_ctx && ww_ctx)
- ww_mutex_set_context_fastpath(ww, ww_ctx);
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
- preempt_enable();
- return 0;
- }
-@@ -1003,6 +1013,9 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- waiter.task = current;
-
- set_current_state(state);
-+ if (DTRACE_LOCKSTAT_ENABLED(adaptive__spin))
-+ spinstart = dtrace_gethrtime_ns();
-+
- for (;;) {
- /*
- * Once we hold wait_lock, we're serialized against
-@@ -1030,7 +1043,15 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- }
-
- spin_unlock(&lock->wait_lock);
-- schedule_preempt_disabled();
-+
-+ if (DTRACE_LOCKSTAT_ENABLED(adaptive__block)) {
-+ waitstart = dtrace_gethrtime_ns();
-+ schedule_preempt_disabled();
-+ waitend = dtrace_gethrtime_ns();
-+ if (waitend > waitstart)
-+ waittotal += waitend - waitstart;
-+ } else
-+ schedule_preempt_disabled();
-
- /*
- * ww_mutex needs to always recheck its position since its waiter
-@@ -1082,6 +1103,19 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- ww_mutex_lock_acquired(ww, ww_ctx);
-
- spin_unlock(&lock->wait_lock);
-+
-+ if (DTRACE_LOCKSTAT_ENABLED(adaptive__spin) && spinstart) {
-+ spinend = dtrace_gethrtime_ns();
-+ spintotal = (spinend > spinstart) ? (spinend - spinstart) : 0;
-+ spintotal = (spintotal > waittotal) ?
-+ (spintotal - waittotal) : 0;
-+ DTRACE_LOCKSTAT(adaptive__spin, struct mutex *, lock,
-+ uint64_t, spintotal);
-+ }
-+ if (DTRACE_LOCKSTAT_ENABLED(adaptive__block) && waittotal)
-+ DTRACE_LOCKSTAT(adaptive__block, struct mutex *, lock,
-+ uint64_t, waittotal);
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
- preempt_enable();
- return 0;
-
-@@ -1092,6 +1126,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- spin_unlock(&lock->wait_lock);
- debug_mutex_free_waiter(&waiter);
- mutex_release(&lock->dep_map, ip);
-+ DTRACE_LOCKSTAT(adaptive__acquire__error, struct mutex *, lock,
-+ int, ret);
- preempt_enable();
- return ret;
- }
-@@ -1307,8 +1343,10 @@ int __sched mutex_lock_interruptible(struct mutex *lock)
- {
- might_sleep();
-
-- if (__mutex_trylock_fast(lock))
-+ if (__mutex_trylock_fast(lock)) {
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
- return 0;
-+ }
-
- return __mutex_lock_interruptible_slowpath(lock);
- }
-@@ -1331,8 +1369,10 @@ int __sched mutex_lock_killable(struct mutex *lock)
- {
- might_sleep();
-
-- if (__mutex_trylock_fast(lock))
-+ if (__mutex_trylock_fast(lock)) {
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
- return 0;
-+ }
-
- return __mutex_lock_killable_slowpath(lock);
- }
-@@ -1416,8 +1456,10 @@ int __sched mutex_trylock(struct mutex *lock)
- #endif
-
- locked = __mutex_trylock(lock);
-- if (locked)
-+ if (locked) {
- mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_);
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
-+ }
-
- return locked;
- }
-diff --git a/kernel/locking/qrwlock.c b/kernel/locking/qrwlock.c
-index fe9ca92faa2a..6b1511be7805 100644
---- a/kernel/locking/qrwlock.c
-+++ b/kernel/locking/qrwlock.c
-@@ -11,6 +11,7 @@
- #include <linux/cpumask.h>
- #include <linux/percpu.h>
- #include <linux/hardirq.h>
-+#include <linux/sdt.h>
- #include <linux/spinlock.h>
- #include <asm/qrwlock.h>
-
-@@ -20,9 +21,13 @@
- */
- void queued_read_lock_slowpath(struct qrwlock *lock)
- {
-+ u64 spinstart = 0, spinend, spintime;
-+
- /*
- * Readers come here when they cannot get the lock without waiting
- */
-+ if (DTRACE_LOCKSTAT_ENABLED(rw__spin))
-+ spinstart = dtrace_gethrtime_ns();
- if (unlikely(in_interrupt())) {
- /*
- * Readers in interrupt context will get the lock immediately
-@@ -31,7 +36,7 @@ void queued_read_lock_slowpath(struct qrwlock *lock)
- * without waiting in the queue.
- */
- atomic_cond_read_acquire(&lock->cnts, !(VAL & _QW_LOCKED));
-- return;
-+ goto done;
- }
- atomic_sub(_QR_BIAS, &lock->cnts);
-
-@@ -52,6 +57,13 @@ void queued_read_lock_slowpath(struct qrwlock *lock)
- * Signal the next one in queue to become queue head
- */
- arch_spin_unlock(&lock->wait_lock);
-+done:
-+ if (DTRACE_LOCKSTAT_ENABLED(rw__spin) && spinstart) {
-+ spinend = dtrace_gethrtime_ns();
-+ spintime = spinend > spinstart ? spinend - spinstart : 0;
-+ DTRACE_LOCKSTAT(rw__spin, rwlock_t *, lock, uint64_t, spintime,
-+ int, DTRACE_LOCKSTAT_RW_READER);
-+ }
- }
- EXPORT_SYMBOL(queued_read_lock_slowpath);
-
-@@ -61,7 +73,11 @@ EXPORT_SYMBOL(queued_read_lock_slowpath);
- */
- void queued_write_lock_slowpath(struct qrwlock *lock)
- {
-+ u64 spinstart = 0, spinend, spintime;
-+
- /* Put the writer into the wait queue */
-+ if (DTRACE_LOCKSTAT_ENABLED(rw__spin))
-+ spinstart = dtrace_gethrtime_ns();
- arch_spin_lock(&lock->wait_lock);
-
- /* Try to acquire the lock directly if no reader is present */
-@@ -79,5 +95,11 @@ void queued_write_lock_slowpath(struct qrwlock *lock)
- _QW_LOCKED) != _QW_WAITING);
- unlock:
- arch_spin_unlock(&lock->wait_lock);
-+ if (DTRACE_LOCKSTAT_ENABLED(rw__spin) && spinstart) {
-+ spinend = dtrace_gethrtime_ns();
-+ spintime = spinend > spinstart ? spinend - spinstart : 0;
-+ DTRACE_LOCKSTAT(rw__spin, rwlock_t *, lock, uint64_t, spintime,
-+ int, DTRACE_LOCKSTAT_RW_WRITER);
-+ }
- }
- EXPORT_SYMBOL(queued_write_lock_slowpath);
-diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
-index cbff6ba53d56..44853c2b0183 100644
---- a/kernel/locking/qspinlock.c
-+++ b/kernel/locking/qspinlock.c
-@@ -20,6 +20,7 @@
- #include <linux/hardirq.h>
- #include <linux/mutex.h>
- #include <linux/prefetch.h>
-+#include <linux/sdt.h>
- #include <asm/byteorder.h>
- #include <asm/qspinlock.h>
-
-@@ -315,16 +316,20 @@ static __always_inline u32 __pv_wait_head_or_lock(struct qspinlock *lock,
- void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
- {
- struct mcs_spinlock *prev, *next, *node;
-+ u64 spinstart = 0, spinend, spintime;
- u32 old, tail;
- int idx;
-
- BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
-
-+ if (DTRACE_LOCKSTAT_ENABLED(spin__spin))
-+ spinstart = dtrace_gethrtime_ns();
-+
- if (pv_enabled())
- goto pv_queue;
-
- if (virt_spin_lock(lock))
-- return;
-+ goto out;
-
- /*
- * Wait for in-progress pending->locked hand-overs with a bounded
-@@ -388,7 +393,7 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
- */
- clear_pending_set_locked(lock);
- lockevent_inc(lock_pending);
-- return;
-+ goto out;
-
- /*
- * End of pending bit optimistic spinning and beginning of MCS
-@@ -558,6 +563,17 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
- * release the node
- */
- __this_cpu_dec(qnodes[0].mcs.count);
-+
-+ /*
-+ * Fire spin-spin probe to note time waiting for a lock.
-+ */
-+out:
-+ if (DTRACE_LOCKSTAT_ENABLED(spin__spin)) {
-+ spinend = dtrace_gethrtime_ns();
-+ spintime = spinend > spinstart ? spinend - spinstart : 0;
-+ DTRACE_LOCKSTAT(spin__spin, spinlock_t *, lock,
-+ uint64_t, spintime);
-+ }
- }
- EXPORT_SYMBOL(queued_spin_lock_slowpath);
-
-diff --git a/kernel/sched/core.c b/kernel/sched/core.c
-index db893818f3ea..f035f9859ae7 100644
---- a/kernel/sched/core.c
-+++ b/kernel/sched/core.c
-@@ -1561,6 +1561,9 @@ static inline void init_uclamp(void) { }
-
- static inline void enqueue_task(struct rq *rq, struct task_struct *p, int flags)
- {
-+ DTRACE_SCHED(enqueue, struct task_struct * : (lwpsinfo_t *,
-+ psinfo_t *), p,
-+ cpuinfo_t *, rq->dtrace_cpu_info);
- if (!(flags & ENQUEUE_NOCLOCK))
- update_rq_clock(rq);
-
-@@ -1575,6 +1578,10 @@ static inline void enqueue_task(struct rq *rq, struct task_struct *p, int flags)
-
- static inline void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
- {
-+ DTRACE_SCHED(dequeue, struct task_struct * : (lwpsinfo_t *,
-+ psinfo_t *), p,
-+ cpuinfo_t *, rq->dtrace_cpu_info,
-+ int, 0);
- if (!(flags & DEQUEUE_NOCLOCK))
- update_rq_clock(rq);
-
-@@ -2864,6 +2871,8 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
- goto unlock;
-
- trace_sched_waking(p);
-+ DTRACE_SCHED(wakeup, struct task_struct * : (lwpsinfo_t *,
-+ psinfo_t *), p);
-
- /* We're going to change ->state: */
- success = 1;
-@@ -3552,6 +3561,8 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
- sched_info_switch(rq, prev, next);
- perf_event_task_sched_out(prev, next);
- rseq_preempt(prev);
-+ DTRACE_SCHED(off__cpu, struct task_struct * : (lwpsinfo_t *,
-+ psinfo_t *), next);
- fire_sched_out_preempt_notifiers(prev, next);
- prepare_task(next);
- prepare_arch_switch(next);
-@@ -3625,6 +3636,7 @@ static struct rq *finish_task_switch(struct task_struct *prev)
- finish_arch_post_lock_switch();
- kcov_finish_switch(current);
-
-+ DTRACE_SCHED(on__cpu);
- fire_sched_in_preempt_notifiers(current);
- /*
- * When switching through a kernel thread, the loop in
-@@ -3725,6 +3737,8 @@ asmlinkage __visible void schedule_tail(struct task_struct *prev)
- put_user(task_pid_vnr(current), current->set_child_tid);
-
- calculate_sigpending();
-+ DTRACE_PROC(start);
-+ DTRACE_PROC(lwp__start);
- }
-
- /*
-@@ -4467,6 +4481,7 @@ static void __sched notrace __schedule(bool preempt)
- */
- prev_state = prev->state;
- if (!preempt && prev_state) {
-+ DTRACE_SCHED(sleep);
- if (signal_pending_state(prev_state, prev)) {
- prev->state = TASK_RUNNING;
- } else {
-@@ -4497,7 +4512,8 @@ static void __sched notrace __schedule(bool preempt)
- }
- }
- switch_count = &prev->nvcsw;
-- }
-+ } else
-+ DTRACE_SCHED(preempt);
-
- next = pick_next_task(rq, prev, &rf);
- clear_tsk_need_resched(prev);
-@@ -4534,6 +4550,7 @@ static void __sched notrace __schedule(bool preempt)
- rq = context_switch(rq, prev, next, &rf);
- } else {
- rq->clock_update_flags &= ~(RQCF_ACT_SKIP|RQCF_REQ_SKIP);
-+ DTRACE_SCHED(remain__cpu);
- rq_unlock_irq(rq, &rf);
- }
-
-@@ -4999,6 +5016,9 @@ void set_user_nice(struct task_struct *p, long nice)
- old_prio = p->prio;
- p->prio = effective_prio(p);
-
-+ DTRACE_SCHED(change__pri, struct task_struct * : (lwpsinfo_t *,
-+ psinfo_t *), p,
-+ int, old_prio);
- if (queued)
- enqueue_task(rq, p, ENQUEUE_RESTORE | ENQUEUE_NOCLOCK);
- if (running)
-@@ -6110,6 +6130,9 @@ static void do_sched_yield(void)
- rq_unlock_irq(rq, &rf);
- sched_preempt_enable_no_resched();
-
-+ DTRACE_SCHED(surrender,
-+ struct task_struct * : (lwpsinfo_t *, psinfo_t *),
-+ current);
- schedule();
- }
-
-@@ -6256,8 +6279,12 @@ int __sched yield_to(struct task_struct *p, bool preempt)
- out_irq:
- local_irq_restore(flags);
-
-- if (yielded > 0)
-+ if (yielded > 0) {
-+ DTRACE_SCHED(surrender,
-+ struct task_struct * : (lwpsinfo_t *, psinfo_t *),
-+ curr);
- schedule();
-+ }
-
- return yielded;
- }
-diff --git a/kernel/signal.c b/kernel/signal.c
-index ef8f2a28d37c..23cefab66287 100644
---- a/kernel/signal.c
-+++ b/kernel/signal.c
-@@ -49,6 +49,7 @@
-
- #define CREATE_TRACE_POINTS
- #include <trace/events/signal.h>
-+#include <linux/sdt.h>
-
- #include <asm/param.h>
- #include <linux/uaccess.h>
-@@ -1079,8 +1080,12 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
- assert_spin_locked(&t->sighand->siglock);
-
- result = TRACE_SIGNAL_IGNORED;
-- if (!prepare_signal(sig, t, force))
-+ if (!prepare_signal(sig, t, force)) {
-+ DTRACE_PROC(signal__discard,
-+ struct task_struct * : (lwpsinfo_t *, psinfo_t *), t,
-+ int, sig);
- goto ret;
-+ }
-
- pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending;
- /*
-@@ -1179,6 +1184,9 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
- }
-
- complete_signal(sig, t, type);
-+ DTRACE_PROC(signal__send,
-+ struct task_struct * : (lwpsinfo_t *, psinfo_t *), t,
-+ int, sig);
- ret:
- trace_signal_generate(sig, info, t, type != PIDTYPE_PID, result);
- return ret;
-@@ -1879,6 +1887,9 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type)
- list_add_tail(&q->list, &pending->list);
- sigaddset(&pending->signal, sig);
- complete_signal(sig, t, type);
-+ DTRACE_PROC(signal__send,
-+ struct task_struct * : (lwpsinfo_t *, psinfo_t *), t,
-+ int, sig);
- result = TRACE_SIGNAL_DELIVERED;
- out:
- trace_signal_generate(sig, &q->info, t, type != PIDTYPE_PID, result);
-@@ -2601,6 +2612,11 @@ bool get_signal(struct ksignal *ksig)
-
- /* Has this task already been marked for death? */
- if (signal_group_exit(signal)) {
-+ DTRACE_PROC(signal__handle,
-+ int, signal->group_exit_code
-+ ? signal->group_exit_code
-+ : signr,
-+ siginfo_t *, NULL, void (*)(void), NULL);
- ksig->info.si_signo = signr = SIGKILL;
- sigdelset(&current->pending.signal, SIGKILL);
- trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO,
-@@ -2658,6 +2674,15 @@ bool get_signal(struct ksignal *ksig)
-
- ka = &sighand->action[signr-1];
-
-+ DTRACE_PROC(signal__handle,
-+ int, signal->group_exit_code
-+ ? signal->group_exit_code
-+ : signr,
-+ siginfo_t *, ksig->ka.sa.sa_handler != SIG_DFL
-+ ? NULL
-+ : &ksig->info,
-+ void (*)(void), ksig->ka.sa.sa_handler);
-+
- /* Trace actually delivered signals. */
- trace_signal_deliver(signr, &ksig->info, ka);
-
-@@ -3498,8 +3523,10 @@ static int do_sigtimedwait(const sigset_t *which, kernel_siginfo_t *info,
- }
- spin_unlock_irq(&tsk->sighand->siglock);
-
-- if (sig)
-+ if (sig) {
-+ DTRACE_PROC(signal__clear, int, sig);
- return sig;
-+ }
- return ret ? -EINTR : -EAGAIN;
- }
-
-diff --git a/kernel/time/timer.c b/kernel/time/timer.c
-index c3ad64fb9d8b..a1b822cbdb80 100644
---- a/kernel/time/timer.c
-+++ b/kernel/time/timer.c
-@@ -44,6 +44,7 @@
- #include <linux/slab.h>
- #include <linux/compat.h>
- #include <linux/random.h>
-+#include <linux/sdt.h>
-
- #include <linux/uaccess.h>
- #include <asm/unistd.h>
-@@ -1702,6 +1703,8 @@ void update_process_times(int user_tick)
- struct task_struct *p = current;
-
- PRANDOM_ADD_NOISE(jiffies, user_tick, p, 0);
-+ DTRACE_SCHED(tick, struct task_struct * : (lwpsinfo_t *, psinfo_t *),
-+ p);
-
- /* Note: this timer irq context must be accounted for as well. */
- account_process_tick(p, user_tick);
-diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
-index b0c244af1e4d..038868b61cd8 100644
---- a/net/ipv4/ip_input.c
-+++ b/net/ipv4/ip_input.c
-@@ -141,6 +141,7 @@
- #include <linux/mroute.h>
- #include <linux/netlink.h>
- #include <net/dst_metadata.h>
-+#include <linux/sdt.h>
-
- /*
- * Process Router Attention IP option (RFC 2113)
-@@ -239,16 +240,26 @@ static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_b
- */
- int ip_local_deliver(struct sk_buff *skb)
- {
-+ struct iphdr *iph = ip_hdr(skb);
-+
- /*
- * Reassemble IP fragments.
- */
- struct net *net = dev_net(skb->dev);
-
-- if (ip_is_fragment(ip_hdr(skb))) {
-+ if (ip_is_fragment(iph)) {
- if (ip_defrag(net, skb, IP_DEFRAG_LOCAL_DELIVER))
- return 0;
- }
-
-+ DTRACE_IP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, iph,
-+ struct ipv6hdr * : ipv6info_t *, NULL);
-+
- return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN,
- net, NULL, skb, skb->dev, NULL,
- ip_local_deliver_finish);
-@@ -257,7 +268,8 @@ int ip_local_deliver(struct sk_buff *skb)
- static inline bool ip_rcv_options(struct sk_buff *skb, struct net_device *dev)
- {
- struct ip_options *opt;
-- const struct iphdr *iph;
-+ const struct iphdr *iph = NULL;
-+ const char *dropreason;
-
- /* It looks as overkill, because not all
- IP options require packet mangling.
-@@ -267,6 +279,7 @@ static inline bool ip_rcv_options(struct sk_buff *skb, struct net_device *dev)
- --ANK (980813)
- */
- if (skb_cow(skb, skb_headroom(skb))) {
-+ dropreason = "copy-on-write failed";
- __IP_INC_STATS(dev_net(dev), IPSTATS_MIB_INDISCARDS);
- goto drop;
- }
-@@ -276,6 +289,7 @@ static inline bool ip_rcv_options(struct sk_buff *skb, struct net_device *dev)
- opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
-
- if (ip_options_compile(dev_net(dev), opt, skb)) {
-+ dropreason = "invalid options";
- __IP_INC_STATS(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
- goto drop;
- }
-@@ -289,16 +303,28 @@ static inline bool ip_rcv_options(struct sk_buff *skb, struct net_device *dev)
- net_info_ratelimited("source route option %pI4 -> %pI4\n",
- &iph->saddr,
- &iph->daddr);
-+ dropreason = "invalid source route options";
- goto drop;
- }
- }
-
-- if (ip_options_rcv_srr(skb, dev))
-+ if (ip_options_rcv_srr(skb, dev)) {
-+ dropreason = "invalid options";
- goto drop;
-+ }
- }
-
- return false;
- drop:
-+ DTRACE_IP(drop__in,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, iph,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- return true;
- }
-
-@@ -432,27 +458,35 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
- /*
- * Main IP Receive routine.
- */
--static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
-+static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net,
-+ struct net_device *dev
-+ __attribute__((__unused__)))
- {
-- const struct iphdr *iph;
-+ const struct iphdr *iph = NULL;
- u32 len;
-+ const char *dropreason = "header invalid";
-
- /* When the interface is in promisc. mode, drop all the crap
- * that it receives, do not try to analyse it.
- */
-- if (skb->pkt_type == PACKET_OTHERHOST)
-+ if (skb->pkt_type == PACKET_OTHERHOST) {
-+ dropreason = "for other host";
- goto drop;
-+ }
-
- __IP_UPD_PO_STATS(net, IPSTATS_MIB_IN, skb->len);
-
- skb = skb_share_check(skb, GFP_ATOMIC);
- if (!skb) {
-+ dropreason = "could not clone shared buffer";
- __IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS);
-- goto out;
-+ goto drop;
- }
-
-- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-+ if (!pskb_may_pull(skb, sizeof(struct iphdr))) {
-+ dropreason = "could not pull skb";
- goto inhdr_error;
-+ }
-
- iph = ip_hdr(skb);
-
-@@ -487,6 +521,7 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
-
- len = ntohs(iph->tot_len);
- if (skb->len < len) {
-+ dropreason = "packet too short";
- __IP_INC_STATS(net, IPSTATS_MIB_INTRUNCATEDPKTS);
- goto drop;
- } else if (len < (iph->ihl*4))
-@@ -497,6 +532,7 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
- * Note this now means skb->len holds ntohs(iph->tot_len).
- */
- if (pskb_trim_rcsum(skb, len)) {
-+ dropreason = "could not trim buffer";
- __IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS);
- goto drop;
- }
-@@ -516,11 +552,19 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
-
- csum_error:
- __IP_INC_STATS(net, IPSTATS_MIB_CSUMERRORS);
-+ dropreason = "checksum error";
- inhdr_error:
- __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
- drop:
-+ DTRACE_IP(drop__in,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, dev,
-+ struct iphdr * : ipv4info_t *, iph,
-+ void * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
- kfree_skb(skb);
--out:
- return NULL;
- }
-
-@@ -532,7 +576,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
- {
- struct net *net = dev_net(dev);
-
-- skb = ip_rcv_core(skb, net);
-+ skb = ip_rcv_core(skb, net, dev);
- if (skb == NULL)
- return NET_RX_DROP;
-
-@@ -623,7 +667,7 @@ void ip_list_rcv(struct list_head *head, struct packet_type *pt,
- struct net *net = dev_net(dev);
-
- skb_list_del_init(skb);
-- skb = ip_rcv_core(skb, net);
-+ skb = ip_rcv_core(skb, net, dev);
- if (skb == NULL)
- continue;
-
-diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
-index 97975bed491a..9e194f4e2050 100644
---- a/net/ipv4/ip_output.c
-+++ b/net/ipv4/ip_output.c
-@@ -82,6 +82,7 @@
- #include <linux/netfilter_bridge.h>
- #include <linux/netlink.h>
- #include <linux/tcp.h>
-+#include <linux/sdt.h>
-
- static int
- ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
-@@ -112,6 +113,14 @@ int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
-
- skb->protocol = htons(ETH_P_IP);
-
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, iph,
-+ struct ipv6hdr * : ipv6info_t *, NULL);
-+
- return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
- net, sk, skb, NULL, skb_dst(skb)->dev,
- dst_output);
-@@ -983,6 +992,7 @@ static int __ip_append_data(struct sock *sk,
- unsigned int wmem_alloc_delta = 0;
- bool paged, extra_uref = false;
- u32 tskey = 0;
-+ const char *dropreason;
-
- skb = skb_peek_tail(queue);
-
-@@ -1001,9 +1011,13 @@ static int __ip_append_data(struct sock *sk,
- maxnonfragsize = ip_sk_ignore_df(sk) ? IP_MAX_MTU : mtu;
-
- if (cork->length + length > maxnonfragsize - fragheaderlen) {
-+ struct iphdr *iph __attribute__((unused)) = ip_hdr(skb);
-+
- ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
- mtu - (opt ? opt->optlen : 0));
-- return -EMSGSIZE;
-+ dropreason = "packet too big";
-+ err = -EMSGSIZE;
-+ goto error2;
- }
-
- /*
-@@ -1103,8 +1117,10 @@ static int __ip_append_data(struct sock *sk,
- 2 * sk->sk_sndbuf)
- skb = alloc_skb(alloclen + hh_len + 15,
- sk->sk_allocation);
-- if (unlikely(!skb))
-+ if (unlikely(!skb)) {
-+ dropreason = "no buffers";
- err = -ENOBUFS;
-+ }
- }
- if (!skb)
- goto error;
-@@ -1138,7 +1154,9 @@ static int __ip_append_data(struct sock *sk,
- copy = datalen - transhdrlen - fraggap - pagedlen;
- if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
- err = -EFAULT;
-+ dropreason = "could not fragment packet";
- kfree_skb(skb);
-+ skb = NULL;
- goto error;
- }
-
-@@ -1181,6 +1199,7 @@ static int __ip_append_data(struct sock *sk,
- if (getfrag(from, skb_put(skb, copy),
- offset, copy, off, skb) < 0) {
- __skb_trim(skb, off);
-+ dropreason = "could not fragment packet";
- err = -EFAULT;
- goto error;
- }
-@@ -1188,14 +1207,18 @@ static int __ip_append_data(struct sock *sk,
- int i = skb_shinfo(skb)->nr_frags;
-
- err = -ENOMEM;
-- if (!sk_page_frag_refill(sk, pfrag))
-+ if (!sk_page_frag_refill(sk, pfrag)) {
-+ dropreason = "no memory";
- goto error;
-+ }
-
- if (!skb_can_coalesce(skb, i, pfrag->page,
- pfrag->offset)) {
- err = -EMSGSIZE;
-- if (i == MAX_SKB_FRAGS)
-+ if (i == MAX_SKB_FRAGS) {
-+ dropreason = "too many fragments";
- goto error;
-+ }
-
- __skb_fill_page_desc(skb, i, pfrag->page,
- pfrag->offset, 0);
-@@ -1205,8 +1228,10 @@ static int __ip_append_data(struct sock *sk,
- copy = min_t(int, copy, pfrag->size - pfrag->offset);
- if (getfrag(from,
- page_address(pfrag->page) + pfrag->offset,
-- offset, copy, skb->len, skb) < 0)
-+ offset, copy, skb->len, skb) < 0) {
-+ dropreason = "could not framgent packet";
- goto error_efault;
-+ }
-
- pfrag->offset += copy;
- skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
-@@ -1235,6 +1260,16 @@ static int __ip_append_data(struct sock *sk,
- cork->length -= length;
- IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
- refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
-+error2:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, skb ? ip_hdr(skb) : NULL,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, skb ? ip_hdr(skb) : NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- return err;
- }
-
-@@ -1338,6 +1373,8 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
- int len;
- int err;
- unsigned int maxfraglen, fragheaderlen, fraggap, maxnonfragsize;
-+ struct iphdr *iph;
-+ const char *dropreason;
-
- if (inet->hdrincl)
- return -EPERM;
-@@ -1391,6 +1428,7 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
- alloclen = fragheaderlen + hh_len + fraggap + 15;
- skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
- if (unlikely(!skb)) {
-+ dropreason = "no buffers";
- err = -ENOBUFS;
- goto error;
- }
-@@ -1430,6 +1468,7 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
- len = size;
-
- if (skb_append_pagefrags(skb, page, offset, len)) {
-+ dropreason = "packet too big";
- err = -EMSGSIZE;
- goto error;
- }
-@@ -1452,6 +1491,16 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
- error:
- cork->length -= size;
- IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
-+ iph = skb ? ip_hdr(skb) : NULL;
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, iph,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- return err;
- }
-
-@@ -1569,8 +1618,18 @@ int ip_send_skb(struct net *net, struct sk_buff *skb)
- if (err) {
- if (err > 0)
- err = net_xmit_errno(err);
-- if (err)
-+ if (err) {
- IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
-+ /* skb may have been freed */
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, NULL,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ char * : string, "packet too short");
-+ }
- }
-
- return err;
-diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
-index 7d26e0f8bdae..7ae1ad2bad09 100644
---- a/net/ipv4/raw.c
-+++ b/net/ipv4/raw.c
-@@ -75,6 +75,7 @@
- #include <linux/netfilter_ipv4.h>
- #include <linux/compat.h>
- #include <linux/uio.h>
-+#include <linux/sdt.h>
-
- struct raw_frag_vec {
- struct msghdr *msg;
-@@ -349,19 +350,25 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
- struct inet_sock *inet = inet_sk(sk);
- struct net *net = sock_net(sk);
- struct iphdr *iph;
-- struct sk_buff *skb;
-+ struct sk_buff *skb = NULL;
- unsigned int iphlen;
- int err;
- struct rtable *rt = *rtp;
- int hlen, tlen;
-+ const char *dropreason;
-
- if (length > rt->dst.dev->mtu) {
- ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
- rt->dst.dev->mtu);
-- return -EMSGSIZE;
-+ dropreason = "packet too big";
-+ err = -EMSGSIZE;
-+ goto trace_drop;
-+ }
-+ if (length < sizeof(struct iphdr)) {
-+ dropreason = "packet too short";
-+ err = -EINVAL;
-+ goto trace_drop;
- }
-- if (length < sizeof(struct iphdr))
-- return -EINVAL;
-
- if (flags&MSG_PROBE)
- goto out;
-@@ -371,8 +378,10 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
- skb = sock_alloc_send_skb(sk,
- length + hlen + tlen + 15,
- flags & MSG_DONTWAIT, &err);
-- if (!skb)
-+ if (!skb) {
-+ dropreason = "out of memory";
- goto error;
-+ }
- skb_reserve(skb, hlen);
-
- skb->priority = sk->sk_priority;
-@@ -394,8 +403,10 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
-
- skb->transport_header = skb->network_header;
- err = -EFAULT;
-- if (memcpy_from_msg(iph, msg, length))
-+ if (memcpy_from_msg(iph, msg, length)) {
-+ dropreason = "could not copy msg";
- goto error_free;
-+ }
-
- iphlen = iph->ihl * 4;
-
-@@ -407,8 +418,10 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
- * in, reject the frame as invalid
- */
- err = -EINVAL;
-- if (iphlen > length)
-+ if (iphlen > length) {
-+ dropreason = "IP header too big";
- goto error_free;
-+ }
-
- if (iphlen >= sizeof(*iph)) {
- if (!iph->saddr)
-@@ -426,20 +439,40 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
- skb_transport_header(skb))->type);
- }
-
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, iph,
-+ struct ipv6hdr * : ipv6info_t *, NULL);
-+
- err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
- net, sk, skb, NULL, rt->dst.dev,
- dst_output);
- if (err > 0)
- err = net_xmit_errno(err);
-- if (err)
-+ if (err) {
-+ dropreason = "device dropping packets of this priority";
- goto error;
-+ }
- out:
- return 0;
-
- error_free:
- kfree_skb(skb);
-+ skb = NULL;
- error:
- IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
-+trace_drop:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, skb ? ip_hdr(skb) : NULL,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, skb ? ip_hdr(skb) : NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
- if (err == -ENOBUFS && !inet->recverr)
- err = 0;
- return err;
-diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
-index 41d03683b13d..197946038626 100644
---- a/net/ipv4/tcp.c
-+++ b/net/ipv4/tcp.c
-@@ -267,6 +267,7 @@
- #include <linux/slab.h>
- #include <linux/errqueue.h>
- #include <linux/static_key.h>
-+#include <linux/sdt.h>
-
- #include <net/icmp.h>
- #include <net/inet_common.h>
-@@ -2277,6 +2278,19 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
- }
- EXPORT_SYMBOL(tcp_recvmsg);
-
-+/* We wish to avoid instrumenting TCP state transitions to SYN_SENT as we trace
-+ * those state changes later once the destination address is committed to the
-+ * sk. We also need to deal with the fact that separate timewait sockets are
-+ * used to handle the TIME_WAIT state. We do not want to trace direct
-+ * transitions from CLOSING/FIN_WAIT2 -> CLOSE since they do not represent
-+ * connection close, rather a transition to using the timewait socket.
-+ * Accordingly skip instrumentation of transitions from CLOSING/FIN_WAIT2 to
-+ * CLOSE.
-+ */
-+#define REAL_STATE_CHANGE(old, new) \
-+ (old != new && new != TCP_SYN_SENT && \
-+ ((old != TCP_CLOSING && old != TCP_FIN_WAIT2) || new != TCP_CLOSE))
-+
- void tcp_set_state(struct sock *sk, int state)
- {
- int oldstate = sk->sk_state;
-@@ -2329,6 +2343,18 @@ void tcp_set_state(struct sock *sk, int state)
- * socket sitting in hash tables.
- */
- inet_sk_state_store(sk, state);
-+
-+ if (DTRACE_TCP_ENABLED(state__change) &&
-+ REAL_STATE_CHANGE(oldstate, state))
-+ DTRACE_TCP_NOCHECK(state__change,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, NULL,
-+ struct tcp_sock * : tcpsinfo_t *, tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, NULL,
-+ int : tcplsinfo_t *, oldstate,
-+ int : int, state,
-+ int : int, DTRACE_NET_PROBE_OUTBOUND);
- }
- EXPORT_SYMBOL_GPL(tcp_set_state);
-
-diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
-index 6bf066f924c1..e29846f27328 100644
---- a/net/ipv4/tcp_input.c
-+++ b/net/ipv4/tcp_input.c
-@@ -80,6 +80,7 @@
- #include <linux/jump_label_ratelimit.h>
- #include <net/busy_poll.h>
- #include <net/mptcp.h>
-+#include <linux/sdt.h>
-
- int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
-
-@@ -5914,6 +5915,14 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
- struct tcp_sock *tp = tcp_sk(sk);
- struct inet_connection_sock *icsk = inet_csk(sk);
-
-+ DTRACE_TCP(connect__established,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *, TCP_ESTABLISHED,
-+ int, TCP_ESTABLISHED, int, DTRACE_NET_PROBE_INBOUND);
- tcp_set_state(sk, TCP_ESTABLISHED);
- icsk->icsk_ack.lrcvtime = tcp_jiffies32;
-
-@@ -6078,6 +6087,17 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
- */
-
- if (th->rst) {
-+ DTRACE_TCP(connect__refused,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *,
-+ ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, th,
-+ int : tcplsinfo_t *,
-+ sk ? sk->sk_state : TCP_CLOSE,
-+ int, sk ? sk->sk_state : TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_INBOUND);
- tcp_reset(sk);
- goto discard;
- }
-@@ -6400,6 +6420,16 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
- WRITE_ONCE(tp->copied_seq, tp->rcv_nxt);
- }
- smp_mb();
-+
-+ DTRACE_TCP(accept__established,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *, TCP_ESTABLISHED,
-+ int, TCP_ESTABLISHED,
-+ int, DTRACE_NET_PROBE_INBOUND);
- tcp_set_state(sk, TCP_ESTABLISHED);
- sk->sk_state_change(sk);
-
-@@ -6873,6 +6903,19 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
- !want_cookie ? TCP_SYNACK_NORMAL :
- TCP_SYNACK_COOKIE,
- skb);
-+ /* Do not pass in tcp sock as ports/addresses are not yet
-+ * populated - instead translators will fill them in from
-+ * skb data.
-+ */
-+ DTRACE_TCP(state__change,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, NULL,
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *, TCP_LISTEN,
-+ int, TCP_SYN_RECV, int, DTRACE_NET_PROBE_INBOUND);
-+
- if (want_cookie) {
- reqsk_free(req);
- return 0;
-diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
-index ab8ed0fc4769..5f76469093a2 100644
---- a/net/ipv4/tcp_ipv4.c
-+++ b/net/ipv4/tcp_ipv4.c
-@@ -80,6 +80,7 @@
-
- #include <crypto/hash.h>
- #include <linux/scatterlist.h>
-+#include <linux/sdt.h>
-
- #include <trace/events/tcp.h>
-
-@@ -642,6 +643,21 @@ void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb)
- }
- EXPORT_SYMBOL(tcp_v4_send_check);
-
-+/* Since we want to trace send events in TCP prior to pushing the segment to
-+ * IP - where the IP header is added - we need to construct an argument
-+ * containing relevant IP info so that TCP probe consumers can utilize it.
-+ */
-+static inline void dtrace_tcp_build_iphdr(__be32 saddr, __be32 daddr,
-+ struct iphdr *iph)
-+{
-+ iph->version = 4;
-+ iph->ihl = 5;
-+ iph->tot_len = 5;
-+ iph->protocol = IPPROTO_TCP;
-+ iph->saddr = saddr;
-+ iph->daddr = daddr;
-+}
-+
- /*
- * This routine will send an RST to the other tcp.
- *
-@@ -800,6 +816,39 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
- inet_twsk(sk)->tw_priority : sk->sk_priority;
- transmit_time = tcp_transmit_time(sk);
- }
-+
-+ if (DTRACE_TCP_ENABLED(send) ||
-+ DTRACE_TCP_ENABLED(accept__refused)) {
-+ struct iphdr iph;
-+
-+ dtrace_tcp_build_iphdr(ip_hdr(skb)->daddr, ip_hdr(skb)->saddr,
-+ &iph);
-+
-+ DTRACE_TCP_NOCHECK(send,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, &iph,
-+ struct tcp_sock * : tcpsinfo_t *, NULL,
-+ struct tcphdr * : tcpinfo_t *, &rep.th,
-+ int : tcplsinfo_t *, TCP_CLOSE,
-+ int : int, TCP_CLOSE,
-+ int : int, DTRACE_NET_PROBE_OUTBOUND);
-+ if (th->syn && rep.th.seq == 0)
-+ DTRACE_TCP_NOCHECK(accept__refused,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, &iph,
-+ struct tcp_sock * : tcpsinfo_t *,
-+ NULL,
-+ struct tcphdr * : tcpinfo_t *,
-+ &rep.th,
-+ int : tcplsinfo_t *, TCP_CLOSE,
-+ int : int, TCP_CLOSE,
-+ int : int,
-+ DTRACE_NET_PROBE_OUTBOUND);
-+ }
-+
- ip_send_unicast_reply(ctl_sk,
- skb, &TCP_SKB_CB(skb)->header.h4.opt,
- ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
-@@ -896,6 +945,24 @@ static void tcp_v4_send_ack(const struct sock *sk,
- ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ?
- inet_twsk(sk)->tw_priority : sk->sk_priority;
- transmit_time = tcp_transmit_time(sk);
-+
-+ if (DTRACE_TCP_ENABLED(send)) {
-+ struct iphdr iph;
-+
-+ dtrace_tcp_build_iphdr(ip_hdr(skb)->daddr, ip_hdr(skb)->saddr,
-+ &iph);
-+
-+ DTRACE_TCP_NOCHECK(send,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, &iph,
-+ struct tcp_sock * : tcpsinfo_t *, NULL,
-+ struct tcphdr * : tcpinfo_t *, &rep,
-+ int : tcplsinfo_t *, TCP_CLOSE,
-+ int : int, TCP_CLOSE,
-+ int : int, DTRACE_NET_PROBE_OUTBOUND);
-+ }
-+
- ip_send_unicast_reply(ctl_sk,
- skb, &TCP_SKB_CB(skb)->header.h4.opt,
- ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
-@@ -992,6 +1059,30 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
- tcp_bpf_ca_needs_ecn((struct sock *)req))
- tos |= INET_ECN_ECT_0;
-
-+ if (DTRACE_TCP_ENABLED(send)) {
-+ struct iphdr iph;
-+
-+ dtrace_tcp_build_iphdr(ireq->ir_loc_addr,
-+ ireq->ir_rmt_addr, &iph);
-+
-+ /* Do not supply tcp sk - addresses/ports are not
-+ * committed yet - instead translators will fill them
-+ * in from skb/IP info.
-+ */
-+ DTRACE_TCP_NOCHECK(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, &iph,
-+ struct tcp_sock * : tcpsinfo_t *,
-+ NULL,
-+ struct tcphdr * : tcpinfo_t *,
-+ tcp_hdr(skb),
-+ int : tcplsinfo_t *, TCP_LISTEN,
-+ int, TCP_LISTEN,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
-+ }
-+
- rcu_read_lock();
- err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
- ireq->ir_rmt_addr,
-@@ -1922,7 +2013,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
- const struct iphdr *iph;
- const struct tcphdr *th;
- bool refcounted;
-- struct sock *sk;
-+ struct sock *sk = NULL;
- int ret;
-
- if (skb->pkt_type != PACKET_HOST)
-@@ -1957,6 +2048,15 @@ int tcp_v4_rcv(struct sk_buff *skb)
- if (!sk)
- goto no_tcp_socket;
-
-+ DTRACE_TCP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *, sk ? sk->sk_state : TCP_CLOSE,
-+ int, sk ? sk->sk_state : TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_INBOUND);
- process:
- if (sk->sk_state == TCP_TIME_WAIT)
- goto do_time_wait;
-@@ -2084,6 +2184,18 @@ int tcp_v4_rcv(struct sk_buff *skb)
-
- discard_it:
- /* Discard frame. */
-+ if (DTRACE_TCP_ENABLED(receive) && skb->pkt_type == PACKET_HOST)
-+ DTRACE_TCP_NOCHECK(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *,
-+ ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *,
-+ sk ? sk->sk_state : TCP_CLOSE,
-+ int, sk ? sk->sk_state : TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_INBOUND);
- kfree_skb(skb);
- return 0;
-
-diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
-index 495dda2449fe..d2e368b7072d 100644
---- a/net/ipv4/tcp_minisocks.c
-+++ b/net/ipv4/tcp_minisocks.c
-@@ -24,6 +24,7 @@
- #include <linux/slab.h>
- #include <linux/sysctl.h>
- #include <linux/workqueue.h>
-+#include <linux/sdt.h>
- #include <linux/static_key.h>
- #include <net/tcp.h>
- #include <net/inet_common.h>
-@@ -328,6 +329,20 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
- */
- inet_twsk_hashdance(tw, sk, &tcp_hashinfo);
- local_bh_enable();
-+
-+ if (DTRACE_TCP_ENABLED(state__change) &&
-+ state != sk->sk_state)
-+ DTRACE_TCP_NOCHECK(state__change,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, NULL,
-+ struct tcp_sock * : tcpsinfo_t *,
-+ tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, NULL,
-+ int : tcplsinfo_t *, sk->sk_state,
-+ int, state,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
- } else {
- /* Sorry, if we're out of memory, just CLOSE this
- * socket up. We've got bigger problems than
-diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
-index e58e2589d7f9..aee3d4d6a2ae 100644
---- a/net/ipv4/tcp_output.c
-+++ b/net/ipv4/tcp_output.c
-@@ -44,6 +44,7 @@
- #include <linux/gfp.h>
- #include <linux/module.h>
- #include <linux/static_key.h>
-+#include <linux/sdt.h>
-
- #include <trace/events/tcp.h>
-
-@@ -1384,6 +1385,27 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
- tp->bytes_sent += skb->len - tcp_header_size;
- }
-
-+ DTRACE_TCP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, NULL,
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *, sk->sk_state, int, sk->sk_state,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
-+ if (DTRACE_TCP_ENABLED(connect__request) && th->syn &&
-+ th->ack_seq == 0)
-+ DTRACE_TCP_NOCHECK(connect__request,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *,
-+ ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, th,
-+ int : tcplsinfo_t *, sk->sk_state,
-+ int, sk->sk_state,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
-+
- if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
- TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS,
- tcp_skb_pcount(skb));
-@@ -3845,6 +3867,13 @@ int tcp_connect(struct sock *sk)
- tp->retrans_stamp = tcp_time_stamp(tp);
- tcp_connect_queue_skb(sk, buff);
- tcp_ecn_send_syn(sk, buff);
-+ DTRACE_TCP(state__change, struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, ip_hdr(buff),
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(buff),
-+ int : tcplsinfo_t *, TCP_CLOSE,
-+ int, sk->sk_state, int, DTRACE_NET_PROBE_OUTBOUND);
- tcp_rbtree_insert(&sk->tcp_rtx_queue, buff);
-
- /* Send off SYN; include data in Fast Open. */
-diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
-index e37a2fa65c29..5d32f5471d85 100644
---- a/net/ipv4/udp.c
-+++ b/net/ipv4/udp.c
-@@ -107,6 +107,7 @@
- #include <trace/events/udp.h>
- #include <linux/static_key.h>
- #include <linux/btf_ids.h>
-+#include <linux/sdt.h>
- #include <trace/events/skb.h>
- #include <net/busy_poll.h>
- #include "udp_impl.h"
-@@ -945,6 +946,13 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
- uh->check = CSUM_MANGLED_0;
-
- send:
-+ DTRACE_UDP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *, udp_sk(sk),
-+ struct udphdr * : udpinfo_t *, uh);
-+
- err = ip_send_skb(sock_net(sk), skb);
- if (err) {
- if (err == -ENOBUFS && !inet->recverr) {
-@@ -1845,9 +1853,16 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
- return err;
- }
-
-- if (!peeking)
-+ if (!peeking) {
-+ DTRACE_UDP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *, udp_sk(sk),
-+ struct udphdr * : udpinfo_t *, udp_hdr(skb));
- UDP_INC_STATS(sock_net(sk),
- UDP_MIB_INDATAGRAMS, is_udplite);
-+ }
-
- sock_recv_ts_and_drops(msg, sk, skb);
-
-@@ -2092,6 +2107,15 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
-
- ret = encap_rcv(sk, skb);
- if (ret <= 0) {
-+ DTRACE_UDP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *,
-+ ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *,
-+ udp_sk(sk),
-+ struct udphdr * : udpinfo_t *,
-+ udp_hdr(skb));
- __UDP_INC_STATS(sock_net(sk),
- UDP_MIB_INDATAGRAMS,
- is_udplite);
-diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
-index e96304d8a4a7..aed39e366b60 100644
---- a/net/ipv6/ip6_input.c
-+++ b/net/ipv6/ip6_input.c
-@@ -43,6 +43,7 @@
- #include <net/xfrm.h>
- #include <net/inet_ecn.h>
- #include <net/dst_metadata.h>
-+#include <linux/sdt.h>
-
- INDIRECT_CALLABLE_DECLARE(void udp_v6_early_demux(struct sk_buff *));
- INDIRECT_CALLABLE_DECLARE(void tcp_v6_early_demux(struct sk_buff *));
-@@ -145,13 +146,14 @@ static void ip6_list_rcv_finish(struct net *net, struct sock *sk,
- static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- struct net *net)
- {
-- const struct ipv6hdr *hdr;
-+ const struct ipv6hdr *hdr = NULL;
- u32 pkt_len;
- struct inet6_dev *idev;
-+ const char *dropreason;
-
- if (skb->pkt_type == PACKET_OTHERHOST) {
-- kfree_skb(skb);
-- return NULL;
-+ dropreason = "for other host";
-+ goto trace_drop;
- }
-
- rcu_read_lock();
-@@ -163,6 +165,7 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
- !idev || unlikely(idev->cnf.disable_ipv6)) {
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
-+ dropreason = "could not clone shared buffer";
- goto drop;
- }
-
-@@ -181,13 +184,18 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- */
- IP6CB(skb)->iif = skb_valid_dst(skb) ? ip6_dst_idev(skb_dst(skb))->dev->ifindex : dev->ifindex;
-
-- if (unlikely(!pskb_may_pull(skb, sizeof(*hdr))))
-+ if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) {
-+ hdr = ipv6_hdr(skb);
-+ dropreason = "could not pull skb";
- goto err;
-+ }
-
- hdr = ipv6_hdr(skb);
-
-- if (hdr->version != 6)
-+ if (hdr->version != 6) {
-+ dropreason = "header invalid";
- goto err;
-+ }
-
- __IP6_ADD_STATS(net, idev,
- IPSTATS_MIB_NOECTPKTS +
-@@ -203,8 +211,10 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- if ((ipv6_addr_loopback(&hdr->saddr) ||
- ipv6_addr_loopback(&hdr->daddr)) &&
- !(dev->flags & IFF_LOOPBACK) &&
-- !netif_is_l3_master(dev))
-+ !netif_is_l3_master(dev)) {
-+ dropreason = "loopback destination received on interface";
- goto err;
-+ }
-
- /* RFC4291 Errata ID: 3480
- * Interface-Local scope spans only a single interface on a
-@@ -215,8 +225,10 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- if (!(skb->pkt_type == PACKET_LOOPBACK ||
- dev->flags & IFF_LOOPBACK) &&
- ipv6_addr_is_multicast(&hdr->daddr) &&
-- IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
-+ IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1) {
-+ dropreason = "interface-local scope received from other node";
- goto err;
-+ }
-
- /* If enabled, drop unicast packets that were encapsulated in link-layer
- * multicast or broadcast to protected against the so-called "hole-196"
-@@ -225,8 +237,10 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- if (!ipv6_addr_is_multicast(&hdr->daddr) &&
- (skb->pkt_type == PACKET_BROADCAST ||
- skb->pkt_type == PACKET_MULTICAST) &&
-- idev->cnf.drop_unicast_in_l2_multicast)
-+ idev->cnf.drop_unicast_in_l2_multicast) {
-+ dropreason = "unicast packet encapsulated in multi/broadcast";
- goto err;
-+ }
-
- /* RFC4291 2.7
- * Nodes must not originate a packet to a multicast address whose scope
-@@ -234,16 +248,21 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- * must be silently dropped.
- */
- if (ipv6_addr_is_multicast(&hdr->daddr) &&
-- IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0)
-+ IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0) {
-+ dropreason =
-+ "packet to multicast address with reserved scope 0";
- goto err;
-+ }
-
- /*
- * RFC4291 2.7
- * Multicast addresses must not be used as source addresses in IPv6
- * packets or appear in any Routing header.
- */
-- if (ipv6_addr_is_multicast(&hdr->saddr))
-+ if (ipv6_addr_is_multicast(&hdr->saddr)) {
-+ dropreason = "multicast source address in IPv6 packet";
- goto err;
-+ }
-
- /* While RFC4291 is not explicit about v4mapped addresses
- * in IPv6 headers, it seems clear linux dual-stack
-@@ -253,7 +272,10 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- * https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02
- */
- if (ipv6_addr_v4mapped(&hdr->saddr))
-+ {
-+ dropreason = "v4-mapped address in IPv6 packet";
- goto err;
-+ }
-
- skb->transport_header = skb->network_header + sizeof(*hdr);
- IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
-@@ -265,10 +287,12 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- if (pkt_len + sizeof(struct ipv6hdr) > skb->len) {
- __IP6_INC_STATS(net,
- idev, IPSTATS_MIB_INTRUNCATEDPKTS);
-+ dropreason = "truncated packet";
- goto drop;
- }
- if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
-+ dropreason = "could not trim buffer";
- goto drop;
- }
- hdr = ipv6_hdr(skb);
-@@ -276,9 +300,10 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
-
- if (hdr->nexthdr == NEXTHDR_HOP) {
- if (ipv6_parse_hopopts(skb) < 0) {
-- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
-- rcu_read_unlock();
-- return NULL;
-+ dropreason = "could not parse hop opts";
-+ /* do not free skb */
-+ skb = NULL;
-+ goto err;
- }
- }
-
-@@ -293,6 +318,15 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
- drop:
- rcu_read_unlock();
-+trace_drop:
-+ DTRACE_IP(drop__in,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, hdr,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, hdr,
-+ const char * : string, dropreason);
- kfree_skb(skb);
- return NULL;
- }
-@@ -365,6 +399,8 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- struct inet6_dev *idev;
- unsigned int nhoff;
- bool raw;
-+ const struct ipv6hdr *hdr;
-+ const char *dropreason;
-
- /*
- * Parse extension headers
-@@ -374,8 +410,10 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- idev = ip6_dst_idev(skb_dst(skb));
- nhoff = IP6CB(skb)->nhoff;
- if (!have_final) {
-- if (!pskb_pull(skb, skb_transport_offset(skb)))
-+ if (!pskb_pull(skb, skb_transport_offset(skb))) {
-+ dropreason = "could not pull skb";
- goto discard;
-+ }
- nexthdr = skb_network_header(skb)[nhoff];
- }
-
-@@ -392,10 +430,10 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- * ones. This allows foo in UDP encapsulation
- * to work.
- */
-+ dropreason = "non-final protocol";
- goto discard;
- }
- } else if (ipprot->flags & INET6_PROTO_FINAL) {
-- const struct ipv6hdr *hdr;
- int sdif = inet6_sdif(skb);
- struct net_device *dev;
-
-@@ -414,8 +452,10 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- /* skb->dev passed may be master dev for vrfs. */
- if (sdif) {
- dev = dev_get_by_index_rcu(net, sdif);
-- if (!dev)
-+ if (!dev) {
-+ dropreason = "device disappeared";
- goto discard;
-+ }
- } else {
- dev = skb->dev;
- }
-@@ -423,12 +463,16 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- if (ipv6_addr_is_multicast(&hdr->daddr) &&
- !ipv6_chk_mcast_addr(dev, &hdr->daddr,
- &hdr->saddr) &&
-- !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb)))
-+ !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb))) {
-+ dropreason = "destination is multicast";
- goto discard;
-+ }
- }
- if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
-- !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
-+ !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-+ dropreason = "policy failure";
- goto discard;
-+ }
-
- ret = INDIRECT_CALL_2(ipprot->handler, tcp_v6_rcv, udpv6_rcv,
- skb);
-@@ -454,6 +498,8 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- IPSTATS_MIB_INUNKNOWNPROTOS);
- icmpv6_send(skb, ICMPV6_PARAMPROB,
- ICMPV6_UNK_NEXTHDR, nhoff);
-+ dropreason = "policy failure";
-+ goto trace_drop;
- }
- kfree_skb(skb);
- } else {
-@@ -465,6 +511,17 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
-
- discard:
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
-+trace_drop:
-+ hdr = ipv6_hdr(skb);
-+ DTRACE_IP(drop__in,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, hdr,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, hdr,
-+ const char * : string, dropreason);
-+ rcu_read_unlock();
- kfree_skb(skb);
- }
-
-@@ -480,6 +537,16 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk
-
- int ip6_input(struct sk_buff *skb)
- {
-+ struct ipv6hdr *hdr = ipv6_hdr(skb);
-+
-+ DTRACE_IP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, hdr,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, hdr);
-+
- return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN,
- dev_net(skb->dev), NULL, skb, skb->dev, NULL,
- ip6_input_finish);
-diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
-index 077d43af8226..1c972fb379b5 100644
---- a/net/ipv6/ip6_output.c
-+++ b/net/ipv6/ip6_output.c
-@@ -55,6 +55,7 @@
- #include <net/l3mdev.h>
- #include <net/lwtunnel.h>
- #include <net/ip_tunnels.h>
-+#include <linux/sdt.h>
-
- static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *skb)
- {
-@@ -62,7 +63,8 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
- struct net_device *dev = dst->dev;
- const struct in6_addr *nexthop;
- struct neighbour *neigh;
-- int ret;
-+ const char *dropreason;
-+ int ret = 0;
-
- if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
- struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
-@@ -83,10 +85,11 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
- dev_loopback_xmit);
-
- if (ipv6_hdr(skb)->hop_limit == 0) {
-+ dropreason = "hoplimit exceeded";
-+
- IP6_INC_STATS(net, idev,
- IPSTATS_MIB_OUTDISCARDS);
-- kfree_skb(skb);
-- return 0;
-+ goto drop;
- }
- }
-
-@@ -95,8 +98,8 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
- if (IPV6_ADDR_MC_SCOPE(&ipv6_hdr(skb)->daddr) <=
- IPV6_ADDR_SCOPE_NODELOCAL &&
- !(dev->flags & IFF_LOOPBACK)) {
-- kfree_skb(skb);
-- return 0;
-+ dropreason = "invalid scope";
-+ goto drop;
- }
- }
-
-@@ -120,9 +123,20 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
- }
- rcu_read_unlock_bh();
-
-+ dropreason = "no route to host";
- IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
-+ ret = -EINVAL;
-+drop:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb),
-+ const char * : string, dropreason);
- kfree_skb(skb);
-- return -EINVAL;
-+ return ret;
- }
-
- static int
-@@ -207,6 +221,15 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
- skb->dev = dev;
-
- if (unlikely(idev->cnf.disable_ipv6)) {
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, "IPv6 is disabled");
-+
- IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
- kfree_skb(skb);
- return 0;
-@@ -243,8 +266,10 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
- struct ipv6hdr *hdr;
- u8 proto = fl6->flowi6_proto;
- int seg_len = skb->len;
-+ const char *dropreason;
- int hlimit = -1;
- u32 mtu;
-+ int err;
-
- head_room = sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dst->dev);
- if (opt)
-@@ -253,10 +278,12 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
- if (unlikely(skb_headroom(skb) < head_room)) {
- struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
- if (!skb2) {
-+ dropreason = "out of memory";
- IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
- IPSTATS_MIB_OUTDISCARDS);
- kfree_skb(skb);
-- return -ENOBUFS;
-+ err = -ENOBUFS;
-+ goto drop;
- }
- if (skb->sk)
- skb_set_owner_w(skb2, skb->sk);
-@@ -313,6 +340,14 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
- if (unlikely(!skb))
- return 0;
-
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, hdr,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, hdr);
-+
- /* hooks should never assume socket lock is held.
- * we promote our socket to non const
- */
-@@ -327,9 +362,21 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
- */
- ipv6_local_error((struct sock *)sk, EMSGSIZE, fl6, mtu);
-
-+ dropreason = "fragmentation failure";
- IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS);
-+ err = -EMSGSIZE;
-+drop:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- kfree_skb(skb);
-- return -EMSGSIZE;
-+ return err;
- }
- EXPORT_SYMBOL(ip6_xmit);
-
-@@ -464,22 +511,33 @@ int ip6_forward(struct sk_buff *skb)
- struct ipv6hdr *hdr = ipv6_hdr(skb);
- struct inet6_skb_parm *opt = IP6CB(skb);
- struct net *net = dev_net(dst->dev);
-+ const char *dropreason;
-+ int err = -EINVAL;
- u32 mtu;
-
-- if (net->ipv6.devconf_all->forwarding == 0)
-+ if (net->ipv6.devconf_all->forwarding == 0) {
-+ dropreason = "forwarding disabled";
- goto error;
-+ }
-
-- if (skb->pkt_type != PACKET_HOST)
-+ if (skb->pkt_type != PACKET_HOST) {
-+ dropreason = "non-host packet type cannot be forwarded";
- goto drop;
-+ }
-
-- if (unlikely(skb->sk))
-+ if (unlikely(skb->sk)) {
-+ dropreason = "socket found for packet to be forwarded";
- goto drop;
-+ }
-
-- if (skb_warn_if_lro(skb))
-+ if (skb_warn_if_lro(skb)) {
-+ dropreason = "LRO warning";
- goto drop;
-+ }
-
- if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
-+ dropreason = "forwarding disabled by policy";
- goto drop;
- }
-
-@@ -510,8 +568,9 @@ int ip6_forward(struct sk_buff *skb)
- icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0);
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
-
-- kfree_skb(skb);
-- return -ETIMEDOUT;
-+ dropreason = "hoplimit exceeded";
-+ err = -ETIMEDOUT;
-+ goto drop;
- }
-
- /* XXX: idev->cnf.proxy_ndp? */
-@@ -521,6 +580,7 @@ int ip6_forward(struct sk_buff *skb)
- if (proxied > 0)
- return ip6_input(skb);
- else if (proxied < 0) {
-+ dropreason = "proxy router cannot forward";
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
- goto drop;
- }
-@@ -528,6 +588,7 @@ int ip6_forward(struct sk_buff *skb)
-
- if (!xfrm6_route_forward(skb)) {
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
-+ dropreason = "forwarding disabled for destination";
- goto drop;
- }
- dst = skb_dst(skb);
-@@ -567,9 +628,12 @@ int ip6_forward(struct sk_buff *skb)
-
- /* This check is security critical. */
- if (addrtype == IPV6_ADDR_ANY ||
-- addrtype & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LOOPBACK))
-+ addrtype & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LOOPBACK)) {
-+ dropreason = "invalid address type for forwarding";
- goto error;
-+ }
- if (addrtype & IPV6_ADDR_LINKLOCAL) {
-+ dropreason = "invalid address type for forwarding";
- icmpv6_send(skb, ICMPV6_DEST_UNREACH,
- ICMPV6_NOT_NEIGHBOUR, 0);
- goto error;
-@@ -583,17 +647,20 @@ int ip6_forward(struct sk_buff *skb)
- if (ip6_pkt_too_big(skb, mtu)) {
- /* Again, force OUTPUT device used as source address */
- skb->dev = dst->dev;
-+
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INTOOBIGERRORS);
- __IP6_INC_STATS(net, ip6_dst_idev(dst),
- IPSTATS_MIB_FRAGFAILS);
-- kfree_skb(skb);
-- return -EMSGSIZE;
-+ dropreason = "packet too big";
-+ err = -EMSGSIZE;
-+ goto drop;
- }
-
- if (skb_cow(skb, dst->dev->hard_header_len)) {
- __IP6_INC_STATS(net, ip6_dst_idev(dst),
- IPSTATS_MIB_OUTDISCARDS);
-+ dropreason = "copy-on-write failed";
- goto drop;
- }
-
-@@ -610,6 +677,15 @@ int ip6_forward(struct sk_buff *skb)
- error:
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
- drop:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, hdr,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, hdr,
-+ const char * : string, dropreason);
-+
- kfree_skb(skb);
- return -EINVAL;
- }
-@@ -1445,6 +1521,7 @@ static int __ip6_append_data(struct sock *sk,
- unsigned int maxnonfragsize, headersize;
- unsigned int wmem_alloc_delta = 0;
- bool paged, extra_uref = false;
-+ const char *dropreason;
-
- skb = skb_peek_tail(queue);
- if (!skb) {
-@@ -1484,6 +1561,7 @@ static int __ip6_append_data(struct sock *sk,
- sk->sk_protocol == IPPROTO_RAW)) {
- ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
- sizeof(struct ipv6hdr));
-+ dropreason = "fragmentation needed but disabled";
- goto emsgsize;
- }
-
-@@ -1496,7 +1574,9 @@ static int __ip6_append_data(struct sock *sk,
- emsgsize:
- pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0);
- ipv6_local_error(sk, EMSGSIZE, fl6, pmtu);
-- return -EMSGSIZE;
-+ dropreason = "packet too big";
-+ err = -EMSGSIZE;
-+ goto trace_drop;
- }
-
- /* CHECKSUM_PARTIAL only with no extension headers and when
-@@ -1511,8 +1591,11 @@ static int __ip6_append_data(struct sock *sk,
-
- if (flags & MSG_ZEROCOPY && length && sock_flag(sk, SOCK_ZEROCOPY)) {
- uarg = sock_zerocopy_realloc(sk, length, skb_zcopy(skb));
-- if (!uarg)
-- return -ENOBUFS;
-+ if (!uarg) {
-+ err = -ENOBUFS;
-+ dropreason = "out of memory";
-+ goto error;
-+ }
- extra_uref = !skb_zcopy(skb); /* only ref on new uarg */
- if (rt->dst.dev->features & NETIF_F_SG &&
- csummode == CHECKSUM_PARTIAL) {
-@@ -1614,6 +1697,7 @@ static int __ip6_append_data(struct sock *sk,
- copy = datalen - transhdrlen - fraggap - pagedlen;
- if (copy < 0) {
- err = -EINVAL;
-+ dropreason = "invalid fragment";
- goto error;
- }
- if (transhdrlen) {
-@@ -1626,11 +1710,13 @@ static int __ip6_append_data(struct sock *sk,
- 2 * sk->sk_sndbuf)
- skb = alloc_skb(alloclen + hh_len,
- sk->sk_allocation);
-- if (unlikely(!skb))
-- err = -ENOBUFS;
- }
-- if (!skb)
-+ if (unlikely(!skb)) {
-+ err = -ENOBUFS;
-+ dropreason = "out of memory";
- goto error;
-+ }
-+
- /*
- * Fill in the control structures
- */
-@@ -1662,7 +1748,9 @@ static int __ip6_append_data(struct sock *sk,
- getfrag(from, data + transhdrlen, offset,
- copy, fraggap, skb) < 0) {
- err = -EFAULT;
-+ dropreason = "could not get fragment";
- kfree_skb(skb);
-+ skb = NULL;
- goto error;
- }
-
-@@ -1706,20 +1794,25 @@ static int __ip6_append_data(struct sock *sk,
- offset, copy, off, skb) < 0) {
- __skb_trim(skb, off);
- err = -EFAULT;
-+ dropreason = "could not get fragment";
- goto error;
- }
- } else if (!uarg || !uarg->zerocopy) {
- int i = skb_shinfo(skb)->nr_frags;
-
- err = -ENOMEM;
-- if (!sk_page_frag_refill(sk, pfrag))
-+ if (!sk_page_frag_refill(sk, pfrag)) {
-+ dropreason = "out of memory";
- goto error;
-+ }
-
- if (!skb_can_coalesce(skb, i, pfrag->page,
- pfrag->offset)) {
- err = -EMSGSIZE;
-- if (i == MAX_SKB_FRAGS)
-+ if (i == MAX_SKB_FRAGS) {
-+ dropreason = "too many fragments";
- goto error;
-+ }
-
- __skb_fill_page_desc(skb, i, pfrag->page,
- pfrag->offset, 0);
-@@ -1729,8 +1822,10 @@ static int __ip6_append_data(struct sock *sk,
- copy = min_t(int, copy, pfrag->size - pfrag->offset);
- if (getfrag(from,
- page_address(pfrag->page) + pfrag->offset,
-- offset, copy, skb->len, skb) < 0)
-+ offset, copy, skb->len, skb) < 0) {
-+ dropreason = "could not get fragment";
- goto error_efault;
-+ }
-
- pfrag->offset += copy;
- skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
-@@ -1740,8 +1835,10 @@ static int __ip6_append_data(struct sock *sk,
- wmem_alloc_delta += copy;
- } else {
- err = skb_zerocopy_iter_dgram(skb, from, copy);
-- if (err < 0)
-+ if (err < 0) {
-+ dropreason = "skb iteration failure\n";
- goto error;
-+ }
- }
- offset += copy;
- length -= copy;
-@@ -1758,6 +1855,16 @@ static int __ip6_append_data(struct sock *sk,
- sock_zerocopy_put_abort(uarg, extra_uref);
- cork->length -= length;
- IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
-+trace_drop:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
- return err;
- }
-@@ -1905,9 +2012,20 @@ int ip6_send_skb(struct sk_buff *skb)
- if (err) {
- if (err > 0)
- err = net_xmit_errno(err);
-- if (err)
-+ if (err) {
-+ /* skb may have been freed */
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, NULL,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, "out of memory");
-+
- IP6_INC_STATS(net, rt->rt6i_idev,
- IPSTATS_MIB_OUTDISCARDS);
-+ }
- }
-
- return err;
-@@ -1933,9 +2051,19 @@ static void __ip6_flush_pending_frames(struct sock *sk,
- struct sk_buff *skb;
-
- while ((skb = __skb_dequeue_tail(queue)) != NULL) {
-- if (skb_dst(skb))
-+ if (skb_dst(skb)) {
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *,
-+ ipv6_hdr(skb),
-+ const char * : string, "flushing pending frames");
- IP6_INC_STATS(sock_net(sk), ip6_dst_idev(skb_dst(skb)),
- IPSTATS_MIB_OUTDISCARDS);
-+ }
- kfree_skb(skb);
- }
-
-diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
-index 8cd2782a31e4..e90cb6e0781d 100644
---- a/net/ipv6/mcast.c
-+++ b/net/ipv6/mcast.c
-@@ -60,6 +60,8 @@
-
- #include <net/ip6_checksum.h>
-
-+#include <linux/sdt.h>
-+
- /* Ensure that we have struct in6_addr aligned on 32bit word. */
- static int __mld2_query_bugs[] __attribute__((__unused__)) = {
- BUILD_BUG_ON_ZERO(offsetof(struct mld2_query, mld2q_srcs) % 4),
-@@ -1644,6 +1646,7 @@ static void mld_sendpack(struct sk_buff *skb)
- int payload_len, mldlen;
- struct inet6_dev *idev;
- struct net *net = dev_net(skb->dev);
-+ const char *dropreason;
- int err;
- struct flowi6 fl6;
- struct dst_entry *dst;
-@@ -1673,26 +1676,45 @@ static void mld_sendpack(struct sk_buff *skb)
- dst = NULL;
- }
- skb_dst_set(skb, dst);
-- if (err)
-- goto err_out;
-+ if (err) {
-+ kfree_skb(skb);
-+ skb = NULL;
-+ dropreason = "out of memory";
-+ goto out;
-+ }
-+
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
-
- err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
- net, net->ipv6.igmp_sk, skb, NULL, skb->dev,
- dst_output);
-+ dropreason = "multicast send error";
- out:
- if (!err) {
- ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT);
- ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
- } else {
-+ /* skb may have been freed */
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, idev->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
- }
-
- rcu_read_unlock();
- return;
--
--err_out:
-- kfree_skb(skb);
-- goto out;
- }
-
- static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
-@@ -1979,7 +2001,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
- {
- struct net *net = dev_net(dev);
- struct sock *sk = net->ipv6.igmp_sk;
-- struct inet6_dev *idev;
-+ struct inet6_dev *idev = NULL;
- struct sk_buff *skb;
- struct mld_msg *hdr;
- const struct in6_addr *snd_addr, *saddr;
-@@ -1990,6 +2012,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
- u8 ra[8] = { IPPROTO_ICMPV6, 0,
- IPV6_TLV_ROUTERALERT, 2, 0, 0,
- IPV6_TLV_PADN, 0 };
-+ const char *dropreason;
- struct flowi6 fl6;
- struct dst_entry *dst;
-
-@@ -2011,10 +2034,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
-
- if (!skb) {
- rcu_read_lock();
-- IP6_INC_STATS(net, __in6_dev_get(dev),
-- IPSTATS_MIB_OUTDISCARDS);
-- rcu_read_unlock();
-- return;
-+ dropreason = "out of memory";
-+ goto out;
- }
- skb->priority = TC_PRIO_CONTROL;
- skb_reserve(skb, hlen);
-@@ -2049,26 +2070,43 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
- dst = icmp6_dst_alloc(skb->dev, &fl6);
- if (IS_ERR(dst)) {
- err = PTR_ERR(dst);
-- goto err_out;
-+ kfree_skb(skb);
-+ skb = NULL;
-+ dropreason = "out of memory";
-+ goto out;
- }
-
- skb_dst_set(skb, dst);
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
- err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
- net, sk, skb, NULL, skb->dev,
- dst_output);
-+ dropreason = "multicast send error";
- out:
- if (!err) {
- ICMP6MSGOUT_INC_STATS(net, idev, type);
- ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
-- } else
-+ } else {
-+ /* skb may have been freed */
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, idev->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
- IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
-+ }
-
- rcu_read_unlock();
- return;
--
--err_out:
-- kfree_skb(skb);
-- goto out;
- }
-
- static void mld_send_initial_cr(struct inet6_dev *idev)
-diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
-index 76717478f173..35ae4eaffd89 100644
---- a/net/ipv6/ndisc.c
-+++ b/net/ipv6/ndisc.c
-@@ -68,6 +68,7 @@
-
- #include <linux/netfilter.h>
- #include <linux/netfilter_ipv6.h>
-+#include <linux/sdt.h>
-
- static u32 ndisc_hash(const void *pkey,
- const struct net_device *dev,
-@@ -505,6 +506,14 @@ static void ndisc_send_skb(struct sk_buff *skb,
- idev = __in6_dev_get(dst->dev);
- IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
-
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
-+
- err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
- net, sk, skb, NULL, dst->dev,
- dst_output);
-diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
-index af36acc1a644..811a88767a5c 100644
---- a/net/ipv6/output_core.c
-+++ b/net/ipv6/output_core.c
-@@ -10,6 +10,7 @@
- #include <net/addrconf.h>
- #include <net/secure_seq.h>
- #include <linux/netfilter.h>
-+#include <linux/sdt.h>
-
- static u32 __ipv6_select_ident(struct net *net,
- const struct in6_addr *dst,
-@@ -164,6 +165,14 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
-
- skb->protocol = htons(ETH_P_IPV6);
-
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
-+
- return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
- net, sk, skb, NULL, skb_dst(skb)->dev,
- dst_output);
-diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
-index 6e4ab80a3b94..f88c9441ec51 100644
---- a/net/ipv6/raw.c
-+++ b/net/ipv6/raw.c
-@@ -58,6 +58,7 @@
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/export.h>
-+#include <linux/sdt.h>
-
- #define ICMPV6_HDRLEN 4 /* ICMPv6 header, RFC 4443 Section 2.1 */
-
-@@ -622,26 +623,34 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
- struct ipv6_pinfo *np = inet6_sk(sk);
- struct net *net = sock_net(sk);
- struct ipv6hdr *iph;
-- struct sk_buff *skb;
-+ struct sk_buff *skb = NULL;
- int err;
- struct rt6_info *rt = (struct rt6_info *)*dstp;
- int hlen = LL_RESERVED_SPACE(rt->dst.dev);
- int tlen = rt->dst.dev->needed_tailroom;
-+ const char *dropreason;
-
- if (length > rt->dst.dev->mtu) {
- ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu);
-- return -EMSGSIZE;
-+ dropreason = "packet too big";
-+ err = -EMSGSIZE;
-+ goto error_check;
-+ }
-+ if (length < sizeof(struct ipv6hdr)) {
-+ dropreason = "packet too short";
-+ err = -EINVAL;
-+ goto error_check;
- }
-- if (length < sizeof(struct ipv6hdr))
-- return -EINVAL;
- if (flags&MSG_PROBE)
- goto out;
-
- skb = sock_alloc_send_skb(sk,
- length + hlen + tlen + 15,
- flags & MSG_DONTWAIT, &err);
-- if (!skb)
-+ if (!skb) {
-+ dropreason = "out of memory";
- goto error;
-+ }
- skb_reserve(skb, hlen);
-
- skb->protocol = htons(ETH_P_IPV6);
-@@ -665,7 +674,8 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
- if (err) {
- err = -EFAULT;
- kfree_skb(skb);
-- goto error;
-+ dropreason = "could not copy msg";
-+ goto error_check;
- }
-
- skb_dst_set(skb, &rt->dst);
-@@ -684,6 +694,13 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
- */
- rcu_read_lock();
- IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
- err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb,
- NULL, rt->dst.dev, dst_output);
- if (err > 0)
-@@ -691,6 +708,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
- if (err) {
- IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
- rcu_read_unlock();
-+ dropreason = "raw send error";
- goto error_check;
- }
- rcu_read_unlock();
-@@ -700,6 +718,14 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
- error:
- IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
- error_check:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, skb ? ipv6_hdr(skb) : NULL,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, skb ? ipv6_hdr(skb) : NULL,
-+ const char * : string, dropreason);
- if (err == -ENOBUFS && !np->recverr)
- err = 0;
- return err;
-diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
-index 991dc36f95ff..acc63c455651 100644
---- a/net/ipv6/tcp_ipv6.c
-+++ b/net/ipv6/tcp_ipv6.c
-@@ -65,6 +65,7 @@
-
- #include <crypto/hash.h>
- #include <linux/scatterlist.h>
-+#include <linux/sdt.h>
-
- #include <trace/events/tcp.h>
-
-@@ -496,6 +497,20 @@ static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- return 0;
- }
-
-+/* Since we want to trace send events in TCP prior to pushing the segment to
-+ * IP - where the IP header is added - we need to construct an argument
-+ * containing relevant IP info so that TCP probe consumers can utilize it.
-+ */
-+static inline void dtrace_tcp_build_ipv6hdr(struct in6_addr *saddr,
-+ struct in6_addr *daddr,
-+ struct ipv6hdr *ip6h)
-+{
-+ ip6h->version = 6;
-+ ip6h->payload_len = 0;
-+ ip6h->nexthdr = IPPROTO_TCP;
-+ ip6h->saddr = *saddr;
-+ ip6h->daddr = *daddr;
-+}
-
- static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
- struct flowi *fl,
-@@ -540,6 +555,32 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
- opt = ireq->ipv6_opt;
- if (!opt)
- opt = rcu_dereference(np->opt);
-+
-+ if (DTRACE_TCP_ENABLED(send)) {
-+ struct ipv6hdr ip6h;
-+
-+ dtrace_tcp_build_ipv6hdr(&ireq->ir_v6_loc_addr,
-+ &ireq->ir_v6_rmt_addr, &ip6h);
-+
-+ /* Do not supply tcp sk - addresses/ports are not
-+ * committed yet - instead translators will fill them
-+ * in from IP/TCP data.
-+ */
-+ DTRACE_TCP_NOCHECK(send,
-+ struct sk_buff * : pktinfo_t *,
-+ NULL,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, &ip6h,
-+ struct tcp_sock * : tcpsinfo_t *,
-+ NULL,
-+ struct tcphdr * : tcpinfo_t *,
-+ tcp_hdr(skb),
-+ int : tcplsinfo_t *, TCP_LISTEN,
-+ int, TCP_LISTEN,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
-+ }
-+
- err = ip6_xmit(sk, skb, fl6, sk->sk_mark, opt,
- tclass, sk->sk_priority);
- rcu_read_unlock();
-@@ -969,6 +1010,49 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
- dst = ip6_dst_lookup_flow(sock_net(ctl_sk), ctl_sk, &fl6, NULL);
- if (!IS_ERR(dst)) {
- skb_dst_set(buff, dst);
-+
-+ if (DTRACE_TCP_ENABLED(send) ||
-+ DTRACE_TCP_ENABLED(accept__refused)) {
-+ struct ipv6hdr ip6h;
-+
-+ dtrace_tcp_build_ipv6hdr(&fl6.saddr, &fl6.daddr,
-+ &ip6h);
-+
-+ /* Do not supply tcp sk - addresses/ports are not
-+ * committed yet - instead translators will fill them
-+ * in from IP/TCP data.
-+ */
-+ DTRACE_TCP_NOCHECK(send,
-+ struct sk_buff * : pktinfo_t *,
-+ NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, &ip6h,
-+ struct tcp_sock * : tcpsinfo_t *,
-+ NULL,
-+ struct tcphdr * : tcpinfo_t *, t1,
-+ int : tcplsinfo_t *, TCP_CLOSE,
-+ int, TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
-+ if (rst && th->syn && th->ack == 0)
-+ DTRACE_TCP_NOCHECK(accept__refused,
-+ struct sk_buff * :
-+ pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *,
-+ NULL,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, &ip6h,
-+ struct tcp_sock * :
-+ tcpsinfo_t *, NULL,
-+ struct tcphdr * :
-+ tcpinfo_t *, t1,
-+ int : tcplsinfo_t *,
-+ TCP_CLOSE,
-+ int, TCP_CLOSE,
-+ int,
-+ DTRACE_NET_PROBE_OUTBOUND);
-+ }
-+
- ip6_xmit(ctl_sk, buff, &fl6, fl6.flowi6_mark, NULL,
- tclass & ~INET_ECN_MASK, priority);
- TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
-@@ -1583,7 +1667,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
- const struct tcphdr *th;
- const struct ipv6hdr *hdr;
- bool refcounted;
-- struct sock *sk;
-+ struct sock *sk = NULL;
- int ret;
- struct net *net = dev_net(skb->dev);
-
-@@ -1618,6 +1702,15 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
- if (!sk)
- goto no_tcp_socket;
-
-+ DTRACE_TCP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, hdr,
-+ struct tcp_sock * : tcpsinfo_t *, tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, th,
-+ int : tcplsinfo_t *, sk ? sk->sk_state : TCP_CLOSE,
-+ int, sk ? sk->sk_state : TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_INBOUND);
- process:
- if (sk->sk_state == TCP_TIME_WAIT)
- goto do_time_wait;
-@@ -1737,6 +1830,18 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
- }
-
- discard_it:
-+ if (DTRACE_TCP_ENABLED(receive) && skb->pkt_type == PACKET_HOST)
-+ DTRACE_TCP_NOCHECK(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *,
-+ ipv6_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *,
-+ sk ? sk->sk_state : TCP_CLOSE,
-+ int, sk ? sk->sk_state : TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_INBOUND);
- kfree_skb(skb);
- return 0;
-
-diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
-index 29d9691359b9..996afe0fb057 100644
---- a/net/ipv6/udp.c
-+++ b/net/ipv6/udp.c
-@@ -51,6 +51,7 @@
-
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
-+#include <linux/sdt.h>
- #include <trace/events/skb.h>
- #include "udp_impl.h"
-
-@@ -386,8 +387,15 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
- kfree_skb(skb);
- return err;
- }
-- if (!peeking)
-+ if (!peeking) {
- SNMP_INC_STATS(mib, UDP_MIB_INDATAGRAMS);
-+ DTRACE_UDP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *, udp_sk(sk),
-+ struct udphdr * : udpinfo_t *, udp_hdr(skb));
-+ }
-
- sock_recv_ts_and_drops(msg, sk, skb);
-
-@@ -685,6 +693,15 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
-
- ret = encap_rcv(sk, skb);
- if (ret <= 0) {
-+ DTRACE_UDP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *,
-+ ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *,
-+ udp_sk(sk),
-+ struct udphdr * : udpinfo_t *,
-+ udp_hdr(skb));
- __UDP_INC_STATS(sock_net(sk),
- UDP_MIB_INDATAGRAMS,
- is_udplite);
-@@ -1238,6 +1255,13 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
- err = 0;
- }
- } else {
-+ DTRACE_UDP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *, udp_sk(sk),
-+ struct udphdr * : udpinfo_t *, uh);
-+
- UDP6_INC_STATS(sock_net(sk),
- UDP_MIB_OUTDATAGRAMS, is_udplite);
- }
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch
deleted file mode 100644
index a19e99b5fa67..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch
+++ /dev/null
@@ -1,241 +0,0 @@
-From 6e49525673d614475c5e9b7b164bd48bad93b4a3 Mon Sep 17 00:00:00 2001
-From: Eugene Loh <eugene.loh@oracle.com>
-Date: Mon, 12 Aug 2019 20:51:06 -0700
-Subject: [PATCH 18/19] dtrace: add sample script for building DTrace on Fedora
-
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
----
- samples/dtrace/DTrace-on-Fedora.sh | 221 +++++++++++++++++++++++++++++
- 1 file changed, 221 insertions(+)
- create mode 100755 samples/dtrace/DTrace-on-Fedora.sh
-
-diff --git a/samples/dtrace/DTrace-on-Fedora.sh b/samples/dtrace/DTrace-on-Fedora.sh
-new file mode 100755
-index 000000000000..3857027381a5
---- /dev/null
-+++ b/samples/dtrace/DTrace-on-Fedora.sh
-@@ -0,0 +1,221 @@
-+#!/bin/sh
-+
-+# Oracle Linux DTrace.
-+# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
-+# Licensed under the Universal Permissive License v 1.0 as shown at
-+# http://oss.oracle.com/licenses/upl.
-+#
-+
-+# Oracle has been working in recent years on porting DTrace, the
-+# dynamic tracing tool, to Linux. DTrace offers easy-to-use, powerful,
-+# safe, and unintrusive tracing. Oracle's initial focus was the Oracle
-+# Unbreakable Enterprise Kernel (UEK), but DTrace runs on upstream Linux
-+# kernels and other distributions' Linux kernels as well. Note that at
-+# the moment, Oracle is in the process of upstreaming DTrace-related work
-+# and reimplementing DTrace itself on top of existing kernel infrastructure
-+# such as eBPF.
-+
-+# This script illustrates how to build DTrace on Fedora on x86.
-+# It is intended as a tutorial rather than a robust, turn-key utility.
-+# Read and understand the steps as you execute them. The steps are
-+# similar to what one does to build DTrace on other Linux distributions.
-+
-+# Useful references on building a custom Fedora kernel include:
-+# https://fedoraproject.org/wiki/Building_a_custom_kernel
-+# https://fedoraproject.org/wiki/Building_a_custom_kernel#Building_Vanilla_upstream_kernel
-+# Roughly speaking, you should have about 20 Gbyte of disk space
-+# available and expect to wait a few hours for the build to complete.
-+
-+# The overall process is:
-+# 1. download and build the CTF library for DTrace to use
-+# 2. download Fedora kernel source code
-+# 3. prepare DTrace patches to apply
-+# 4. prepare the kernel source code
-+# a. Linux base code
-+# b. apply Linux patches (if any)
-+# c. apply Fedora patches
-+# d. apply DTrace patches
-+# e. prepare makefile and config
-+# 5. build the kernel
-+# 6. reboot
-+# 7. download and build the DTrace userspace utility
-+
-+
-+# pick one
-+# DTrace patches change relatively infrequently.
-+# So DTrace_branch might not have to match your Fedora kernel version exactly.
-+#fedora_release=f29; DTrace_branch=5.2.7 ; num_DTrace_patches=19
-+ fedora_release=f30; DTrace_branch=5.2.7 ; num_DTrace_patches=19
-+
-+# Step 1: download and build the CTF library for DTrace to use
-+
-+sudo dnf install -y git
-+git clone https://github.com/oracle/libdtrace-ctf.git
-+cd libdtrace-ctf
-+sudo dnf builddep -y libdtrace-ctf.spec # install dependencies
-+make
-+sudo make install
-+cd ..
-+
-+# Step 2: download Fedora kernel source code
-+
-+sudo dnf install -y fedora-packager
-+fedpkg co -a kernel # anonymous clone of Fedora patches
-+cd kernel
-+git checkout origin/$fedora_release
-+fedpkg sources # download tarballs of kernel sources
-+sudo dnf builddep -y kernel.spec # install dependencies
-+cd ..
-+
-+# Step 3: prepare DTrace patches to apply
-+
-+# download DTrace kernel code
-+git clone https://github.com/oracle/dtrace-linux-kernel.git
-+cd dtrace-linux-kernel/
-+git checkout origin/$DTrace_branch
-+
-+# The DTrace patches will be the most recent commits.
-+# Make sure you use all of them but nothing before that.
-+# Make sure the top patches are DTrace
-+# and the next one after them is the Linux baseline you want.
-+# E.g., the top commits here are DTrace, and the last one is Linux upstream:
-+# [...]
-+# 66f76fef08e3 dtrace: modular components and x86 support
-+# 25f11bb97fb9 dtrace: core and x86
-+# 3c5af76fa5fb waitfd: new syscall implementing waitpid() over fds
-+# e95e4350d02b kallsyms: introduce new /proc/kallmodsyms including builtin modules too
-+# 86e43efc644c ctf: generate CTF information for the kernel
-+# a3b22b9f11d9 (tag: v5.0-rc7) Linux 5.0-rc7
-+git log -n $(($num_DTrace_patches + 1)) --oneline
-+
-+# generate the DTrace patches
-+git format-patch -$num_DTrace_patches
-+
-+cd ..
-+
-+# Step 4: prepare the kernel source code
-+
-+# Step 4a: Linux base code
-+
-+if [ -e kernel/linux-*.xz ]; then
-+ /usr/bin/xz -dc kernel/linux-*.tar.xz | /usr/bin/tar -xof -
-+else
-+ tar xzf kernel/linux-*.tar.gz
-+fi
-+
-+# make a git repo so patches can be applied
-+cd linux-*
-+git init
-+git config user.email "kernel-team@fedoraproject.org"
-+git config user.name "Fedora Kernel Team"
-+git config gc.auto 0
-+git add .
-+git commit -a -q -m "baseline"
-+
-+# Step 4b: apply Linux patches (if any)
-+
-+if [ -e ../kernel/patch-*.xz ]; then
-+ xzcat ../kernel/patch-*.xz | patch -p1 -F1 -s
-+ git commit -a -m "Stable update"
-+fi
-+
-+# Step 4c: apply Fedora patches
-+
-+for x in `awk '/^Patch/ {print $2}' ../kernel/kernel.spec`; do
-+ git am ../kernel/$x
-+done
-+
-+# Step 4d: apply DTrace patches
-+
-+for x in ../dtrace-linux-kernel/00*.patch; do
-+ git am $x
-+ if [ $? -ne 0 ]; then
-+ echo DTrace patch did not apply cleanly
-+ exit 1
-+ fi
-+done
-+
-+# Step 4e: prepare makefile and config
-+
-+# modify the version tag in the Makefile
-+sed -i.old \
-+ 's/^EXTRAVERSION =.*$/EXTRAVERSION = -200.DTrace_'$fedora_release'.x86_64/' \
-+ Makefile
-+
-+# use the Fedora config file
-+cp ../kernel/kernel-x86_64.config .config
-+
-+# modify the config file for DTrace
-+sed -i \
-+ -e 's/# CONFIG_UNWINDER_FRAME_POINTER is not set/CONFIG_UNWINDER_FRAME_POINTER=y/' \
-+ -e 's/CONFIG_UNWINDER_ORC=y/# CONFIG_UNWINDER_ORC is not set/' .config
-+echo "CONFIG_DTRACE=y" >> .config
-+echo "CONFIG_DT_CORE=m" >> .config
-+echo "CONFIG_DT_FASTTRAP=m" >> .config
-+echo "CONFIG_DT_PROFILE=m" >> .config
-+echo "CONFIG_DT_SDT=m" >> .config
-+echo "CONFIG_DT_SDT_PERF=y" >> .config
-+echo "CONFIG_DT_FBT=m" >> .config
-+echo "CONFIG_DT_SYSTRACE=m" >> .config
-+echo "CONFIG_DT_DT_TEST=m" >> .config
-+echo "CONFIG_DT_DT_PERF=m" >> .config
-+echo "CONFIG_DT_DEBUG=y" >> .config
-+echo "# CONFIG_DT_DEBUG_MUTEX is not set" >> .config
-+
-+# Step 5: build the kernel
-+
-+# (might take hours)
-+make olddefconfig
-+make -j4
-+make -j4 ctf
-+
-+# install
-+sudo make modules_install
-+sudo make install
-+sudo make INSTALL_HDR_PATH=/usr headers_install
-+cd ..
-+
-+# Step 6: reboot
-+
-+sudo reboot
-+
-+# Step 7: download and build the DTrace userspace utility
-+
-+git clone https://github.com/oracle/dtrace-utils.git
-+cd dtrace-utils
-+
-+# The DTrace packages are missing from Fedora repos,
-+# and we just built that software ourselves.
-+# So eliminate those packages from the .spec file
-+# before calling dnf builddep.
-+sed -i.old \
-+ -e 's/-devel libdtrace-ctf-devel >= [0-9\.]*/-devel/' \
-+ -e '/^BuildRequires: dtrace-kernel-headers = [0-9\.]*$/d' dtrace-utils.spec
-+sudo dnf builddep -y dtrace-utils.spec
-+
-+make
-+sudo make install
-+cd ..
-+
-+exit 0
-+
-+# Now, we can use DTrace on Fedora! (Notice that it is installed at /usr/sbin/dtrace.
-+# Some other utility is at /usr/bin/dtrace.) You must be logged in as
-+# root to use DTrace. The first thing to do is to list the available probes:
-+#
-+# # /usr/sbin/dtrace -l
-+# ID PROVIDER MODULE FUNCTION NAME
-+# 1 dtrace BEGIN
-+# 2 dtrace END
-+# 3 dtrace ERROR
-+# 5 fbt isofs isofs_hashi entry
-+# 6 fbt isofs isofs_hashi return
-+# 7 fbt isofs isofs_statfs entry
-+# 8 fbt isofs isofs_statfs return
-+# 9 fbt isofs isofs_iget5_test entry
-+# 10 fbt isofs isofs_iget5_test return
-+# [...thousands of lines omitted...]
-+#
-+# Next, check out the Oracle DTrace Guide for simple examples and more information.
-+# https://docs.oracle.com/cd/E52668_01/E38608/html/index.html
-+
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch b/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch
deleted file mode 100644
index df04191dcf9d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/dtrace-patches/0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-From cbc0fec32fc028d2e75a00f7a0609bc1960b02ee Mon Sep 17 00:00:00 2001
-From: Nick Alcock <nick.alcock@oracle.com>
-Date: Mon, 9 Dec 2019 16:51:44 +0000
-Subject: [PATCH 19/19] locking: publicize mutex_owner and mutex_owned again
-
-DTrace uses both of them.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
----
- dtrace/dtrace_dif.c | 2 +-
- include/linux/mutex.h | 16 +++++-----------
- kernel/locking/mutex.c | 19 +++++++++++++++++++
- 3 files changed, 25 insertions(+), 12 deletions(-)
-
-diff --git a/dtrace/dtrace_dif.c b/dtrace/dtrace_dif.c
-index ae7f01b4ed9b..798302d322a3 100644
---- a/dtrace/dtrace_dif.c
-+++ b/dtrace/dtrace_dif.c
-@@ -2439,7 +2439,7 @@ static void dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
- break;
-
- #ifdef CONFIG_SMP
-- regs[rd] = (uintptr_t)__mutex_owner(&mtx);
-+ regs[rd] = (uintptr_t)mutex_owner(&mtx);
- #else
- regs[rd] = 0;
- #endif
-diff --git a/include/linux/mutex.h b/include/linux/mutex.h
-index bb18028db361..a1f15a42ea16 100644
---- a/include/linux/mutex.h
-+++ b/include/linux/mutex.h
-@@ -228,16 +228,10 @@ enum mutex_trylock_recursive_enum {
- extern /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
- mutex_trylock_recursive(struct mutex *lock);
-
--#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
--static inline int mutex_owned(struct mutex *lock)
--{
-- return mutex_is_locked(lock) && __mutex_owner(lock) == current;
--}
--#else
--static inline int mutex_owned(struct mutex *lock)
--{
-- return mutex_is_locked(lock);
--}
--#endif
-+extern int
-+mutex_owned(struct mutex *lock);
-+
-+extern struct task_struct *
-+mutex_owner(struct mutex *lock);
-
- #endif /* __LINUX_MUTEX_H */
-diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
-index e784dd89d924..b856d7ffc51c 100644
---- a/kernel/locking/mutex.c
-+++ b/kernel/locking/mutex.c
-@@ -97,6 +97,25 @@ mutex_trylock_recursive(struct mutex *lock)
- }
- EXPORT_SYMBOL(mutex_trylock_recursive);
-
-+struct task_struct *mutex_owner(struct mutex *lock)
-+{
-+ return __mutex_owner (lock);
-+}
-+EXPORT_SYMBOL(mutex_owner);
-+
-+#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
-+int mutex_owned(struct mutex *lock)
-+{
-+ return mutex_is_locked(lock) && __mutex_owner(lock) == current;
-+}
-+#else
-+int mutex_owned(struct mutex *lock)
-+{
-+ return mutex_is_locked(lock);
-+}
-+#endif
-+EXPORT_SYMBOL(mutex_owned);
-+
- static inline unsigned long __owner_flags(unsigned long owner)
- {
- return owner & MUTEX_FLAGS;
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/0000_README b/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/0000_README
deleted file mode 100644
index fe8a77823d04..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/0000_README
+++ /dev/null
@@ -1,120 +0,0 @@
-README
---------------------------------------------------------------------------
-This patchset is to be the series of patches for gentoo-sources.
-It is designed for cross-compatibility, fixes and stability, with performance
-and additional features/driver support being a second.
-
-Unless otherwise stated and marked as such, this kernel should be suitable for
-all environments.
-
-
-Patchset Numbering Scheme
---------------------------------------------------------------------------
-
-FIXES
-1000-1400 linux-stable
-1400-1500 linux-stable queue
-1500-1700 security
-1700-1800 architecture-related
-1800-1900 mm/scheduling/misc
-1900-2000 filesystems
-2000-2100 networking core
-2100-2200 storage core
-2200-2300 power management (ACPI, APM)
-2300-2400 bus (USB, IEEE1394, PCI, PCMCIA, ...)
-2400-2500 network drivers
-2500-2600 storage drivers
-2600-2700 input
-2700-2900 media (graphics, sound, tv)
-2900-3000 other
-3000-4000 reserved
-
-FEATURES
-4000-4100 network
-4100-4200 storage
-4200-4300 graphics
-4300-4400 filesystem
-4400-4500 security enhancement
-4500-4600 other
-
-EXPERIMENTAL
-5000-5100 experimental patches (BFQ, ...)
-
-Individual Patch Descriptions:
---------------------------------------------------------------------------
-
-Patch: 1000_linux-5.10.1.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.1
-
-Patch: 1001_linux-5.10.2.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.2
-
-Patch: 1002_linux-5.10.3.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.3
-
-Patch: 1003_linux-5.10.4.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.4
-
-Patch: 1004_linux-5.10.5.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.5
-
-Patch: 1005_linux-5.10.6.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.6
-
-Patch: 1006_linux-5.10.7.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.7
-
-Patch: 1007_linux-5.10.8.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.8
-
-Patch: 1008_linux-5.10.9.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.9
-
-Patch: 1009_linux-5.10.10.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.10
-
-Patch: 1010_linux-5.10.11.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.11
-
-Patch: 1500_XATTR_USER_PREFIX.patch
-From: https://bugs.gentoo.org/show_bug.cgi?id=470644
-Desc: Support for namespace user.pax.* on tmpfs.
-
-Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
-From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
-Desc: Enable link security restrictions by default.
-
-Patch: 2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
-From: https://lore.kernel.org/linux-bluetooth/20190522070540.48895-1-marcel@holtmann.org/raw
-Desc: Bluetooth: Check key sizes only when Secure Simple Pairing is enabled. See bug #686758
-
-Patch: 2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch
-From: https://bugs.gentoo.org/710790
-Desc: tmp513 requies REGMAP_I2C to build. Select it by default in Kconfig. See bug #710790. Thanks to Phil Stracchino
-
-Patch: 2920_sign-file-patch-for-libressl.patch
-From: https://bugs.gentoo.org/717166
-Desc: sign-file: full functionality with modern LibreSSL
-
-Patch: 4567_distro-Gentoo-Kconfig.patch
-From: Tom Wijsman <TomWij@gentoo.org>
-Desc: Add Gentoo Linux support config settings and defaults.
-
-Patch: 5000_shifts-ubuntu-20.04.patch
-From: https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/focal
-Desc: UID/GID shifting overlay filesystem for containers
-
-Patch: 5013_enable-cpu-optimizations-for-gcc10.patch
-From: https://github.com/graysky2/kernel_gcc_patch/
-Desc: Kernel patch enables gcc = v10.1+ optimizations for additional CPUs.
diff --git a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/1500_XATTR_USER_PREFIX.patch b/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/1500_XATTR_USER_PREFIX.patch
deleted file mode 100644
index 245dcc29fa56..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/1500_XATTR_USER_PREFIX.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From: Anthony G. Basile <blueness@gentoo.org>
-
-This patch adds support for a restricted user-controlled namespace on
-tmpfs filesystem used to house PaX flags. The namespace must be of the
-form user.pax.* and its value cannot exceed a size of 8 bytes.
-
-This is needed even on all Gentoo systems so that XATTR_PAX flags
-are preserved for users who might build packages using portage on
-a tmpfs system with a non-hardened kernel and then switch to a
-hardened kernel with XATTR_PAX enabled.
-
-The namespace is added to any user with Extended Attribute support
-enabled for tmpfs. Users who do not enable xattrs will not have
-the XATTR_PAX flags preserved.
-
-diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h
-index 1590c49..5eab462 100644
---- a/include/uapi/linux/xattr.h
-+++ b/include/uapi/linux/xattr.h
-@@ -73,5 +73,9 @@
- #define XATTR_POSIX_ACL_DEFAULT "posix_acl_default"
- #define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT
-
-+/* User namespace */
-+#define XATTR_PAX_PREFIX XATTR_USER_PREFIX "pax."
-+#define XATTR_PAX_FLAGS_SUFFIX "flags"
-+#define XATTR_NAME_PAX_FLAGS XATTR_PAX_PREFIX XATTR_PAX_FLAGS_SUFFIX
-
- #endif /* _UAPI_LINUX_XATTR_H */
---- a/mm/shmem.c 2020-05-04 15:30:27.042035334 -0400
-+++ b/mm/shmem.c 2020-05-04 15:34:57.013881725 -0400
-@@ -3238,6 +3238,14 @@ static int shmem_xattr_handler_set(const
- struct shmem_inode_info *info = SHMEM_I(inode);
-
- name = xattr_full_name(handler, name);
-+
-+ if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
-+ if (strcmp(name, XATTR_NAME_PAX_FLAGS))
-+ return -EOPNOTSUPP;
-+ if (size > 8)
-+ return -EINVAL;
-+ }
-+
- return simple_xattr_set(&info->xattrs, name, value, size, flags, NULL);
- }
-
-@@ -3253,6 +3261,12 @@ static const struct xattr_handler shmem_
- .set = shmem_xattr_handler_set,
- };
-
-+static const struct xattr_handler shmem_user_xattr_handler = {
-+ .prefix = XATTR_USER_PREFIX,
-+ .get = shmem_xattr_handler_get,
-+ .set = shmem_xattr_handler_set,
-+};
-+
- static const struct xattr_handler *shmem_xattr_handlers[] = {
- #ifdef CONFIG_TMPFS_POSIX_ACL
- &posix_acl_access_xattr_handler,
-@@ -3260,6 +3274,7 @@ static const struct xattr_handler *shmem
- #endif
- &shmem_security_xattr_handler,
- &shmem_trusted_xattr_handler,
-+ &shmem_user_xattr_handler,
- NULL
- };
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch
deleted file mode 100644
index f0ed144fb17a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-From: Ben Hutchings <ben@decadent.org.uk>
-Subject: fs: Enable link security restrictions by default
-Date: Fri, 02 Nov 2012 05:32:06 +0000
-Bug-Debian: https://bugs.debian.org/609455
-Forwarded: not-needed
-This reverts commit 561ec64ae67ef25cac8d72bb9c4bfc955edfd415
-('VFS: don't do protected {sym,hard}links by default').
---- a/fs/namei.c 2018-09-28 07:56:07.770005006 -0400
-+++ b/fs/namei.c 2018-09-28 07:56:43.370349204 -0400
-@@ -885,8 +885,8 @@ static inline void put_link(struct namei
- path_put(&last->link);
- }
-
--int sysctl_protected_symlinks __read_mostly = 0;
--int sysctl_protected_hardlinks __read_mostly = 0;
-+int sysctl_protected_symlinks __read_mostly = 1;
-+int sysctl_protected_hardlinks __read_mostly = 1;
- int sysctl_protected_fifos __read_mostly;
- int sysctl_protected_regular __read_mostly;
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch b/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
deleted file mode 100644
index 394ad48fc20c..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-The encryption is only mandatory to be enforced when both sides are using
-Secure Simple Pairing and this means the key size check makes only sense
-in that case.
-
-On legacy Bluetooth 2.0 and earlier devices like mice the encryption was
-optional and thus causing an issue if the key size check is not bound to
-using Secure Simple Pairing.
-
-Fixes: d5bb334a8e17 ("Bluetooth: Align minimum encryption key size for LE and BR/EDR connections")
-Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-Cc: stable@vger.kernel.org
----
- net/bluetooth/hci_conn.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
-index 3cf0764d5793..7516cdde3373 100644
---- a/net/bluetooth/hci_conn.c
-+++ b/net/bluetooth/hci_conn.c
-@@ -1272,8 +1272,13 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
- return 0;
- }
-
-- if (hci_conn_ssp_enabled(conn) &&
-- !test_bit(HCI_CONN_ENCRYPT, &conn->flags))
-+ /* If Secure Simple Pairing is not enabled, then legacy connection
-+ * setup is used and no encryption or key sizes can be enforced.
-+ */
-+ if (!hci_conn_ssp_enabled(conn))
-+ return 1;
-+
-+ if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
- return 0;
-
- /* The minimum encryption key size needs to be enforced by the
---
-2.20.1
diff --git a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch b/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch
deleted file mode 100644
index 433568579cab..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From dc328d75a6f37f4ff11a81ae16b1ec88c3197640 Mon Sep 17 00:00:00 2001
-From: Mike Pagano <mpagano@gentoo.org>
-Date: Mon, 23 Mar 2020 08:20:06 -0400
-Subject: [PATCH 1/1] This driver requires REGMAP_I2C to build. Select it by
- default in Kconfig. Reported at gentoo bugzilla:
- https://bugs.gentoo.org/710790
-Cc: mpagano@gentoo.org
-
-Reported-by: Phil Stracchino <phils@caerllewys.net>
-
-Signed-off-by: Mike Pagano <mpagano@gentoo.org>
----
- drivers/hwmon/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
-index 47ac20aee06f..530b4f29ba85 100644
---- a/drivers/hwmon/Kconfig
-+++ b/drivers/hwmon/Kconfig
-@@ -1769,6 +1769,7 @@ config SENSORS_TMP421
- config SENSORS_TMP513
- tristate "Texas Instruments TMP513 and compatibles"
- depends on I2C
-+ select REGMAP_I2C
- help
- If you say yes here you get support for Texas Instruments TMP512,
- and TMP513 temperature and power supply sensor chips.
---
-2.24.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2920_sign-file-patch-for-libressl.patch b/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2920_sign-file-patch-for-libressl.patch
deleted file mode 100644
index e6ec017d46c8..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/2920_sign-file-patch-for-libressl.patch
+++ /dev/null
@@ -1,16 +0,0 @@
---- a/scripts/sign-file.c 2020-05-20 18:47:21.282820662 -0400
-+++ b/scripts/sign-file.c 2020-05-20 18:48:37.991081899 -0400
-@@ -41,9 +41,10 @@
- * signing with anything other than SHA1 - so we're stuck with that if such is
- * the case.
- */
--#if defined(LIBRESSL_VERSION_NUMBER) || \
-- OPENSSL_VERSION_NUMBER < 0x10000000L || \
-- defined(OPENSSL_NO_CMS)
-+#if defined(OPENSSL_NO_CMS) || \
-+ ( defined(LIBRESSL_VERSION_NUMBER) \
-+ && (LIBRESSL_VERSION_NUMBER < 0x3010000fL) ) || \
-+ OPENSSL_VERSION_NUMBER < 0x10000000L
- #define USE_PKCS7
- #endif
- #ifndef USE_PKCS7
diff --git a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/4567_distro-Gentoo-Kconfig.patch b/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/4567_distro-Gentoo-Kconfig.patch
deleted file mode 100644
index e754a3e6e459..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/4567_distro-Gentoo-Kconfig.patch
+++ /dev/null
@@ -1,169 +0,0 @@
---- a/Kconfig 2020-04-15 11:05:30.202413863 -0400
-+++ b/Kconfig 2020-04-15 10:37:45.683952949 -0400
-@@ -32,3 +32,5 @@ source "lib/Kconfig"
- source "lib/Kconfig.debug"
-
- source "Documentation/Kconfig"
-+
-+source "distro/Kconfig"
---- /dev/null 2020-09-24 03:06:47.590000000 -0400
-+++ b/distro/Kconfig 2020-09-24 11:31:29.403150624 -0400
-@@ -0,0 +1,158 @@
-+menu "Gentoo Linux"
-+
-+config GENTOO_LINUX
-+ bool "Gentoo Linux support"
-+
-+ default y
-+
-+ help
-+ In order to boot Gentoo Linux a minimal set of config settings needs to
-+ be enabled in the kernel; to avoid the users from having to enable them
-+ manually as part of a Gentoo Linux installation or a new clean config,
-+ we enable these config settings by default for convenience.
-+
-+ See the settings that become available for more details and fine-tuning.
-+
-+config GENTOO_LINUX_UDEV
-+ bool "Linux dynamic and persistent device naming (userspace devfs) support"
-+
-+ depends on GENTOO_LINUX
-+ default y if GENTOO_LINUX
-+
-+ select DEVTMPFS
-+ select TMPFS
-+ select UNIX
-+
-+ select MMU
-+ select SHMEM
-+
-+ help
-+ In order to boot Gentoo Linux a minimal set of config settings needs to
-+ be enabled in the kernel; to avoid the users from having to enable them
-+ manually as part of a Gentoo Linux installation or a new clean config,
-+ we enable these config settings by default for convenience.
-+
-+ Currently this only selects TMPFS, DEVTMPFS and their dependencies.
-+ TMPFS is enabled to maintain a tmpfs file system at /dev/shm, /run and
-+ /sys/fs/cgroup; DEVTMPFS to maintain a devtmpfs file system at /dev.
-+
-+ Some of these are critical files that need to be available early in the
-+ boot process; if not available, it causes sysfs and udev to malfunction.
-+
-+ To ensure Gentoo Linux boots, it is best to leave this setting enabled;
-+ if you run a custom setup, you could consider whether to disable this.
-+
-+config GENTOO_LINUX_PORTAGE
-+ bool "Select options required by Portage features"
-+
-+ depends on GENTOO_LINUX
-+ default y if GENTOO_LINUX
-+
-+ select CGROUPS
-+ select NAMESPACES
-+ select IPC_NS
-+ select NET_NS
-+ select PID_NS
-+ select SYSVIPC
-+ select UTS_NS
-+
-+ help
-+ This enables options required by various Portage FEATURES.
-+ Currently this selects:
-+
-+ CGROUPS (required for FEATURES=cgroup)
-+ IPC_NS (required for FEATURES=ipc-sandbox)
-+ NET_NS (required for FEATURES=network-sandbox)
-+ PID_NS (required for FEATURES=pid-sandbox)
-+ SYSVIPC (required by IPC_NS)
-+
-+
-+ It is highly recommended that you leave this enabled as these FEATURES
-+ are, or will soon be, enabled by default.
-+
-+menu "Support for init systems, system and service managers"
-+ visible if GENTOO_LINUX
-+
-+config GENTOO_LINUX_INIT_SCRIPT
-+ bool "OpenRC, runit and other script based systems and managers"
-+
-+ default y if GENTOO_LINUX
-+
-+ depends on GENTOO_LINUX
-+
-+ select BINFMT_SCRIPT
-+ select CGROUPS
-+ select EPOLL
-+ select FILE_LOCKING
-+ select INOTIFY_USER
-+ select SIGNALFD
-+ select TIMERFD
-+
-+ help
-+ The init system is the first thing that loads after the kernel booted.
-+
-+ These config settings allow you to select which init systems to support;
-+ instead of having to select all the individual settings all over the
-+ place, these settings allows you to select all the settings at once.
-+
-+ This particular setting enables all the known requirements for OpenRC,
-+ runit and similar script based systems and managers.
-+
-+ If you are unsure about this, it is best to leave this setting enabled.
-+
-+config GENTOO_LINUX_INIT_SYSTEMD
-+ bool "systemd"
-+
-+ default n
-+
-+ depends on GENTOO_LINUX && GENTOO_LINUX_UDEV
-+
-+ select AUTOFS4_FS
-+ select BLK_DEV_BSG
-+ select BPF_SYSCALL
-+ select CGROUP_BPF
-+ select CGROUPS
-+ select CHECKPOINT_RESTORE
-+ select CRYPTO_HMAC
-+ select CRYPTO_SHA256
-+ select CRYPTO_USER_API_HASH
-+ select DEVPTS_MULTIPLE_INSTANCES
-+ select DMIID if X86_32 || X86_64 || X86
-+ select EPOLL
-+ select FANOTIFY
-+ select FHANDLE
-+ select FILE_LOCKING
-+ select INOTIFY_USER
-+ select IPV6
-+ select NET
-+ select NET_NS
-+ select PROC_FS
-+ select SECCOMP
-+ select SECCOMP_FILTER
-+ select SIGNALFD
-+ select SYSFS
-+ select TIMERFD
-+ select TMPFS_POSIX_ACL
-+ select TMPFS_XATTR
-+ select USER_NS
-+
-+ select ANON_INODES
-+ select BLOCK
-+ select EVENTFD
-+ select FSNOTIFY
-+ select INET
-+ select NLATTR
-+
-+ help
-+ The init system is the first thing that loads after the kernel booted.
-+
-+ These config settings allow you to select which init systems to support;
-+ instead of having to select all the individual settings all over the
-+ place, these settings allows you to select all the settings at once.
-+
-+ This particular setting enables all the known requirements for systemd;
-+ it also enables suggested optional settings, as the package suggests to.
-+
-+endmenu
-+
-+endmenu
diff --git a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/5000_shiftfs-ubuntu-20.04.patch b/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/5000_shiftfs-ubuntu-20.04.patch
deleted file mode 100644
index 665fc660b0de..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/gentoo-patches/5000_shiftfs-ubuntu-20.04.patch
+++ /dev/null
@@ -1,2203 +0,0 @@
---- /dev/null 2021-01-08 13:33:13.190303432 -0500
-+++ b/fs/shiftfs.c 2021-01-08 19:02:40.000000000 -0500
-@@ -0,0 +1,2157 @@
-+#include <linux/btrfs.h>
-+#include <linux/capability.h>
-+#include <linux/cred.h>
-+#include <linux/mount.h>
-+#include <linux/fdtable.h>
-+#include <linux/file.h>
-+#include <linux/fs.h>
-+#include <linux/namei.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/magic.h>
-+#include <linux/parser.h>
-+#include <linux/security.h>
-+#include <linux/seq_file.h>
-+#include <linux/statfs.h>
-+#include <linux/slab.h>
-+#include <linux/user_namespace.h>
-+#include <linux/uidgid.h>
-+#include <linux/xattr.h>
-+#include <linux/posix_acl.h>
-+#include <linux/posix_acl_xattr.h>
-+#include <linux/uio.h>
-+#include <linux/fiemap.h>
-+
-+struct shiftfs_super_info {
-+ struct vfsmount *mnt;
-+ struct user_namespace *userns;
-+ /* creds of process who created the super block */
-+ const struct cred *creator_cred;
-+ bool mark;
-+ unsigned int passthrough;
-+ unsigned int passthrough_mark;
-+};
-+
-+static void shiftfs_fill_inode(struct inode *inode, unsigned long ino,
-+ umode_t mode, dev_t dev, struct dentry *dentry);
-+
-+#define SHIFTFS_PASSTHROUGH_NONE 0
-+#define SHIFTFS_PASSTHROUGH_STAT 1
-+#define SHIFTFS_PASSTHROUGH_IOCTL 2
-+#define SHIFTFS_PASSTHROUGH_ALL \
-+ (SHIFTFS_PASSTHROUGH_STAT | SHIFTFS_PASSTHROUGH_IOCTL)
-+
-+static inline bool shiftfs_passthrough_ioctls(struct shiftfs_super_info *info)
-+{
-+ if (!(info->passthrough & SHIFTFS_PASSTHROUGH_IOCTL))
-+ return false;
-+
-+ return true;
-+}
-+
-+static inline bool shiftfs_passthrough_statfs(struct shiftfs_super_info *info)
-+{
-+ if (!(info->passthrough & SHIFTFS_PASSTHROUGH_STAT))
-+ return false;
-+
-+ return true;
-+}
-+
-+enum {
-+ OPT_MARK,
-+ OPT_PASSTHROUGH,
-+ OPT_LAST,
-+};
-+
-+/* global filesystem options */
-+static const match_table_t tokens = {
-+ { OPT_MARK, "mark" },
-+ { OPT_PASSTHROUGH, "passthrough=%u" },
-+ { OPT_LAST, NULL }
-+};
-+
-+static const struct cred *shiftfs_override_creds(const struct super_block *sb)
-+{
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+
-+ return override_creds(sbinfo->creator_cred);
-+}
-+
-+static inline void shiftfs_revert_object_creds(const struct cred *oldcred,
-+ struct cred *newcred)
-+{
-+ revert_creds(oldcred);
-+ put_cred(newcred);
-+}
-+
-+static kuid_t shift_kuid(struct user_namespace *from, struct user_namespace *to,
-+ kuid_t kuid)
-+{
-+ uid_t uid = from_kuid(from, kuid);
-+ return make_kuid(to, uid);
-+}
-+
-+static kgid_t shift_kgid(struct user_namespace *from, struct user_namespace *to,
-+ kgid_t kgid)
-+{
-+ gid_t gid = from_kgid(from, kgid);
-+ return make_kgid(to, gid);
-+}
-+
-+static int shiftfs_override_object_creds(const struct super_block *sb,
-+ const struct cred **oldcred,
-+ struct cred **newcred,
-+ struct dentry *dentry, umode_t mode,
-+ bool hardlink)
-+{
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+ kuid_t fsuid = current_fsuid();
-+ kgid_t fsgid = current_fsgid();
-+
-+ *oldcred = shiftfs_override_creds(sb);
-+
-+ *newcred = prepare_creds();
-+ if (!*newcred) {
-+ revert_creds(*oldcred);
-+ return -ENOMEM;
-+ }
-+
-+ (*newcred)->fsuid = shift_kuid(sb->s_user_ns, sbinfo->userns, fsuid);
-+ (*newcred)->fsgid = shift_kgid(sb->s_user_ns, sbinfo->userns, fsgid);
-+
-+ if (!hardlink) {
-+ int err = security_dentry_create_files_as(dentry, mode,
-+ &dentry->d_name,
-+ *oldcred, *newcred);
-+ if (err) {
-+ shiftfs_revert_object_creds(*oldcred, *newcred);
-+ return err;
-+ }
-+ }
-+
-+ put_cred(override_creds(*newcred));
-+ return 0;
-+}
-+
-+static void shiftfs_copyattr(struct inode *from, struct inode *to)
-+{
-+ struct user_namespace *from_ns = from->i_sb->s_user_ns;
-+ struct user_namespace *to_ns = to->i_sb->s_user_ns;
-+
-+ to->i_uid = shift_kuid(from_ns, to_ns, from->i_uid);
-+ to->i_gid = shift_kgid(from_ns, to_ns, from->i_gid);
-+ to->i_mode = from->i_mode;
-+ to->i_atime = from->i_atime;
-+ to->i_mtime = from->i_mtime;
-+ to->i_ctime = from->i_ctime;
-+ i_size_write(to, i_size_read(from));
-+}
-+
-+static void shiftfs_copyflags(struct inode *from, struct inode *to)
-+{
-+ unsigned int mask = S_SYNC | S_IMMUTABLE | S_APPEND | S_NOATIME;
-+
-+ inode_set_flags(to, from->i_flags & mask, mask);
-+}
-+
-+static void shiftfs_file_accessed(struct file *file)
-+{
-+ struct inode *upperi, *loweri;
-+
-+ if (file->f_flags & O_NOATIME)
-+ return;
-+
-+ upperi = file_inode(file);
-+ loweri = upperi->i_private;
-+
-+ if (!loweri)
-+ return;
-+
-+ upperi->i_mtime = loweri->i_mtime;
-+ upperi->i_ctime = loweri->i_ctime;
-+
-+ touch_atime(&file->f_path);
-+}
-+
-+static int shiftfs_parse_mount_options(struct shiftfs_super_info *sbinfo,
-+ char *options)
-+{
-+ char *p;
-+ substring_t args[MAX_OPT_ARGS];
-+
-+ sbinfo->mark = false;
-+ sbinfo->passthrough = 0;
-+
-+ while ((p = strsep(&options, ",")) != NULL) {
-+ int err, intarg, token;
-+
-+ if (!*p)
-+ continue;
-+
-+ token = match_token(p, tokens, args);
-+ switch (token) {
-+ case OPT_MARK:
-+ sbinfo->mark = true;
-+ break;
-+ case OPT_PASSTHROUGH:
-+ err = match_int(&args[0], &intarg);
-+ if (err)
-+ return err;
-+
-+ if (intarg & ~SHIFTFS_PASSTHROUGH_ALL)
-+ return -EINVAL;
-+
-+ sbinfo->passthrough = intarg;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static void shiftfs_d_release(struct dentry *dentry)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+
-+ if (lowerd)
-+ dput(lowerd);
-+}
-+
-+static struct dentry *shiftfs_d_real(struct dentry *dentry,
-+ const struct inode *inode)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+
-+ if (inode && d_inode(dentry) == inode)
-+ return dentry;
-+
-+ lowerd = d_real(lowerd, inode);
-+ if (lowerd && (!inode || inode == d_inode(lowerd)))
-+ return lowerd;
-+
-+ WARN(1, "shiftfs_d_real(%pd4, %s:%lu): real dentry not found\n", dentry,
-+ inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0);
-+ return dentry;
-+}
-+
-+static int shiftfs_d_weak_revalidate(struct dentry *dentry, unsigned int flags)
-+{
-+ int err = 1;
-+ struct dentry *lowerd = dentry->d_fsdata;
-+
-+ if (d_is_negative(lowerd) != d_is_negative(dentry))
-+ return 0;
-+
-+ if ((lowerd->d_flags & DCACHE_OP_WEAK_REVALIDATE))
-+ err = lowerd->d_op->d_weak_revalidate(lowerd, flags);
-+
-+ if (d_really_is_positive(dentry)) {
-+ struct inode *inode = d_inode(dentry);
-+ struct inode *loweri = d_inode(lowerd);
-+
-+ shiftfs_copyattr(loweri, inode);
-+ }
-+
-+ return err;
-+}
-+
-+static int shiftfs_d_revalidate(struct dentry *dentry, unsigned int flags)
-+{
-+ int err = 1;
-+ struct dentry *lowerd = dentry->d_fsdata;
-+
-+ if (d_unhashed(lowerd) ||
-+ ((d_is_negative(lowerd) != d_is_negative(dentry))))
-+ return 0;
-+
-+ if (flags & LOOKUP_RCU)
-+ return -ECHILD;
-+
-+ if ((lowerd->d_flags & DCACHE_OP_REVALIDATE))
-+ err = lowerd->d_op->d_revalidate(lowerd, flags);
-+
-+ if (d_really_is_positive(dentry)) {
-+ struct inode *inode = d_inode(dentry);
-+ struct inode *loweri = d_inode(lowerd);
-+
-+ shiftfs_copyattr(loweri, inode);
-+ }
-+
-+ return err;
-+}
-+
-+static const struct dentry_operations shiftfs_dentry_ops = {
-+ .d_release = shiftfs_d_release,
-+ .d_real = shiftfs_d_real,
-+ .d_revalidate = shiftfs_d_revalidate,
-+ .d_weak_revalidate = shiftfs_d_weak_revalidate,
-+};
-+
-+static const char *shiftfs_get_link(struct dentry *dentry, struct inode *inode,
-+ struct delayed_call *done)
-+{
-+ const char *p;
-+ const struct cred *oldcred;
-+ struct dentry *lowerd;
-+
-+ /* RCU lookup not supported */
-+ if (!dentry)
-+ return ERR_PTR(-ECHILD);
-+
-+ lowerd = dentry->d_fsdata;
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ p = vfs_get_link(lowerd, done);
-+ revert_creds(oldcred);
-+
-+ return p;
-+}
-+
-+static int shiftfs_setxattr(struct dentry *dentry, struct inode *inode,
-+ const char *name, const void *value,
-+ size_t size, int flags)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ int err;
-+ const struct cred *oldcred;
-+
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ err = vfs_setxattr(lowerd, name, value, size, flags);
-+ revert_creds(oldcred);
-+
-+ shiftfs_copyattr(lowerd->d_inode, inode);
-+
-+ return err;
-+}
-+
-+static int shiftfs_xattr_get(const struct xattr_handler *handler,
-+ struct dentry *dentry, struct inode *inode,
-+ const char *name, void *value, size_t size)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ int err;
-+ const struct cred *oldcred;
-+
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ err = vfs_getxattr(lowerd, name, value, size);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+static ssize_t shiftfs_listxattr(struct dentry *dentry, char *list,
-+ size_t size)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ int err;
-+ const struct cred *oldcred;
-+
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ err = vfs_listxattr(lowerd, list, size);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+static int shiftfs_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ int err;
-+ const struct cred *oldcred;
-+
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ err = vfs_removexattr(lowerd, name);
-+ revert_creds(oldcred);
-+
-+ /* update c/mtime */
-+ shiftfs_copyattr(lowerd->d_inode, d_inode(dentry));
-+
-+ return err;
-+}
-+
-+static int shiftfs_xattr_set(const struct xattr_handler *handler,
-+ struct dentry *dentry, struct inode *inode,
-+ const char *name, const void *value, size_t size,
-+ int flags)
-+{
-+ if (!value)
-+ return shiftfs_removexattr(dentry, name);
-+ return shiftfs_setxattr(dentry, inode, name, value, size, flags);
-+}
-+
-+static int shiftfs_inode_test(struct inode *inode, void *data)
-+{
-+ return inode->i_private == data;
-+}
-+
-+static int shiftfs_inode_set(struct inode *inode, void *data)
-+{
-+ inode->i_private = data;
-+ return 0;
-+}
-+
-+static int shiftfs_create_object(struct inode *diri, struct dentry *dentry,
-+ umode_t mode, const char *symlink,
-+ struct dentry *hardlink, bool excl)
-+{
-+ int err;
-+ const struct cred *oldcred;
-+ struct cred *newcred;
-+ void *loweri_iop_ptr = NULL;
-+ umode_t modei = mode;
-+ struct super_block *dir_sb = diri->i_sb;
-+ struct dentry *lowerd_new = dentry->d_fsdata;
-+ struct inode *inode = NULL, *loweri_dir = diri->i_private;
-+ const struct inode_operations *loweri_dir_iop = loweri_dir->i_op;
-+ struct dentry *lowerd_link = NULL;
-+
-+ if (hardlink) {
-+ loweri_iop_ptr = loweri_dir_iop->link;
-+ } else {
-+ switch (mode & S_IFMT) {
-+ case S_IFDIR:
-+ loweri_iop_ptr = loweri_dir_iop->mkdir;
-+ break;
-+ case S_IFREG:
-+ loweri_iop_ptr = loweri_dir_iop->create;
-+ break;
-+ case S_IFLNK:
-+ loweri_iop_ptr = loweri_dir_iop->symlink;
-+ break;
-+ case S_IFSOCK:
-+ /* fall through */
-+ case S_IFIFO:
-+ loweri_iop_ptr = loweri_dir_iop->mknod;
-+ break;
-+ }
-+ }
-+ if (!loweri_iop_ptr) {
-+ err = -EINVAL;
-+ goto out_iput;
-+ }
-+
-+ inode_lock_nested(loweri_dir, I_MUTEX_PARENT);
-+
-+ if (!hardlink) {
-+ inode = new_inode(dir_sb);
-+ if (!inode) {
-+ err = -ENOMEM;
-+ goto out_iput;
-+ }
-+
-+ /*
-+ * new_inode() will have added the new inode to the super
-+ * block's list of inodes. Further below we will call
-+ * inode_insert5() Which would perform the same operation again
-+ * thereby corrupting the list. To avoid this raise I_CREATING
-+ * in i_state which will cause inode_insert5() to skip this
-+ * step. I_CREATING will be cleared by d_instantiate_new()
-+ * below.
-+ */
-+ spin_lock(&inode->i_lock);
-+ inode->i_state |= I_CREATING;
-+ spin_unlock(&inode->i_lock);
-+
-+ inode_init_owner(inode, diri, mode);
-+ modei = inode->i_mode;
-+ }
-+
-+ err = shiftfs_override_object_creds(dentry->d_sb, &oldcred, &newcred,
-+ dentry, modei, hardlink != NULL);
-+ if (err)
-+ goto out_iput;
-+
-+ if (hardlink) {
-+ lowerd_link = hardlink->d_fsdata;
-+ err = vfs_link(lowerd_link, loweri_dir, lowerd_new, NULL);
-+ } else {
-+ switch (modei & S_IFMT) {
-+ case S_IFDIR:
-+ err = vfs_mkdir(loweri_dir, lowerd_new, modei);
-+ break;
-+ case S_IFREG:
-+ err = vfs_create(loweri_dir, lowerd_new, modei, excl);
-+ break;
-+ case S_IFLNK:
-+ err = vfs_symlink(loweri_dir, lowerd_new, symlink);
-+ break;
-+ case S_IFSOCK:
-+ /* fall through */
-+ case S_IFIFO:
-+ err = vfs_mknod(loweri_dir, lowerd_new, modei, 0);
-+ break;
-+ default:
-+ err = -EINVAL;
-+ break;
-+ }
-+ }
-+
-+ shiftfs_revert_object_creds(oldcred, newcred);
-+
-+ if (!err && WARN_ON(!lowerd_new->d_inode))
-+ err = -EIO;
-+ if (err)
-+ goto out_iput;
-+
-+ if (hardlink) {
-+ inode = d_inode(hardlink);
-+ ihold(inode);
-+
-+ /* copy up times from lower inode */
-+ shiftfs_copyattr(d_inode(lowerd_link), inode);
-+ set_nlink(d_inode(hardlink), d_inode(lowerd_link)->i_nlink);
-+ d_instantiate(dentry, inode);
-+ } else {
-+ struct inode *inode_tmp;
-+ struct inode *loweri_new = d_inode(lowerd_new);
-+
-+ inode_tmp = inode_insert5(inode, (unsigned long)loweri_new,
-+ shiftfs_inode_test, shiftfs_inode_set,
-+ loweri_new);
-+ if (unlikely(inode_tmp != inode)) {
-+ pr_err_ratelimited("shiftfs: newly created inode found in cache\n");
-+ iput(inode_tmp);
-+ err = -EINVAL;
-+ goto out_iput;
-+ }
-+
-+ ihold(loweri_new);
-+ shiftfs_fill_inode(inode, loweri_new->i_ino, loweri_new->i_mode,
-+ 0, lowerd_new);
-+ d_instantiate_new(dentry, inode);
-+ }
-+
-+ shiftfs_copyattr(loweri_dir, diri);
-+ if (loweri_iop_ptr == loweri_dir_iop->mkdir)
-+ set_nlink(diri, loweri_dir->i_nlink);
-+
-+ inode = NULL;
-+
-+out_iput:
-+ iput(inode);
-+ inode_unlock(loweri_dir);
-+
-+ return err;
-+}
-+
-+static int shiftfs_create(struct inode *dir, struct dentry *dentry,
-+ umode_t mode, bool excl)
-+{
-+ mode |= S_IFREG;
-+
-+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, excl);
-+}
-+
-+static int shiftfs_mkdir(struct inode *dir, struct dentry *dentry,
-+ umode_t mode)
-+{
-+ mode |= S_IFDIR;
-+
-+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, false);
-+}
-+
-+static int shiftfs_link(struct dentry *hardlink, struct inode *dir,
-+ struct dentry *dentry)
-+{
-+ return shiftfs_create_object(dir, dentry, 0, NULL, hardlink, false);
-+}
-+
-+static int shiftfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
-+ dev_t rdev)
-+{
-+ if (!S_ISFIFO(mode) && !S_ISSOCK(mode))
-+ return -EPERM;
-+
-+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, false);
-+}
-+
-+static int shiftfs_symlink(struct inode *dir, struct dentry *dentry,
-+ const char *symlink)
-+{
-+ return shiftfs_create_object(dir, dentry, S_IFLNK, symlink, NULL, false);
-+}
-+
-+static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ struct inode *loweri = dir->i_private;
-+ struct inode *inode = d_inode(dentry);
-+ int err;
-+ const struct cred *oldcred;
-+
-+ dget(lowerd);
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ inode_lock_nested(loweri, I_MUTEX_PARENT);
-+ if (rmdir)
-+ err = vfs_rmdir(loweri, lowerd);
-+ else
-+ err = vfs_unlink(loweri, lowerd, NULL);
-+ revert_creds(oldcred);
-+
-+ if (!err) {
-+ d_drop(dentry);
-+
-+ if (rmdir)
-+ clear_nlink(inode);
-+ else
-+ drop_nlink(inode);
-+ }
-+ inode_unlock(loweri);
-+
-+ shiftfs_copyattr(loweri, dir);
-+ dput(lowerd);
-+
-+ return err;
-+}
-+
-+static int shiftfs_unlink(struct inode *dir, struct dentry *dentry)
-+{
-+ return shiftfs_rm(dir, dentry, false);
-+}
-+
-+static int shiftfs_rmdir(struct inode *dir, struct dentry *dentry)
-+{
-+ return shiftfs_rm(dir, dentry, true);
-+}
-+
-+static int shiftfs_rename(struct inode *olddir, struct dentry *old,
-+ struct inode *newdir, struct dentry *new,
-+ unsigned int flags)
-+{
-+ struct dentry *lowerd_dir_old = old->d_parent->d_fsdata,
-+ *lowerd_dir_new = new->d_parent->d_fsdata,
-+ *lowerd_old = old->d_fsdata, *lowerd_new = new->d_fsdata,
-+ *trapd;
-+ struct inode *loweri_dir_old = lowerd_dir_old->d_inode,
-+ *loweri_dir_new = lowerd_dir_new->d_inode;
-+ int err = -EINVAL;
-+ const struct cred *oldcred;
-+
-+ trapd = lock_rename(lowerd_dir_new, lowerd_dir_old);
-+
-+ if (trapd == lowerd_old || trapd == lowerd_new)
-+ goto out_unlock;
-+
-+ oldcred = shiftfs_override_creds(old->d_sb);
-+ err = vfs_rename(loweri_dir_old, lowerd_old, loweri_dir_new, lowerd_new,
-+ NULL, flags);
-+ revert_creds(oldcred);
-+
-+ shiftfs_copyattr(loweri_dir_old, olddir);
-+ shiftfs_copyattr(loweri_dir_new, newdir);
-+
-+out_unlock:
-+ unlock_rename(lowerd_dir_new, lowerd_dir_old);
-+
-+ return err;
-+}
-+
-+static struct dentry *shiftfs_lookup(struct inode *dir, struct dentry *dentry,
-+ unsigned int flags)
-+{
-+ struct dentry *new;
-+ struct inode *newi;
-+ const struct cred *oldcred;
-+ struct dentry *lowerd = dentry->d_parent->d_fsdata;
-+ struct inode *inode = NULL, *loweri = lowerd->d_inode;
-+
-+ inode_lock(loweri);
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ new = lookup_one_len(dentry->d_name.name, lowerd, dentry->d_name.len);
-+ revert_creds(oldcred);
-+ inode_unlock(loweri);
-+
-+ if (IS_ERR(new))
-+ return new;
-+
-+ dentry->d_fsdata = new;
-+
-+ newi = new->d_inode;
-+ if (!newi)
-+ goto out;
-+
-+ inode = iget5_locked(dentry->d_sb, (unsigned long)newi,
-+ shiftfs_inode_test, shiftfs_inode_set, newi);
-+ if (!inode) {
-+ dput(new);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+ if (inode->i_state & I_NEW) {
-+ /*
-+ * inode->i_private set by shiftfs_inode_set(), but we still
-+ * need to take a reference
-+ */
-+ ihold(newi);
-+ shiftfs_fill_inode(inode, newi->i_ino, newi->i_mode, 0, new);
-+ unlock_new_inode(inode);
-+ }
-+
-+out:
-+ return d_splice_alias(inode, dentry);
-+}
-+
-+static int shiftfs_permission(struct inode *inode, int mask)
-+{
-+ int err;
-+ const struct cred *oldcred;
-+ struct inode *loweri = inode->i_private;
-+
-+ if (!loweri) {
-+ WARN_ON(!(mask & MAY_NOT_BLOCK));
-+ return -ECHILD;
-+ }
-+
-+ err = generic_permission(inode, mask);
-+ if (err)
-+ return err;
-+
-+ oldcred = shiftfs_override_creds(inode->i_sb);
-+ err = inode_permission(loweri, mask);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+static int shiftfs_fiemap(struct inode *inode,
-+ struct fiemap_extent_info *fieinfo, u64 start,
-+ u64 len)
-+{
-+ int err;
-+ const struct cred *oldcred;
-+ struct inode *loweri = inode->i_private;
-+
-+ if (!loweri->i_op->fiemap)
-+ return -EOPNOTSUPP;
-+
-+ oldcred = shiftfs_override_creds(inode->i_sb);
-+ if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC)
-+ filemap_write_and_wait(loweri->i_mapping);
-+ err = loweri->i_op->fiemap(loweri, fieinfo, start, len);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+static int shiftfs_tmpfile(struct inode *dir, struct dentry *dentry,
-+ umode_t mode)
-+{
-+ int err;
-+ const struct cred *oldcred;
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ struct inode *loweri = dir->i_private;
-+
-+ if (!loweri->i_op->tmpfile)
-+ return -EOPNOTSUPP;
-+
-+ oldcred = shiftfs_override_creds(dir->i_sb);
-+ err = loweri->i_op->tmpfile(loweri, lowerd, mode);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ struct inode *loweri = lowerd->d_inode;
-+ struct iattr newattr;
-+ const struct cred *oldcred;
-+ struct super_block *sb = dentry->d_sb;
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+ int err;
-+
-+ err = setattr_prepare(dentry, attr);
-+ if (err)
-+ return err;
-+
-+ newattr = *attr;
-+ newattr.ia_uid = shift_kuid(sb->s_user_ns, sbinfo->userns, attr->ia_uid);
-+ newattr.ia_gid = shift_kgid(sb->s_user_ns, sbinfo->userns, attr->ia_gid);
-+
-+ /*
-+ * mode change is for clearing setuid/setgid bits. Allow lower fs
-+ * to interpret this in its own way.
-+ */
-+ if (newattr.ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
-+ newattr.ia_valid &= ~ATTR_MODE;
-+
-+ inode_lock(loweri);
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ err = notify_change(lowerd, &newattr, NULL);
-+ revert_creds(oldcred);
-+ inode_unlock(loweri);
-+
-+ shiftfs_copyattr(loweri, d_inode(dentry));
-+
-+ return err;
-+}
-+
-+static int shiftfs_getattr(const struct path *path, struct kstat *stat,
-+ u32 request_mask, unsigned int query_flags)
-+{
-+ struct inode *inode = path->dentry->d_inode;
-+ struct dentry *lowerd = path->dentry->d_fsdata;
-+ struct inode *loweri = lowerd->d_inode;
-+ struct shiftfs_super_info *info = path->dentry->d_sb->s_fs_info;
-+ struct path newpath = { .mnt = info->mnt, .dentry = lowerd };
-+ struct user_namespace *from_ns = loweri->i_sb->s_user_ns;
-+ struct user_namespace *to_ns = inode->i_sb->s_user_ns;
-+ const struct cred *oldcred;
-+ int err;
-+
-+ oldcred = shiftfs_override_creds(inode->i_sb);
-+ err = vfs_getattr(&newpath, stat, request_mask, query_flags);
-+ revert_creds(oldcred);
-+
-+ if (err)
-+ return err;
-+
-+ /* transform the underlying id */
-+ stat->uid = shift_kuid(from_ns, to_ns, stat->uid);
-+ stat->gid = shift_kgid(from_ns, to_ns, stat->gid);
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SHIFT_FS_POSIX_ACL
-+
-+static int
-+shift_acl_ids(struct user_namespace *from, struct user_namespace *to,
-+ struct posix_acl *acl)
-+{
-+ int i;
-+
-+ for (i = 0; i < acl->a_count; i++) {
-+ struct posix_acl_entry *e = &acl->a_entries[i];
-+ switch(e->e_tag) {
-+ case ACL_USER:
-+ e->e_uid = shift_kuid(from, to, e->e_uid);
-+ if (!uid_valid(e->e_uid))
-+ return -EOVERFLOW;
-+ break;
-+ case ACL_GROUP:
-+ e->e_gid = shift_kgid(from, to, e->e_gid);
-+ if (!gid_valid(e->e_gid))
-+ return -EOVERFLOW;
-+ break;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static void
-+shift_acl_xattr_ids(struct user_namespace *from, struct user_namespace *to,
-+ void *value, size_t size)
-+{
-+ struct posix_acl_xattr_header *header = value;
-+ struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
-+ int count;
-+ kuid_t kuid;
-+ kgid_t kgid;
-+
-+ if (!value)
-+ return;
-+ if (size < sizeof(struct posix_acl_xattr_header))
-+ return;
-+ if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
-+ return;
-+
-+ count = posix_acl_xattr_count(size);
-+ if (count < 0)
-+ return;
-+ if (count == 0)
-+ return;
-+
-+ for (end = entry + count; entry != end; entry++) {
-+ switch(le16_to_cpu(entry->e_tag)) {
-+ case ACL_USER:
-+ kuid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id));
-+ kuid = shift_kuid(from, to, kuid);
-+ entry->e_id = cpu_to_le32(from_kuid(&init_user_ns, kuid));
-+ break;
-+ case ACL_GROUP:
-+ kgid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id));
-+ kgid = shift_kgid(from, to, kgid);
-+ entry->e_id = cpu_to_le32(from_kgid(&init_user_ns, kgid));
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+}
-+
-+static struct posix_acl *shiftfs_get_acl(struct inode *inode, int type)
-+{
-+ struct inode *loweri = inode->i_private;
-+ const struct cred *oldcred;
-+ struct posix_acl *lower_acl, *acl = NULL;
-+ struct user_namespace *from_ns = loweri->i_sb->s_user_ns;
-+ struct user_namespace *to_ns = inode->i_sb->s_user_ns;
-+ int size;
-+ int err;
-+
-+ if (!IS_POSIXACL(loweri))
-+ return NULL;
-+
-+ oldcred = shiftfs_override_creds(inode->i_sb);
-+ lower_acl = get_acl(loweri, type);
-+ revert_creds(oldcred);
-+
-+ if (lower_acl && !IS_ERR(lower_acl)) {
-+ /* XXX: export posix_acl_clone? */
-+ size = sizeof(struct posix_acl) +
-+ lower_acl->a_count * sizeof(struct posix_acl_entry);
-+ acl = kmemdup(lower_acl, size, GFP_KERNEL);
-+ posix_acl_release(lower_acl);
-+
-+ if (!acl)
-+ return ERR_PTR(-ENOMEM);
-+
-+ refcount_set(&acl->a_refcount, 1);
-+
-+ err = shift_acl_ids(from_ns, to_ns, acl);
-+ if (err) {
-+ kfree(acl);
-+ return ERR_PTR(err);
-+ }
-+ }
-+
-+ return acl;
-+}
-+
-+static int
-+shiftfs_posix_acl_xattr_get(const struct xattr_handler *handler,
-+ struct dentry *dentry, struct inode *inode,
-+ const char *name, void *buffer, size_t size)
-+{
-+ struct inode *loweri = inode->i_private;
-+ int ret;
-+
-+ ret = shiftfs_xattr_get(NULL, dentry, inode, handler->name,
-+ buffer, size);
-+ if (ret < 0)
-+ return ret;
-+
-+ inode_lock(loweri);
-+ shift_acl_xattr_ids(loweri->i_sb->s_user_ns, inode->i_sb->s_user_ns,
-+ buffer, size);
-+ inode_unlock(loweri);
-+ return ret;
-+}
-+
-+static int
-+shiftfs_posix_acl_xattr_set(const struct xattr_handler *handler,
-+ struct dentry *dentry, struct inode *inode,
-+ const char *name, const void *value,
-+ size_t size, int flags)
-+{
-+ struct inode *loweri = inode->i_private;
-+ int err;
-+
-+ if (!IS_POSIXACL(loweri) || !loweri->i_op->set_acl)
-+ return -EOPNOTSUPP;
-+ if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
-+ return value ? -EACCES : 0;
-+ if (!inode_owner_or_capable(inode))
-+ return -EPERM;
-+
-+ if (value) {
-+ shift_acl_xattr_ids(inode->i_sb->s_user_ns,
-+ loweri->i_sb->s_user_ns,
-+ (void *)value, size);
-+ err = shiftfs_setxattr(dentry, inode, handler->name, value,
-+ size, flags);
-+ } else {
-+ err = shiftfs_removexattr(dentry, handler->name);
-+ }
-+
-+ if (!err)
-+ shiftfs_copyattr(loweri, inode);
-+
-+ return err;
-+}
-+
-+static const struct xattr_handler
-+shiftfs_posix_acl_access_xattr_handler = {
-+ .name = XATTR_NAME_POSIX_ACL_ACCESS,
-+ .flags = ACL_TYPE_ACCESS,
-+ .get = shiftfs_posix_acl_xattr_get,
-+ .set = shiftfs_posix_acl_xattr_set,
-+};
-+
-+static const struct xattr_handler
-+shiftfs_posix_acl_default_xattr_handler = {
-+ .name = XATTR_NAME_POSIX_ACL_DEFAULT,
-+ .flags = ACL_TYPE_DEFAULT,
-+ .get = shiftfs_posix_acl_xattr_get,
-+ .set = shiftfs_posix_acl_xattr_set,
-+};
-+
-+#else /* !CONFIG_SHIFT_FS_POSIX_ACL */
-+
-+#define shiftfs_get_acl NULL
-+
-+#endif /* CONFIG_SHIFT_FS_POSIX_ACL */
-+
-+static const struct inode_operations shiftfs_dir_inode_operations = {
-+ .lookup = shiftfs_lookup,
-+ .mkdir = shiftfs_mkdir,
-+ .symlink = shiftfs_symlink,
-+ .unlink = shiftfs_unlink,
-+ .rmdir = shiftfs_rmdir,
-+ .rename = shiftfs_rename,
-+ .link = shiftfs_link,
-+ .setattr = shiftfs_setattr,
-+ .create = shiftfs_create,
-+ .mknod = shiftfs_mknod,
-+ .permission = shiftfs_permission,
-+ .getattr = shiftfs_getattr,
-+ .listxattr = shiftfs_listxattr,
-+ .get_acl = shiftfs_get_acl,
-+};
-+
-+static const struct inode_operations shiftfs_file_inode_operations = {
-+ .fiemap = shiftfs_fiemap,
-+ .getattr = shiftfs_getattr,
-+ .get_acl = shiftfs_get_acl,
-+ .listxattr = shiftfs_listxattr,
-+ .permission = shiftfs_permission,
-+ .setattr = shiftfs_setattr,
-+ .tmpfile = shiftfs_tmpfile,
-+};
-+
-+static const struct inode_operations shiftfs_special_inode_operations = {
-+ .getattr = shiftfs_getattr,
-+ .get_acl = shiftfs_get_acl,
-+ .listxattr = shiftfs_listxattr,
-+ .permission = shiftfs_permission,
-+ .setattr = shiftfs_setattr,
-+};
-+
-+static const struct inode_operations shiftfs_symlink_inode_operations = {
-+ .getattr = shiftfs_getattr,
-+ .get_link = shiftfs_get_link,
-+ .listxattr = shiftfs_listxattr,
-+ .setattr = shiftfs_setattr,
-+};
-+
-+static struct file *shiftfs_open_realfile(const struct file *file,
-+ struct inode *realinode)
-+{
-+ struct file *realfile;
-+ const struct cred *old_cred;
-+ struct inode *inode = file_inode(file);
-+ struct dentry *lowerd = file->f_path.dentry->d_fsdata;
-+ struct shiftfs_super_info *info = inode->i_sb->s_fs_info;
-+ struct path realpath = { .mnt = info->mnt, .dentry = lowerd };
-+
-+ old_cred = shiftfs_override_creds(inode->i_sb);
-+ realfile = open_with_fake_path(&realpath, file->f_flags, realinode,
-+ info->creator_cred);
-+ revert_creds(old_cred);
-+
-+ return realfile;
-+}
-+
-+#define SHIFTFS_SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT)
-+
-+static int shiftfs_change_flags(struct file *file, unsigned int flags)
-+{
-+ struct inode *inode = file_inode(file);
-+ int err;
-+
-+ /* if some flag changed that cannot be changed then something's amiss */
-+ if (WARN_ON((file->f_flags ^ flags) & ~SHIFTFS_SETFL_MASK))
-+ return -EIO;
-+
-+ flags &= SHIFTFS_SETFL_MASK;
-+
-+ if (((flags ^ file->f_flags) & O_APPEND) && IS_APPEND(inode))
-+ return -EPERM;
-+
-+ if (flags & O_DIRECT) {
-+ if (!file->f_mapping->a_ops ||
-+ !file->f_mapping->a_ops->direct_IO)
-+ return -EINVAL;
-+ }
-+
-+ if (file->f_op->check_flags) {
-+ err = file->f_op->check_flags(flags);
-+ if (err)
-+ return err;
-+ }
-+
-+ spin_lock(&file->f_lock);
-+ file->f_flags = (file->f_flags & ~SHIFTFS_SETFL_MASK) | flags;
-+ spin_unlock(&file->f_lock);
-+
-+ return 0;
-+}
-+
-+static int shiftfs_open(struct inode *inode, struct file *file)
-+{
-+ struct file *realfile;
-+
-+ realfile = shiftfs_open_realfile(file, inode->i_private);
-+ if (IS_ERR(realfile))
-+ return PTR_ERR(realfile);
-+
-+ file->private_data = realfile;
-+ /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO. */
-+ file->f_mapping = realfile->f_mapping;
-+
-+ return 0;
-+}
-+
-+static int shiftfs_dir_open(struct inode *inode, struct file *file)
-+{
-+ struct file *realfile;
-+ const struct cred *oldcred;
-+ struct dentry *lowerd = file->f_path.dentry->d_fsdata;
-+ struct shiftfs_super_info *info = inode->i_sb->s_fs_info;
-+ struct path realpath = { .mnt = info->mnt, .dentry = lowerd };
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ realfile = dentry_open(&realpath, file->f_flags | O_NOATIME,
-+ info->creator_cred);
-+ revert_creds(oldcred);
-+ if (IS_ERR(realfile))
-+ return PTR_ERR(realfile);
-+
-+ file->private_data = realfile;
-+
-+ return 0;
-+}
-+
-+static int shiftfs_release(struct inode *inode, struct file *file)
-+{
-+ struct file *realfile = file->private_data;
-+
-+ if (realfile)
-+ fput(realfile);
-+
-+ return 0;
-+}
-+
-+static int shiftfs_dir_release(struct inode *inode, struct file *file)
-+{
-+ return shiftfs_release(inode, file);
-+}
-+
-+static loff_t shiftfs_dir_llseek(struct file *file, loff_t offset, int whence)
-+{
-+ struct file *realfile = file->private_data;
-+
-+ return vfs_llseek(realfile, offset, whence);
-+}
-+
-+static loff_t shiftfs_file_llseek(struct file *file, loff_t offset, int whence)
-+{
-+ struct inode *realinode = file_inode(file)->i_private;
-+
-+ return generic_file_llseek_size(file, offset, whence,
-+ realinode->i_sb->s_maxbytes,
-+ i_size_read(realinode));
-+}
-+
-+/* XXX: Need to figure out what to to about atime updates, maybe other
-+ * timestamps too ... ref. ovl_file_accessed() */
-+
-+static rwf_t shiftfs_iocb_to_rwf(struct kiocb *iocb)
-+{
-+ int ifl = iocb->ki_flags;
-+ rwf_t flags = 0;
-+
-+ if (ifl & IOCB_NOWAIT)
-+ flags |= RWF_NOWAIT;
-+ if (ifl & IOCB_HIPRI)
-+ flags |= RWF_HIPRI;
-+ if (ifl & IOCB_DSYNC)
-+ flags |= RWF_DSYNC;
-+ if (ifl & IOCB_SYNC)
-+ flags |= RWF_SYNC;
-+
-+ return flags;
-+}
-+
-+static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd)
-+{
-+ struct file *realfile;
-+
-+ if (file->f_op->open != shiftfs_open &&
-+ file->f_op->open != shiftfs_dir_open)
-+ return -EINVAL;
-+
-+ realfile = file->private_data;
-+ lowerfd->flags = 0;
-+ lowerfd->file = realfile;
-+
-+ /* Did the flags change since open? */
-+ if (unlikely(file->f_flags & ~lowerfd->file->f_flags))
-+ return shiftfs_change_flags(lowerfd->file, file->f_flags);
-+
-+ return 0;
-+}
-+
-+static ssize_t shiftfs_read_iter(struct kiocb *iocb, struct iov_iter *iter)
-+{
-+ struct file *file = iocb->ki_filp;
-+ struct fd lowerfd;
-+ const struct cred *oldcred;
-+ ssize_t ret;
-+
-+ if (!iov_iter_count(iter))
-+ return 0;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ return ret;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ ret = vfs_iter_read(lowerfd.file, iter, &iocb->ki_pos,
-+ shiftfs_iocb_to_rwf(iocb));
-+ revert_creds(oldcred);
-+
-+ shiftfs_file_accessed(file);
-+
-+ fdput(lowerfd);
-+ return ret;
-+}
-+
-+static ssize_t shiftfs_write_iter(struct kiocb *iocb, struct iov_iter *iter)
-+{
-+ struct file *file = iocb->ki_filp;
-+ struct inode *inode = file_inode(file);
-+ struct fd lowerfd;
-+ const struct cred *oldcred;
-+ ssize_t ret;
-+
-+ if (!iov_iter_count(iter))
-+ return 0;
-+
-+ inode_lock(inode);
-+ /* Update mode */
-+ shiftfs_copyattr(inode->i_private, inode);
-+ ret = file_remove_privs(file);
-+ if (ret)
-+ goto out_unlock;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ goto out_unlock;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ file_start_write(lowerfd.file);
-+ ret = vfs_iter_write(lowerfd.file, iter, &iocb->ki_pos,
-+ shiftfs_iocb_to_rwf(iocb));
-+ file_end_write(lowerfd.file);
-+ revert_creds(oldcred);
-+
-+ /* Update size */
-+ shiftfs_copyattr(inode->i_private, inode);
-+
-+ fdput(lowerfd);
-+
-+out_unlock:
-+ inode_unlock(inode);
-+ return ret;
-+}
-+
-+static int shiftfs_fsync(struct file *file, loff_t start, loff_t end,
-+ int datasync)
-+{
-+ struct fd lowerfd;
-+ const struct cred *oldcred;
-+ int ret;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ return ret;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ ret = vfs_fsync_range(lowerfd.file, start, end, datasync);
-+ revert_creds(oldcred);
-+
-+ fdput(lowerfd);
-+ return ret;
-+}
-+
-+static int shiftfs_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ struct file *realfile = file->private_data;
-+ const struct cred *oldcred;
-+ int ret;
-+
-+ if (!realfile->f_op->mmap)
-+ return -ENODEV;
-+
-+ if (WARN_ON(file != vma->vm_file))
-+ return -EIO;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ vma->vm_file = get_file(realfile);
-+ ret = call_mmap(vma->vm_file, vma);
-+ revert_creds(oldcred);
-+
-+ shiftfs_file_accessed(file);
-+
-+ if (ret) {
-+ /*
-+ * Drop refcount from new vm_file value and restore original
-+ * vm_file value
-+ */
-+ vma->vm_file = file;
-+ fput(realfile);
-+ } else {
-+ /* Drop refcount from previous vm_file value */
-+ fput(file);
-+ }
-+
-+ return ret;
-+}
-+
-+static long shiftfs_fallocate(struct file *file, int mode, loff_t offset,
-+ loff_t len)
-+{
-+ struct inode *inode = file_inode(file);
-+ struct inode *loweri = inode->i_private;
-+ struct fd lowerfd;
-+ const struct cred *oldcred;
-+ int ret;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ return ret;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ ret = vfs_fallocate(lowerfd.file, mode, offset, len);
-+ revert_creds(oldcred);
-+
-+ /* Update size */
-+ shiftfs_copyattr(loweri, inode);
-+
-+ fdput(lowerfd);
-+ return ret;
-+}
-+
-+static int shiftfs_fadvise(struct file *file, loff_t offset, loff_t len,
-+ int advice)
-+{
-+ struct fd lowerfd;
-+ const struct cred *oldcred;
-+ int ret;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ return ret;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ ret = vfs_fadvise(lowerfd.file, offset, len, advice);
-+ revert_creds(oldcred);
-+
-+ fdput(lowerfd);
-+ return ret;
-+}
-+
-+static int shiftfs_override_ioctl_creds(int cmd, const struct super_block *sb,
-+ const struct cred **oldcred,
-+ struct cred **newcred)
-+{
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+ kuid_t fsuid = current_fsuid();
-+ kgid_t fsgid = current_fsgid();
-+
-+ *oldcred = shiftfs_override_creds(sb);
-+
-+ *newcred = prepare_creds();
-+ if (!*newcred) {
-+ revert_creds(*oldcred);
-+ return -ENOMEM;
-+ }
-+
-+ (*newcred)->fsuid = shift_kuid(sb->s_user_ns, sbinfo->userns, fsuid);
-+ (*newcred)->fsgid = shift_kgid(sb->s_user_ns, sbinfo->userns, fsgid);
-+
-+ /* clear all caps to prevent bypassing capable() checks */
-+ cap_clear((*newcred)->cap_bset);
-+ cap_clear((*newcred)->cap_effective);
-+ cap_clear((*newcred)->cap_inheritable);
-+ cap_clear((*newcred)->cap_permitted);
-+
-+ if (cmd == BTRFS_IOC_SNAP_DESTROY) {
-+ kuid_t kuid_root = make_kuid(sb->s_user_ns, 0);
-+ /*
-+ * Allow the root user in the container to remove subvolumes
-+ * from other users.
-+ */
-+ if (uid_valid(kuid_root) && uid_eq(fsuid, kuid_root))
-+ cap_raise((*newcred)->cap_effective, CAP_DAC_OVERRIDE);
-+ }
-+
-+ put_cred(override_creds(*newcred));
-+ return 0;
-+}
-+
-+static inline void shiftfs_revert_ioctl_creds(const struct cred *oldcred,
-+ struct cred *newcred)
-+{
-+ return shiftfs_revert_object_creds(oldcred, newcred);
-+}
-+
-+static inline bool is_btrfs_snap_ioctl(int cmd)
-+{
-+ if ((cmd == BTRFS_IOC_SNAP_CREATE) || (cmd == BTRFS_IOC_SNAP_CREATE_V2))
-+ return true;
-+
-+ return false;
-+}
-+
-+static int shiftfs_btrfs_ioctl_fd_restore(int cmd, int fd, void __user *arg,
-+ struct btrfs_ioctl_vol_args *v1,
-+ struct btrfs_ioctl_vol_args_v2 *v2)
-+{
-+ int ret;
-+
-+ if (!is_btrfs_snap_ioctl(cmd))
-+ return 0;
-+
-+ if (cmd == BTRFS_IOC_SNAP_CREATE)
-+ ret = copy_to_user(arg, v1, sizeof(*v1));
-+ else
-+ ret = copy_to_user(arg, v2, sizeof(*v2));
-+
-+ __close_fd(current->files, fd);
-+ kfree(v1);
-+ kfree(v2);
-+
-+ return ret;
-+}
-+
-+static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
-+ struct btrfs_ioctl_vol_args **b1,
-+ struct btrfs_ioctl_vol_args_v2 **b2,
-+ int *newfd)
-+{
-+ int oldfd, ret;
-+ struct fd src;
-+ struct fd lfd = {};
-+ struct btrfs_ioctl_vol_args *v1 = NULL;
-+ struct btrfs_ioctl_vol_args_v2 *v2 = NULL;
-+
-+ if (!is_btrfs_snap_ioctl(cmd))
-+ return 0;
-+
-+ if (cmd == BTRFS_IOC_SNAP_CREATE) {
-+ v1 = memdup_user(arg, sizeof(*v1));
-+ if (IS_ERR(v1))
-+ return PTR_ERR(v1);
-+ oldfd = v1->fd;
-+ *b1 = v1;
-+ } else {
-+ v2 = memdup_user(arg, sizeof(*v2));
-+ if (IS_ERR(v2))
-+ return PTR_ERR(v2);
-+ oldfd = v2->fd;
-+ *b2 = v2;
-+ }
-+
-+ src = fdget(oldfd);
-+ if (!src.file)
-+ return -EINVAL;
-+
-+ ret = shiftfs_real_fdget(src.file, &lfd);
-+ if (ret) {
-+ fdput(src);
-+ return ret;
-+ }
-+
-+ /*
-+ * shiftfs_real_fdget() does not take a reference to lfd.file, so
-+ * take a reference here to offset the one which will be put by
-+ * __close_fd(), and make sure that reference is put on fdput(lfd).
-+ */
-+ get_file(lfd.file);
-+ lfd.flags |= FDPUT_FPUT;
-+ fdput(src);
-+
-+ *newfd = get_unused_fd_flags(lfd.file->f_flags);
-+ if (*newfd < 0) {
-+ fdput(lfd);
-+ return *newfd;
-+ }
-+
-+ fd_install(*newfd, lfd.file);
-+
-+ if (cmd == BTRFS_IOC_SNAP_CREATE) {
-+ v1->fd = *newfd;
-+ ret = copy_to_user(arg, v1, sizeof(*v1));
-+ v1->fd = oldfd;
-+ } else {
-+ v2->fd = *newfd;
-+ ret = copy_to_user(arg, v2, sizeof(*v2));
-+ v2->fd = oldfd;
-+ }
-+
-+ if (ret)
-+ shiftfs_btrfs_ioctl_fd_restore(cmd, *newfd, arg, v1, v2);
-+
-+ return ret;
-+}
-+
-+static long shiftfs_real_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ struct fd lowerfd;
-+ struct cred *newcred;
-+ const struct cred *oldcred;
-+ int newfd = -EBADF;
-+ long err = 0, ret = 0;
-+ void __user *argp = (void __user *)arg;
-+ struct super_block *sb = file->f_path.dentry->d_sb;
-+ struct btrfs_ioctl_vol_args *btrfs_v1 = NULL;
-+ struct btrfs_ioctl_vol_args_v2 *btrfs_v2 = NULL;
-+
-+ ret = shiftfs_btrfs_ioctl_fd_replace(cmd, argp, &btrfs_v1, &btrfs_v2,
-+ &newfd);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ goto out_restore;
-+
-+ ret = shiftfs_override_ioctl_creds(cmd, sb, &oldcred, &newcred);
-+ if (ret)
-+ goto out_fdput;
-+
-+ ret = vfs_ioctl(lowerfd.file, cmd, arg);
-+
-+ shiftfs_revert_ioctl_creds(oldcred, newcred);
-+
-+ shiftfs_copyattr(file_inode(lowerfd.file), file_inode(file));
-+ shiftfs_copyflags(file_inode(lowerfd.file), file_inode(file));
-+
-+out_fdput:
-+ fdput(lowerfd);
-+
-+out_restore:
-+ err = shiftfs_btrfs_ioctl_fd_restore(cmd, newfd, argp,
-+ btrfs_v1, btrfs_v2);
-+ if (!ret)
-+ ret = err;
-+
-+ return ret;
-+}
-+
-+static bool in_ioctl_whitelist(int flag, unsigned long arg)
-+{
-+ void __user *argp = (void __user *)arg;
-+ u64 flags = 0;
-+
-+ switch (flag) {
-+ case BTRFS_IOC_FS_INFO:
-+ return true;
-+ case BTRFS_IOC_SNAP_CREATE:
-+ return true;
-+ case BTRFS_IOC_SNAP_CREATE_V2:
-+ return true;
-+ case BTRFS_IOC_SUBVOL_CREATE:
-+ return true;
-+ case BTRFS_IOC_SUBVOL_CREATE_V2:
-+ return true;
-+ case BTRFS_IOC_SUBVOL_GETFLAGS:
-+ return true;
-+ case BTRFS_IOC_SUBVOL_SETFLAGS:
-+ if (copy_from_user(&flags, argp, sizeof(flags)))
-+ return false;
-+
-+ if (flags & ~BTRFS_SUBVOL_RDONLY)
-+ return false;
-+
-+ return true;
-+ case BTRFS_IOC_SNAP_DESTROY:
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+static long shiftfs_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ switch (cmd) {
-+ case FS_IOC_GETVERSION:
-+ /* fall through */
-+ case FS_IOC_GETFLAGS:
-+ /* fall through */
-+ case FS_IOC_SETFLAGS:
-+ break;
-+ default:
-+ if (!in_ioctl_whitelist(cmd, arg) ||
-+ !shiftfs_passthrough_ioctls(file->f_path.dentry->d_sb->s_fs_info))
-+ return -ENOTTY;
-+ }
-+
-+ return shiftfs_real_ioctl(file, cmd, arg);
-+}
-+
-+static long shiftfs_compat_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ switch (cmd) {
-+ case FS_IOC32_GETVERSION:
-+ /* fall through */
-+ case FS_IOC32_GETFLAGS:
-+ /* fall through */
-+ case FS_IOC32_SETFLAGS:
-+ break;
-+ default:
-+ if (!in_ioctl_whitelist(cmd, arg) ||
-+ !shiftfs_passthrough_ioctls(file->f_path.dentry->d_sb->s_fs_info))
-+ return -ENOIOCTLCMD;
-+ }
-+
-+ return shiftfs_real_ioctl(file, cmd, arg);
-+}
-+
-+enum shiftfs_copyop {
-+ SHIFTFS_COPY,
-+ SHIFTFS_CLONE,
-+ SHIFTFS_DEDUPE,
-+};
-+
-+static ssize_t shiftfs_copyfile(struct file *file_in, loff_t pos_in,
-+ struct file *file_out, loff_t pos_out, u64 len,
-+ unsigned int flags, enum shiftfs_copyop op)
-+{
-+ ssize_t ret;
-+ struct fd real_in, real_out;
-+ const struct cred *oldcred;
-+ struct inode *inode_out = file_inode(file_out);
-+ struct inode *loweri = inode_out->i_private;
-+
-+ ret = shiftfs_real_fdget(file_out, &real_out);
-+ if (ret)
-+ return ret;
-+
-+ ret = shiftfs_real_fdget(file_in, &real_in);
-+ if (ret) {
-+ fdput(real_out);
-+ return ret;
-+ }
-+
-+ oldcred = shiftfs_override_creds(inode_out->i_sb);
-+ switch (op) {
-+ case SHIFTFS_COPY:
-+ ret = vfs_copy_file_range(real_in.file, pos_in, real_out.file,
-+ pos_out, len, flags);
-+ break;
-+
-+ case SHIFTFS_CLONE:
-+ ret = vfs_clone_file_range(real_in.file, pos_in, real_out.file,
-+ pos_out, len, flags);
-+ break;
-+
-+ case SHIFTFS_DEDUPE:
-+ ret = vfs_dedupe_file_range_one(real_in.file, pos_in,
-+ real_out.file, pos_out, len,
-+ flags);
-+ break;
-+ }
-+ revert_creds(oldcred);
-+
-+ /* Update size */
-+ shiftfs_copyattr(loweri, inode_out);
-+
-+ fdput(real_in);
-+ fdput(real_out);
-+
-+ return ret;
-+}
-+
-+static ssize_t shiftfs_copy_file_range(struct file *file_in, loff_t pos_in,
-+ struct file *file_out, loff_t pos_out,
-+ size_t len, unsigned int flags)
-+{
-+ return shiftfs_copyfile(file_in, pos_in, file_out, pos_out, len, flags,
-+ SHIFTFS_COPY);
-+}
-+
-+static loff_t shiftfs_remap_file_range(struct file *file_in, loff_t pos_in,
-+ struct file *file_out, loff_t pos_out,
-+ loff_t len, unsigned int remap_flags)
-+{
-+ enum shiftfs_copyop op;
-+
-+ if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
-+ return -EINVAL;
-+
-+ if (remap_flags & REMAP_FILE_DEDUP)
-+ op = SHIFTFS_DEDUPE;
-+ else
-+ op = SHIFTFS_CLONE;
-+
-+ return shiftfs_copyfile(file_in, pos_in, file_out, pos_out, len,
-+ remap_flags, op);
-+}
-+
-+static int shiftfs_iterate_shared(struct file *file, struct dir_context *ctx)
-+{
-+ const struct cred *oldcred;
-+ int err = -ENOTDIR;
-+ struct file *realfile = file->private_data;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ err = iterate_dir(realfile, ctx);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+const struct file_operations shiftfs_file_operations = {
-+ .open = shiftfs_open,
-+ .release = shiftfs_release,
-+ .llseek = shiftfs_file_llseek,
-+ .read_iter = shiftfs_read_iter,
-+ .write_iter = shiftfs_write_iter,
-+ .fsync = shiftfs_fsync,
-+ .mmap = shiftfs_mmap,
-+ .fallocate = shiftfs_fallocate,
-+ .fadvise = shiftfs_fadvise,
-+ .unlocked_ioctl = shiftfs_ioctl,
-+ .compat_ioctl = shiftfs_compat_ioctl,
-+ .copy_file_range = shiftfs_copy_file_range,
-+ .remap_file_range = shiftfs_remap_file_range,
-+};
-+
-+const struct file_operations shiftfs_dir_operations = {
-+ .open = shiftfs_dir_open,
-+ .release = shiftfs_dir_release,
-+ .compat_ioctl = shiftfs_compat_ioctl,
-+ .fsync = shiftfs_fsync,
-+ .iterate_shared = shiftfs_iterate_shared,
-+ .llseek = shiftfs_dir_llseek,
-+ .read = generic_read_dir,
-+ .unlocked_ioctl = shiftfs_ioctl,
-+};
-+
-+static const struct address_space_operations shiftfs_aops = {
-+ /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO */
-+ .direct_IO = noop_direct_IO,
-+};
-+
-+static void shiftfs_fill_inode(struct inode *inode, unsigned long ino,
-+ umode_t mode, dev_t dev, struct dentry *dentry)
-+{
-+ struct inode *loweri;
-+
-+ inode->i_ino = ino;
-+ inode->i_flags |= S_NOCMTIME;
-+
-+ mode &= S_IFMT;
-+ inode->i_mode = mode;
-+ switch (mode & S_IFMT) {
-+ case S_IFDIR:
-+ inode->i_op = &shiftfs_dir_inode_operations;
-+ inode->i_fop = &shiftfs_dir_operations;
-+ break;
-+ case S_IFLNK:
-+ inode->i_op = &shiftfs_symlink_inode_operations;
-+ break;
-+ case S_IFREG:
-+ inode->i_op = &shiftfs_file_inode_operations;
-+ inode->i_fop = &shiftfs_file_operations;
-+ inode->i_mapping->a_ops = &shiftfs_aops;
-+ break;
-+ default:
-+ inode->i_op = &shiftfs_special_inode_operations;
-+ init_special_inode(inode, mode, dev);
-+ break;
-+ }
-+
-+ if (!dentry)
-+ return;
-+
-+ loweri = dentry->d_inode;
-+ if (!loweri->i_op->get_link)
-+ inode->i_opflags |= IOP_NOFOLLOW;
-+
-+ shiftfs_copyattr(loweri, inode);
-+ shiftfs_copyflags(loweri, inode);
-+ set_nlink(inode, loweri->i_nlink);
-+}
-+
-+static int shiftfs_show_options(struct seq_file *m, struct dentry *dentry)
-+{
-+ struct super_block *sb = dentry->d_sb;
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+
-+ if (sbinfo->mark)
-+ seq_show_option(m, "mark", NULL);
-+
-+ if (sbinfo->passthrough)
-+ seq_printf(m, ",passthrough=%u", sbinfo->passthrough);
-+
-+ return 0;
-+}
-+
-+static int shiftfs_statfs(struct dentry *dentry, struct kstatfs *buf)
-+{
-+ struct super_block *sb = dentry->d_sb;
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+ struct dentry *root = sb->s_root;
-+ struct dentry *realroot = root->d_fsdata;
-+ struct path realpath = { .mnt = sbinfo->mnt, .dentry = realroot };
-+ int err;
-+
-+ err = vfs_statfs(&realpath, buf);
-+ if (err)
-+ return err;
-+
-+ if (!shiftfs_passthrough_statfs(sbinfo))
-+ buf->f_type = sb->s_magic;
-+
-+ return 0;
-+}
-+
-+static void shiftfs_evict_inode(struct inode *inode)
-+{
-+ struct inode *loweri = inode->i_private;
-+
-+ clear_inode(inode);
-+
-+ if (loweri)
-+ iput(loweri);
-+}
-+
-+static void shiftfs_put_super(struct super_block *sb)
-+{
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+
-+ if (sbinfo) {
-+ mntput(sbinfo->mnt);
-+ put_cred(sbinfo->creator_cred);
-+ kfree(sbinfo);
-+ }
-+}
-+
-+static const struct xattr_handler shiftfs_xattr_handler = {
-+ .prefix = "",
-+ .get = shiftfs_xattr_get,
-+ .set = shiftfs_xattr_set,
-+};
-+
-+const struct xattr_handler *shiftfs_xattr_handlers[] = {
-+#ifdef CONFIG_SHIFT_FS_POSIX_ACL
-+ &shiftfs_posix_acl_access_xattr_handler,
-+ &shiftfs_posix_acl_default_xattr_handler,
-+#endif
-+ &shiftfs_xattr_handler,
-+ NULL
-+};
-+
-+static inline bool passthrough_is_subset(int old_flags, int new_flags)
-+{
-+ if ((new_flags & old_flags) != new_flags)
-+ return false;
-+
-+ return true;
-+}
-+
-+static int shiftfs_super_check_flags(unsigned long old_flags,
-+ unsigned long new_flags)
-+{
-+ if ((old_flags & SB_RDONLY) && !(new_flags & SB_RDONLY))
-+ return -EPERM;
-+
-+ if ((old_flags & SB_NOSUID) && !(new_flags & SB_NOSUID))
-+ return -EPERM;
-+
-+ if ((old_flags & SB_NODEV) && !(new_flags & SB_NODEV))
-+ return -EPERM;
-+
-+ if ((old_flags & SB_NOEXEC) && !(new_flags & SB_NOEXEC))
-+ return -EPERM;
-+
-+ if ((old_flags & SB_NOATIME) && !(new_flags & SB_NOATIME))
-+ return -EPERM;
-+
-+ if ((old_flags & SB_NODIRATIME) && !(new_flags & SB_NODIRATIME))
-+ return -EPERM;
-+
-+ if (!(old_flags & SB_POSIXACL) && (new_flags & SB_POSIXACL))
-+ return -EPERM;
-+
-+ return 0;
-+}
-+
-+static int shiftfs_remount(struct super_block *sb, int *flags, char *data)
-+{
-+ int err;
-+ struct shiftfs_super_info new = {};
-+ struct shiftfs_super_info *info = sb->s_fs_info;
-+
-+ err = shiftfs_parse_mount_options(&new, data);
-+ if (err)
-+ return err;
-+
-+ err = shiftfs_super_check_flags(sb->s_flags, *flags);
-+ if (err)
-+ return err;
-+
-+ /* Mark mount option cannot be changed. */
-+ if (info->mark || (info->mark != new.mark))
-+ return -EPERM;
-+
-+ if (info->passthrough != new.passthrough) {
-+ /* Don't allow exceeding passthrough options of mark mount. */
-+ if (!passthrough_is_subset(info->passthrough_mark,
-+ info->passthrough))
-+ return -EPERM;
-+
-+ info->passthrough = new.passthrough;
-+ }
-+
-+ return 0;
-+}
-+
-+static const struct super_operations shiftfs_super_ops = {
-+ .put_super = shiftfs_put_super,
-+ .show_options = shiftfs_show_options,
-+ .statfs = shiftfs_statfs,
-+ .remount_fs = shiftfs_remount,
-+ .evict_inode = shiftfs_evict_inode,
-+};
-+
-+struct shiftfs_data {
-+ void *data;
-+ const char *path;
-+};
-+
-+static void shiftfs_super_force_flags(struct super_block *sb,
-+ unsigned long lower_flags)
-+{
-+ sb->s_flags |= lower_flags & (SB_RDONLY | SB_NOSUID | SB_NODEV |
-+ SB_NOEXEC | SB_NOATIME | SB_NODIRATIME);
-+
-+ if (!(lower_flags & SB_POSIXACL))
-+ sb->s_flags &= ~SB_POSIXACL;
-+}
-+
-+static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
-+ int silent)
-+{
-+ int err;
-+ struct path path = {};
-+ struct shiftfs_super_info *sbinfo_mp;
-+ char *name = NULL;
-+ struct inode *inode = NULL;
-+ struct dentry *dentry = NULL;
-+ struct shiftfs_data *data = raw_data;
-+ struct shiftfs_super_info *sbinfo = NULL;
-+
-+ if (!data->path)
-+ return -EINVAL;
-+
-+ sb->s_fs_info = kzalloc(sizeof(*sbinfo), GFP_KERNEL);
-+ if (!sb->s_fs_info)
-+ return -ENOMEM;
-+ sbinfo = sb->s_fs_info;
-+
-+ err = shiftfs_parse_mount_options(sbinfo, data->data);
-+ if (err)
-+ return err;
-+
-+ /* to mount a mark, must be userns admin */
-+ if (!sbinfo->mark && !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
-+ return -EPERM;
-+
-+ name = kstrdup(data->path, GFP_KERNEL);
-+ if (!name)
-+ return -ENOMEM;
-+
-+ err = kern_path(name, LOOKUP_FOLLOW, &path);
-+ if (err)
-+ goto out_free_name;
-+
-+ if (!S_ISDIR(path.dentry->d_inode->i_mode)) {
-+ err = -ENOTDIR;
-+ goto out_put_path;
-+ }
-+
-+ sb->s_flags |= SB_POSIXACL;
-+
-+ if (sbinfo->mark) {
-+ struct cred *cred_tmp;
-+ struct super_block *lower_sb = path.mnt->mnt_sb;
-+
-+ /* to mark a mount point, must root wrt lower s_user_ns */
-+ if (!ns_capable(lower_sb->s_user_ns, CAP_SYS_ADMIN)) {
-+ err = -EPERM;
-+ goto out_put_path;
-+ }
-+
-+ /*
-+ * this part is visible unshifted, so make sure no
-+ * executables that could be used to give suid
-+ * privileges
-+ */
-+ sb->s_iflags = SB_I_NOEXEC;
-+
-+ shiftfs_super_force_flags(sb, lower_sb->s_flags);
-+
-+ /*
-+ * Handle nesting of shiftfs mounts by referring this mark
-+ * mount back to the original mark mount. This is more
-+ * efficient and alleviates concerns about stack depth.
-+ */
-+ if (lower_sb->s_magic == SHIFTFS_MAGIC) {
-+ sbinfo_mp = lower_sb->s_fs_info;
-+
-+ /* Doesn't make sense to mark a mark mount */
-+ if (sbinfo_mp->mark) {
-+ err = -EINVAL;
-+ goto out_put_path;
-+ }
-+
-+ if (!passthrough_is_subset(sbinfo_mp->passthrough,
-+ sbinfo->passthrough)) {
-+ err = -EPERM;
-+ goto out_put_path;
-+ }
-+
-+ sbinfo->mnt = mntget(sbinfo_mp->mnt);
-+ dentry = dget(path.dentry->d_fsdata);
-+ /*
-+ * Copy up the passthrough mount options from the
-+ * parent mark mountpoint.
-+ */
-+ sbinfo->passthrough_mark = sbinfo_mp->passthrough_mark;
-+ sbinfo->creator_cred = get_cred(sbinfo_mp->creator_cred);
-+ } else {
-+ sbinfo->mnt = mntget(path.mnt);
-+ dentry = dget(path.dentry);
-+ /*
-+ * For a new mark passthrough_mark and passthrough
-+ * are identical.
-+ */
-+ sbinfo->passthrough_mark = sbinfo->passthrough;
-+
-+ cred_tmp = prepare_creds();
-+ if (!cred_tmp) {
-+ err = -ENOMEM;
-+ goto out_put_path;
-+ }
-+ /* Don't override disk quota limits or use reserved space. */
-+ cap_lower(cred_tmp->cap_effective, CAP_SYS_RESOURCE);
-+ sbinfo->creator_cred = cred_tmp;
-+ }
-+ } else {
-+ /*
-+ * This leg executes if we're admin capable in the namespace,
-+ * so be very careful.
-+ */
-+ err = -EPERM;
-+ if (path.dentry->d_sb->s_magic != SHIFTFS_MAGIC)
-+ goto out_put_path;
-+
-+ sbinfo_mp = path.dentry->d_sb->s_fs_info;
-+ if (!sbinfo_mp->mark)
-+ goto out_put_path;
-+
-+ if (!passthrough_is_subset(sbinfo_mp->passthrough,
-+ sbinfo->passthrough))
-+ goto out_put_path;
-+
-+ sbinfo->mnt = mntget(sbinfo_mp->mnt);
-+ sbinfo->creator_cred = get_cred(sbinfo_mp->creator_cred);
-+ dentry = dget(path.dentry->d_fsdata);
-+ /*
-+ * Copy up passthrough settings from mark mountpoint so we can
-+ * verify when the overlay wants to remount with different
-+ * passthrough settings.
-+ */
-+ sbinfo->passthrough_mark = sbinfo_mp->passthrough;
-+ shiftfs_super_force_flags(sb, path.mnt->mnt_sb->s_flags);
-+ }
-+
-+ sb->s_stack_depth = dentry->d_sb->s_stack_depth + 1;
-+ if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
-+ printk(KERN_ERR "shiftfs: maximum stacking depth exceeded\n");
-+ err = -EINVAL;
-+ goto out_put_path;
-+ }
-+
-+ inode = new_inode(sb);
-+ if (!inode) {
-+ err = -ENOMEM;
-+ goto out_put_path;
-+ }
-+ shiftfs_fill_inode(inode, dentry->d_inode->i_ino, S_IFDIR, 0, dentry);
-+
-+ ihold(dentry->d_inode);
-+ inode->i_private = dentry->d_inode;
-+
-+ sb->s_magic = SHIFTFS_MAGIC;
-+ sb->s_maxbytes = MAX_LFS_FILESIZE;
-+ sb->s_op = &shiftfs_super_ops;
-+ sb->s_xattr = shiftfs_xattr_handlers;
-+ sb->s_d_op = &shiftfs_dentry_ops;
-+ sb->s_root = d_make_root(inode);
-+ if (!sb->s_root) {
-+ err = -ENOMEM;
-+ goto out_put_path;
-+ }
-+
-+ sb->s_root->d_fsdata = dentry;
-+ sbinfo->userns = get_user_ns(dentry->d_sb->s_user_ns);
-+ shiftfs_copyattr(dentry->d_inode, sb->s_root->d_inode);
-+
-+ dentry = NULL;
-+ err = 0;
-+
-+out_put_path:
-+ path_put(&path);
-+
-+out_free_name:
-+ kfree(name);
-+
-+ dput(dentry);
-+
-+ return err;
-+}
-+
-+static struct dentry *shiftfs_mount(struct file_system_type *fs_type,
-+ int flags, const char *dev_name, void *data)
-+{
-+ struct shiftfs_data d = { data, dev_name };
-+
-+ return mount_nodev(fs_type, flags, &d, shiftfs_fill_super);
-+}
-+
-+static struct file_system_type shiftfs_type = {
-+ .owner = THIS_MODULE,
-+ .name = "shiftfs",
-+ .mount = shiftfs_mount,
-+ .kill_sb = kill_anon_super,
-+ .fs_flags = FS_USERNS_MOUNT,
-+};
-+
-+static int __init shiftfs_init(void)
-+{
-+ return register_filesystem(&shiftfs_type);
-+}
-+
-+static void __exit shiftfs_exit(void)
-+{
-+ unregister_filesystem(&shiftfs_type);
-+}
-+
-+MODULE_ALIAS_FS("shiftfs");
-+MODULE_AUTHOR("James Bottomley");
-+MODULE_AUTHOR("Seth Forshee <seth.forshee@canonical.com>");
-+MODULE_AUTHOR("Christian Brauner <christian.brauner@ubuntu.com>");
-+MODULE_DESCRIPTION("id shifting filesystem");
-+MODULE_LICENSE("GPL v2");
-+module_init(shiftfs_init)
-+module_exit(shiftfs_exit)
---- a/include/uapi/linux/magic.h 2021-01-06 19:08:45.234777659 -0500
-+++ b/include/uapi/linux/magic.h 2021-01-06 19:09:53.900375394 -0500
-@@ -96,4 +96,6 @@
- #define DEVMEM_MAGIC 0x454d444d /* "DMEM" */
- #define Z3FOLD_MAGIC 0x33
-
-+#define SHIFTFS_MAGIC 0x6a656a62
-+
- #endif /* __LINUX_MAGIC_H__ */
---- a/fs/Makefile 2021-01-08 18:08:28.187064015 -0500
-+++ b/fs/Makefile 2021-01-08 18:09:00.788217579 -0500
-@@ -136,3 +136,4 @@ obj-$(CONFIG_EFIVAR_FS) += efivarfs/
- obj-$(CONFIG_EROFS_FS) += erofs/
- obj-$(CONFIG_VBOXSF_FS) += vboxsf/
- obj-$(CONFIG_ZONEFS_FS) += zonefs/
-+obj-$(CONFIG_SHIFT_FS) += shiftfs.o
---- a/fs/Kconfig 2021-01-06 19:14:17.709697891 -0500
-+++ b/fs/Kconfig 2021-01-06 19:15:23.413281282 -0500
-@@ -122,6 +122,24 @@ source "fs/autofs/Kconfig"
- source "fs/fuse/Kconfig"
- source "fs/overlayfs/Kconfig"
-
-+config SHIFT_FS
-+ tristate "UID/GID shifting overlay filesystem for containers"
-+ help
-+ This filesystem can overlay any mounted filesystem and shift
-+ the uid/gid the files appear at. The idea is that
-+ unprivileged containers can use this to mount root volumes
-+ using this technique.
-+
-+config SHIFT_FS_POSIX_ACL
-+ bool "shiftfs POSIX Access Control Lists"
-+ depends on SHIFT_FS
-+ select FS_POSIX_ACL
-+ help
-+ POSIX Access Control Lists (ACLs) support permissions for users and
-+ groups beyond the owner/group/world scheme.
-+
-+ If you don't know what Access Control Lists are, say N.
-+
- menu "Caches"
-
- source "fs/fscache/Kconfig"
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch
deleted file mode 100644
index 4dcd7523054f..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From d9d30b2b018fa6ee76deb27ebb1d8820f511a732 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 27 May 2017 07:22:12 -0400
-Subject: [PATCH 001/113] make DEFAULT_MMAP_MIN_ADDR match LSM_MMAP_MIN_ADDR
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/Kconfig | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/mm/Kconfig b/mm/Kconfig
-index 390165ffbb0f..3b24c9e3535e 100644
---- a/mm/Kconfig
-+++ b/mm/Kconfig
-@@ -321,7 +321,8 @@ config KSM
- config DEFAULT_MMAP_MIN_ADDR
- int "Low address space to protect from user allocation"
- depends on MMU
-- default 4096
-+ default 32768 if ARM || (ARM64 && COMPAT)
-+ default 65536
- help
- This is the portion of low virtual memory which should be protected
- from userspace allocation. Keeping a user from writing to low pages
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0002-enable-HARDENED_USERCOPY-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0002-enable-HARDENED_USERCOPY-by-default.patch
deleted file mode 100644
index e972ca800f5e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0002-enable-HARDENED_USERCOPY-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 86d91201e7eaa175f380a7d7c6dfa238a73cb816 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 29 May 2017 06:17:41 -0400
-Subject: [PATCH 002/113] enable HARDENED_USERCOPY by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- security/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 7561f6f99f1d..9446ddf40974 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -154,6 +154,7 @@ config HARDENED_USERCOPY
- bool "Harden memory copies between kernel and userspace"
- depends on HAVE_HARDENED_USERCOPY_ALLOCATOR
- imply STRICT_DEVMEM
-+ default y
- help
- This option checks for obviously wrong memory regions when
- copying memory to/from the kernel (via copy_to_user() and
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch
deleted file mode 100644
index 056d3b0dd6ae..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From c91c4da25ecdb24c7ce90778d33184c2ad3c306c Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 26 Apr 2018 02:01:26 -0400
-Subject: [PATCH 003/113] disable HARDENED_USERCOPY_FALLBACK by default
-
----
- security/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 9446ddf40974..5c388f7fe09d 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -167,7 +167,6 @@ config HARDENED_USERCOPY
- config HARDENED_USERCOPY_FALLBACK
- bool "Allow usercopy whitelist violations to fallback to object size"
- depends on HARDENED_USERCOPY
-- default y
- help
- This is a temporary option that allows missing usercopy whitelists
- to be discovered via a WARN() to the kernel log, instead of
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch
deleted file mode 100644
index e7c85fc85348..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 8706ca7dbe2b4bf85f7549b5e532172ec70ecb33 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:05:15 -0400
-Subject: [PATCH 004/113] enable SECURITY_DMESG_RESTRICT by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- security/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 5c388f7fe09d..428ad7622370 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -9,7 +9,7 @@ source "security/keys/Kconfig"
-
- config SECURITY_DMESG_RESTRICT
- bool "Restrict unprivileged access to the kernel syslog"
-- default n
-+ default y
- help
- This enforces restrictions on unprivileged users reading the kernel
- syslog via dmesg(8).
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0005-set-kptr_restrict-2-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0005-set-kptr_restrict-2-by-default.patch
deleted file mode 100644
index ebc662b49cc8..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0005-set-kptr_restrict-2-by-default.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From cfa910285b72779ce423fe38eeb194f6adcbf9d4 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:06:14 -0400
-Subject: [PATCH 005/113] set kptr_restrict=2 by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- lib/vsprintf.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/lib/vsprintf.c b/lib/vsprintf.c
-index 14c9a6af1b23..2501f75bd74d 100644
---- a/lib/vsprintf.c
-+++ b/lib/vsprintf.c
-@@ -821,7 +821,7 @@ static char *ptr_to_id(char *buf, char *end, const void *ptr,
- return pointer_string(buf, end, (const void *)hashval, spec);
- }
-
--int kptr_restrict __read_mostly;
-+int kptr_restrict __read_mostly = 2;
-
- static noinline_for_stack
- char *restricted_pointer(char *buf, char *end, const void *ptr,
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0006-enable-DEBUG_LIST-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0006-enable-DEBUG_LIST-by-default.patch
deleted file mode 100644
index cc518b81a539..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0006-enable-DEBUG_LIST-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From f06c970c3a69ceaa4653e8db98175c3e276995d6 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:10:57 -0400
-Subject: [PATCH 006/113] enable DEBUG_LIST by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- lib/Kconfig.debug | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index c789b39ed527..89c9d6aebf77 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -1471,6 +1471,7 @@ menu "Debug kernel data structures"
- config DEBUG_LIST
- bool "Debug linked list manipulation"
- depends on DEBUG_KERNEL || BUG_ON_DATA_CORRUPTION
-+ default y
- help
- Enable this to turn on extended checks in the linked-list
- walking routines.
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch
deleted file mode 100644
index 8d5725148e80..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 1ed4992d5312b9f195fb25a5db794243e411349c Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 29 May 2017 12:21:21 -0400
-Subject: [PATCH 007/113] enable BUG_ON_DATA_CORRUPTION by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- lib/Kconfig.debug | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index 89c9d6aebf77..11068e77d146 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -1511,6 +1511,7 @@ config DEBUG_NOTIFIERS
- config BUG_ON_DATA_CORRUPTION
- bool "Trigger a BUG when data corruption is detected"
- select DEBUG_LIST
-+ default y
- help
- Select this option if the kernel should BUG when it encounters
- data corruption in kernel memory structures when they get checked
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch
deleted file mode 100644
index 27c93f3cdf6e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 69f9e43c30be97a4bac4ed7e019190842824fe42 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 01:39:32 -0500
-Subject: [PATCH 008/113] enable ARM64_SW_TTBR0_PAN by default
-
----
- arch/arm64/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index a6b5b7ef40ae..a145245ec5e7 100644
---- a/arch/arm64/Kconfig
-+++ b/arch/arm64/Kconfig
-@@ -1199,6 +1199,7 @@ config RODATA_FULL_DEFAULT_ENABLED
-
- config ARM64_SW_TTBR0_PAN
- bool "Emulate Privileged Access Never using TTBR0_EL1 switching"
-+ default y
- help
- Enabling this option prevents the kernel from accessing
- user-space memory directly by pointing TTBR0_EL1 to a reserved
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0009-arm64-enable-RANDOMIZE_BASE-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0009-arm64-enable-RANDOMIZE_BASE-by-default.patch
deleted file mode 100644
index d53952c79d9d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0009-arm64-enable-RANDOMIZE_BASE-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 2d8a717c80114334be591d35b9e09fdcc56c9368 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 01:33:48 -0500
-Subject: [PATCH 009/113] arm64: enable RANDOMIZE_BASE by default
-
----
- arch/arm64/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index a145245ec5e7..21088a6532d8 100644
---- a/arch/arm64/Kconfig
-+++ b/arch/arm64/Kconfig
-@@ -1790,6 +1790,7 @@ config RANDOMIZE_BASE
- bool "Randomize the address of the kernel image"
- select ARM64_MODULE_PLTS if MODULES
- select RELOCATABLE
-+ default y
- help
- Randomizes the virtual address at which the kernel image is
- loaded, as a security feature that deters exploit attempts
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0010-enable-SLAB_FREELIST_RANDOM-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0010-enable-SLAB_FREELIST_RANDOM-by-default.patch
deleted file mode 100644
index 8353e06ca342..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0010-enable-SLAB_FREELIST_RANDOM-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 9d94f16c3379f590e962739a865e86daef05a0bd Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 19:43:38 -0400
-Subject: [PATCH 010/113] enable SLAB_FREELIST_RANDOM by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- init/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 0872a5a2e759..dcbcb4243316 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1929,6 +1929,7 @@ config SLAB_MERGE_DEFAULT
- config SLAB_FREELIST_RANDOM
- bool "Randomize slab freelist"
- depends on SLAB || SLUB
-+ default y
- help
- Randomizes the freelist order used on creating new pages. This
- security feature reduces the predictability of the kernel slab
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0011-enable-SLAB_FREELIST_HARDENED-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0011-enable-SLAB_FREELIST_HARDENED-by-default.patch
deleted file mode 100644
index 6a3683cc5b2e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0011-enable-SLAB_FREELIST_HARDENED-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 32ee17a35ba371cefc7bd7fed7a8686e040dabcb Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 20 Aug 2017 15:39:25 -0400
-Subject: [PATCH 011/113] enable SLAB_FREELIST_HARDENED by default
-
----
- init/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index dcbcb4243316..667d1c6c021b 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1938,6 +1938,7 @@ config SLAB_FREELIST_RANDOM
- config SLAB_FREELIST_HARDENED
- bool "Harden slab freelist metadata"
- depends on SLAB || SLUB
-+ default y
- help
- Many kernel heap attacks try to target slab cache metadata and
- other infrastructure. This options makes minor performance
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0012-disable-SLAB_MERGE_DEFAULT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0012-disable-SLAB_MERGE_DEFAULT-by-default.patch
deleted file mode 100644
index 2ab0649fba29..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0012-disable-SLAB_MERGE_DEFAULT-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From add6f0f716837cb517911ad94ca80faf98ca1b21 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 8 Jul 2017 02:38:54 -0400
-Subject: [PATCH 012/113] disable SLAB_MERGE_DEFAULT by default
-
----
- init/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 667d1c6c021b..859ab5ae66ff 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1914,7 +1914,6 @@ endchoice
-
- config SLAB_MERGE_DEFAULT
- bool "Allow slab caches to be merged"
-- default y
- help
- For reduced kernel memory fragmentation, slab caches can be
- merged when they share the same size and other characteristics.
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0013-enable-FORTIFY_SOURCE-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0013-enable-FORTIFY_SOURCE-by-default.patch
deleted file mode 100644
index 2b17e240ca4a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0013-enable-FORTIFY_SOURCE-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 1c354980f5d5132617e3f17a80dea1bbd34a0e3f Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 8 May 2017 12:51:54 -0400
-Subject: [PATCH 013/113] enable FORTIFY_SOURCE by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- security/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 428ad7622370..3a2c68c7b50f 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -191,6 +191,7 @@ config HARDENED_USERCOPY_PAGESPAN
- config FORTIFY_SOURCE
- bool "Harden common str/mem functions against buffer overflows"
- depends on ARCH_HAS_FORTIFY_SOURCE
-+ default y
- help
- Detect overflows of buffers in common string and memory functions
- where the compiler can determine and validate the buffer sizes.
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0014-enable-PANIC_ON_OOPS-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0014-enable-PANIC_ON_OOPS-by-default.patch
deleted file mode 100644
index 70939ea89c19..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0014-enable-PANIC_ON_OOPS-by-default.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From f9249a0e6ddb4d8550cd268d22ba80fb475ac0fe Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:09:17 -0400
-Subject: [PATCH 014/113] enable PANIC_ON_OOPS by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- lib/Kconfig.debug | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index 11068e77d146..45b169177fb9 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -894,6 +894,7 @@ menu "Debug Oops, Lockups and Hangs"
-
- config PANIC_ON_OOPS
- bool "Panic on Oops"
-+ default y
- help
- Say Y here to enable the kernel to panic when it oopses. This
- has the same effect as setting oops=panic on the kernel command
-@@ -903,7 +904,7 @@ config PANIC_ON_OOPS
- anything erroneous after an oops which could result in data
- corruption or other issues.
-
-- Say N if unsure.
-+ Say Y if unsure.
-
- config PANIC_ON_OOPS_VALUE
- int
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch
deleted file mode 100644
index 57729fc4588c..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 7606dac7028e3e79600656d1a93ca21a04cbf684 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 14 May 2017 22:39:34 -0400
-Subject: [PATCH 015/113] stop hiding SLUB_DEBUG behind EXPERT
-
-It can make sense to disable this to reduce attack surface / complexity.
----
- init/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 859ab5ae66ff..74680a15ceb4 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1843,7 +1843,7 @@ config VM_EVENT_COUNTERS
-
- config SLUB_DEBUG
- default y
-- bool "Enable SLUB debugging support" if EXPERT
-+ bool "Enable SLUB debugging support"
- depends on SLUB && SYSFS
- help
- SLUB has extensive debug support features. Disabling these can
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0016-stop-hiding-X86_16BIT-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0016-stop-hiding-X86_16BIT-behind-EXPERT.patch
deleted file mode 100644
index 8734c952758e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0016-stop-hiding-X86_16BIT-behind-EXPERT.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 36b1d1ea9f227293955790f03eb7e00fe4e45441 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 18:11:31 -0400
-Subject: [PATCH 016/113] stop hiding X86_16BIT behind EXPERT
-
----
- arch/x86/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 3a5ecb1039bf..d2d5e0cbf85c 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -1194,7 +1194,7 @@ config VM86
- default X86_LEGACY_VM86
-
- config X86_16BIT
-- bool "Enable support for 16-bit segments" if EXPERT
-+ bool "Enable support for 16-bit segments"
- default y
- depends on MODIFY_LDT_SYSCALL
- help
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0017-disable-X86_16BIT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0017-disable-X86_16BIT-by-default.patch
deleted file mode 100644
index fd505e4ed16c..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0017-disable-X86_16BIT-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 5f32dbb0e3343ed1aeef7fbad9727cbe51982604 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 18:11:52 -0400
-Subject: [PATCH 017/113] disable X86_16BIT by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index d2d5e0cbf85c..ab6e7e2d3cf0 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -1195,7 +1195,6 @@ config VM86
-
- config X86_16BIT
- bool "Enable support for 16-bit segments"
-- default y
- depends on MODIFY_LDT_SYSCALL
- help
- This option is required by programs like Wine to run 16-bit
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch
deleted file mode 100644
index 782c0b45dd1d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From b3cd6107dc0d9ef30ea155577406837b97b85473 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 18:15:52 -0400
-Subject: [PATCH 018/113] stop hiding MODIFY_LDT_SYSCALL behind EXPERT
-
----
- arch/x86/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index ab6e7e2d3cf0..7b9df510469b 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -2392,7 +2392,7 @@ config CMDLINE_OVERRIDE
- be set to 'N' under normal conditions.
-
- config MODIFY_LDT_SYSCALL
-- bool "Enable the LDT (local descriptor table)" if EXPERT
-+ bool "Enable the LDT (local descriptor table)"
- default y
- help
- Linux can allow user programs to install a per-process x86
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0019-disable-MODIFY_LDT_SYSCALL-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0019-disable-MODIFY_LDT_SYSCALL-by-default.patch
deleted file mode 100644
index 584025aaf34d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0019-disable-MODIFY_LDT_SYSCALL-by-default.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 8ba7c14d933792448f918192fecad81fde249b7b Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 18:16:16 -0400
-Subject: [PATCH 019/113] disable MODIFY_LDT_SYSCALL by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- arch/x86/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 7b9df510469b..63e1e9fc18dd 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -2393,7 +2393,6 @@ config CMDLINE_OVERRIDE
-
- config MODIFY_LDT_SYSCALL
- bool "Enable the LDT (local descriptor table)"
-- default y
- help
- Linux can allow user programs to install a per-process x86
- Local Descriptor Table (LDT) using the modify_ldt(2) system
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0020-set-LEGACY_VSYSCALL_NONE-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0020-set-LEGACY_VSYSCALL_NONE-by-default.patch
deleted file mode 100644
index 53eb35761de6..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0020-set-LEGACY_VSYSCALL_NONE-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 5d2790cf2628a95c5dc731e85c7d82eb490edb08 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 29 May 2017 07:08:42 -0400
-Subject: [PATCH 020/113] set LEGACY_VSYSCALL_NONE by default
-
----
- arch/x86/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 63e1e9fc18dd..4fd082de7420 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -2296,7 +2296,7 @@ config COMPAT_VDSO
- choice
- prompt "vsyscall table for legacy applications"
- depends on X86_64
-- default LEGACY_VSYSCALL_XONLY
-+ default LEGACY_VSYSCALL_NONE
- help
- Legacy user code that does not know how to find the vDSO expects
- to be able to issue three syscalls by calling fixed addresses in
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0021-stop-hiding-AIO-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0021-stop-hiding-AIO-behind-EXPERT.patch
deleted file mode 100644
index e935f1e25198..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0021-stop-hiding-AIO-behind-EXPERT.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 6625069c32a40b9618f4d5974f07b35de8c76b2f Mon Sep 17 00:00:00 2001
-From: Bernhard40 <32568352+Bernhard40@users.noreply.github.com>
-Date: Fri, 6 Oct 2017 10:21:50 +0000
-Subject: [PATCH 021/113] stop hiding AIO behind EXPERT
-
----
- init/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 74680a15ceb4..8605f3e78e47 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1591,7 +1591,7 @@ config SHMEM
- which may be appropriate on small systems without swap.
-
- config AIO
-- bool "Enable AIO support" if EXPERT
-+ bool "Enable AIO support"
- default y
- help
- This option enables POSIX asynchronous I/O which may by used
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0022-disable-AIO-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0022-disable-AIO-by-default.patch
deleted file mode 100644
index ef2e59c8b84f..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0022-disable-AIO-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 135b0c2b580a3b29e39d68ebd4cb6968363464fe Mon Sep 17 00:00:00 2001
-From: Bernhard40 <32568352+Bernhard40@users.noreply.github.com>
-Date: Fri, 6 Oct 2017 10:24:10 +0000
-Subject: [PATCH 022/113] disable AIO by default
-
----
- init/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 8605f3e78e47..21f0b6926cf3 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1592,7 +1592,6 @@ config SHMEM
-
- config AIO
- bool "Enable AIO support"
-- default y
- help
- This option enables POSIX asynchronous I/O which may by used
- by some high performance threaded applications. Disabling
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch
deleted file mode 100644
index 4d9e336414dd..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From c5a80cfe5b6f64df3c8b2fae4713001fd8094577 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 02:08:49 -0500
-Subject: [PATCH 023/113] remove SYSVIPC from arm64/x86_64 defconfigs
-
----
- arch/arm64/configs/defconfig | 1 -
- arch/x86/configs/x86_64_defconfig | 1 -
- 2 files changed, 2 deletions(-)
-
-diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
-index 5cfe3cf6f2ac..f25871361bdc 100644
---- a/arch/arm64/configs/defconfig
-+++ b/arch/arm64/configs/defconfig
-@@ -1,4 +1,3 @@
--CONFIG_SYSVIPC=y
- CONFIG_POSIX_MQUEUE=y
- CONFIG_AUDIT=y
- CONFIG_NO_HZ_IDLE=y
-diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
-index 9936528e1939..981ee8c0e330 100644
---- a/arch/x86/configs/x86_64_defconfig
-+++ b/arch/x86/configs/x86_64_defconfig
-@@ -1,5 +1,4 @@
- # CONFIG_LOCALVERSION_AUTO is not set
--CONFIG_SYSVIPC=y
- CONFIG_POSIX_MQUEUE=y
- CONFIG_AUDIT=y
- CONFIG_NO_HZ=y
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0024-disable-DEVPORT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0024-disable-DEVPORT-by-default.patch
deleted file mode 100644
index 81db083a942a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0024-disable-DEVPORT-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 9d988d867cf28b220c4b613b85405c6db1e4cf34 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 27 May 2017 07:28:10 -0400
-Subject: [PATCH 024/113] disable DEVPORT by default
-
----
- drivers/char/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
-index d229a2d0c017..68178c3a25de 100644
---- a/drivers/char/Kconfig
-+++ b/drivers/char/Kconfig
-@@ -391,7 +391,6 @@ config MAX_RAW_DEVS
- config DEVPORT
- bool "/dev/port character device"
- depends on ISA || PCI
-- default y
- help
- Say Y here if you want to support the /dev/port device. The /dev/port
- device is similar to /dev/mem, but for I/O ports.
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0025-disable-PROC_VMCORE-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0025-disable-PROC_VMCORE-by-default.patch
deleted file mode 100644
index 61fb56ca60b4..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0025-disable-PROC_VMCORE-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 6635f4bbe167dd2138fbbb6a3e9861518f4c5b74 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 27 May 2017 07:29:45 -0400
-Subject: [PATCH 025/113] disable PROC_VMCORE by default
-
----
- fs/proc/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig
-index c930001056f9..6a0a51b3f593 100644
---- a/fs/proc/Kconfig
-+++ b/fs/proc/Kconfig
-@@ -41,7 +41,6 @@ config PROC_KCORE
- config PROC_VMCORE
- bool "/proc/vmcore support"
- depends on PROC_FS && CRASH_DUMP
-- default y
- help
- Exports the dump image of crashed kernel in ELF format.
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0026-disable-NFS_DEBUG-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0026-disable-NFS_DEBUG-by-default.patch
deleted file mode 100644
index 29a8a6fe50c6..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0026-disable-NFS_DEBUG-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 2e80bbb8ba13e71a45394e0921cad61c3e301c8f Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 28 May 2017 03:03:46 -0400
-Subject: [PATCH 026/113] disable NFS_DEBUG by default
-
----
- fs/nfs/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
-index e2a488d403a6..ce54c1c693a8 100644
---- a/fs/nfs/Kconfig
-+++ b/fs/nfs/Kconfig
-@@ -195,7 +195,6 @@ config NFS_DEBUG
- bool
- depends on NFS_FS && SUNRPC_DEBUG
- select CRC32
-- default y
-
- config NFS_DISABLE_UDP_SUPPORT
- bool "NFS: Disable NFS UDP protocol support"
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0027-enable-DEBUG_WX-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0027-enable-DEBUG_WX-by-default.patch
deleted file mode 100644
index 26182c55bd8d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0027-enable-DEBUG_WX-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 13ebbd23324bfc02069a34f5653a74f584b7a4a3 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 29 May 2017 12:11:11 -0400
-Subject: [PATCH 027/113] enable DEBUG_WX by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/Kconfig.debug | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug
-index 864f129f1937..929d585bd267 100644
---- a/mm/Kconfig.debug
-+++ b/mm/Kconfig.debug
-@@ -126,6 +126,7 @@ config DEBUG_WX
- depends on ARCH_HAS_DEBUG_WX
- depends on MMU
- select PTDUMP_CORE
-+ default y
- help
- Generate a warning if any W+X mappings are found at boot.
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0028-disable-LEGACY_PTYS-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0028-disable-LEGACY_PTYS-by-default.patch
deleted file mode 100644
index 6fb9b280fff3..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0028-disable-LEGACY_PTYS-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From a323baa5554e3094f9bdc305a0fd4800de8fd808 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Fri, 5 Jan 2018 13:21:16 -0500
-Subject: [PATCH 028/113] disable LEGACY_PTYS by default
-
----
- drivers/tty/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
-index 93fd984eb2f5..d9086484d2de 100644
---- a/drivers/tty/Kconfig
-+++ b/drivers/tty/Kconfig
-@@ -122,7 +122,6 @@ config UNIX98_PTYS
-
- config LEGACY_PTYS
- bool "Legacy (BSD) PTY support"
-- default y
- help
- A pseudo terminal (PTY) is a software device consisting of two
- halves: a master and a slave. The slave device behaves identical to
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0029-disable-DEVMEM-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0029-disable-DEVMEM-by-default.patch
deleted file mode 100644
index 756cdb9e893e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0029-disable-DEVMEM-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 6921af5937c9d74c6f5ea18b6af69bf50e9c112e Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Fri, 5 Jan 2018 12:41:42 -0500
-Subject: [PATCH 029/113] disable DEVMEM by default
-
----
- drivers/char/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
-index 68178c3a25de..2fd45f01e7a2 100644
---- a/drivers/char/Kconfig
-+++ b/drivers/char/Kconfig
-@@ -327,7 +327,6 @@ config NSC_GPIO
-
- config DEVMEM
- bool "/dev/mem virtual device support"
-- default y
- help
- Say Y here if you want to support the /dev/mem device.
- The /dev/mem device is used to access areas of physical
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0030-enable-IO_STRICT_DEVMEM-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0030-enable-IO_STRICT_DEVMEM-by-default.patch
deleted file mode 100644
index 68234a544720..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0030-enable-IO_STRICT_DEVMEM-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 5576916518af221c6848a39466df67b6d5f6286d Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Fri, 5 Jan 2018 12:43:49 -0500
-Subject: [PATCH 030/113] enable IO_STRICT_DEVMEM by default
-
----
- lib/Kconfig.debug | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index 45b169177fb9..a46f21a56125 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -1668,6 +1668,7 @@ config STRICT_DEVMEM
- config IO_STRICT_DEVMEM
- bool "Filter I/O access to /dev/mem"
- depends on STRICT_DEVMEM
-+ default y
- help
- If this option is disabled, you allow userspace (root) access to all
- io-memory regardless of whether a driver is actively using that
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0031-disable-COMPAT_BRK-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0031-disable-COMPAT_BRK-by-default.patch
deleted file mode 100644
index b40cee775ff1..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0031-disable-COMPAT_BRK-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 014e9eef97e005f5032a4ab0fb57b57d01a4030b Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 7 May 2017 18:28:33 -0400
-Subject: [PATCH 031/113] disable COMPAT_BRK by default
-
----
- init/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 21f0b6926cf3..4f5827e10be3 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1866,7 +1866,6 @@ config SLUB_MEMCG_SYSFS_ON
-
- config COMPAT_BRK
- bool "Disable heap randomization"
-- default y
- help
- Randomizing heap placement makes heap exploits harder, but it
- also breaks ancient binaries (including anything libc5 based).
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch
deleted file mode 100644
index e2cf38edb18f..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 298c0203615e31629f9a2c50ff3b650b168eec3c Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 7 May 2017 16:16:39 -0400
-Subject: [PATCH 032/113] use maximum supported mmap rnd entropy by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/Kconfig | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/Kconfig b/arch/Kconfig
-index 69fe7133c765..8b5c346d5dd8 100644
---- a/arch/Kconfig
-+++ b/arch/Kconfig
-@@ -752,7 +752,7 @@ config ARCH_MMAP_RND_BITS
- int "Number of bits to use for ASLR of mmap base address" if EXPERT
- range ARCH_MMAP_RND_BITS_MIN ARCH_MMAP_RND_BITS_MAX
- default ARCH_MMAP_RND_BITS_DEFAULT if ARCH_MMAP_RND_BITS_DEFAULT
-- default ARCH_MMAP_RND_BITS_MIN
-+ default ARCH_MMAP_RND_BITS_MAX
- depends on HAVE_ARCH_MMAP_RND_BITS
- help
- This value can be used to select the number of bits to use to
-@@ -786,7 +786,7 @@ config ARCH_MMAP_RND_COMPAT_BITS
- int "Number of bits to use for ASLR of mmap base address for compatible applications" if EXPERT
- range ARCH_MMAP_RND_COMPAT_BITS_MIN ARCH_MMAP_RND_COMPAT_BITS_MAX
- default ARCH_MMAP_RND_COMPAT_BITS_DEFAULT if ARCH_MMAP_RND_COMPAT_BITS_DEFAULT
-- default ARCH_MMAP_RND_COMPAT_BITS_MIN
-+ default ARCH_MMAP_RND_COMPAT_BITS_MAX
- depends on HAVE_ARCH_MMAP_RND_COMPAT_BITS
- help
- This value can be used to select the number of bits to use to
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0033-enable-protected_-symlinks-hardlinks-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0033-enable-protected_-symlinks-hardlinks-by-default.patch
deleted file mode 100644
index 4bfcfc063d6e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0033-enable-protected_-symlinks-hardlinks-by-default.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From ee6fa41fbfd9a1c5f8285ddf1acf2409afc47f07 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 30 May 2017 10:47:23 -0400
-Subject: [PATCH 033/113] enable protected_{symlinks,hardlinks} by default
-
----
- fs/namei.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/fs/namei.c b/fs/namei.c
-index d4a6dd772303..59ff3ce21026 100644
---- a/fs/namei.c
-+++ b/fs/namei.c
-@@ -932,8 +932,8 @@ static inline void put_link(struct nameidata *nd)
- path_put(&last->link);
- }
-
--int sysctl_protected_symlinks __read_mostly = 0;
--int sysctl_protected_hardlinks __read_mostly = 0;
-+int sysctl_protected_symlinks __read_mostly = 1;
-+int sysctl_protected_hardlinks __read_mostly = 1;
- int sysctl_protected_fifos __read_mostly;
- int sysctl_protected_regular __read_mostly;
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0034-enable-SECURITY-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0034-enable-SECURITY-by-default.patch
deleted file mode 100644
index 4fe943c41cde..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0034-enable-SECURITY-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 5e504c79ed89f04712c33813ee796e3b803e8872 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 02:13:48 -0500
-Subject: [PATCH 034/113] enable SECURITY by default
-
----
- security/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 3a2c68c7b50f..fa037a250821 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -23,6 +23,7 @@ config SECURITY
- bool "Enable different security models"
- depends on SYSFS
- depends on MULTIUSER
-+ default y
- help
- This allows you to choose different security modules to be
- configured into your kernel.
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0035-enable-SECURITY_YAMA-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0035-enable-SECURITY_YAMA-by-default.patch
deleted file mode 100644
index 8fe1318f9f6d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0035-enable-SECURITY_YAMA-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From aaa52818bc7880648b9fce16ca48cf665180f96f Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 29 May 2017 06:17:59 -0400
-Subject: [PATCH 035/113] enable SECURITY_YAMA by default
-
----
- security/yama/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/security/yama/Kconfig b/security/yama/Kconfig
-index a810304123ca..b809050b25d2 100644
---- a/security/yama/Kconfig
-+++ b/security/yama/Kconfig
-@@ -2,7 +2,7 @@
- config SECURITY_YAMA
- bool "Yama support"
- depends on SECURITY
-- default n
-+ default y
- help
- This selects Yama, which extends DAC support with additional
- system-wide security settings beyond regular Linux discretionary
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0036-enable-SECURITY_NETWORK-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0036-enable-SECURITY_NETWORK-by-default.patch
deleted file mode 100644
index 80267ded3c3a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0036-enable-SECURITY_NETWORK-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 48545330ffe33eb3e82e674a5f528b6abbd7330c Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 02:14:02 -0500
-Subject: [PATCH 036/113] enable SECURITY_NETWORK by default
-
----
- security/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index fa037a250821..81d0a08736aa 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -49,6 +49,7 @@ config SECURITYFS
- config SECURITY_NETWORK
- bool "Socket and Networking Security Hooks"
- depends on SECURITY
-+ default y
- help
- This enables the socket and networking security hooks.
- If enabled, a security module can use these hooks to
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0037-enable-AUDIT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0037-enable-AUDIT-by-default.patch
deleted file mode 100644
index 6789b4a7a696..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0037-enable-AUDIT-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From b533c40a16bd32ced2cc233d75f3f8a0eb7cad14 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 02:15:24 -0500
-Subject: [PATCH 037/113] enable AUDIT by default
-
----
- init/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 4f5827e10be3..9b75a4921575 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -419,6 +419,7 @@ config USELIB
- config AUDIT
- bool "Auditing support"
- depends on NET
-+ default y
- help
- Enable auditing infrastructure that can be used with another
- kernel subsystem, such as SELinux (which requires this for
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0038-enable-SECURITY_SELINUX-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0038-enable-SECURITY_SELINUX-by-default.patch
deleted file mode 100644
index 572487a584c2..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0038-enable-SECURITY_SELINUX-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 310b7f7802779cbaefa9d09edb668a5022305bd0 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 02:16:49 -0500
-Subject: [PATCH 038/113] enable SECURITY_SELINUX by default
-
----
- security/selinux/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
-index 9e921fc72538..76d7ed11513c 100644
---- a/security/selinux/Kconfig
-+++ b/security/selinux/Kconfig
-@@ -3,7 +3,7 @@ config SECURITY_SELINUX
- bool "NSA SELinux Support"
- depends on SECURITY_NETWORK && AUDIT && NET && INET
- select NETWORK_SECMARK
-- default n
-+ default y
- help
- This selects NSA Security-Enhanced Linux (SELinux).
- You will also need a policy configuration and a labeled filesystem.
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0039-enable-SYN_COOKIES-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0039-enable-SYN_COOKIES-by-default.patch
deleted file mode 100644
index ab0ff0a57ef7..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0039-enable-SYN_COOKIES-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From d2d0adc9e3bcf502bf71928752fc9ab0b589e458 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 6 Jan 2018 13:41:11 -0500
-Subject: [PATCH 039/113] enable SYN_COOKIES by default
-
----
- net/ipv4/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
-index 87983e70f03f..989e005bf698 100644
---- a/net/ipv4/Kconfig
-+++ b/net/ipv4/Kconfig
-@@ -267,6 +267,7 @@ config IP_PIMSM_V2
-
- config SYN_COOKIES
- bool "IP: TCP syncookie support"
-+ default y
- help
- Normal TCP/IP networking is open to an attack known as "SYN
- flooding". This denial-of-service attack prevents legitimate remote
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch
deleted file mode 100644
index c6ae1f45435a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 7e6d075eb0bad24cb984de968b98555c4130de6d Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Thu, 19 Sep 2019 19:02:23 +0200
-Subject: [PATCH 040/113] enable INIT_ON_ALLOC_DEFAULT_ON by default
-
----
- security/Kconfig.hardening | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
-index 269967c4fc1b..1e279f6d7633 100644
---- a/security/Kconfig.hardening
-+++ b/security/Kconfig.hardening
-@@ -190,6 +190,7 @@ config STACKLEAK_RUNTIME_DISABLE
-
- config INIT_ON_ALLOC_DEFAULT_ON
- bool "Enable heap memory zeroing on allocation by default"
-+ default yes
- help
- This has the effect of setting "init_on_alloc=1" on the kernel
- command line. This can be disabled with "init_on_alloc=0".
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch
deleted file mode 100644
index 5711346bc582..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 5af0c8005ecc18cbbd2508502fcbe10d29ccffb3 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Thu, 19 Sep 2019 19:03:01 +0200
-Subject: [PATCH 041/113] enable INIT_ON_FREE_DEFAULT_ON by default
-
----
- security/Kconfig.hardening | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
-index 1e279f6d7633..2fa447823405 100644
---- a/security/Kconfig.hardening
-+++ b/security/Kconfig.hardening
-@@ -203,6 +203,7 @@ config INIT_ON_ALLOC_DEFAULT_ON
-
- config INIT_ON_FREE_DEFAULT_ON
- bool "Enable heap memory zeroing on free by default"
-+ default yes
- help
- This has the effect of setting "init_on_free=1" on the kernel
- command line. This can be disabled with "init_on_free=0".
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch
deleted file mode 100644
index 904c2462bf04..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 04c0c41e5e366e7197b87a8f6561af64f87c51ce Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Sun, 27 Sep 2020 00:43:48 +0200
-Subject: [PATCH 042/113] kconfig: select DEBUG_FS_ALLOW_NONE by default if
- DEBUG_FS is enabled
-
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- lib/Kconfig.debug | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index a46f21a56125..4a1a32a059f4 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -488,7 +488,7 @@ config DEBUG_FS
- choice
- prompt "Debugfs default access"
- depends on DEBUG_FS
-- default DEBUG_FS_ALLOW_ALL
-+ default DEBUG_FS_ALLOW_NONE
- help
- This selects the default access restrictions for debugfs.
- It can be overridden with kernel command line option
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch
deleted file mode 100644
index 4e52cabbcfa0..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From d1b970b059d3ff73991183053053ed2774ebc638 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Tue, 22 Dec 2020 23:35:53 +0100
-Subject: [PATCH 043/113] stop hiding SYSFS_SYSCALL behind EXPERT
-
----
- init/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 9b75a4921575..006d4d41e3af 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1434,7 +1434,7 @@ config SGETMASK_SYSCALL
- If unsure, leave the default option here.
-
- config SYSFS_SYSCALL
-- bool "Sysfs syscall support" if EXPERT
-+ bool "Sysfs syscall support"
- default y
- help
- sys_sysfs is an obsolete system call no longer supported in libc.
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0044-disable-SYSFS_SYSCALL-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0044-disable-SYSFS_SYSCALL-by-default.patch
deleted file mode 100644
index 687b5d71f893..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0044-disable-SYSFS_SYSCALL-by-default.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 53e350265c1574a899183650400619c5874889d8 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Tue, 22 Dec 2020 23:36:54 +0100
-Subject: [PATCH 044/113] disable SYSFS_SYSCALL by default
-
----
- init/Kconfig | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 006d4d41e3af..3d6b1b23e2db 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1435,13 +1435,12 @@ config SGETMASK_SYSCALL
-
- config SYSFS_SYSCALL
- bool "Sysfs syscall support"
-- default y
- help
- sys_sysfs is an obsolete system call no longer supported in libc.
- Note that disabling this option is more secure but might break
- compatibility with some systems.
-
-- If unsure say Y here.
-+ If unsure say N here.
-
- config FHANDLE
- bool "open by fhandle syscalls" if EXPERT
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0045-stop-hiding-UID16-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0045-stop-hiding-UID16-behind-EXPERT.patch
deleted file mode 100644
index 3b3b9edf3b54..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0045-stop-hiding-UID16-behind-EXPERT.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 31ed255051d07e3cc4eba6046f2b2a7597025793 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Tue, 22 Dec 2020 23:40:09 +0100
-Subject: [PATCH 045/113] stop hiding UID16 behind EXPERT
-
----
- init/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 3d6b1b23e2db..2b6d0492def5 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1403,7 +1403,7 @@ menuconfig EXPERT
- Only use this if you really know what you are doing.
-
- config UID16
-- bool "Enable 16-bit UID system calls" if EXPERT
-+ bool "Enable 16-bit UID system calls"
- depends on HAVE_UID16 && MULTIUSER
- default y
- help
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0046-disable-UID16-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0046-disable-UID16-by-default.patch
deleted file mode 100644
index e0fa54022fa1..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0046-disable-UID16-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From b4176b366266bd6e1338016640c01bf499615352 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Tue, 22 Dec 2020 23:41:32 +0100
-Subject: [PATCH 046/113] disable UID16 by default
-
----
- init/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 2b6d0492def5..58df4930995f 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1405,7 +1405,6 @@ menuconfig EXPERT
- config UID16
- bool "Enable 16-bit UID system calls"
- depends on HAVE_UID16 && MULTIUSER
-- default y
- help
- This enables the legacy 16-bit UID syscall wrappers.
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0047-add-__read_only-for-non-init-related-usage.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0047-add-__read_only-for-non-init-related-usage.patch
deleted file mode 100644
index 62d94d53777e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0047-add-__read_only-for-non-init-related-usage.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 30acc7eb764b9d493b289216420d40b964d2bdad Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 7 May 2017 00:28:23 -0400
-Subject: [PATCH 047/113] add __read_only for non-init related usage
-
----
- include/linux/cache.h | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/include/linux/cache.h b/include/linux/cache.h
-index d742c57eaee5..f0222c070458 100644
---- a/include/linux/cache.h
-+++ b/include/linux/cache.h
-@@ -37,6 +37,8 @@
- #define __ro_after_init __section(".data..ro_after_init")
- #endif
-
-+#define __read_only __ro_after_init
-+
- #ifndef ____cacheline_aligned
- #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
- #endif
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0048-make-sysctl-constants-read-only.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0048-make-sysctl-constants-read-only.patch
deleted file mode 100644
index 1d7c3a9cbde7..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0048-make-sysctl-constants-read-only.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-From e072e215c7638643d97034e5256edfa2a7e99ca8 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 7 May 2017 00:43:03 -0400
-Subject: [PATCH 048/113] make sysctl constants read-only
-
-Most of this is extracted from the last publicly available version of
-the PaX patches where it's part of KERNEXEC as __read_only. It has been
-extended to a few more of these constants.
----
- kernel/sysctl.c | 54 ++++++++++++++++++++++++-------------------------
- 1 file changed, 27 insertions(+), 27 deletions(-)
-
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index afad085960b8..b2cd3dbbb17a 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -108,33 +108,33 @@
-
- /* Constants used for minimum and maximum */
- #ifdef CONFIG_LOCKUP_DETECTOR
--static int sixty = 60;
--#endif
--
--static int __maybe_unused neg_one = -1;
--static int __maybe_unused two = 2;
--static int __maybe_unused four = 4;
--static unsigned long zero_ul;
--static unsigned long one_ul = 1;
--static unsigned long long_max = LONG_MAX;
--static int one_hundred = 100;
--static int two_hundred = 200;
--static int one_thousand = 1000;
-+static int sixty __read_only = 60;
-+#endif
-+
-+static int __maybe_unused neg_one __read_only = -1;
-+static int __maybe_unused two __read_only = 2;
-+static int __maybe_unused four __read_only = 4;
-+static unsigned long zero_ul __read_only;
-+static unsigned long one_ul __read_only = 1;
-+static unsigned long long_max __read_only = LONG_MAX;
-+static int one_hundred __read_only = 100;
-+static int two_hundred __read_only = 200;
-+static int one_thousand __read_only = 1000;
- #ifdef CONFIG_PRINTK
--static int ten_thousand = 10000;
-+static int ten_thousand __read_only = 10000;
- #endif
- #ifdef CONFIG_PERF_EVENTS
--static int six_hundred_forty_kb = 640 * 1024;
-+static int six_hundred_forty_kb __read_only = 640 * 1024;
- #endif
-
- /* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */
--static unsigned long dirty_bytes_min = 2 * PAGE_SIZE;
-+static unsigned long dirty_bytes_min __read_only = 2 * PAGE_SIZE;
-
- /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
--static int maxolduid = 65535;
--static int minolduid;
-+static int maxolduid __read_only = 65535;
-+static int minolduid __read_only;
-
--static int ngroups_max = NGROUPS_MAX;
-+static int ngroups_max __read_only = NGROUPS_MAX;
- static const int cap_last_cap = CAP_LAST_CAP;
-
- /*
-@@ -142,7 +142,7 @@ static const int cap_last_cap = CAP_LAST_CAP;
- * and hung_task_check_interval_secs
- */
- #ifdef CONFIG_DETECT_HUNG_TASK
--static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
-+static unsigned long hung_task_timeout_max __read_only = (LONG_MAX/HZ);
- #endif
-
- #ifdef CONFIG_INOTIFY_USER
-@@ -185,19 +185,19 @@ int sysctl_legacy_va_layout;
- #endif
-
- #ifdef CONFIG_SCHED_DEBUG
--static int min_sched_granularity_ns = 100000; /* 100 usecs */
--static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */
--static int min_wakeup_granularity_ns; /* 0 usecs */
--static int max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */
-+static int min_sched_granularity_ns __read_only = 100000; /* 100 usecs */
-+static int max_sched_granularity_ns __read_only = NSEC_PER_SEC; /* 1 second */
-+static int min_wakeup_granularity_ns __read_only; /* 0 usecs */
-+static int max_wakeup_granularity_ns __read_only = NSEC_PER_SEC; /* 1 second */
- #ifdef CONFIG_SMP
--static int min_sched_tunable_scaling = SCHED_TUNABLESCALING_NONE;
--static int max_sched_tunable_scaling = SCHED_TUNABLESCALING_END-1;
-+static int min_sched_tunable_scaling __read_only = SCHED_TUNABLESCALING_NONE;
-+static int max_sched_tunable_scaling __read_only = SCHED_TUNABLESCALING_END-1;
- #endif /* CONFIG_SMP */
- #endif /* CONFIG_SCHED_DEBUG */
-
- #ifdef CONFIG_COMPACTION
--static int min_extfrag_threshold;
--static int max_extfrag_threshold = 1000;
-+static int min_extfrag_threshold __read_only;
-+static int max_extfrag_threshold __read_only = 1000;
- #endif
-
- #endif /* CONFIG_SYSCTL */
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch
deleted file mode 100644
index 21abe2cd07cc..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 2225770e9e617726c0479070670a5f5320ca1a68 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Fri, 12 May 2017 03:22:00 -0400
-Subject: [PATCH 049/113] mark kernel_set_to_readonly as __ro_after_init
-
-This change was extracted from PaX where it's part of KERNEXEC.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/mm/init_32.c | 5 ++---
- arch/x86/mm/init_64.c | 5 ++---
- 2 files changed, 4 insertions(+), 6 deletions(-)
-
-diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
-index 7c055259de3a..77192cbc1dd7 100644
---- a/arch/x86/mm/init_32.c
-+++ b/arch/x86/mm/init_32.c
-@@ -828,7 +828,7 @@ void arch_remove_memory(int nid, u64 start, u64 size,
- }
- #endif
-
--int kernel_set_to_readonly __read_mostly;
-+int kernel_set_to_readonly __ro_after_init;
-
- static void mark_nxdata_nx(void)
- {
-@@ -852,12 +852,11 @@ void mark_rodata_ro(void)
- unsigned long start = PFN_ALIGN(_text);
- unsigned long size = (unsigned long)__end_rodata - start;
-
-+ kernel_set_to_readonly = 1;
- set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
- pr_info("Write protecting kernel text and read-only data: %luk\n",
- size >> 10);
-
-- kernel_set_to_readonly = 1;
--
- #ifdef CONFIG_CPA_DEBUG
- pr_info("Testing CPA: Reverting %lx-%lx\n", start, start + size);
- set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT);
-diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
-index b5a3fa4033d3..63a0f8097d0a 100644
---- a/arch/x86/mm/init_64.c
-+++ b/arch/x86/mm/init_64.c
-@@ -1322,7 +1322,7 @@ int __init deferred_page_init_max_threads(const struct cpumask *node_cpumask)
- }
- #endif
-
--int kernel_set_to_readonly;
-+int kernel_set_to_readonly __ro_after_init;
-
- void mark_rodata_ro(void)
- {
-@@ -1335,9 +1335,8 @@ void mark_rodata_ro(void)
-
- printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
- (end - start) >> 10);
-- set_memory_ro(start, (end - start) >> PAGE_SHIFT);
--
- kernel_set_to_readonly = 1;
-+ set_memory_ro(start, (end - start) >> PAGE_SHIFT);
-
- /*
- * The rodata/data/bss/brk section (but not the kernel text!)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch
deleted file mode 100644
index da795428a267..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From 8f8a6e20ae25c4e2955b3c1918392ef54bb7dccf Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Sun, 13 Jan 2019 21:42:45 +0100
-Subject: [PATCH 050/113] Revert "mark kernel_set_to_readonly as
- __ro_after_init"
-
- This commit causes CPA conflicts, cf.
- https://github.com/anthraxx/linux-hardened/issues/4.
-
- Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
----
- arch/x86/mm/init_32.c | 5 +++--
- arch/x86/mm/init_64.c | 5 +++--
- 2 files changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
-index 77192cbc1dd7..7c055259de3a 100644
---- a/arch/x86/mm/init_32.c
-+++ b/arch/x86/mm/init_32.c
-@@ -828,7 +828,7 @@ void arch_remove_memory(int nid, u64 start, u64 size,
- }
- #endif
-
--int kernel_set_to_readonly __ro_after_init;
-+int kernel_set_to_readonly __read_mostly;
-
- static void mark_nxdata_nx(void)
- {
-@@ -852,11 +852,12 @@ void mark_rodata_ro(void)
- unsigned long start = PFN_ALIGN(_text);
- unsigned long size = (unsigned long)__end_rodata - start;
-
-- kernel_set_to_readonly = 1;
- set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
- pr_info("Write protecting kernel text and read-only data: %luk\n",
- size >> 10);
-
-+ kernel_set_to_readonly = 1;
-+
- #ifdef CONFIG_CPA_DEBUG
- pr_info("Testing CPA: Reverting %lx-%lx\n", start, start + size);
- set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT);
-diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
-index 63a0f8097d0a..b5a3fa4033d3 100644
---- a/arch/x86/mm/init_64.c
-+++ b/arch/x86/mm/init_64.c
-@@ -1322,7 +1322,7 @@ int __init deferred_page_init_max_threads(const struct cpumask *node_cpumask)
- }
- #endif
-
--int kernel_set_to_readonly __ro_after_init;
-+int kernel_set_to_readonly;
-
- void mark_rodata_ro(void)
- {
-@@ -1335,9 +1335,10 @@ void mark_rodata_ro(void)
-
- printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
- (end - start) >> 10);
-- kernel_set_to_readonly = 1;
- set_memory_ro(start, (end - start) >> PAGE_SHIFT);
-
-+ kernel_set_to_readonly = 1;
-+
- /*
- * The rodata/data/bss/brk section (but not the kernel text!)
- * should also be not-executable.
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0051-mark-slub-runtime-configuration-as-__ro_after_init.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0051-mark-slub-runtime-configuration-as-__ro_after_init.patch
deleted file mode 100644
index 0a3e389a276b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0051-mark-slub-runtime-configuration-as-__ro_after_init.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 198bdbf6f07004c19ed43beed00b9362a2b7c0d1 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 14 May 2017 19:01:58 -0400
-Subject: [PATCH 051/113] mark slub runtime configuration as __ro_after_init
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/slub.c | 16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/mm/slub.c b/mm/slub.c
-index 071e41067ea6..e01d54dc46e1 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -486,13 +486,13 @@ static inline void *restore_red_left(struct kmem_cache *s, void *p)
- * Debug settings:
- */
- #if defined(CONFIG_SLUB_DEBUG_ON)
--static slab_flags_t slub_debug = DEBUG_DEFAULT_FLAGS;
-+static slab_flags_t slub_debug __ro_after_init = DEBUG_DEFAULT_FLAGS;
- #else
--static slab_flags_t slub_debug;
-+static slab_flags_t slub_debug __ro_after_init;
- #endif
-
--static char *slub_debug_string;
--static int disable_higher_order_debug;
-+static char *slub_debug_string __ro_after_init;
-+static int disable_higher_order_debug __ro_after_init;
-
- /*
- * slub is about to manipulate internal object metadata. This memory lies
-@@ -3363,9 +3363,9 @@ EXPORT_SYMBOL(kmem_cache_alloc_bulk);
- * and increases the number of allocations possible without having to
- * take the list_lock.
- */
--static unsigned int slub_min_order;
--static unsigned int slub_max_order = PAGE_ALLOC_COSTLY_ORDER;
--static unsigned int slub_min_objects;
-+static unsigned int slub_min_order __ro_after_init;
-+static unsigned int slub_max_order __ro_after_init = PAGE_ALLOC_COSTLY_ORDER;
-+static unsigned int slub_min_objects __ro_after_init;
-
- /*
- * Calculate the order of allocation given an slab object size.
-@@ -4883,7 +4883,7 @@ enum slab_stat_type {
- #define SO_TOTAL (1 << SL_TOTAL)
-
- #ifdef CONFIG_MEMCG
--static bool memcg_sysfs_enabled = IS_ENABLED(CONFIG_SLUB_MEMCG_SYSFS_ON);
-+static bool memcg_sysfs_enabled __ro_after_init = IS_ENABLED(CONFIG_SLUB_MEMCG_SYSFS_ON);
-
- static int __init setup_slub_memcg_sysfs(char *str)
- {
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch
deleted file mode 100644
index 14654130eb71..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From e047a42de28f9c44533b166e08fa308011eecdfa Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 11:35:35 -0400
-Subject: [PATCH 052/113] add __ro_after_init to slab_nomerge and slab_state
-
-This was extracted from the PaX patch where it's part of the KERNEXEC
-feature as __read_only.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/slab_common.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/mm/slab_common.c b/mm/slab_common.c
-index f9ccd5dc13f3..bff04048559f 100644
---- a/mm/slab_common.c
-+++ b/mm/slab_common.c
-@@ -30,7 +30,7 @@
-
- #include "slab.h"
-
--enum slab_state slab_state;
-+enum slab_state slab_state __ro_after_init;
- LIST_HEAD(slab_caches);
- DEFINE_MUTEX(slab_mutex);
- struct kmem_cache *kmem_cache;
-@@ -61,7 +61,7 @@ static DECLARE_WORK(slab_caches_to_rcu_destroy_work,
- /*
- * Merge control. If this is set then no merging of slab caches will occur.
- */
--static bool slab_nomerge = !IS_ENABLED(CONFIG_SLAB_MERGE_DEFAULT);
-+static bool slab_nomerge __ro_after_init = !IS_ENABLED(CONFIG_SLAB_MERGE_DEFAULT);
-
- static int __init setup_slab_nomerge(char *str)
- {
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0053-mark-kmem_cache-as-__ro_after_init.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0053-mark-kmem_cache-as-__ro_after_init.patch
deleted file mode 100644
index 263c05d35b31..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0053-mark-kmem_cache-as-__ro_after_init.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 27946a5aa907b739ad7618f5068ef3fbc16d6a1b Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 28 May 2017 18:51:30 -0400
-Subject: [PATCH 053/113] mark kmem_cache as __ro_after_init
-
----
- mm/slab_common.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/mm/slab_common.c b/mm/slab_common.c
-index bff04048559f..2b73c12d8fce 100644
---- a/mm/slab_common.c
-+++ b/mm/slab_common.c
-@@ -33,7 +33,7 @@
- enum slab_state slab_state __ro_after_init;
- LIST_HEAD(slab_caches);
- DEFINE_MUTEX(slab_mutex);
--struct kmem_cache *kmem_cache;
-+struct kmem_cache *kmem_cache __ro_after_init;
-
- #ifdef CONFIG_HARDENED_USERCOPY
- bool usercopy_fallback __ro_after_init =
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0054-mark-__supported_pte_mask-as-__ro_after_init.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0054-mark-__supported_pte_mask-as-__ro_after_init.patch
deleted file mode 100644
index 2d9cf6d81bbd..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0054-mark-__supported_pte_mask-as-__ro_after_init.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 5b076434040e271325cfbe308697669866d0dbad Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Fri, 12 May 2017 00:06:16 -0400
-Subject: [PATCH 054/113] mark __supported_pte_mask as __ro_after_init
-
-These changes were extracted from PaX where it was part of KERNEXEC as
-__read_only.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/mm/init_32.c | 4 ++--
- arch/x86/mm/init_64.c | 4 ++--
- 2 files changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
-index 7c055259de3a..291b7b4476a9 100644
---- a/arch/x86/mm/init_32.c
-+++ b/arch/x86/mm/init_32.c
-@@ -546,9 +546,9 @@ static void __init pagetable_init(void)
-
- #define DEFAULT_PTE_MASK ~(_PAGE_NX | _PAGE_GLOBAL)
- /* Bits supported by the hardware: */
--pteval_t __supported_pte_mask __read_mostly = DEFAULT_PTE_MASK;
-+pteval_t __supported_pte_mask __ro_after_init = DEFAULT_PTE_MASK;
- /* Bits allowed in normal kernel mappings: */
--pteval_t __default_kernel_pte_mask __read_mostly = DEFAULT_PTE_MASK;
-+pteval_t __default_kernel_pte_mask __ro_after_init = DEFAULT_PTE_MASK;
- EXPORT_SYMBOL_GPL(__supported_pte_mask);
- /* Used in PAGE_KERNEL_* macros which are reasonably used out-of-tree: */
- EXPORT_SYMBOL(__default_kernel_pte_mask);
-diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
-index b5a3fa4033d3..c3d771ffc178 100644
---- a/arch/x86/mm/init_64.c
-+++ b/arch/x86/mm/init_64.c
-@@ -97,9 +97,9 @@ DEFINE_ENTRY(pte, pte, init)
- */
-
- /* Bits supported by the hardware: */
--pteval_t __supported_pte_mask __read_mostly = ~0;
-+pteval_t __supported_pte_mask __ro_after_init = ~0;
- /* Bits allowed in normal kernel mappings: */
--pteval_t __default_kernel_pte_mask __read_mostly = ~0;
-+pteval_t __default_kernel_pte_mask __ro_after_init = ~0;
- EXPORT_SYMBOL_GPL(__supported_pte_mask);
- /* Used in PAGE_KERNEL_* macros which are reasonably used out-of-tree: */
- EXPORT_SYMBOL(__default_kernel_pte_mask);
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0055-mark-kobj_ns_type_register-as-only-used-for-init.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0055-mark-kobj_ns_type_register-as-only-used-for-init.patch
deleted file mode 100644
index e67e1a04ba1e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0055-mark-kobj_ns_type_register-as-only-used-for-init.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From a9c8d6781479778a5f4d3b6a37dcab43f7e4e5f0 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 01:24:28 -0400
-Subject: [PATCH 055/113] mark kobj_ns_type_register as only used for init
-
-This allows kobj_ns_ops_tbl to be __ro_after_init.
-
-Extracted from PaX.
----
- include/linux/kobject_ns.h | 2 +-
- lib/kobject.c | 4 ++--
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/include/linux/kobject_ns.h b/include/linux/kobject_ns.h
-index 2b5b64256cf4..8cdce21dce0f 100644
---- a/include/linux/kobject_ns.h
-+++ b/include/linux/kobject_ns.h
-@@ -45,7 +45,7 @@ struct kobj_ns_type_operations {
- void (*drop_ns)(void *);
- };
-
--int kobj_ns_type_register(const struct kobj_ns_type_operations *ops);
-+int __init kobj_ns_type_register(const struct kobj_ns_type_operations *ops);
- int kobj_ns_type_registered(enum kobj_ns_type type);
- const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent);
- const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj);
-diff --git a/lib/kobject.c b/lib/kobject.c
-index ea53b30cf483..5343bbeea5f8 100644
---- a/lib/kobject.c
-+++ b/lib/kobject.c
-@@ -1023,9 +1023,9 @@ EXPORT_SYMBOL_GPL(kset_create_and_add);
-
-
- static DEFINE_SPINLOCK(kobj_ns_type_lock);
--static const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES];
-+static const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES] __ro_after_init;
-
--int kobj_ns_type_register(const struct kobj_ns_type_operations *ops)
-+int __init kobj_ns_type_register(const struct kobj_ns_type_operations *ops)
- {
- enum kobj_ns_type type = ops->type;
- int error;
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0056-mark-open_softirq-as-only-used-for-init.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0056-mark-open_softirq-as-only-used-for-init.patch
deleted file mode 100644
index ab6fb5c02d7e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0056-mark-open_softirq-as-only-used-for-init.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 5c392668b5b1de733d318a4a78a1cdbd5e4e8364 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 01:32:30 -0400
-Subject: [PATCH 056/113] mark open_softirq as only used for init
-
----
- include/linux/interrupt.h | 2 +-
- kernel/softirq.c | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
-index ee8299eb1f52..f03b78ae5f0a 100644
---- a/include/linux/interrupt.h
-+++ b/include/linux/interrupt.h
-@@ -569,7 +569,7 @@ static inline void do_softirq_own_stack(void)
- }
- #endif
-
--extern void open_softirq(int nr, void (*action)(struct softirq_action *));
-+extern void __init open_softirq(int nr, void (*action)(struct softirq_action *));
- extern void softirq_init(void);
- extern void __raise_softirq_irqoff(unsigned int nr);
-
-diff --git a/kernel/softirq.c b/kernel/softirq.c
-index 09229ad82209..0595a8248c4a 100644
---- a/kernel/softirq.c
-+++ b/kernel/softirq.c
-@@ -486,7 +486,7 @@ void __raise_softirq_irqoff(unsigned int nr)
- or_softirq_pending(1UL << nr);
- }
-
--void open_softirq(int nr, void (*action)(struct softirq_action *))
-+void __init open_softirq(int nr, void (*action)(struct softirq_action *))
- {
- softirq_vec[nr].action = action;
- }
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0057-remove-unused-softirq_action-callback-parameter.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0057-remove-unused-softirq_action-callback-parameter.patch
deleted file mode 100644
index bec6f980588d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0057-remove-unused-softirq_action-callback-parameter.patch
+++ /dev/null
@@ -1,208 +0,0 @@
-From afc4f4480c3f45cc088ae887f06e0472e3846667 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 01:41:11 -0400
-Subject: [PATCH 057/113] remove unused softirq_action callback parameter
-
-Extracted from PaX.
----
- block/blk-mq.c | 2 +-
- include/linux/interrupt.h | 4 ++--
- kernel/rcu/tiny.c | 2 +-
- kernel/rcu/tree.c | 2 +-
- kernel/sched/fair.c | 2 +-
- kernel/softirq.c | 15 +++++++--------
- kernel/time/hrtimer.c | 2 +-
- kernel/time/timer.c | 2 +-
- lib/irq_poll.c | 2 +-
- net/core/dev.c | 4 ++--
- 10 files changed, 18 insertions(+), 19 deletions(-)
-
-diff --git a/block/blk-mq.c b/block/blk-mq.c
-index 2a1eff60c797..75a0077ea1a9 100644
---- a/block/blk-mq.c
-+++ b/block/blk-mq.c
-@@ -569,7 +569,7 @@ EXPORT_SYMBOL(blk_mq_end_request);
- * Softirq action handler - move entries to local list and loop over them
- * while passing them to the queue registered handler.
- */
--static __latent_entropy void blk_done_softirq(struct softirq_action *h)
-+static __latent_entropy void blk_done_softirq(void)
- {
- struct list_head *cpu_list, local_list;
-
-diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
-index f03b78ae5f0a..4381b79f76cf 100644
---- a/include/linux/interrupt.h
-+++ b/include/linux/interrupt.h
-@@ -554,7 +554,7 @@ extern const char * const softirq_to_name[NR_SOFTIRQS];
-
- struct softirq_action
- {
-- void (*action)(struct softirq_action *);
-+ void (*action)(void);
- };
-
- asmlinkage void do_softirq(void);
-@@ -569,7 +569,7 @@ static inline void do_softirq_own_stack(void)
- }
- #endif
-
--extern void __init open_softirq(int nr, void (*action)(struct softirq_action *));
-+extern void __init open_softirq(int nr, void (*action)(void));
- extern void softirq_init(void);
- extern void __raise_softirq_irqoff(unsigned int nr);
-
-diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
-index aa897c3f2e92..d8976886fd68 100644
---- a/kernel/rcu/tiny.c
-+++ b/kernel/rcu/tiny.c
-@@ -101,7 +101,7 @@ static inline bool rcu_reclaim_tiny(struct rcu_head *head)
- }
-
- /* Invoke the RCU callbacks whose grace period has elapsed. */
--static __latent_entropy void rcu_process_callbacks(struct softirq_action *unused)
-+static __latent_entropy void rcu_process_callbacks(void)
- {
- struct rcu_head *next, *list;
- unsigned long flags;
-diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
-index 593df7edfe97..3285d81d8a26 100644
---- a/kernel/rcu/tree.c
-+++ b/kernel/rcu/tree.c
-@@ -2722,7 +2722,7 @@ static __latent_entropy void rcu_core(void)
- queue_work_on(rdp->cpu, rcu_gp_wq, &rdp->strict_work);
- }
-
--static void rcu_core_si(struct softirq_action *h)
-+static void rcu_core_si(void)
- {
- rcu_core();
- }
-diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
-index ae7ceba8fd4f..d118be5f18b8 100644
---- a/kernel/sched/fair.c
-+++ b/kernel/sched/fair.c
-@@ -10628,7 +10628,7 @@ static int newidle_balance(struct rq *this_rq, struct rq_flags *rf)
- * run_rebalance_domains is triggered when needed from the scheduler tick.
- * Also triggered for nohz idle balancing (with nohz_balancing_kick set).
- */
--static __latent_entropy void run_rebalance_domains(struct softirq_action *h)
-+static __latent_entropy void run_rebalance_domains(void)
- {
- struct rq *this_rq = this_rq();
- enum cpu_idle_type idle = this_rq->idle_balance ?
-diff --git a/kernel/softirq.c b/kernel/softirq.c
-index 0595a8248c4a..3a21b22227c1 100644
---- a/kernel/softirq.c
-+++ b/kernel/softirq.c
-@@ -295,7 +295,7 @@ asmlinkage __visible void __softirq_entry __do_softirq(void)
- kstat_incr_softirqs_this_cpu(vec_nr);
-
- trace_softirq_entry(vec_nr);
-- h->action(h);
-+ h->action();
- trace_softirq_exit(vec_nr);
- if (unlikely(prev_count != preempt_count())) {
- pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n",
-@@ -486,7 +486,7 @@ void __raise_softirq_irqoff(unsigned int nr)
- or_softirq_pending(1UL << nr);
- }
-
--void __init open_softirq(int nr, void (*action)(struct softirq_action *))
-+void __init open_softirq(int nr, void (*action)(void))
- {
- softirq_vec[nr].action = action;
- }
-@@ -532,8 +532,7 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
- }
- EXPORT_SYMBOL(__tasklet_hi_schedule);
-
--static void tasklet_action_common(struct softirq_action *a,
-- struct tasklet_head *tl_head,
-+static void tasklet_action_common(struct tasklet_head *tl_head,
- unsigned int softirq_nr)
- {
- struct tasklet_struct *list;
-@@ -573,14 +572,14 @@ static void tasklet_action_common(struct softirq_action *a,
- }
- }
-
--static __latent_entropy void tasklet_action(struct softirq_action *a)
-+static __latent_entropy void tasklet_action(void)
- {
-- tasklet_action_common(a, this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ);
-+ tasklet_action_common(this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ);
- }
-
--static __latent_entropy void tasklet_hi_action(struct softirq_action *a)
-+static __latent_entropy void tasklet_hi_action(void)
- {
-- tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);
-+ tasklet_action_common(this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);
- }
-
- void tasklet_setup(struct tasklet_struct *t,
-diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
-index 387b4bef7dd1..8fe28c28a906 100644
---- a/kernel/time/hrtimer.c
-+++ b/kernel/time/hrtimer.c
-@@ -1587,7 +1587,7 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now,
- }
- }
-
--static __latent_entropy void hrtimer_run_softirq(struct softirq_action *h)
-+static __latent_entropy void hrtimer_run_softirq(void)
- {
- struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
- unsigned long flags;
-diff --git a/kernel/time/timer.c b/kernel/time/timer.c
-index c3ad64fb9d8b..217bc49a3856 100644
---- a/kernel/time/timer.c
-+++ b/kernel/time/timer.c
-@@ -1753,7 +1753,7 @@ static inline void __run_timers(struct timer_base *base)
- /*
- * This function runs timers and the timer-tq in bottom half context.
- */
--static __latent_entropy void run_timer_softirq(struct softirq_action *h)
-+static __latent_entropy void run_timer_softirq(void)
- {
- struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
-
-diff --git a/lib/irq_poll.c b/lib/irq_poll.c
-index 2f17b488d58e..b6e7996a0058 100644
---- a/lib/irq_poll.c
-+++ b/lib/irq_poll.c
-@@ -75,7 +75,7 @@ void irq_poll_complete(struct irq_poll *iop)
- }
- EXPORT_SYMBOL(irq_poll_complete);
-
--static void __latent_entropy irq_poll_softirq(struct softirq_action *h)
-+static void __latent_entropy irq_poll_softirq(void)
- {
- struct list_head *list = this_cpu_ptr(&blk_cpu_iopoll);
- int rearm = 0, budget = irq_poll_budget;
-diff --git a/net/core/dev.c b/net/core/dev.c
-index 81e5d482c238..172fd10f4b01 100644
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -4856,7 +4856,7 @@ int netif_rx_any_context(struct sk_buff *skb)
- }
- EXPORT_SYMBOL(netif_rx_any_context);
-
--static __latent_entropy void net_tx_action(struct softirq_action *h)
-+static __latent_entropy void net_tx_action(void)
- {
- struct softnet_data *sd = this_cpu_ptr(&softnet_data);
-
-@@ -6803,7 +6803,7 @@ static int napi_poll(struct napi_struct *n, struct list_head *repoll)
- return work;
- }
-
--static __latent_entropy void net_rx_action(struct softirq_action *h)
-+static __latent_entropy void net_rx_action(void)
- {
- struct softnet_data *sd = this_cpu_ptr(&softnet_data);
- unsigned long time_limit = jiffies +
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0058-mark-softirq_vec-as-__ro_after_init.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0058-mark-softirq_vec-as-__ro_after_init.patch
deleted file mode 100644
index 016600649186..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0058-mark-softirq_vec-as-__ro_after_init.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 63b8a34267f8199af0898ec9ceeed076da78d138 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 01:42:33 -0400
-Subject: [PATCH 058/113] mark softirq_vec as __ro_after_init
-
-Note: __cacheline_aligned_in_smp conflicts with __ro_after_init on x86.
-
-Extracted from PaX.
----
- kernel/softirq.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/kernel/softirq.c b/kernel/softirq.c
-index 3a21b22227c1..6a02d63b135a 100644
---- a/kernel/softirq.c
-+++ b/kernel/softirq.c
-@@ -52,7 +52,7 @@ DEFINE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat);
- EXPORT_PER_CPU_SYMBOL(irq_stat);
- #endif
-
--static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
-+static struct softirq_action softirq_vec[NR_SOFTIRQS] __ro_after_init __aligned(PAGE_SIZE);
-
- DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch
deleted file mode 100644
index 46a7e739985f..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 571b2ad3a286d61ad03c540f39254232e6b3a2c4 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 17 Sep 2019 18:00:54 +0200
-Subject: [PATCH 059/113] mm: slab: trigger BUG if requested object is not a
- slab page
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
----
- mm/slab.h | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/mm/slab.h b/mm/slab.h
-index f9977d6613d6..5adb48bb2e68 100644
---- a/mm/slab.h
-+++ b/mm/slab.h
-@@ -435,9 +435,13 @@ static inline struct kmem_cache *virt_to_cache(const void *obj)
- struct page *page;
-
- page = virt_to_head_page(obj);
-+#ifdef CONFIG_BUG_ON_DATA_CORRUPTION
-+ BUG_ON(!PageSlab(page));
-+#else
- if (WARN_ONCE(!PageSlab(page), "%s: Object is not a Slab page!\n",
- __func__))
- return NULL;
-+#endif
- return page->slab_cache;
- }
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch
deleted file mode 100644
index 59b6d982192e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 0f86c29273194d587c300415e1ad0d1f10b44142 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 11:50:53 -0400
-Subject: [PATCH 060/113] bug on kmem_cache_free with the wrong cache
-
-At least when CONFIG_BUG_ON_DATA_CORRUPTION is enabled.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- mm/slab.h | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
-diff --git a/mm/slab.h b/mm/slab.h
-index 5adb48bb2e68..9fef4285514a 100644
---- a/mm/slab.h
-+++ b/mm/slab.h
-@@ -471,10 +471,15 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x)
- return s;
-
- cachep = virt_to_cache(x);
-- if (WARN(cachep && cachep != s,
-- "%s: Wrong slab cache. %s but object is from %s\n",
-- __func__, s->name, cachep->name))
-+ if (cachep && cachep != s) {
-+#ifdef CONFIG_BUG_ON_DATA_CORRUPTION
-+ BUG();
-+#else
-+ WARN(1, "%s: Wrong slab cache. %s but object is from %s\n",
-+ __func__, s->name, cachep->name);
-+#endif
- print_tracking(cachep, x);
-+ }
- return cachep;
- }
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0061-bug-on-PageSlab-PageCompound-in-ksize.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0061-bug-on-PageSlab-PageCompound-in-ksize.patch
deleted file mode 100644
index 493213c185e2..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0061-bug-on-PageSlab-PageCompound-in-ksize.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 7393e858694ce70187c84975acbd0bae812b4971 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 11:57:35 -0400
-Subject: [PATCH 061/113] bug on !PageSlab && !PageCompound in ksize
-
-At least when CONFIG_BUG_ON_DATA_CORRUPTION is enabled.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/slub.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/mm/slub.c b/mm/slub.c
-index e01d54dc46e1..07ce7cac2612 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -4092,7 +4092,11 @@ size_t __ksize(const void *object)
- page = virt_to_head_page(object);
-
- if (unlikely(!PageSlab(page))) {
-+#ifdef CONFIG_BUG_ON_DATA_CORRUPTION
-+ BUG_ON(!PageCompound(page));
-+#else
- WARN_ON(!PageCompound(page));
-+#endif
- return page_size(page);
- }
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0062-mm-add-support-for-verifying-page-sanitization.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0062-mm-add-support-for-verifying-page-sanitization.patch
deleted file mode 100644
index 7736c1777364..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0062-mm-add-support-for-verifying-page-sanitization.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From bc7dde0b61e6e2338808b8ec67bd3215842b4679 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 21:54:56 -0400
-Subject: [PATCH 062/113] mm: add support for verifying page sanitization
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- include/linux/highmem.h | 7 +++++++
- mm/page_alloc.c | 6 ++++++
- security/Kconfig.hardening | 7 +++++++
- 3 files changed, 20 insertions(+)
-
-diff --git a/include/linux/highmem.h b/include/linux/highmem.h
-index 14e6202ce47f..4348ad7f5c50 100644
---- a/include/linux/highmem.h
-+++ b/include/linux/highmem.h
-@@ -284,6 +284,13 @@ static inline void clear_highpage(struct page *page)
- kunmap_atomic(kaddr);
- }
-
-+static inline void verify_zero_highpage(struct page *page)
-+{
-+ void *kaddr = kmap_atomic(page);
-+ BUG_ON(memchr_inv(kaddr, 0, PAGE_SIZE));
-+ kunmap_atomic(kaddr);
-+}
-+
- static inline void zero_user_segments(struct page *page,
- unsigned start1, unsigned end1,
- unsigned start2, unsigned end2)
-diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index 88639706ae17..e014e6df1f39 100644
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -2284,6 +2284,12 @@ static void prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags
- {
- post_alloc_hook(page, order, gfp_flags);
-
-+ if (IS_ENABLED(CONFIG_PAGE_SANITIZE_VERIFY) && want_init_on_free()) {
-+ int i;
-+ for (i = 0; i < (1 << order); i++)
-+ verify_zero_highpage(page + i);
-+ }
-+
- if (!free_pages_prezeroed() && want_init_on_alloc(gfp_flags))
- kernel_init_free_pages(page, 1 << order);
-
-diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
-index 2fa447823405..83ad70ae6bc3 100644
---- a/security/Kconfig.hardening
-+++ b/security/Kconfig.hardening
-@@ -219,6 +219,13 @@ config INIT_ON_FREE_DEFAULT_ON
- touching "cold" memory areas. Most cases see 3-5% impact. Some
- synthetic workloads have measured as high as 8%.
-
-+config PAGE_SANITIZE_VERIFY
-+ bool "Verify sanitized pages"
-+ default y
-+ help
-+ When init_on_free is enabled, verify that newly allocated pages
-+ are zeroed to detect write-after-free bugs.
-+
- endmenu
-
- endmenu
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch
deleted file mode 100644
index b25bd5bab8c3..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From a43cf7ac21ce15f4d84e2174d15d6cb425e9b512 Mon Sep 17 00:00:00 2001
-From: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Date: Fri, 20 Sep 2019 14:02:42 +0200
-Subject: [PATCH 063/113] slub: Extend init_on_free to slab caches with
- constructors
-
-This is the remaining non-upstream part of SLAB_SANITIZE, which was a
-partial port, from Daniel Micay, of the feature from PaX without the
-default fast mode based on passing SLAB_NO_SANITIZE in
-performance-critical cases that are not particularly security sensitive.
-
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
----
- mm/slab.h | 12 +++++++++---
- mm/slub.c | 14 +++++++++++++-
- 2 files changed, 22 insertions(+), 4 deletions(-)
-
-diff --git a/mm/slab.h b/mm/slab.h
-index 9fef4285514a..0fcd97a4eb6f 100644
---- a/mm/slab.h
-+++ b/mm/slab.h
-@@ -641,9 +641,15 @@ static inline bool slab_want_init_on_alloc(gfp_t flags, struct kmem_cache *c)
-
- static inline bool slab_want_init_on_free(struct kmem_cache *c)
- {
-- if (static_branch_unlikely(&init_on_free))
-- return !(c->ctor ||
-- (c->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON)));
-+ if (static_branch_unlikely(&init_on_free)) {
-+#ifndef CONFIG_SLUB
-+ if (c->ctor)
-+ return false;
-+#endif
-+ if (c->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON))
-+ return false;
-+ return true;
-+ }
- return false;
- }
-
-diff --git a/mm/slub.c b/mm/slub.c
-index 07ce7cac2612..ac22d6831b9b 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -1571,7 +1571,8 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- : 0;
- memset((char *)object + s->inuse, 0,
- s->size - s->inuse - rsize);
--
-+ if (s->ctor)
-+ s->ctor(object);
- }
- /* If object's reuse doesn't have to be delayed */
- if (!slab_free_hook(s, object)) {
-@@ -1580,6 +1581,17 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- *head = object;
- if (!*tail)
- *tail = object;
-+ } else if (slab_want_init_on_free(s) && s->ctor) {
-+ /* Objects that are put into quarantine by KASAN will
-+ * still undergo free_consistency_checks() and thus
-+ * need to show a valid freepointer to check_object().
-+ *
-+ * Note that doing this for all caches (not just ctor
-+ * ones, which have s->offset != NULL)) causes a GPF,
-+ * due to KASAN poisoning and the way set_freepointer()
-+ * eventually dereferences the freepointer.
-+ */
-+ set_freepointer(s, object, NULL);
- }
- } while (object != old_tail);
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0064-slub-Add-support-for-verifying-slab-sanitization.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0064-slub-Add-support-for-verifying-slab-sanitization.patch
deleted file mode 100644
index ca874b24c2f9..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0064-slub-Add-support-for-verifying-slab-sanitization.patch
+++ /dev/null
@@ -1,116 +0,0 @@
-From 8f0488b0635cde0c47b48f2d37cdf7b24bdb7192 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 15:58:57 -0400
-Subject: [PATCH 064/113] slub: Add support for verifying slab sanitization
-
-This is an extension to the sanitization feature in PaX for when
-sacricifing more performance for security is acceptable.
-
-The initial version from Daniel Micay was relying on PAGE_SANITIZE. It
-now relies on upstream's init_on_free.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- mm/slub.c | 36 ++++++++++++++++++++++++++++++++----
- security/Kconfig.hardening | 8 ++++++++
- 2 files changed, 40 insertions(+), 4 deletions(-)
-
-diff --git a/mm/slub.c b/mm/slub.c
-index ac22d6831b9b..e8e0efa18bd3 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -127,6 +127,12 @@ static inline bool kmem_cache_debug(struct kmem_cache *s)
- return kmem_cache_debug_flags(s, SLAB_DEBUG_FLAGS);
- }
-
-+static inline bool has_sanitize_verify(struct kmem_cache *s)
-+{
-+ return IS_ENABLED(CONFIG_SLAB_SANITIZE_VERIFY) &&
-+ slab_want_init_on_free(s);
-+}
-+
- void *fixup_red_left(struct kmem_cache *s, void *p)
- {
- if (kmem_cache_debug_flags(s, SLAB_RED_ZONE))
-@@ -1571,7 +1577,7 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- : 0;
- memset((char *)object + s->inuse, 0,
- s->size - s->inuse - rsize);
-- if (s->ctor)
-+ if (!IS_ENABLED(CONFIG_SLAB_SANITIZE_VERIFY) && s->ctor)
- s->ctor(object);
- }
- /* If object's reuse doesn't have to be delayed */
-@@ -1606,7 +1612,7 @@ static void *setup_object(struct kmem_cache *s, struct page *page,
- {
- setup_object_debug(s, page, object);
- object = kasan_init_slab_obj(s, object);
-- if (unlikely(s->ctor)) {
-+ if (unlikely(s->ctor) && !has_sanitize_verify(s)) {
- kasan_unpoison_object_data(s, object);
- s->ctor(object);
- kasan_poison_object_data(s, object);
-@@ -2897,7 +2903,16 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
-
- maybe_wipe_obj_freeptr(s, object);
-
-- if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
-+ if (has_sanitize_verify(s) && object) {
-+ /* KASAN hasn't unpoisoned the object yet (this is done in the
-+ * post-alloc hook), so let's do it temporarily.
-+ */
-+ kasan_unpoison_object_data(s, object);
-+ BUG_ON(memchr_inv(object, 0, s->object_size));
-+ if (s->ctor)
-+ s->ctor(object);
-+ kasan_poison_object_data(s, object);
-+ } else if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
- memset(object, 0, s->object_size);
-
- slab_post_alloc_hook(s, objcg, gfpflags, 1, &object);
-@@ -3337,7 +3352,20 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
- local_irq_enable();
-
- /* Clear memory outside IRQ disabled fastpath loop */
-- if (unlikely(slab_want_init_on_alloc(flags, s))) {
-+ if (has_sanitize_verify(s)) {
-+ int j;
-+
-+ for (j = 0; j < i; j++) {
-+ /* KASAN hasn't unpoisoned the object yet (this is done
-+ * in the post-alloc hook), so let's do it temporarily.
-+ */
-+ kasan_unpoison_object_data(s, p[j]);
-+ BUG_ON(memchr_inv(p[j], 0, s->object_size));
-+ if (s->ctor)
-+ s->ctor(p[j]);
-+ kasan_poison_object_data(s, p[j]);
-+ }
-+ } else if (unlikely(slab_want_init_on_alloc(flags, s))) {
- int j;
-
- for (j = 0; j < i; j++)
-diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
-index 83ad70ae6bc3..7dede18f1074 100644
---- a/security/Kconfig.hardening
-+++ b/security/Kconfig.hardening
-@@ -226,6 +226,14 @@ config PAGE_SANITIZE_VERIFY
- When init_on_free is enabled, verify that newly allocated pages
- are zeroed to detect write-after-free bugs.
-
-+config SLAB_SANITIZE_VERIFY
-+ bool "Verify sanitized SLAB allocations"
-+ default y
-+ depends on !KASAN
-+ help
-+ When init_on_free is enabled, verify that newly allocated slab
-+ objects are zeroed to detect write-after-free bugs.
-+
- endmenu
-
- endmenu
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0065-slub-add-multi-purpose-random-canaries.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0065-slub-add-multi-purpose-random-canaries.patch
deleted file mode 100644
index 62df822d3148..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0065-slub-add-multi-purpose-random-canaries.patch
+++ /dev/null
@@ -1,264 +0,0 @@
-From 6a1b579e33c5de45bc28314b0d165953b7b7f0c1 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 16:16:58 -0400
-Subject: [PATCH 065/113] slub: add multi-purpose random canaries
-
-From the configuration option:
-
- Place canaries at the end of kernel slab allocations, sacrificing
- some performance and memory usage for security.
-
- Canaries can detect some forms of heap corruption when allocations
- are freed and as part of the HARDENED_USERCOPY feature. It provides
- basic use-after-free detection for HARDENED_USERCOPY.
-
- Canaries absorb small overflows (rendering them harmless), mitigate
- non-NUL terminated C string overflows on 64-bit via a guaranteed zero
- byte and provide basic double-free detection.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/slub_def.h | 5 +++
- init/Kconfig | 17 ++++++++++
- mm/slab.h | 2 +-
- mm/slub.c | 69 ++++++++++++++++++++++++++++++++++++++--
- 4 files changed, 89 insertions(+), 4 deletions(-)
-
-diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
-index 1be0ed5befa1..c71cf30b5987 100644
---- a/include/linux/slub_def.h
-+++ b/include/linux/slub_def.h
-@@ -113,6 +113,11 @@ struct kmem_cache {
- unsigned long random;
- #endif
-
-+#ifdef CONFIG_SLAB_CANARY
-+ unsigned long random_active;
-+ unsigned long random_inactive;
-+#endif
-+
- #ifdef CONFIG_NUMA
- /*
- * Defragmentation by allocating from a remote node.
-diff --git a/init/Kconfig b/init/Kconfig
-index 58df4930995f..2af6689d9e71 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1943,6 +1943,23 @@ config SLAB_FREELIST_HARDENED
- sanity-checking than others. This option is most effective with
- CONFIG_SLUB.
-
-+config SLAB_CANARY
-+ depends on SLUB
-+ depends on !SLAB_MERGE_DEFAULT
-+ bool "SLAB canaries"
-+ default y
-+ help
-+ Place canaries at the end of kernel slab allocations, sacrificing
-+ some performance and memory usage for security.
-+
-+ Canaries can detect some forms of heap corruption when allocations
-+ are freed and as part of the HARDENED_USERCOPY feature. It provides
-+ basic use-after-free detection for HARDENED_USERCOPY.
-+
-+ Canaries absorb small overflows (rendering them harmless), mitigate
-+ non-NUL terminated C string overflows on 64-bit via a guaranteed zero
-+ byte and provide basic double-free detection.
-+
- config SHUFFLE_PAGE_ALLOCATOR
- bool "Page allocator randomization"
- default SLAB_FREELIST_RANDOM && ACPI_NUMA
-diff --git a/mm/slab.h b/mm/slab.h
-index 0fcd97a4eb6f..105dba485a7e 100644
---- a/mm/slab.h
-+++ b/mm/slab.h
-@@ -504,7 +504,7 @@ static inline size_t slab_ksize(const struct kmem_cache *s)
- * back there or track user information then we can
- * only use the space before that information.
- */
-- if (s->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_STORE_USER))
-+ if ((s->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_STORE_USER)) || IS_ENABLED(CONFIG_SLAB_CANARY))
- return s->inuse;
- /*
- * Else we can use all the padding etc for the allocation
-diff --git a/mm/slub.c b/mm/slub.c
-index e8e0efa18bd3..dd68308c94a9 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -569,6 +569,33 @@ static inline unsigned int get_info_end(struct kmem_cache *s)
- return s->inuse;
- }
-
-+#ifdef CONFIG_SLAB_CANARY
-+static inline unsigned long *get_canary(struct kmem_cache *s, void *object)
-+{
-+ return object + get_info_end(s);
-+}
-+
-+static inline unsigned long get_canary_value(const void *canary, unsigned long value)
-+{
-+ return (value ^ (unsigned long)canary) & CANARY_MASK;
-+}
-+
-+static inline void set_canary(struct kmem_cache *s, void *object, unsigned long value)
-+{
-+ unsigned long *canary = get_canary(s, object);
-+ *canary = get_canary_value(canary, value);
-+}
-+
-+static inline void check_canary(struct kmem_cache *s, void *object, unsigned long value)
-+{
-+ unsigned long *canary = get_canary(s, object);
-+ BUG_ON(*canary != get_canary_value(canary, value));
-+}
-+#else
-+#define set_canary(s, object, value)
-+#define check_canary(s, object, value)
-+#endif
-+
- static struct track *get_track(struct kmem_cache *s, void *object,
- enum track_item alloc)
- {
-@@ -576,6 +603,9 @@ static struct track *get_track(struct kmem_cache *s, void *object,
-
- p = object + get_info_end(s);
-
-+ if (IS_ENABLED(CONFIG_SLAB_CANARY))
-+ p = (void *)p + sizeof(void *);
-+
- return p + alloc;
- }
-
-@@ -717,6 +747,9 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
-
- off = get_info_end(s);
-
-+ if (IS_ENABLED(CONFIG_SLAB_CANARY))
-+ off += sizeof(void *);
-+
- if (s->flags & SLAB_STORE_USER)
- off += 2 * sizeof(struct track);
-
-@@ -825,8 +858,9 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
- * Meta data starts here.
- *
- * A. Free pointer (if we cannot overwrite object on free)
-- * B. Tracking data for SLAB_STORE_USER
-- * C. Padding to reach required alignment boundary or at mininum
-+ * B. Canary for SLAB_CANARY
-+ * C. Tracking data for SLAB_STORE_USER
-+ * D. Padding to reach required alignment boundary or at mininum
- * one word if debugging is on to be able to detect writes
- * before the word boundary.
- *
-@@ -844,6 +878,9 @@ static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
- {
- unsigned long off = get_info_end(s); /* The end of info */
-
-+ if (IS_ENABLED(CONFIG_SLAB_CANARY))
-+ off += sizeof(void *);
-+
- if (s->flags & SLAB_STORE_USER)
- /* We also have user information there */
- off += 2 * sizeof(struct track);
-@@ -1567,6 +1604,8 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- object = next;
- next = get_freepointer(s, object);
-
-+ check_canary(s, object, s->random_active);
-+
- if (slab_want_init_on_free(s)) {
- /*
- * Clear the object and the metadata, but don't touch
-@@ -1580,6 +1619,9 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- if (!IS_ENABLED(CONFIG_SLAB_SANITIZE_VERIFY) && s->ctor)
- s->ctor(object);
- }
-+
-+ set_canary(s, object, s->random_inactive);
-+
- /* If object's reuse doesn't have to be delayed */
- if (!slab_free_hook(s, object)) {
- /* Move object to the new freelist */
-@@ -1611,6 +1653,7 @@ static void *setup_object(struct kmem_cache *s, struct page *page,
- void *object)
- {
- setup_object_debug(s, page, object);
-+ set_canary(s, object, s->random_inactive);
- object = kasan_init_slab_obj(s, object);
- if (unlikely(s->ctor) && !has_sanitize_verify(s)) {
- kasan_unpoison_object_data(s, object);
-@@ -2915,6 +2958,11 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
- } else if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
- memset(object, 0, s->object_size);
-
-+ if (object) {
-+ check_canary(s, object, s->random_inactive);
-+ set_canary(s, object, s->random_active);
-+ }
-+
- slab_post_alloc_hook(s, objcg, gfpflags, 1, &object);
-
- return object;
-@@ -3302,7 +3350,7 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
- void **p)
- {
- struct kmem_cache_cpu *c;
-- int i;
-+ int i, k;
- struct obj_cgroup *objcg = NULL;
-
- /* memcg and kmem_cache debug support */
-@@ -3372,6 +3420,11 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
- memset(p[j], 0, s->object_size);
- }
-
-+ for (k = 0; k < i; k++) {
-+ check_canary(s, p[k], s->random_inactive);
-+ set_canary(s, p[k], s->random_active);
-+ }
-+
- /* memcg and kmem_cache debug support */
- slab_post_alloc_hook(s, objcg, flags, size, p);
- return i;
-@@ -3573,6 +3626,7 @@ static void early_kmem_cache_node_alloc(int node)
- init_object(kmem_cache_node, n, SLUB_RED_ACTIVE);
- init_tracking(kmem_cache_node, n);
- #endif
-+ set_canary(kmem_cache_node, n, kmem_cache_node->random_active);
- n = kasan_kmalloc(kmem_cache_node, n, sizeof(struct kmem_cache_node),
- GFP_KERNEL);
- page->freelist = get_freepointer(kmem_cache_node, n);
-@@ -3753,6 +3807,9 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
- s->offset = ALIGN(freepointer_area / 2, sizeof(void *));
- }
-
-+ if (IS_ENABLED(CONFIG_SLAB_CANARY))
-+ size += sizeof(void *);
-+
- #ifdef CONFIG_SLUB_DEBUG
- if (flags & SLAB_STORE_USER)
- /*
-@@ -3826,6 +3883,10 @@ static int kmem_cache_open(struct kmem_cache *s, slab_flags_t flags)
- #ifdef CONFIG_SLAB_FREELIST_HARDENED
- s->random = get_random_long();
- #endif
-+#ifdef CONFIG_SLAB_CANARY
-+ s->random_active = get_random_long();
-+ s->random_inactive = get_random_long();
-+#endif
-
- if (!calculate_sizes(s, -1))
- goto error;
-@@ -4099,6 +4160,8 @@ void __check_heap_object(const void *ptr, unsigned long n, struct page *page,
- offset -= s->red_left_pad;
- }
-
-+ check_canary(s, (void *)ptr - offset, s->random_active);
-+
- /* Allow address range falling entirely within usercopy region. */
- if (offset >= s->useroffset &&
- offset - s->useroffset <= s->usersize &&
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0066-security-perf-Allow-further-restriction-of-perf_even.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0066-security-perf-Allow-further-restriction-of-perf_even.patch
deleted file mode 100644
index 261283f05ff3..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0066-security-perf-Allow-further-restriction-of-perf_even.patch
+++ /dev/null
@@ -1,122 +0,0 @@
-From b0162949f7d49b21bc7fe2bfab91e0b8c5da90f7 Mon Sep 17 00:00:00 2001
-From: Ben Hutchings <ben@decadent.org.uk>
-Date: Mon, 11 Jan 2016 15:23:55 +0000
-Subject: [PATCH 066/113] security,perf: Allow further restriction of
- perf_event_open
-
-When kernel.perf_event_open is set to 3 (or greater), disallow all
-access to performance events by users without CAP_SYS_ADMIN.
-Add a Kconfig symbol CONFIG_SECURITY_PERF_EVENTS_RESTRICT that
-makes this value the default.
-
-This is based on a similar feature in grsecurity
-(CONFIG_GRKERNSEC_PERF_HARDEN). This version doesn't include making
-the variable read-only. It also allows enabling further restriction
-at run-time regardless of whether the default is changed.
-
-Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
-[thibaut.sautereau@ssi.gouv.fr: Adapt to work with the new CAP_PERFMON capability]
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
----
- Documentation/admin-guide/sysctl/kernel.rst | 2 ++
- include/linux/perf_event.h | 8 ++++++++
- kernel/events/core.c | 7 ++++++-
- security/Kconfig | 9 +++++++++
- tools/perf/Documentation/security.txt | 1 +
- 5 files changed, 26 insertions(+), 1 deletion(-)
-
-diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
-index d4b32cc32bb7..4c20e6ded0af 100644
---- a/Documentation/admin-guide/sysctl/kernel.rst
-+++ b/Documentation/admin-guide/sysctl/kernel.rst
-@@ -860,6 +860,8 @@ with respect to CAP_PERFMON use cases.
- >=1 Disallow CPU event access by users without ``CAP_PERFMON``.
-
- >=2 Disallow kernel profiling by users without ``CAP_PERFMON``.
-+
-+>=3 Disallow use of any event by users without ``CAP_PERFMON``.
- === ==================================================================
-
-
-diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
-index 96450f6fb1de..d020c26b612a 100644
---- a/include/linux/perf_event.h
-+++ b/include/linux/perf_event.h
-@@ -1312,6 +1312,14 @@ static inline int perf_is_paranoid(void)
- return sysctl_perf_event_paranoid > -1;
- }
-
-+static inline int perf_allow_open(struct perf_event_attr *attr)
-+{
-+ if (sysctl_perf_event_paranoid > 2 && !perfmon_capable())
-+ return -EACCES;
-+
-+ return security_perf_event_open(attr, PERF_SECURITY_OPEN);
-+}
-+
- static inline int perf_allow_kernel(struct perf_event_attr *attr)
- {
- if (sysctl_perf_event_paranoid > 1 && !perfmon_capable())
-diff --git a/kernel/events/core.c b/kernel/events/core.c
-index c3ba29d058b7..6efbf92763b1 100644
---- a/kernel/events/core.c
-+++ b/kernel/events/core.c
-@@ -407,8 +407,13 @@ static cpumask_var_t perf_online_mask;
- * 0 - disallow raw tracepoint access for unpriv
- * 1 - disallow cpu events for unpriv
- * 2 - disallow kernel profiling for unpriv
-+ * 3 - disallow all unpriv perf event use
- */
-+#ifdef CONFIG_SECURITY_PERF_EVENTS_RESTRICT
-+int sysctl_perf_event_paranoid __read_mostly = 3;
-+#else
- int sysctl_perf_event_paranoid __read_mostly = 2;
-+#endif
-
- /* Minimum for 512 kiB + 1 user control page */
- int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */
-@@ -11638,7 +11643,7 @@ SYSCALL_DEFINE5(perf_event_open,
- return -EINVAL;
-
- /* Do we allow access to perf_event_open(2) ? */
-- err = security_perf_event_open(&attr, PERF_SECURITY_OPEN);
-+ err = perf_allow_open(&attr);
- if (err)
- return err;
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 81d0a08736aa..c797326308f1 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -19,6 +19,15 @@ config SECURITY_DMESG_RESTRICT
-
- If you are unsure how to answer this question, answer N.
-
-+config SECURITY_PERF_EVENTS_RESTRICT
-+ bool "Restrict unprivileged use of performance events"
-+ depends on PERF_EVENTS
-+ help
-+ If you say Y here, the kernel.perf_event_paranoid sysctl
-+ will be set to 3 by default, and no unprivileged use of the
-+ perf_event_open syscall will be permitted unless it is
-+ changed.
-+
- config SECURITY
- bool "Enable different security models"
- depends on SYSFS
-diff --git a/tools/perf/Documentation/security.txt b/tools/perf/Documentation/security.txt
-index 4fe3b8b1958f..a7d88cc23a70 100644
---- a/tools/perf/Documentation/security.txt
-+++ b/tools/perf/Documentation/security.txt
-@@ -148,6 +148,7 @@ Perf tool provides a message similar to the one below:
- >= 0: Disallow raw and ftrace function tracepoint access
- >= 1: Disallow CPU event access
- >= 2: Disallow kernel profiling
-+ >= 3: Disallow use of any event
- To make the adjusted perf_event_paranoid setting permanent preserve it
- in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch
deleted file mode 100644
index d6d9e17692d1..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 06a8f90667eaa999aaf2225fc4221fc455ad953a Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 14:45:59 -0400
-Subject: [PATCH 067/113] enable SECURITY_PERF_EVENTS_RESTRICT by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- security/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index c797326308f1..2348ff7d4e1d 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -22,6 +22,7 @@ config SECURITY_DMESG_RESTRICT
- config SECURITY_PERF_EVENTS_RESTRICT
- bool "Restrict unprivileged use of performance events"
- depends on PERF_EVENTS
-+ default y
- help
- If you say Y here, the kernel.perf_event_paranoid sysctl
- will be set to 3 by default, and no unprivileged use of the
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch
deleted file mode 100644
index b920225fc31c..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch
+++ /dev/null
@@ -1,124 +0,0 @@
-From fb241fbe65be75b423445df03475adefcddb6830 Mon Sep 17 00:00:00 2001
-From: Serge Hallyn <serge.hallyn@canonical.com>
-Date: Fri, 31 May 2013 19:12:12 +0100
-Subject: [PATCH 068/113] add sysctl to disallow unprivileged CLONE_NEWUSER by
- default
-
-Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
-[bwh: Remove unneeded binary sysctl bits]
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-[thibaut.sautereau@ssi.gouv.fr: Adapt to sysctl code refactoring]
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- include/linux/user_namespace.h | 4 ++++
- kernel/fork.c | 11 +++++++++++
- kernel/sysctl.c | 12 ++++++++++++
- kernel/user_namespace.c | 3 +++
- 4 files changed, 30 insertions(+)
-
-diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
-index 6ef1c7109fc4..2140091b0b8d 100644
---- a/include/linux/user_namespace.h
-+++ b/include/linux/user_namespace.h
-@@ -106,6 +106,8 @@ void dec_ucount(struct ucounts *ucounts, enum ucount_type type);
-
- #ifdef CONFIG_USER_NS
-
-+extern int unprivileged_userns_clone;
-+
- static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
- {
- if (ns)
-@@ -139,6 +141,8 @@ extern bool current_in_userns(const struct user_namespace *target_ns);
- struct ns_common *ns_get_owner(struct ns_common *ns);
- #else
-
-+#define unprivileged_userns_clone 0
-+
- static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
- {
- return &init_user_ns;
-diff --git a/kernel/fork.c b/kernel/fork.c
-index c675fdbd3dce..cba344194fba 100644
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -82,6 +82,7 @@
- #include <linux/perf_event.h>
- #include <linux/posix-timers.h>
- #include <linux/user-return-notifier.h>
-+#include <linux/user_namespace.h>
- #include <linux/oom.h>
- #include <linux/khugepaged.h>
- #include <linux/signalfd.h>
-@@ -1863,6 +1864,10 @@ static __latent_entropy struct task_struct *copy_process(
- if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
- return ERR_PTR(-EINVAL);
-
-+ if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone)
-+ if (!capable(CAP_SYS_ADMIN))
-+ return ERR_PTR(-EPERM);
-+
- /*
- * Thread groups must share signals as well, and detached threads
- * can only be started up within the thread group.
-@@ -2928,6 +2933,12 @@ int ksys_unshare(unsigned long unshare_flags)
- if (unshare_flags & CLONE_NEWNS)
- unshare_flags |= CLONE_FS;
-
-+ if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
-+ err = -EPERM;
-+ if (!capable(CAP_SYS_ADMIN))
-+ goto bad_unshare_out;
-+ }
-+
- err = check_unshare_flags(unshare_flags);
- if (err)
- goto bad_unshare_out;
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index b2cd3dbbb17a..fccf24a08c8a 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -103,6 +103,9 @@
- #ifdef CONFIG_LOCKUP_DETECTOR
- #include <linux/nmi.h>
- #endif
-+#ifdef CONFIG_USER_NS
-+#include <linux/user_namespace.h>
-+#endif
-
- #if defined(CONFIG_SYSCTL)
-
-@@ -1902,6 +1905,15 @@ static struct ctl_table kern_table[] = {
- .proc_handler = proc_dointvec,
- },
- #endif
-+#ifdef CONFIG_USER_NS
-+ {
-+ .procname = "unprivileged_userns_clone",
-+ .data = &unprivileged_userns_clone,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec,
-+ },
-+#endif
- #ifdef CONFIG_PROC_SYSCTL
- {
- .procname = "tainted",
-diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
-index e703d5d9cbe8..29a30cff5e60 100644
---- a/kernel/user_namespace.c
-+++ b/kernel/user_namespace.c
-@@ -21,6 +21,9 @@
- #include <linux/bsearch.h>
- #include <linux/sort.h>
-
-+/* sysctl */
-+int unprivileged_userns_clone;
-+
- static struct kmem_cache *user_ns_cachep __read_mostly;
- static DEFINE_MUTEX(userns_state_mutex);
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0069-add-CONFIG-for-unprivileged_userns_clone.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0069-add-CONFIG-for-unprivileged_userns_clone.patch
deleted file mode 100644
index da79ac4598de..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0069-add-CONFIG-for-unprivileged_userns_clone.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-From 54f2484c6173d5d112777e65b69bd2c8dcd992ae Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Wed, 31 Jul 2019 20:50:48 +0100
-Subject: [PATCH 069/113] add CONFIG for unprivileged_userns_clone
-
-When disabled, unprivileged users will not be able to create
-new namespaces. Allowing users to create their own namespaces
-has been part of several recent local privilege escalation
-exploits, so if you need user namespaces but are
-paranoid^Wsecurity-conscious you want to disable this.
-
-By default unprivileged user namespaces are disabled.
-
-Authored-by: Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
-Edited-by: Levente Polyak (anthraxx) <levente@leventepolyak.net>
----
- init/Kconfig | 16 ++++++++++++++++
- kernel/user_namespace.c | 4 ++++
- 2 files changed, 20 insertions(+)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 2af6689d9e71..a7b5a4cb7939 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1174,6 +1174,22 @@ config USER_NS
-
- If unsure, say N.
-
-+config USER_NS_UNPRIVILEGED
-+ bool "Allow unprivileged users to create namespaces"
-+ depends on USER_NS
-+ default n
-+ help
-+ When disabled, unprivileged users will not be able to create
-+ new namespaces. Allowing users to create their own namespaces
-+ has been part of several recent local privilege escalation
-+ exploits, so if you need user namespaces but are
-+ paranoid^Wsecurity-conscious you want to disable this.
-+
-+ This setting can be overridden at runtime via the
-+ kernel.unprivileged_userns_clone sysctl.
-+
-+ If unsure, say N.
-+
- config PID_NS
- bool "PID Namespaces"
- default y
-diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
-index 29a30cff5e60..5758274feaee 100644
---- a/kernel/user_namespace.c
-+++ b/kernel/user_namespace.c
-@@ -22,7 +22,11 @@
- #include <linux/sort.h>
-
- /* sysctl */
-+#ifdef CONFIG_USER_NS_UNPRIVILEGED
-+int unprivileged_userns_clone = 1;
-+#else
- int unprivileged_userns_clone;
-+#endif
-
- static struct kmem_cache *user_ns_cachep __read_mostly;
- static DEFINE_MUTEX(userns_state_mutex);
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0070-add-kmalloc-krealloc-alloc_size-attributes.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0070-add-kmalloc-krealloc-alloc_size-attributes.patch
deleted file mode 100644
index a2ab6d14968a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0070-add-kmalloc-krealloc-alloc_size-attributes.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From ccf251e3b0fe0dfc30650b5d373e8ad22c40f2a7 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:02:56 -0400
-Subject: [PATCH 070/113] add kmalloc/krealloc alloc_size attributes
-
-Note that this is overly strict when combined with ksize users accessing
-beyond the requested data size.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/slab.h | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/include/linux/slab.h b/include/linux/slab.h
-index dd6897f62010..78f99835b91b 100644
---- a/include/linux/slab.h
-+++ b/include/linux/slab.h
-@@ -181,7 +181,7 @@ int kmem_cache_shrink(struct kmem_cache *);
- /*
- * Common kmalloc functions provided by all allocators
- */
--void * __must_check krealloc(const void *, size_t, gfp_t);
-+void * __must_check krealloc(const void *, size_t, gfp_t) __attribute((alloc_size(2)));
- void kfree(const void *);
- void kfree_sensitive(const void *);
- size_t __ksize(const void *);
-@@ -386,7 +386,7 @@ static __always_inline unsigned int kmalloc_index(size_t size)
- }
- #endif /* !CONFIG_SLOB */
-
--void *__kmalloc(size_t size, gfp_t flags) __assume_kmalloc_alignment __malloc;
-+void *__kmalloc(size_t size, gfp_t flags) __assume_kmalloc_alignment __malloc __attribute__((alloc_size(1)));
- void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __assume_slab_alignment __malloc;
- void kmem_cache_free(struct kmem_cache *, void *);
-
-@@ -410,7 +410,7 @@ static __always_inline void kfree_bulk(size_t size, void **p)
- }
-
- #ifdef CONFIG_NUMA
--void *__kmalloc_node(size_t size, gfp_t flags, int node) __assume_kmalloc_alignment __malloc;
-+void *__kmalloc_node(size_t size, gfp_t flags, int node) __assume_kmalloc_alignment __malloc __attribute__((alloc_size(1)));
- void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node) __assume_slab_alignment __malloc;
- #else
- static __always_inline void *__kmalloc_node(size_t size, gfp_t flags, int node)
-@@ -535,7 +535,7 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
- * Try really hard to succeed the allocation but fail
- * eventually.
- */
--static __always_inline void *kmalloc(size_t size, gfp_t flags)
-+static __always_inline __attribute__((alloc_size(1))) void *kmalloc(size_t size, gfp_t flags)
- {
- if (__builtin_constant_p(size)) {
- #ifndef CONFIG_SLOB
-@@ -557,7 +557,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
- return __kmalloc(size, flags);
- }
-
--static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
-+static __always_inline __attribute__((alloc_size(1))) void *kmalloc_node(size_t size, gfp_t flags, int node)
- {
- #ifndef CONFIG_SLOB
- if (__builtin_constant_p(size) &&
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0071-add-vmalloc-alloc_size-attributes.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0071-add-vmalloc-alloc_size-attributes.patch
deleted file mode 100644
index 2280d4441b9b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0071-add-vmalloc-alloc_size-attributes.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 765b15be971302f62d5d4952ce3db1c5369cb158 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:04:03 -0400
-Subject: [PATCH 071/113] add vmalloc alloc_size attributes
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- include/linux/vmalloc.h | 18 +++++++++---------
- 1 file changed, 9 insertions(+), 9 deletions(-)
-
-diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
-index 938eaf9517e2..7c069063c20d 100644
---- a/include/linux/vmalloc.h
-+++ b/include/linux/vmalloc.h
-@@ -102,18 +102,18 @@ static inline void vmalloc_init(void)
- static inline unsigned long vmalloc_nr_pages(void) { return 0; }
- #endif
-
--extern void *vmalloc(unsigned long size);
--extern void *vzalloc(unsigned long size);
--extern void *vmalloc_user(unsigned long size);
--extern void *vmalloc_node(unsigned long size, int node);
--extern void *vzalloc_node(unsigned long size, int node);
--extern void *vmalloc_32(unsigned long size);
--extern void *vmalloc_32_user(unsigned long size);
--extern void *__vmalloc(unsigned long size, gfp_t gfp_mask);
-+extern void *vmalloc(unsigned long size) __attribute__((alloc_size(1)));
-+extern void *vzalloc(unsigned long size) __attribute__((alloc_size(1)));
-+extern void *vmalloc_user(unsigned long size) __attribute__((alloc_size(1)));
-+extern void *vmalloc_node(unsigned long size, int node) __attribute__((alloc_size(1)));
-+extern void *vzalloc_node(unsigned long size, int node) __attribute__((alloc_size(1)));
-+extern void *vmalloc_32(unsigned long size) __attribute__((alloc_size(1)));
-+extern void *vmalloc_32_user(unsigned long size) __attribute__((alloc_size(1)));
-+extern void *__vmalloc(unsigned long size, gfp_t gfp_mask) __attribute__((alloc_size(1)));
- extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
- unsigned long start, unsigned long end, gfp_t gfp_mask,
- pgprot_t prot, unsigned long vm_flags, int node,
-- const void *caller);
-+ const void *caller) __attribute__((alloc_size(1)));
- void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask,
- int node, const void *caller);
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0072-add-kvmalloc-alloc_size-attribute.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0072-add-kvmalloc-alloc_size-attribute.patch
deleted file mode 100644
index b3c8f0c0a801..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0072-add-kvmalloc-alloc_size-attribute.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From a558df65a5308d73eb0455e711d012a461b9efdb Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 00:51:33 -0400
-Subject: [PATCH 072/113] add kvmalloc alloc_size attribute
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/mm.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/include/linux/mm.h b/include/linux/mm.h
-index cd5c313729ea..746f6d05bd81 100644
---- a/include/linux/mm.h
-+++ b/include/linux/mm.h
-@@ -759,7 +759,7 @@ static inline int is_vmalloc_or_module_addr(const void *x)
- }
- #endif
-
--extern void *kvmalloc_node(size_t size, gfp_t flags, int node);
-+extern void *kvmalloc_node(size_t size, gfp_t flags, int node) __attribute__((alloc_size(1)));
- static inline void *kvmalloc(size_t size, gfp_t flags)
- {
- return kvmalloc_node(size, flags, NUMA_NO_NODE);
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0073-add-percpu-alloc_size-attributes.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0073-add-percpu-alloc_size-attributes.patch
deleted file mode 100644
index 6900b23bdf50..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0073-add-percpu-alloc_size-attributes.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From bf3b905e708babea7cedc1e0afc4f5482e66b2b7 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 14 May 2017 16:39:36 -0400
-Subject: [PATCH 073/113] add percpu alloc_size attributes
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/percpu.h | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/include/linux/percpu.h b/include/linux/percpu.h
-index 5e76af742c80..9a6c682ec127 100644
---- a/include/linux/percpu.h
-+++ b/include/linux/percpu.h
-@@ -123,7 +123,7 @@ extern int __init pcpu_page_first_chunk(size_t reserved_size,
- pcpu_fc_populate_pte_fn_t populate_pte_fn);
- #endif
-
--extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align);
-+extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align) __attribute__((alloc_size(1)));
- extern bool __is_kernel_percpu_address(unsigned long addr, unsigned long *can_addr);
- extern bool is_kernel_percpu_address(unsigned long addr);
-
-@@ -131,8 +131,8 @@ extern bool is_kernel_percpu_address(unsigned long addr);
- extern void __init setup_per_cpu_areas(void);
- #endif
-
--extern void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp);
--extern void __percpu *__alloc_percpu(size_t size, size_t align);
-+extern void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp) __attribute__((alloc_size(1)));
-+extern void __percpu *__alloc_percpu(size_t size, size_t align) __attribute__((alloc_size(1)));
- extern void free_percpu(void __percpu *__pdata);
- extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0074-add-alloc_pages_exact-alloc_size-attributes.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0074-add-alloc_pages_exact-alloc_size-attributes.patch
deleted file mode 100644
index 5793fe518bff..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0074-add-alloc_pages_exact-alloc_size-attributes.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 5a0e958093741bc7210e07d3f4fb75faa40b44a0 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 14 May 2017 16:53:59 -0400
-Subject: [PATCH 074/113] add alloc_pages_exact alloc_size attributes
-
-Edited-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/gfp.h | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/include/linux/gfp.h b/include/linux/gfp.h
-index c603237e006c..893378b0262e 100644
---- a/include/linux/gfp.h
-+++ b/include/linux/gfp.h
-@@ -568,9 +568,9 @@ static inline struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
- extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
- extern unsigned long get_zeroed_page(gfp_t gfp_mask);
-
--void *alloc_pages_exact(size_t size, gfp_t gfp_mask);
-+void *alloc_pages_exact(size_t size, gfp_t gfp_mask) __attribute__((alloc_size(1)));
- void free_pages_exact(void *virt, size_t size);
--void * __meminit alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask);
-+void * __meminit alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask) __attribute__((alloc_size(2)));
-
- #define __get_free_page(gfp_mask) \
- __get_free_pages((gfp_mask), 0)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0075-Add-the-extra_latent_entropy-kernel-parameter.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0075-Add-the-extra_latent_entropy-kernel-parameter.patch
deleted file mode 100644
index ebd1abcb5bc2..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0075-Add-the-extra_latent_entropy-kernel-parameter.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-From b5355e1d89cc343036dec751091e8bdbc70b790a Mon Sep 17 00:00:00 2001
-From: Emese Revfy <re.emese@gmail.com>
-Date: Tue, 31 May 2016 01:34:02 +0200
-Subject: [PATCH 075/113] Add the extra_latent_entropy kernel parameter
-
-When extra_latent_entropy is passed on the kernel command line,
-entropy will be extracted from up to the first 4GB of RAM while the
-runtime memory allocator is being initialized.
-
-Based on work created by the PaX Team.
-
-Signed-off-by: Emese Revfy <re.emese@gmail.com>
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- .../admin-guide/kernel-parameters.txt | 5 ++++
- mm/page_alloc.c | 25 +++++++++++++++++++
- scripts/gcc-plugins/Kconfig | 5 ++++
- 3 files changed, 35 insertions(+)
-
-diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
-index 26bfe7ae711b..e7ea794320e8 100644
---- a/Documentation/admin-guide/kernel-parameters.txt
-+++ b/Documentation/admin-guide/kernel-parameters.txt
-@@ -3566,6 +3566,11 @@
- the specified number of seconds. This is to be used if
- your oopses keep scrolling off the screen.
-
-+ extra_latent_entropy
-+ Enable a very simple form of latent entropy extraction
-+ from the first 4GB of memory as the bootmem allocator
-+ passes the memory pages to the buddy allocator.
-+
- pcbit= [HW,ISDN]
-
- pcd. [PARIDE]
-diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index e014e6df1f39..965d49be78ed 100644
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -70,6 +70,7 @@
- #include <linux/psi.h>
- #include <linux/padata.h>
- #include <linux/khugepaged.h>
-+#include <linux/random.h>
-
- #include <asm/sections.h>
- #include <asm/tlbflush.h>
-@@ -136,6 +137,15 @@ struct pcpu_drain {
- static DEFINE_MUTEX(pcpu_drain_mutex);
- static DEFINE_PER_CPU(struct pcpu_drain, pcpu_drain);
-
-+bool __meminitdata extra_latent_entropy;
-+
-+static int __init setup_extra_latent_entropy(char *str)
-+{
-+ extra_latent_entropy = true;
-+ return 0;
-+}
-+early_param("extra_latent_entropy", setup_extra_latent_entropy);
-+
- #ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
- volatile unsigned long latent_entropy __latent_entropy;
- EXPORT_SYMBOL(latent_entropy);
-@@ -1549,6 +1559,21 @@ void __free_pages_core(struct page *page, unsigned int order)
- __ClearPageReserved(p);
- set_page_count(p, 0);
-
-+ if (extra_latent_entropy && !PageHighMem(page) && page_to_pfn(page) < 0x100000) {
-+ unsigned long hash = 0;
-+ size_t index, end = PAGE_SIZE * nr_pages / sizeof hash;
-+ const unsigned long *data = lowmem_page_address(page);
-+
-+ for (index = 0; index < end; index++)
-+ hash ^= hash + data[index];
-+#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
-+ latent_entropy ^= hash;
-+ add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy));
-+#else
-+ add_device_randomness((const void *)&hash, sizeof(hash));
-+#endif
-+ }
-+
- atomic_long_add(nr_pages, &page_zone(page)->managed_pages);
-
- /*
-diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig
-index ae19fb0243b9..ad78375ece5e 100644
---- a/scripts/gcc-plugins/Kconfig
-+++ b/scripts/gcc-plugins/Kconfig
-@@ -53,6 +53,11 @@ config GCC_PLUGIN_LATENT_ENTROPY
- is some slowdown of the boot process (about 0.5%) and fork and
- irq processing.
-
-+ When extra_latent_entropy is passed on the kernel command line,
-+ entropy will be extracted from up to the first 4GB of RAM while the
-+ runtime memory allocator is being initialized. This costs even more
-+ slowdown of the boot process.
-+
- Note that entropy extracted this way is not cryptographically
- secure!
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0076-ata-avoid-null-pointer-dereference-on-bug.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0076-ata-avoid-null-pointer-dereference-on-bug.patch
deleted file mode 100644
index 2bc0b9064262..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0076-ata-avoid-null-pointer-dereference-on-bug.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 77619f5ebb01fd8bdac4673099bc5f89ed3ec7df Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 15 May 2017 23:45:34 -0400
-Subject: [PATCH 076/113] ata: avoid null pointer dereference on bug
-
-Extracted from PaX.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- drivers/ata/libata-core.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
-index 61c762961ca8..02a83039c25b 100644
---- a/drivers/ata/libata-core.c
-+++ b/drivers/ata/libata-core.c
-@@ -4540,7 +4540,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
- struct ata_port *ap;
- unsigned int tag;
-
-- WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
-+ BUG_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
- ap = qc->ap;
-
- qc->flags = 0;
-@@ -4557,7 +4557,7 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
- struct ata_port *ap;
- struct ata_link *link;
-
-- WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
-+ BUG_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
- WARN_ON_ONCE(!(qc->flags & ATA_QCFLAG_ACTIVE));
- ap = qc->ap;
- link = qc->dev->link;
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0077-sanity-check-for-negative-length-in-nla_memcpy.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0077-sanity-check-for-negative-length-in-nla_memcpy.patch
deleted file mode 100644
index a7980a7cba24..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0077-sanity-check-for-negative-length-in-nla_memcpy.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From efd3c3591dfc72a35355e17461d2e839f16fbdbb Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 15 May 2017 23:51:12 -0400
-Subject: [PATCH 077/113] sanity check for negative length in nla_memcpy
-
-Extracted from PaX.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- lib/nlattr.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/lib/nlattr.c b/lib/nlattr.c
-index 74019c8ebf6b..c480b4e7ffef 100644
---- a/lib/nlattr.c
-+++ b/lib/nlattr.c
-@@ -778,6 +778,8 @@ int nla_memcpy(void *dest, const struct nlattr *src, int count)
- {
- int minlen = min_t(int, count, nla_len(src));
-
-+ BUG_ON(minlen < 0);
-+
- memcpy(dest, nla_data(src), minlen);
- if (count > minlen)
- memset(dest + minlen, 0, count - minlen);
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0078-add-page-destructor-sanity-check.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0078-add-page-destructor-sanity-check.patch
deleted file mode 100644
index 82954e6c4741..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0078-add-page-destructor-sanity-check.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 2d537a637635831105f4113592892f0b4e1e31ea Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 15 May 2017 23:59:18 -0400
-Subject: [PATCH 078/113] add page destructor sanity check
-
-Taken from the public PaX patches.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-[thibaut.sautereau@ssi.gouv.fr: Restore get_compound_page_dtor()]
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Reviewd-by: Levente Polyak <levente@leventepolyak.net>
----
- include/linux/mm.h | 9 +++++++--
- mm/swap.c | 12 +++++++++++-
- 2 files changed, 18 insertions(+), 3 deletions(-)
-
-diff --git a/include/linux/mm.h b/include/linux/mm.h
-index 746f6d05bd81..a463ffe84eb4 100644
---- a/include/linux/mm.h
-+++ b/include/linux/mm.h
-@@ -894,10 +894,15 @@ static inline void set_compound_page_dtor(struct page *page,
- page[1].compound_dtor = compound_dtor;
- }
-
--static inline void destroy_compound_page(struct page *page)
-+static inline compound_page_dtor *get_compound_page_dtor(struct page *page)
- {
- VM_BUG_ON_PAGE(page[1].compound_dtor >= NR_COMPOUND_DTORS, page);
-- compound_page_dtors[page[1].compound_dtor](page);
-+ return compound_page_dtors[page[1].compound_dtor];
-+}
-+
-+static inline void destroy_compound_page(struct page *page)
-+{
-+ (*get_compound_page_dtor(page))(page);
- }
-
- static inline unsigned int compound_order(struct page *page)
-diff --git a/mm/swap.c b/mm/swap.c
-index 47a47681c86b..762095d95092 100644
---- a/mm/swap.c
-+++ b/mm/swap.c
-@@ -102,6 +102,8 @@ static void __put_single_page(struct page *page)
-
- static void __put_compound_page(struct page *page)
- {
-+ compound_page_dtor *dtor;
-+
- /*
- * __page_cache_release() is supposed to be called for thp, not for
- * hugetlb. This is because hugetlb page does never have PageLRU set
-@@ -110,7 +112,15 @@ static void __put_compound_page(struct page *page)
- */
- if (!PageHuge(page))
- __page_cache_release(page);
-- destroy_compound_page(page);
-+ dtor = get_compound_page_dtor(page);
-+ if (!PageHuge(page))
-+ BUG_ON(dtor != free_compound_page
-+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-+ && dtor != free_transhuge_page
-+#endif
-+ );
-+
-+ (*dtor)(page);
- }
-
- void __put_page(struct page *page)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch
deleted file mode 100644
index 74a08131fce2..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From 464796164b4bb82bee57a88f0da25c61ea76a72b Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 16 May 2017 00:59:48 -0400
-Subject: [PATCH 079/113] PaX shadow cr4 sanity check (essentially a revert)
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- arch/x86/kernel/cpu/common.c | 1 +
- arch/x86/kernel/process.c | 1 +
- arch/x86/mm/tlb.c | 1 +
- 3 files changed, 3 insertions(+)
-
-diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
-index 35ad8480c464..edaeeab9df4b 100644
---- a/arch/x86/kernel/cpu/common.c
-+++ b/arch/x86/kernel/cpu/common.c
-@@ -399,6 +399,7 @@ EXPORT_SYMBOL_GPL(native_write_cr4);
- void cr4_update_irqsoff(unsigned long set, unsigned long clear)
- {
- unsigned long newval, cr4 = this_cpu_read(cpu_tlbstate.cr4);
-+ BUG_ON(cr4 != __read_cr4());
-
- lockdep_assert_irqs_disabled();
-
-diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
-index 145a7ac0c19a..058941e9ae40 100644
---- a/arch/x86/kernel/process.c
-+++ b/arch/x86/kernel/process.c
-@@ -596,6 +596,7 @@ void speculation_ctrl_update_current(void)
- static inline void cr4_toggle_bits_irqsoff(unsigned long mask)
- {
- unsigned long newval, cr4 = this_cpu_read(cpu_tlbstate.cr4);
-+ BUG_ON(cr4 != __read_cr4());
-
- newval = cr4 ^ mask;
- if (newval != cr4) {
-diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
-index 569ac1d57f55..044d88da4aee 100644
---- a/arch/x86/mm/tlb.c
-+++ b/arch/x86/mm/tlb.c
-@@ -1066,6 +1066,7 @@ STATIC_NOPV void native_flush_tlb_global(void)
- raw_local_irq_save(flags);
-
- cr4 = this_cpu_read(cpu_tlbstate.cr4);
-+ BUG_ON(cr4 != __read_cr4());
- /* toggle PGE */
- native_write_cr4(cr4 ^ X86_CR4_PGE);
- /* write old PGE again and flush TLBs */
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0080-add-writable-function-pointer-detection.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0080-add-writable-function-pointer-detection.patch
deleted file mode 100644
index 2b9481298465..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0080-add-writable-function-pointer-detection.patch
+++ /dev/null
@@ -1,98 +0,0 @@
-From c8a90c462a2c97516e76c80f9fdf93f615303b5a Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 9 Jul 2017 17:53:23 -0400
-Subject: [PATCH 080/113] add writable function pointer detection
-
-Taken from the public PaX patches.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- scripts/mod/modpost.c | 28 +++++++++++++++++++++++++---
- 1 file changed, 25 insertions(+), 3 deletions(-)
-
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index f882ce0d9327..50e9baefc4e7 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -34,6 +34,7 @@ static int external_module = 0;
- static int warn_unresolved = 0;
- /* How a symbol is exported */
- static int sec_mismatch_count = 0;
-+static int writable_fptr_count = 0;
- static int sec_mismatch_fatal = 0;
- /* ignore missing files */
- static int ignore_missing_files;
-@@ -1007,6 +1008,7 @@ enum mismatch {
- ANY_EXIT_TO_ANY_INIT,
- EXPORT_TO_INIT_EXIT,
- EXTABLE_TO_NON_TEXT,
-+ DATA_TO_TEXT
- };
-
- /**
-@@ -1133,6 +1135,12 @@ static const struct sectioncheck sectioncheck[] = {
- .good_tosec = {ALL_TEXT_SECTIONS , NULL},
- .mismatch = EXTABLE_TO_NON_TEXT,
- .handler = extable_mismatch_handler,
-+},
-+/* Do not reference code from writable data */
-+{
-+ .fromsec = { DATA_SECTIONS, NULL },
-+ .bad_tosec = { ALL_TEXT_SECTIONS, NULL },
-+ .mismatch = DATA_TO_TEXT
- }
- };
-
-@@ -1320,10 +1328,10 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
- continue;
- if (!is_valid_name(elf, sym))
- continue;
-- if (sym->st_value == addr)
-- return sym;
- /* Find a symbol nearby - addr are maybe negative */
- d = sym->st_value - addr;
-+ if (d == 0)
-+ return sym;
- if (d < 0)
- d = addr - sym->st_value;
- if (d < distance) {
-@@ -1458,7 +1466,10 @@ static void report_sec_mismatch(const char *modname,
- char *prl_from;
- char *prl_to;
-
-- sec_mismatch_count++;
-+ if (mismatch->mismatch == DATA_TO_TEXT)
-+ writable_fptr_count++;
-+ else
-+ sec_mismatch_count++;
-
- get_pretty_name(from_is_func, &from, &from_p);
- get_pretty_name(to_is_func, &to, &to_p);
-@@ -1580,6 +1591,14 @@ static void report_sec_mismatch(const char *modname,
- fatal("There's a special handler for this mismatch type, "
- "we should never get here.");
- break;
-+ case DATA_TO_TEXT:
-+#if 0
-+ fprintf(stderr,
-+ "The %s %s:%s references\n"
-+ "the %s %s:%s%s\n",
-+ from, fromsec, fromsym, to, tosec, tosym, to_p);
-+#endif
-+ break;
- }
- fprintf(stderr, "\n");
- }
-@@ -2670,6 +2689,9 @@ int main(int argc, char **argv)
- }
-
- free(buf.p);
-+ if (writable_fptr_count)
-+ warn("modpost: Found %d writable function pointer(s).\n",
-+ writable_fptr_count);
-
- return err;
- }
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0081-support-overriding-early-audit-kernel-cmdline.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0081-support-overriding-early-audit-kernel-cmdline.patch
deleted file mode 100644
index f5ae97ad2705..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0081-support-overriding-early-audit-kernel-cmdline.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From c7c946e6ec27727494c6f146430b8b7d8e89ef1b Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 9 Jul 2017 17:20:29 -0400
-Subject: [PATCH 081/113] support overriding early audit kernel cmdline
-
----
- kernel/audit.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/kernel/audit.c b/kernel/audit.c
-index 68cee3bc8cfe..2059c66f7c9b 100644
---- a/kernel/audit.c
-+++ b/kernel/audit.c
-@@ -1693,6 +1693,9 @@ static int __init audit_enable(char *str)
-
- if (audit_default == AUDIT_OFF)
- audit_initialized = AUDIT_DISABLED;
-+ else if (!audit_ever_enabled)
-+ audit_initialized = AUDIT_UNINITIALIZED;
-+
- if (audit_set_enabled(audit_default))
- pr_err("audit: error setting audit state (%d)\n",
- audit_default);
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch
deleted file mode 100644
index 1717c2b9ac10..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch
+++ /dev/null
@@ -1,135 +0,0 @@
-From b5a43b9058570b8124fe98e9e98a60468a5f711d Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 3 Jun 2017 17:34:13 -0400
-Subject: [PATCH 082/113] FORTIFY_SOURCE intra-object overflow checking
-
-This adds supporting for detecting buffer overflows from inner objects
-for the fortified string family functions. It's comparable to the
-_FORTIFY_SOURCE=2 feature in glibc with the additional coverage of
-intra-object read overflows for supported functions.
-
-The mem* family functions are left with only the inter-object overflow
-checks as is the case with glibc _FORTIFY_SOURCE=2.
-
-This feature is currently hidden behind CONFIG_EXPERT because it's a lot
-more likely to uncover benign / intended issues and will need a lot of
-runtime testing. It's already useful for finding bugs but it may not yet
-be a good idea to use it for hardening unless panics for benign issues
-are seen as a lesser evil than the vulnerabilities it can catch.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/string.h | 26 ++++++++++++++++----------
- security/Kconfig | 10 ++++++++++
- 2 files changed, 26 insertions(+), 10 deletions(-)
-
-diff --git a/include/linux/string.h b/include/linux/string.h
-index b1f3894a0a3e..4c5564a6ad80 100644
---- a/include/linux/string.h
-+++ b/include/linux/string.h
-@@ -264,6 +264,12 @@ void __read_overflow2(void) __compiletime_error("detected read beyond size of ob
- void __read_overflow3(void) __compiletime_error("detected read beyond size of object passed as 3rd parameter");
- void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
-
-+#ifdef CONFIG_FORTIFY_SOURCE_STRICT_STRING
-+#define __string_size(p) __builtin_object_size(p, 1)
-+#else
-+#define __string_size(p) __builtin_object_size(p, 0)
-+#endif
-+
- #if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE)
-
- #ifdef CONFIG_KASAN
-@@ -292,7 +298,7 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size)
-
- __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
- {
-- size_t p_size = __builtin_object_size(p, 0);
-+ size_t p_size = __string_size(p);
- if (__builtin_constant_p(size) && p_size < size)
- __write_overflow();
- if (p_size < size)
-@@ -302,7 +308,7 @@ __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
-
- __FORTIFY_INLINE char *strcat(char *p, const char *q)
- {
-- size_t p_size = __builtin_object_size(p, 0);
-+ size_t p_size = __string_size(p);
- if (p_size == (size_t)-1)
- return __underlying_strcat(p, q);
- if (strlcat(p, q, p_size) >= p_size)
-@@ -313,7 +319,7 @@ __FORTIFY_INLINE char *strcat(char *p, const char *q)
- __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
- {
- __kernel_size_t ret;
-- size_t p_size = __builtin_object_size(p, 0);
-+ size_t p_size = __string_size(p);
-
- /* Work around gcc excess stack consumption issue */
- if (p_size == (size_t)-1 ||
-@@ -328,7 +334,7 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
- extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
- __FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen)
- {
-- size_t p_size = __builtin_object_size(p, 0);
-+ size_t p_size = __string_size(p);
- __kernel_size_t ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
- if (p_size <= ret && maxlen != ret)
- fortify_panic(__func__);
-@@ -340,8 +346,8 @@ extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
- __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
- {
- size_t ret;
-- size_t p_size = __builtin_object_size(p, 0);
-- size_t q_size = __builtin_object_size(q, 0);
-+ size_t p_size = __string_size(p);
-+ size_t q_size = __string_size(q);
- if (p_size == (size_t)-1 && q_size == (size_t)-1)
- return __real_strlcpy(p, q, size);
- ret = strlen(q);
-@@ -361,8 +367,8 @@ __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
- __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
- {
- size_t p_len, copy_len;
-- size_t p_size = __builtin_object_size(p, 0);
-- size_t q_size = __builtin_object_size(q, 0);
-+ size_t p_size = __string_size(p);
-+ size_t q_size = __string_size(q);
- if (p_size == (size_t)-1 && q_size == (size_t)-1)
- return __underlying_strncat(p, q, count);
- p_len = strlen(p);
-@@ -475,8 +481,8 @@ __FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp)
- /* defined after fortified strlen and memcpy to reuse them */
- __FORTIFY_INLINE char *strcpy(char *p, const char *q)
- {
-- size_t p_size = __builtin_object_size(p, 0);
-- size_t q_size = __builtin_object_size(q, 0);
-+ size_t p_size = __string_size(p);
-+ size_t q_size = __string_size(q);
- if (p_size == (size_t)-1 && q_size == (size_t)-1)
- return __underlying_strcpy(p, q);
- memcpy(p, q, strlen(q) + 1);
-diff --git a/security/Kconfig b/security/Kconfig
-index 2348ff7d4e1d..f3c995bd79cf 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -208,6 +208,16 @@ config FORTIFY_SOURCE
- Detect overflows of buffers in common string and memory functions
- where the compiler can determine and validate the buffer sizes.
-
-+config FORTIFY_SOURCE_STRICT_STRING
-+ bool "Harden common functions against buffer overflows"
-+ depends on FORTIFY_SOURCE
-+ depends on EXPERT
-+ help
-+ Perform stricter overflow checks catching overflows within objects
-+ for common C string functions rather than only between objects.
-+
-+ This is not yet intended for production use, only bug finding.
-+
- config STATIC_USERMODEHELPER
- bool "Force all usermode helper calls through a single binary"
- help
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch
deleted file mode 100644
index 6e3e58ed378d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From a24e2080e304e3b7ba674bb8dd591fb86302af83 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 26 Aug 2017 20:16:03 -0400
-Subject: [PATCH 083/113] Revert "mm: revert x86_64 and arm64 ELF_ET_DYN_BASE
- base changes"
-
-This reverts commit aab425db4279aeb83b7911693f0cccbd3644c9fd.
----
- arch/arm64/include/asm/elf.h | 8 ++------
- arch/x86/include/asm/elf.h | 4 ++--
- 2 files changed, 4 insertions(+), 8 deletions(-)
-
-diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
-index 8d1c8dcb87fd..26d27c7a2c2e 100644
---- a/arch/arm64/include/asm/elf.h
-+++ b/arch/arm64/include/asm/elf.h
-@@ -124,14 +124,10 @@
-
- /*
- * This is the base location for PIE (ET_DYN with INTERP) loads. On
-- * 64-bit, this is above 4GB to leave the entire 32-bit address
-+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
- * space open for things that want to use the area for 32-bit pointers.
- */
--#ifdef CONFIG_ARM64_FORCE_52BIT
--#define ELF_ET_DYN_BASE (2 * TASK_SIZE_64 / 3)
--#else
--#define ELF_ET_DYN_BASE (2 * DEFAULT_MAP_WINDOW_64 / 3)
--#endif /* CONFIG_ARM64_FORCE_52BIT */
-+#define ELF_ET_DYN_BASE 0x100000000UL
-
- #ifndef __ASSEMBLY__
-
-diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
-index b9a5d488f1a5..b55054566ece 100644
---- a/arch/x86/include/asm/elf.h
-+++ b/arch/x86/include/asm/elf.h
-@@ -246,11 +246,11 @@ extern int force_personality32;
-
- /*
- * This is the base location for PIE (ET_DYN with INTERP) loads. On
-- * 64-bit, this is above 4GB to leave the entire 32-bit address
-+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
- * space open for things that want to use the area for 32-bit pointers.
- */
- #define ELF_ET_DYN_BASE (mmap_is_ia32() ? 0x000400000UL : \
-- (DEFAULT_MAP_WINDOW / 3 * 2))
-+ 0x100000000UL)
-
- /* This yields a mask that user programs can use to figure out what
- instruction set this CPU supports. This could be done in user space,
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch
deleted file mode 100644
index c7c941239fd4..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch
+++ /dev/null
@@ -1,118 +0,0 @@
-From bb18120691acbc0ac0ec0b87f5132019ff5a39fd Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 11 May 2017 16:52:00 -0400
-Subject: [PATCH 084/113] x86_64: move vdso to mmap region from stack region
-
-This removes the only executable code from the stack region and gives
-the vdso the same randomized base as other mmap mappings including the
-linker and other shared objects. It results in a sane amount of entropy
-being provided and there's little to no advantage in separating this
-from the existing executable code there.
-
-It's sensible for userspace to reserve the initial mmap base as a region
-for executable code with a random gap for other mmap allocations, along
-with providing randomization within that region. However, there isn't
-much the kernel can do to help due to how dynamic linkers load the
-shared objects.
-
-This was extracted from the PaX RANDMMAP feature.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/entry/vdso/vma.c | 48 +-----------------------------------
- arch/x86/include/asm/elf.h | 1 -
- arch/x86/kernel/sys_x86_64.c | 7 ------
- 3 files changed, 1 insertion(+), 55 deletions(-)
-
-diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
-index 9185cb1d13b9..543912071557 100644
---- a/arch/x86/entry/vdso/vma.c
-+++ b/arch/x86/entry/vdso/vma.c
-@@ -315,55 +315,9 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
- }
-
- #ifdef CONFIG_X86_64
--/*
-- * Put the vdso above the (randomized) stack with another randomized
-- * offset. This way there is no hole in the middle of address space.
-- * To save memory make sure it is still in the same PTE as the stack
-- * top. This doesn't give that many random bits.
-- *
-- * Note that this algorithm is imperfect: the distribution of the vdso
-- * start address within a PMD is biased toward the end.
-- *
-- * Only used for the 64-bit and x32 vdsos.
-- */
--static unsigned long vdso_addr(unsigned long start, unsigned len)
--{
-- unsigned long addr, end;
-- unsigned offset;
--
-- /*
-- * Round up the start address. It can start out unaligned as a result
-- * of stack start randomization.
-- */
-- start = PAGE_ALIGN(start);
--
-- /* Round the lowest possible end address up to a PMD boundary. */
-- end = (start + len + PMD_SIZE - 1) & PMD_MASK;
-- if (end >= TASK_SIZE_MAX)
-- end = TASK_SIZE_MAX;
-- end -= len;
--
-- if (end > start) {
-- offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
-- addr = start + (offset << PAGE_SHIFT);
-- } else {
-- addr = start;
-- }
--
-- /*
-- * Forcibly align the final address in case we have a hardware
-- * issue that requires alignment for performance reasons.
-- */
-- addr = align_vdso_addr(addr);
--
-- return addr;
--}
--
- static int map_vdso_randomized(const struct vdso_image *image)
- {
-- unsigned long addr = vdso_addr(current->mm->start_stack, image->size-image->sym_vvar_start);
--
-- return map_vdso(image, addr);
-+ return map_vdso(image, 0);
- }
- #endif
-
-diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
-index b55054566ece..58292600112d 100644
---- a/arch/x86/include/asm/elf.h
-+++ b/arch/x86/include/asm/elf.h
-@@ -398,5 +398,4 @@ struct va_alignment {
- } ____cacheline_aligned;
-
- extern struct va_alignment va_align;
--extern unsigned long align_vdso_addr(unsigned long);
- #endif /* _ASM_X86_ELF_H */
-diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
-index 504fa5425bce..c4e35a3b3733 100644
---- a/arch/x86/kernel/sys_x86_64.c
-+++ b/arch/x86/kernel/sys_x86_64.c
-@@ -52,13 +52,6 @@ static unsigned long get_align_bits(void)
- return va_align.bits & get_align_mask();
- }
-
--unsigned long align_vdso_addr(unsigned long addr)
--{
-- unsigned long align_mask = get_align_mask();
-- addr = (addr + align_mask) & ~align_mask;
-- return addr | get_align_bits();
--}
--
- static int __init control_va_addr_alignment(char *str)
- {
- /* guard against enabling this on other CPU families */
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch
deleted file mode 100644
index 8d9aa61d1a0a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 126dd08ead6bc733aeda03b5437be681dcbe79e4 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 21 May 2017 20:30:44 -0400
-Subject: [PATCH 085/113] x86: determine stack entropy based on mmap entropy
-
-Stack mapping entropy is currently hard-wired to 11 bits of entropy on
-32-bit and 22 bits of entropy on 64-bit. The stack itself gains an extra
-8 bits of entropy from lower bit randomization within 16 byte alignment
-constraints. The argument block could have all lower bits randomized but
-it currently only gets the mapping randomization.
-
-Rather than hard-wiring values this switches to using the mmap entropy
-configuration like the mmap base and executable base, resulting in a
-range of 8 to 16 bits on 32-bit and 28 to 32 bits on 64-bit depending on
-kernel configuration and overridable via the sysctl entries.
-
-It's worth noting that since these kernel configuration options default
-to the minimum supported entropy value, the entropy on 32-bit will drop
-from 11 to 8 bits for builds using the defaults. However, following the
-configuration seems like the right thing to do regardless. At the very
-least, changing the defaults for COMPAT (32-bit processes on 64-bit)
-should be considered due to the larger address space compared to real
-32-bit.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/include/asm/elf.h | 10 +++++++---
- 1 file changed, 7 insertions(+), 3 deletions(-)
-
-diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
-index 58292600112d..608cca19cf8c 100644
---- a/arch/x86/include/asm/elf.h
-+++ b/arch/x86/include/asm/elf.h
-@@ -330,8 +330,8 @@ extern bool mmap_address_hint_valid(unsigned long addr, unsigned long len);
-
- #ifdef CONFIG_X86_32
-
--#define __STACK_RND_MASK(is32bit) (0x7ff)
--#define STACK_RND_MASK (0x7ff)
-+#define __STACK_RND_MASK(is32bit) ((1UL << mmap_rnd_bits) - 1)
-+#define STACK_RND_MASK ((1UL << mmap_rnd_bits) - 1)
-
- #define ARCH_DLINFO ARCH_DLINFO_IA32
-
-@@ -340,7 +340,11 @@ extern bool mmap_address_hint_valid(unsigned long addr, unsigned long len);
- #else /* CONFIG_X86_32 */
-
- /* 1GB for 64bit, 8MB for 32bit */
--#define __STACK_RND_MASK(is32bit) ((is32bit) ? 0x7ff : 0x3fffff)
-+#ifdef CONFIG_COMPAT
-+#define __STACK_RND_MASK(is32bit) ((is32bit) ? (1UL << mmap_rnd_compat_bits) - 1 : (1UL << mmap_rnd_bits) - 1)
-+#else
-+#define __STACK_RND_MASK(is32bit) ((1UL << mmap_rnd_bits) - 1)
-+#endif
- #define STACK_RND_MASK __STACK_RND_MASK(mmap_is_ia32())
-
- #define ARCH_DLINFO \
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch
deleted file mode 100644
index 2abbe7353112..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 930f572c37938def097762704a8ba0f599deae6c Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 22 May 2017 05:06:20 -0400
-Subject: [PATCH 086/113] arm64: determine stack entropy based on mmap entropy
-
-Stack mapping entropy is currently hard-wired to 11 bits of entropy on
-32-bit and 18 bits of entropy on 64-bit. The stack itself gains an extra
-8 bits of entropy from lower bit randomization within 16 byte alignment
-constraints. The argument block could have all lower bits randomized but
-it currently only gets the mapping randomization.
-
-Rather than hard-wiring values this switches to using the mmap entropy
-configuration like the mmap base and executable base, resulting in a
-range of 8 to 16 bits on 32-bit and 18 to 24 bits on 64-bit (with 4k
-pages and 3 level page tables) depending on kernel configuration and
-overridable via the sysctl entries.
-
-It's worth noting that since these kernel configuration options default
-to the minimum supported entropy value, the entropy on 32-bit will drop
-from 11 to 8 bits for builds using the defaults. However, following the
-configuration seems like the right thing to do regardless. At the very
-least, changing the defaults for COMPAT (32-bit processes on 64-bit)
-should be considered due to the larger address space compared to real
-32-bit.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/arm64/include/asm/elf.h | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
-index 26d27c7a2c2e..32c1609a1158 100644
---- a/arch/arm64/include/asm/elf.h
-+++ b/arch/arm64/include/asm/elf.h
-@@ -185,10 +185,10 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
- /* 1GB of VA */
- #ifdef CONFIG_COMPAT
- #define STACK_RND_MASK (test_thread_flag(TIF_32BIT) ? \
-- 0x7ff >> (PAGE_SHIFT - 12) : \
-- 0x3ffff >> (PAGE_SHIFT - 12))
-+ ((1UL << mmap_rnd_compat_bits) - 1) >> (PAGE_SHIFT - 12) : \
-+ ((1UL << mmap_rnd_bits) - 1) >> (PAGE_SHIFT - 12))
- #else
--#define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12))
-+#define STACK_RND_MASK (((1UL << mmap_rnd_bits) - 1) >> (PAGE_SHIFT - 12))
- #endif
-
- #ifdef __AARCH64EB__
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0087-randomize-lower-bits-of-the-argument-block.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0087-randomize-lower-bits-of-the-argument-block.patch
deleted file mode 100644
index 1745bc6a925a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0087-randomize-lower-bits-of-the-argument-block.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 51e7598866f4a7df48daada469670254b564b0b1 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 11 May 2017 16:02:49 -0400
-Subject: [PATCH 087/113] randomize lower bits of the argument block
-
-This was based on the PaX RANDUSTACK feature in grsecurity, where all of
-the lower bits are randomized. PaX keeps 16-byte alignment.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-[levente@leventepolyak.net: do not randomize with ADDR_NO_RANDOMIZE personality]
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- fs/exec.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/fs/exec.c b/fs/exec.c
-index ca89e0e3ef10..d2a03d32e195 100644
---- a/fs/exec.c
-+++ b/fs/exec.c
-@@ -34,6 +34,7 @@
- #include <linux/swap.h>
- #include <linux/string.h>
- #include <linux/init.h>
-+#include <linux/sched.h>
- #include <linux/sched/mm.h>
- #include <linux/sched/coredump.h>
- #include <linux/sched/signal.h>
-@@ -64,6 +65,7 @@
- #include <linux/compat.h>
- #include <linux/vmalloc.h>
- #include <linux/io_uring.h>
-+#include <linux/random.h>
-
- #include <linux/uaccess.h>
- #include <asm/mmu_context.h>
-@@ -280,6 +282,8 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
- mm->stack_vm = mm->total_vm = 1;
- mmap_write_unlock(mm);
- bprm->p = vma->vm_end - sizeof(void *);
-+ if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-+ bprm->p ^= get_random_int() & ~PAGE_MASK;
- return 0;
- err:
- mmap_write_unlock(mm);
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0088-x86_64-match-arm64-brk-randomization-entropy.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0088-x86_64-match-arm64-brk-randomization-entropy.patch
deleted file mode 100644
index 19067999acb9..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0088-x86_64-match-arm64-brk-randomization-entropy.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 66c0580a1686bae0d9a90043711e497955118610 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 30 May 2017 07:19:48 -0400
-Subject: [PATCH 088/113] x86_64: match arm64 brk randomization entropy
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/kernel/process.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
-index 058941e9ae40..61460d55dd72 100644
---- a/arch/x86/kernel/process.c
-+++ b/arch/x86/kernel/process.c
-@@ -43,6 +43,8 @@
- #include <asm/io_bitmap.h>
- #include <asm/proto.h>
- #include <asm/frame.h>
-+#include <asm/elf.h>
-+#include <linux/sizes.h>
-
- #include "process.h"
-
-@@ -906,7 +908,10 @@ unsigned long arch_align_stack(unsigned long sp)
-
- unsigned long arch_randomize_brk(struct mm_struct *mm)
- {
-- return randomize_page(mm->brk, 0x02000000);
-+ if (mmap_is_ia32())
-+ return randomize_page(mm->brk, SZ_32M);
-+ else
-+ return randomize_page(mm->brk, SZ_1G);
- }
-
- /*
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0089-support-randomizing-the-lower-bits-of-brk.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0089-support-randomizing-the-lower-bits-of-brk.patch
deleted file mode 100644
index 2da8c5b8f0f1..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0089-support-randomizing-the-lower-bits-of-brk.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 1d0de8a103f3e898d99012d8521f4860340fb536 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 30 May 2017 18:03:30 -0400
-Subject: [PATCH 089/113] support randomizing the lower bits of brk
-
-This adds support for arch_randomize_brk implementations not performing
-page alignment in order to randomize the lower bits of the brk heap.
-
-This idea is taken from PaX but the approach is different. This reuses
-the existing code and avoids forcing early creation of the heap mapping,
-avoiding mapping it if it's not used which is the case with many modern
-allocators based solely on mmap.
-
-The malloc implementation can be relied upon to align this as needed to
-the requirements it has, so using 16 byte alignment here is unnecessary.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/mmap.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/mm/mmap.c b/mm/mmap.c
-index 5c8b4485860d..0e26c225bb53 100644
---- a/mm/mmap.c
-+++ b/mm/mmap.c
-@@ -231,6 +231,13 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
-
- newbrk = PAGE_ALIGN(brk);
- oldbrk = PAGE_ALIGN(mm->brk);
-+ /* properly handle unaligned min_brk as an empty heap */
-+ if (min_brk & ~PAGE_MASK) {
-+ if (brk == min_brk)
-+ newbrk -= PAGE_SIZE;
-+ if (mm->brk == min_brk)
-+ oldbrk -= PAGE_SIZE;
-+ }
- if (oldbrk == newbrk) {
- mm->brk = brk;
- goto success;
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0090-mm-randomize-lower-bits-of-brk.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0090-mm-randomize-lower-bits-of-brk.patch
deleted file mode 100644
index 0c0ef1329ac0..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0090-mm-randomize-lower-bits-of-brk.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From f088fbb3c145b152d7894fae612dc65e533802f7 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 1 Jun 2017 03:22:38 -0400
-Subject: [PATCH 090/113] mm: randomize lower bits of brk
-
-Per PaX, but for this alternate brk randomization approach.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/util.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/mm/util.c b/mm/util.c
-index 4ddb6e186dd5..4ca72f952329 100644
---- a/mm/util.c
-+++ b/mm/util.c
-@@ -336,9 +336,9 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
- {
- /* Is the current task 32bit ? */
- if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task())
-- return randomize_page(mm->brk, SZ_32M);
-+ return mm->brk + get_random_long() % SZ_32M;
-
-- return randomize_page(mm->brk, SZ_1G);
-+ return mm->brk + get_random_long() % SZ_1G;
- }
-
- unsigned long arch_mmap_rnd(void)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0091-x86-randomize-lower-bits-of-brk.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0091-x86-randomize-lower-bits-of-brk.patch
deleted file mode 100644
index b266aa24cdd8..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0091-x86-randomize-lower-bits-of-brk.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From c6844260df07efd637b315c8ca67ec36fb3005d0 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 1 Jun 2017 03:23:06 -0400
-Subject: [PATCH 091/113] x86: randomize lower bits of brk
-
-Per PaX, but for this alternate brk randomization approach.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/kernel/process.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
-index 61460d55dd72..0d4c3887229d 100644
---- a/arch/x86/kernel/process.c
-+++ b/arch/x86/kernel/process.c
-@@ -909,9 +909,9 @@ unsigned long arch_align_stack(unsigned long sp)
- unsigned long arch_randomize_brk(struct mm_struct *mm)
- {
- if (mmap_is_ia32())
-- return randomize_page(mm->brk, SZ_32M);
-+ return mm->brk + get_random_long() % SZ_32M;
- else
-- return randomize_page(mm->brk, SZ_1G);
-+ return mm->brk + get_random_long() % SZ_1G;
- }
-
- /*
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0092-mm-guarantee-brk-gap-is-at-least-one-page.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0092-mm-guarantee-brk-gap-is-at-least-one-page.patch
deleted file mode 100644
index a8d4f1d61ecc..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0092-mm-guarantee-brk-gap-is-at-least-one-page.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From f8919940be09063ec29f0e0ea9da1469d58f2cc1 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 1 Jun 2017 03:23:39 -0400
-Subject: [PATCH 092/113] mm: guarantee brk gap is at least one page
-
-Per PaX, but for this alternate brk randomization approach.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/util.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/mm/util.c b/mm/util.c
-index 4ca72f952329..62ed34dfceb7 100644
---- a/mm/util.c
-+++ b/mm/util.c
-@@ -336,9 +336,9 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
- {
- /* Is the current task 32bit ? */
- if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task())
-- return mm->brk + get_random_long() % SZ_32M;
-+ return mm->brk + get_random_long() % SZ_32M + PAGE_SIZE;
-
-- return mm->brk + get_random_long() % SZ_1G;
-+ return mm->brk + get_random_long() % SZ_1G + PAGE_SIZE;
- }
-
- unsigned long arch_mmap_rnd(void)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0093-x86-guarantee-brk-gap-is-at-least-one-page.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0093-x86-guarantee-brk-gap-is-at-least-one-page.patch
deleted file mode 100644
index 00b4d1fa0aef..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0093-x86-guarantee-brk-gap-is-at-least-one-page.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 6b7efcb39595358c65649b973aef2913ad0d799e Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 1 Jun 2017 03:23:48 -0400
-Subject: [PATCH 093/113] x86: guarantee brk gap is at least one page
-
-Per PaX, but for this alternate brk randomization approach.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/kernel/process.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
-index 0d4c3887229d..161e25d02fd5 100644
---- a/arch/x86/kernel/process.c
-+++ b/arch/x86/kernel/process.c
-@@ -909,9 +909,9 @@ unsigned long arch_align_stack(unsigned long sp)
- unsigned long arch_randomize_brk(struct mm_struct *mm)
- {
- if (mmap_is_ia32())
-- return mm->brk + get_random_long() % SZ_32M;
-+ return mm->brk + get_random_long() % SZ_32M + PAGE_SIZE;
- else
-- return mm->brk + get_random_long() % SZ_1G;
-+ return mm->brk + get_random_long() % SZ_1G + PAGE_SIZE;
- }
-
- /*
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0094-x86_64-bound-mmap-between-legacy-modern-bases.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0094-x86_64-bound-mmap-between-legacy-modern-bases.patch
deleted file mode 100644
index 3140177e5960..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0094-x86_64-bound-mmap-between-legacy-modern-bases.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From d7a9ef8618009dccbcd086c2f3d21c4a29b6b498 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 14:50:54 -0400
-Subject: [PATCH 094/113] x86_64: bound mmap between legacy/modern bases
-
----
- arch/x86/kernel/sys_x86_64.c | 7 ++-----
- 1 file changed, 2 insertions(+), 5 deletions(-)
-
-diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
-index c4e35a3b3733..e30ec4c750d1 100644
---- a/arch/x86/kernel/sys_x86_64.c
-+++ b/arch/x86/kernel/sys_x86_64.c
-@@ -113,10 +113,7 @@ static void find_start_end(unsigned long addr, unsigned long flags,
- }
-
- *begin = get_mmap_base(1);
-- if (in_32bit_syscall())
-- *end = task_size_32bit();
-- else
-- *end = task_size_64bit(addr > DEFAULT_MAP_WINDOW);
-+ *end = get_mmap_base(0);
- }
-
- unsigned long
-@@ -193,7 +190,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
-
- info.flags = VM_UNMAPPED_AREA_TOPDOWN;
- info.length = len;
-- info.low_limit = PAGE_SIZE;
-+ info.low_limit = get_mmap_base(1);
- info.high_limit = get_mmap_base(0);
-
- /*
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0095-restrict-device-timing-side-channels.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0095-restrict-device-timing-side-channels.patch
deleted file mode 100644
index d276152c9a94..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0095-restrict-device-timing-side-channels.patch
+++ /dev/null
@@ -1,174 +0,0 @@
-From ce7b0fe63b30677aeaeb161e21c0d552a800ea70 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 16 May 2017 18:26:10 -0400
-Subject: [PATCH 095/113] restrict device timing side channels
-
-Based on the public grsecurity patches.
-
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- fs/inode.c | 4 ++++
- fs/stat.c | 20 +++++++++++++++-----
- include/linux/capability.h | 5 +++++
- include/linux/fs.h | 11 +++++++++++
- include/linux/fsnotify.h | 4 ++++
- kernel/capability.c | 6 ++++++
- kernel/sysctl.c | 9 +++++++++
- 7 files changed, 54 insertions(+), 5 deletions(-)
-
-diff --git a/fs/inode.c b/fs/inode.c
-index 5eea9912a0b9..f86f383a3e1d 100644
---- a/fs/inode.c
-+++ b/fs/inode.c
-@@ -116,6 +116,10 @@ int proc_nr_inodes(struct ctl_table *table, int write,
- }
- #endif
-
-+/* sysctl */
-+int device_sidechannel_restrict __read_mostly = 1;
-+EXPORT_SYMBOL(device_sidechannel_restrict);
-+
- static int no_open(struct inode *inode, struct file *file)
- {
- return -ENXIO;
-diff --git a/fs/stat.c b/fs/stat.c
-index dacecdda2e79..14173d0f777d 100644
---- a/fs/stat.c
-+++ b/fs/stat.c
-@@ -43,8 +43,13 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
- stat->gid = inode->i_gid;
- stat->rdev = inode->i_rdev;
- stat->size = i_size_read(inode);
-- stat->atime = inode->i_atime;
-- stat->mtime = inode->i_mtime;
-+ if (is_sidechannel_device(inode) && !capable_noaudit(CAP_MKNOD)) {
-+ stat->atime = inode->i_ctime;
-+ stat->mtime = inode->i_ctime;
-+ } else {
-+ stat->atime = inode->i_atime;
-+ stat->mtime = inode->i_mtime;
-+ }
- stat->ctime = inode->i_ctime;
- stat->blksize = i_blocksize(inode);
- stat->blocks = inode->i_blocks;
-@@ -83,9 +88,14 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
- if (IS_DAX(inode))
- stat->attributes |= STATX_ATTR_DAX;
-
-- if (inode->i_op->getattr)
-- return inode->i_op->getattr(path, stat, request_mask,
-- query_flags);
-+ if (inode->i_op->getattr) {
-+ int retval = inode->i_op->getattr(path, stat, request_mask, query_flags);
-+ if (!retval && is_sidechannel_device(inode) && !capable_noaudit(CAP_MKNOD)) {
-+ stat->atime = stat->ctime;
-+ stat->mtime = stat->ctime;
-+ }
-+ return retval;
-+ }
-
- generic_fillattr(inode, stat);
- return 0;
-diff --git a/include/linux/capability.h b/include/linux/capability.h
-index 1e7fe311cabe..a5b6d4c9acf5 100644
---- a/include/linux/capability.h
-+++ b/include/linux/capability.h
-@@ -208,6 +208,7 @@ extern bool has_capability_noaudit(struct task_struct *t, int cap);
- extern bool has_ns_capability_noaudit(struct task_struct *t,
- struct user_namespace *ns, int cap);
- extern bool capable(int cap);
-+extern bool capable_noaudit(int cap);
- extern bool ns_capable(struct user_namespace *ns, int cap);
- extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
- extern bool ns_capable_setid(struct user_namespace *ns, int cap);
-@@ -234,6 +235,10 @@ static inline bool capable(int cap)
- {
- return true;
- }
-+static inline bool capable_noaudit(int cap)
-+{
-+ return true;
-+}
- static inline bool ns_capable(struct user_namespace *ns, int cap)
- {
- return true;
-diff --git a/include/linux/fs.h b/include/linux/fs.h
-index 8bde32cf9711..83d50b0a2a18 100644
---- a/include/linux/fs.h
-+++ b/include/linux/fs.h
-@@ -3475,4 +3475,15 @@ static inline int inode_drain_writes(struct inode *inode)
- return filemap_write_and_wait(inode->i_mapping);
- }
-
-+extern int device_sidechannel_restrict;
-+
-+static inline bool is_sidechannel_device(const struct inode *inode)
-+{
-+ umode_t mode;
-+ if (!device_sidechannel_restrict)
-+ return false;
-+ mode = inode->i_mode;
-+ return ((S_ISCHR(mode) || S_ISBLK(mode)) && (mode & (S_IROTH | S_IWOTH)));
-+}
-+
- #endif /* _LINUX_FS_H */
-diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
-index f8acddcf54fb..7b109980327f 100644
---- a/include/linux/fsnotify.h
-+++ b/include/linux/fsnotify.h
-@@ -83,10 +83,14 @@ static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask)
- static inline int fsnotify_file(struct file *file, __u32 mask)
- {
- const struct path *path = &file->f_path;
-+ struct inode *inode = file_inode(file);
-
- if (file->f_mode & FMODE_NONOTIFY)
- return 0;
-
-+ if (mask & (FS_ACCESS | FS_MODIFY) && is_sidechannel_device(inode))
-+ return 0;
-+
- return fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH);
- }
-
-diff --git a/kernel/capability.c b/kernel/capability.c
-index de7eac903a2a..5602178f3d21 100644
---- a/kernel/capability.c
-+++ b/kernel/capability.c
-@@ -449,6 +449,12 @@ bool capable(int cap)
- return ns_capable(&init_user_ns, cap);
- }
- EXPORT_SYMBOL(capable);
-+
-+bool capable_noaudit(int cap)
-+{
-+ return ns_capable_noaudit(&init_user_ns, cap);
-+}
-+EXPORT_SYMBOL(capable_noaudit);
- #endif /* CONFIG_MULTIUSER */
-
- /**
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index fccf24a08c8a..7fda9f61ea1a 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -2272,6 +2272,15 @@ static struct ctl_table kern_table[] = {
- .extra2 = &two,
- },
- #endif
-+ {
-+ .procname = "device_sidechannel_restrict",
-+ .data = &device_sidechannel_restrict,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax_sysadmin,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
- {
- .procname = "ngroups_max",
- .data = &ngroups_max,
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch
deleted file mode 100644
index 629f8256d952..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From 6a1b1cc37d5d3aa6a23ef6aab6b4726720cd225c Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Sun, 6 Sep 2020 20:28:32 +0200
-Subject: [PATCH 096/113] sysctl: expose proc_dointvec_minmax_sysadmin as API
- function
-
-Orthogonal to the other sysctl proc functions expose the variant that is
-checking CAP_SYS_ADMIN on write for consumption in external subsystem's
-sysctl tables.
-
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- include/linux/sysctl.h | 2 ++
- kernel/sysctl.c | 31 ++++++++++++++++++++++++++++---
- 2 files changed, 30 insertions(+), 3 deletions(-)
-
-diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
-index 51298a4f4623..b835c57330f2 100644
---- a/include/linux/sysctl.h
-+++ b/include/linux/sysctl.h
-@@ -53,6 +53,8 @@ int proc_douintvec(struct ctl_table *, int, void *, size_t *, loff_t *);
- int proc_dointvec_minmax(struct ctl_table *, int, void *, size_t *, loff_t *);
- int proc_douintvec_minmax(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos);
-+int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
-+ void *buffer, size_t *lenp, loff_t *ppos);
- int proc_dointvec_jiffies(struct ctl_table *, int, void *, size_t *, loff_t *);
- int proc_dointvec_userhz_jiffies(struct ctl_table *, int, void *, size_t *,
- loff_t *);
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index 7fda9f61ea1a..13b619e46ade 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -890,8 +890,27 @@ static int proc_taint(struct ctl_table *table, int write,
- return err;
- }
-
--#ifdef CONFIG_PRINTK
--static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
-+/**
-+ * proc_dointvec_minmax_sysadmin - read a vector of integers with min/max values
-+ * checking CAP_SYS_ADMIN on write
-+ * @table: the sysctl table
-+ * @write: %TRUE if this is a write to the sysctl file
-+ * @buffer: the user buffer
-+ * @lenp: the size of the user buffer
-+ * @ppos: file position
-+ *
-+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
-+ * values from/to the user buffer, treated as an ASCII string.
-+ *
-+ * This routine will ensure the values are within the range specified by
-+ * table->extra1 (min) and table->extra2 (max).
-+ *
-+ * Writing is only allowed when root has CAP_SYS_ADMIN.
-+ *
-+ * Returns 0 on success, -EPERM on permission failure or -EINVAL on write
-+ * when the range check fails.
-+ */
-+int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
- {
- if (write && !capable(CAP_SYS_ADMIN))
-@@ -899,7 +918,6 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
-
- return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
- }
--#endif
-
- /**
- * struct do_proc_dointvec_minmax_conv_param - proc_dointvec_minmax() range checking structure
-@@ -1585,6 +1603,12 @@ int proc_douintvec_minmax(struct ctl_table *table, int write,
- return -ENOSYS;
- }
-
-+int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
-+ void *buffer, size_t *lenp, loff_t *ppos)
-+{
-+ return -ENOSYS;
-+}
-+
- int proc_dointvec_jiffies(struct ctl_table *table, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
- {
-@@ -3436,6 +3460,7 @@ EXPORT_SYMBOL(proc_douintvec);
- EXPORT_SYMBOL(proc_dointvec_jiffies);
- EXPORT_SYMBOL(proc_dointvec_minmax);
- EXPORT_SYMBOL_GPL(proc_douintvec_minmax);
-+EXPORT_SYMBOL(proc_dointvec_minmax_sysadmin);
- EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
- EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
- EXPORT_SYMBOL(proc_dostring);
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch
deleted file mode 100644
index 8a965de850f9..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-From 4091a85d5aefe21c2a671e2b8f72f887b6199c54 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 16 May 2017 17:51:48 -0400
-Subject: [PATCH 097/113] usb: add toggle for disabling newly added USB devices
-
-Based on the public grsecurity patches.
-
-[thibaut.sautereau@ssi.gouv.fr: Adapt to sysctl code refactoring]
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- drivers/usb/core/hub.c | 9 +++++++++
- include/linux/usb.h | 3 +++
- kernel/sysctl.c | 14 ++++++++++++++
- 3 files changed, 26 insertions(+)
-
-diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index 17202b2ee063..9385c745d55e 100644
---- a/drivers/usb/core/hub.c
-+++ b/drivers/usb/core/hub.c
-@@ -5054,6 +5054,9 @@ static int descriptors_changed(struct usb_device *udev,
- return changed;
- }
-
-+/* sysctl */
-+int deny_new_usb __read_mostly = 0;
-+
- static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
- u16 portchange)
- {
-@@ -5114,6 +5117,12 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
- goto done;
- return;
- }
-+
-+ if (deny_new_usb) {
-+ dev_err(&port_dev->dev, "denied insert of USB device on port %d\n", port1);
-+ goto done;
-+ }
-+
- if (hub_is_superspeed(hub->hdev))
- unit_load = 150;
- else
-diff --git a/include/linux/usb.h b/include/linux/usb.h
-index 7d72c4e0713c..8e7549e3012a 100644
---- a/include/linux/usb.h
-+++ b/include/linux/usb.h
-@@ -2035,6 +2035,9 @@ extern void usb_led_activity(enum usb_led_event ev);
- static inline void usb_led_activity(enum usb_led_event ev) {}
- #endif
-
-+/* sysctl */
-+extern int deny_new_usb;
-+
- #endif /* __KERNEL__ */
-
- #endif
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index 13b619e46ade..f867606fbd80 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -106,6 +106,9 @@
- #ifdef CONFIG_USER_NS
- #include <linux/user_namespace.h>
- #endif
-+#if IS_ENABLED(CONFIG_USB)
-+#include <linux/usb.h>
-+#endif
-
- #if defined(CONFIG_SYSCTL)
-
-@@ -2305,6 +2308,17 @@ static struct ctl_table kern_table[] = {
- .extra1 = SYSCTL_ZERO,
- .extra2 = SYSCTL_ONE,
- },
-+#if IS_ENABLED(CONFIG_USB)
-+ {
-+ .procname = "deny_new_usb",
-+ .data = &deny_new_usb,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax_sysadmin,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
-+#endif
- {
- .procname = "ngroups_max",
- .data = &ngroups_max,
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0098-usb-implement-dedicated-subsystem-sysctl-tables.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0098-usb-implement-dedicated-subsystem-sysctl-tables.patch
deleted file mode 100644
index 8e747bc33d43..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0098-usb-implement-dedicated-subsystem-sysctl-tables.patch
+++ /dev/null
@@ -1,195 +0,0 @@
-From 9aaa0c74187b97e2ba307931d2c8c28df024fbb0 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Sun, 6 Sep 2020 21:08:16 +0200
-Subject: [PATCH 098/113] usb: implement dedicated subsystem sysctl tables
-
-This moves the usb related sysctl knobs to an own usb local sysctl table
-in order to clean up the global sysctl as well as allow the knob to be
-exported and referenced appropriately when building the usb components
-as dedicated modules.
-
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- drivers/usb/core/Makefile | 1 +
- drivers/usb/core/hub.c | 3 ---
- drivers/usb/core/sysctl.c | 44 +++++++++++++++++++++++++++++++++++++++
- drivers/usb/core/usb.c | 9 ++++++++
- include/linux/usb.h | 10 ++++++++-
- kernel/sysctl.c | 14 -------------
- 6 files changed, 63 insertions(+), 18 deletions(-)
- create mode 100644 drivers/usb/core/sysctl.c
-
-diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
-index 18e874b0441e..fc7a3a9aa72a 100644
---- a/drivers/usb/core/Makefile
-+++ b/drivers/usb/core/Makefile
-@@ -11,6 +11,7 @@ usbcore-y += phy.o port.o
- usbcore-$(CONFIG_OF) += of.o
- usbcore-$(CONFIG_USB_PCI) += hcd-pci.o
- usbcore-$(CONFIG_ACPI) += usb-acpi.o
-+usbcore-$(CONFIG_SYSCTL) += sysctl.o
-
- obj-$(CONFIG_USB) += usbcore.o
-
-diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index 9385c745d55e..b62b3da81ac4 100644
---- a/drivers/usb/core/hub.c
-+++ b/drivers/usb/core/hub.c
-@@ -5054,9 +5054,6 @@ static int descriptors_changed(struct usb_device *udev,
- return changed;
- }
-
--/* sysctl */
--int deny_new_usb __read_mostly = 0;
--
- static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
- u16 portchange)
- {
-diff --git a/drivers/usb/core/sysctl.c b/drivers/usb/core/sysctl.c
-new file mode 100644
-index 000000000000..3fa188ac8f67
---- /dev/null
-+++ b/drivers/usb/core/sysctl.c
-@@ -0,0 +1,44 @@
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/kmemleak.h>
-+#include <linux/sysctl.h>
-+#include <linux/usb.h>
-+
-+static struct ctl_table usb_table[] = {
-+ {
-+ .procname = "deny_new_usb",
-+ .data = &deny_new_usb,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax_sysadmin,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
-+ { }
-+};
-+
-+static struct ctl_table usb_root_table[] = {
-+ { .procname = "kernel",
-+ .mode = 0555,
-+ .child = usb_table },
-+ { }
-+};
-+
-+static struct ctl_table_header *usb_table_header;
-+
-+int __init usb_init_sysctl(void)
-+{
-+ usb_table_header = register_sysctl_table(usb_root_table);
-+ if (!usb_table_header) {
-+ pr_warn("usb: sysctl registration failed\n");
-+ return -ENOMEM;
-+ }
-+
-+ kmemleak_not_leak(usb_table_header);
-+ return 0;
-+}
-+
-+void usb_exit_sysctl(void)
-+{
-+ unregister_sysctl_table(usb_table_header);
-+}
-diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
-index 9b4ac4415f1a..93b4b798bdcc 100644
---- a/drivers/usb/core/usb.c
-+++ b/drivers/usb/core/usb.c
-@@ -72,6 +72,9 @@ MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
- #define usb_autosuspend_delay 0
- #endif
-
-+int deny_new_usb __read_mostly = 0;
-+EXPORT_SYMBOL(deny_new_usb);
-+
- static bool match_endpoint(struct usb_endpoint_descriptor *epd,
- struct usb_endpoint_descriptor **bulk_in,
- struct usb_endpoint_descriptor **bulk_out,
-@@ -978,6 +981,9 @@ static int __init usb_init(void)
- usb_debugfs_init();
-
- usb_acpi_register();
-+ retval = usb_init_sysctl();
-+ if (retval)
-+ goto sysctl_init_failed;
- retval = bus_register(&usb_bus_type);
- if (retval)
- goto bus_register_failed;
-@@ -1012,6 +1018,8 @@ static int __init usb_init(void)
- bus_notifier_failed:
- bus_unregister(&usb_bus_type);
- bus_register_failed:
-+ usb_exit_sysctl();
-+sysctl_init_failed:
- usb_acpi_unregister();
- usb_debugfs_cleanup();
- out:
-@@ -1035,6 +1043,7 @@ static void __exit usb_exit(void)
- usb_hub_cleanup();
- bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
- bus_unregister(&usb_bus_type);
-+ usb_exit_sysctl();
- usb_acpi_unregister();
- usb_debugfs_cleanup();
- idr_destroy(&usb_bus_idr);
-diff --git a/include/linux/usb.h b/include/linux/usb.h
-index 8e7549e3012a..653265115e56 100644
---- a/include/linux/usb.h
-+++ b/include/linux/usb.h
-@@ -2035,8 +2035,16 @@ extern void usb_led_activity(enum usb_led_event ev);
- static inline void usb_led_activity(enum usb_led_event ev) {}
- #endif
-
--/* sysctl */
-+/* sysctl.c */
- extern int deny_new_usb;
-+#ifdef CONFIG_SYSCTL
-+extern int usb_init_sysctl(void);
-+extern void usb_exit_sysctl(void);
-+#else
-+static inline int usb_init_sysctl(void) { return 0; }
-+static inline void usb_exit_sysctl(void) { }
-+#endif /* CONFIG_SYSCTL */
-+
-
- #endif /* __KERNEL__ */
-
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index f867606fbd80..13b619e46ade 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -106,9 +106,6 @@
- #ifdef CONFIG_USER_NS
- #include <linux/user_namespace.h>
- #endif
--#if IS_ENABLED(CONFIG_USB)
--#include <linux/usb.h>
--#endif
-
- #if defined(CONFIG_SYSCTL)
-
-@@ -2308,17 +2305,6 @@ static struct ctl_table kern_table[] = {
- .extra1 = SYSCTL_ZERO,
- .extra2 = SYSCTL_ONE,
- },
--#if IS_ENABLED(CONFIG_USB)
-- {
-- .procname = "deny_new_usb",
-- .data = &deny_new_usb,
-- .maxlen = sizeof(int),
-- .mode = 0644,
-- .proc_handler = proc_dointvec_minmax_sysadmin,
-- .extra1 = SYSCTL_ZERO,
-- .extra2 = SYSCTL_ONE,
-- },
--#endif
- {
- .procname = "ngroups_max",
- .data = &ngroups_max,
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0099-hard-wire-legacy-checkreqprot-option-to-0.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0099-hard-wire-legacy-checkreqprot-option-to-0.patch
deleted file mode 100644
index 49bbec9b2623..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0099-hard-wire-legacy-checkreqprot-option-to-0.patch
+++ /dev/null
@@ -1,133 +0,0 @@
-From 96e5b1d593f3af1ee253cc9fc99a5fb2c456a51f Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 03:26:45 -0500
-Subject: [PATCH 099/113] hard-wire legacy checkreqprot option to 0
-
-The userspace API is left intact for compatibility.
-
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- .../admin-guide/kernel-parameters.txt | 11 ---------
- security/selinux/Kconfig | 23 -------------------
- security/selinux/hooks.c | 16 +------------
- security/selinux/selinuxfs.c | 12 +---------
- 4 files changed, 2 insertions(+), 60 deletions(-)
-
-diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
-index e7ea794320e8..0e8e3fdd7005 100644
---- a/Documentation/admin-guide/kernel-parameters.txt
-+++ b/Documentation/admin-guide/kernel-parameters.txt
-@@ -518,17 +518,6 @@
- nosocket -- Disable socket memory accounting.
- nokmem -- Disable kernel memory accounting.
-
-- checkreqprot [SELINUX] Set initial checkreqprot flag value.
-- Format: { "0" | "1" }
-- See security/selinux/Kconfig help text.
-- 0 -- check protection applied by kernel (includes
-- any implied execute protection).
-- 1 -- check protection requested by application.
-- Default value is set via a kernel config option.
-- Value can be changed at runtime via
-- /sys/fs/selinux/checkreqprot.
-- Setting checkreqprot to 1 is deprecated.
--
- cio_ignore= [S390]
- See Documentation/s390/common_io.rst for details.
- clk_ignore_unused
-diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
-index 76d7ed11513c..ae851a826c26 100644
---- a/security/selinux/Kconfig
-+++ b/security/selinux/Kconfig
-@@ -70,29 +70,6 @@ config SECURITY_SELINUX_AVC_STATS
- /sys/fs/selinux/avc/cache_stats, which may be monitored via
- tools such as avcstat.
-
--config SECURITY_SELINUX_CHECKREQPROT_VALUE
-- int "NSA SELinux checkreqprot default value"
-- depends on SECURITY_SELINUX
-- range 0 1
-- default 0
-- help
-- This option sets the default value for the 'checkreqprot' flag
-- that determines whether SELinux checks the protection requested
-- by the application or the protection that will be applied by the
-- kernel (including any implied execute for read-implies-exec) for
-- mmap and mprotect calls. If this option is set to 0 (zero),
-- SELinux will default to checking the protection that will be applied
-- by the kernel. If this option is set to 1 (one), SELinux will
-- default to checking the protection requested by the application.
-- The checkreqprot flag may be changed from the default via the
-- 'checkreqprot=' boot parameter. It may also be changed at runtime
-- via /sys/fs/selinux/checkreqprot if authorized by policy.
--
-- WARNING: this option is deprecated and will be removed in a future
-- kernel release.
--
-- If you are unsure how to answer this question, answer 0.
--
- config SECURITY_SELINUX_SIDTAB_HASH_BITS
- int "NSA SELinux sidtab hashtable size"
- depends on SECURITY_SELINUX
-diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
-index c46312710e73..541c65650c5e 100644
---- a/security/selinux/hooks.c
-+++ b/security/selinux/hooks.c
-@@ -136,21 +136,7 @@ static int __init selinux_enabled_setup(char *str)
- __setup("selinux=", selinux_enabled_setup);
- #endif
-
--static unsigned int selinux_checkreqprot_boot =
-- CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
--
--static int __init checkreqprot_setup(char *str)
--{
-- unsigned long checkreqprot;
--
-- if (!kstrtoul(str, 0, &checkreqprot)) {
-- selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
-- if (checkreqprot)
-- pr_warn("SELinux: checkreqprot set to 1 via kernel parameter. This is deprecated and will be rejected in a future kernel release.\n");
-- }
-- return 1;
--}
--__setup("checkreqprot=", checkreqprot_setup);
-+static const unsigned int selinux_checkreqprot_boot;
-
- /**
- * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
-diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
-index 4bde570d56a2..cc5caffc07fa 100644
---- a/security/selinux/selinuxfs.c
-+++ b/security/selinux/selinuxfs.c
-@@ -725,7 +725,6 @@ static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
- static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
- {
-- struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
- char *page;
- ssize_t length;
- unsigned int new_value;
-@@ -749,18 +748,9 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
- return PTR_ERR(page);
-
- length = -EINVAL;
-- if (sscanf(page, "%u", &new_value) != 1)
-+ if (sscanf(page, "%u", &new_value) != 1 || new_value)
- goto out;
-
-- if (new_value) {
-- char comm[sizeof(current->comm)];
--
-- memcpy(comm, current->comm, sizeof(comm));
-- pr_warn_once("SELinux: %s (%d) set checkreqprot to 1. This is deprecated and will be rejected in a future kernel release.\n",
-- comm, current->pid);
-- }
--
-- checkreqprot_set(fsi->state, (new_value ? 1 : 0));
- length = count;
- out:
- kfree(page);
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch
deleted file mode 100644
index 3c1ffe524cbd..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From 64560b691de1cbd35e117bb91b97508c2e5ed711 Mon Sep 17 00:00:00 2001
-From: Matt Brown <matt@nmatt.com>
-Date: Mon, 29 May 2017 17:37:59 -0400
-Subject: [PATCH 100/113] security: tty: Add owner user namespace to tty_struct
-
-This patch adds struct user_namespace *owner_user_ns to the tty_struct.
-Then it is set to current_user_ns() in the alloc_tty_struct function.
-
-This is done to facilitate capability checks against the original user
-namespace that allocated the tty.
-
-E.g. ns_capable(tty->owner_user_ns,CAP_SYS_ADMIN)
-
-This combined with the use of user namespace's will allow hardening
-protections to be built to mitigate container escapes that utilize TTY
-ioctls such as TIOCSTI.
-
-See: https://bugzilla.redhat.com/show_bug.cgi?id=1411256
-
-Acked-by: Serge Hallyn <serge@hallyn.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Signed-off-by: Matt Brown <matt@nmatt.com>
----
- drivers/tty/tty_io.c | 2 ++
- include/linux/tty.h | 2 ++
- 2 files changed, 4 insertions(+)
-
-diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
-index 2f8223b2ffa4..4575de4e7520 100644
---- a/drivers/tty/tty_io.c
-+++ b/drivers/tty/tty_io.c
-@@ -171,6 +171,7 @@ static void free_tty_struct(struct tty_struct *tty)
- put_device(tty->dev);
- kfree(tty->write_buf);
- tty->magic = 0xDEADDEAD;
-+ put_user_ns(tty->owner_user_ns);
- kfree(tty);
- }
-
-@@ -3017,6 +3018,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
- tty->index = idx;
- tty_line_name(driver, idx, tty->name);
- tty->dev = tty_get_device(tty);
-+ tty->owner_user_ns = get_user_ns(current_user_ns());
-
- return tty;
- }
-diff --git a/include/linux/tty.h b/include/linux/tty.h
-index bc8caac390fc..29fd018fc255 100644
---- a/include/linux/tty.h
-+++ b/include/linux/tty.h
-@@ -14,6 +14,7 @@
- #include <uapi/linux/tty.h>
- #include <linux/rwsem.h>
- #include <linux/llist.h>
-+#include <linux/user_namespace.h>
-
-
- /*
-@@ -342,6 +343,7 @@ struct tty_struct {
- /* If the tty has a pending do_SAK, queue it here - akpm */
- struct work_struct SAK_work;
- struct tty_port *port;
-+ struct user_namespace *owner_user_ns;
- } __randomize_layout;
-
- /* Each of a tty's open files has private_data pointing to tty_file_private */
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch
deleted file mode 100644
index 530cbeba09ca..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch
+++ /dev/null
@@ -1,197 +0,0 @@
-From 102a2f9c70766abff55a0ae7f83d12a959647ae6 Mon Sep 17 00:00:00 2001
-From: Matt Brown <matt@nmatt.com>
-Date: Mon, 29 May 2017 17:38:00 -0400
-Subject: [PATCH 101/113] security: tty: make TIOCSTI ioctl require
- CAP_SYS_ADMIN
-
-This introduces the tiocsti_restrict sysctl, whose default is controlled
-via CONFIG_SECURITY_TIOCSTI_RESTRICT. When activated, this control
-restricts all TIOCSTI ioctl calls from non CAP_SYS_ADMIN users.
-
-This patch depends on patch 1/2
-
-This patch was inspired from GRKERNSEC_HARDEN_TTY.
-
-This patch would have prevented
-https://bugzilla.redhat.com/show_bug.cgi?id=1411256 under the following
-conditions:
-* non-privileged container
-* container run inside new user namespace
-
-Possible effects on userland:
-
-There could be a few user programs that would be effected by this
-change.
-See: <https://codesearch.debian.net/search?q=ioctl%5C%28.*TIOCSTI>
-notable programs are: agetty, csh, xemacs and tcsh
-
-However, I still believe that this change is worth it given that the
-Kconfig defaults to n. This will be a feature that is turned on for the
-same reason that people activate it when using grsecurity. Users of this
-opt-in feature will realize that they are choosing security over some OS
-features like unprivileged TIOCSTI ioctls, as should be clear in the
-Kconfig help message.
-
-Threat Model/Patch Rational:
-
->From grsecurity's config for GRKERNSEC_HARDEN_TTY.
-
- | There are very few legitimate uses for this functionality and it
- | has made vulnerabilities in several 'su'-like programs possible in
- | the past. Even without these vulnerabilities, it provides an
- | attacker with an easy mechanism to move laterally among other
- | processes within the same user's compromised session.
-
-So if one process within a tty session becomes compromised it can follow
-that additional processes, that are thought to be in different security
-boundaries, can be compromised as a result. When using a program like su
-or sudo, these additional processes could be in a tty session where TTY
-file descriptors are indeed shared over privilege boundaries.
-
-This is also an excellent writeup about the issue:
-<http://www.halfdog.net/Security/2012/TtyPushbackPrivilegeEscalation/>
-
-When user namespaces are in use, the check for the capability
-CAP_SYS_ADMIN is done against the user namespace that originally opened
-the tty.
-
-Acked-by: Serge Hallyn <serge@hallyn.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Signed-off-by: Matt Brown <matt@nmatt.com>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- Documentation/admin-guide/sysctl/kernel.rst | 20 ++++++++++++++++++++
- drivers/tty/tty_io.c | 8 ++++++++
- include/linux/tty.h | 2 ++
- kernel/sysctl.c | 14 ++++++++++++++
- security/Kconfig | 13 +++++++++++++
- 5 files changed, 57 insertions(+)
-
-diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
-index 4c20e6ded0af..3cd263f8ac46 100644
---- a/Documentation/admin-guide/sysctl/kernel.rst
-+++ b/Documentation/admin-guide/sysctl/kernel.rst
-@@ -1385,6 +1385,26 @@ If a value outside of this range is written to ``threads-max`` an
- ``EINVAL`` error occurs.
-
-
-+tiocsti_restrict
-+================
-+
-+This toggle indicates whether unprivileged users are prevented from using the
-+``TIOCSTI`` ioctl to inject commands into other processes which share a tty
-+session.
-+
-+= ============================================================================
-+0 No restriction, except the default one of only being able to inject commands
-+ into one's own tty.
-+1 Users must have ``CAP_SYS_ADMIN`` to use the ``TIOCSTI`` ioctl.
-+= ============================================================================
-+
-+When user namespaces are in use, the check for ``CAP_SYS_ADMIN`` is done
-+against the user namespace that originally opened the tty.
-+
-+The kernel config option ``CONFIG_SECURITY_TIOCSTI_RESTRICT`` sets the default
-+value of ``tiocsti_restrict``.
-+
-+
- traceoff_on_warning
- ===================
-
-diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
-index 4575de4e7520..9c385bfe255a 100644
---- a/drivers/tty/tty_io.c
-+++ b/drivers/tty/tty_io.c
-@@ -2185,11 +2185,19 @@ static int tty_fasync(int fd, struct file *filp, int on)
- * FIXME: may race normal receive processing
- */
-
-+int tiocsti_restrict = IS_ENABLED(CONFIG_SECURITY_TIOCSTI_RESTRICT);
-+
- static int tiocsti(struct tty_struct *tty, char __user *p)
- {
- char ch, mbz = 0;
- struct tty_ldisc *ld;
-
-+ if (tiocsti_restrict &&
-+ !ns_capable(tty->owner_user_ns, CAP_SYS_ADMIN)) {
-+ dev_warn_ratelimited(tty->dev,
-+ "Denied TIOCSTI ioctl for non-privileged process\n");
-+ return -EPERM;
-+ }
- if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (get_user(ch, p))
-diff --git a/include/linux/tty.h b/include/linux/tty.h
-index 29fd018fc255..743e3964a03a 100644
---- a/include/linux/tty.h
-+++ b/include/linux/tty.h
-@@ -353,6 +353,8 @@ struct tty_file_private {
- struct list_head list;
- };
-
-+extern int tiocsti_restrict;
-+
- /* tty magic number */
- #define TTY_MAGIC 0x5401
-
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index 13b619e46ade..8fd007fbec4c 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -106,6 +106,9 @@
- #ifdef CONFIG_USER_NS
- #include <linux/user_namespace.h>
- #endif
-+#if defined CONFIG_TTY
-+#include <linux/tty.h>
-+#endif
-
- #if defined(CONFIG_SYSCTL)
-
-@@ -2295,6 +2298,17 @@ static struct ctl_table kern_table[] = {
- .extra1 = SYSCTL_ZERO,
- .extra2 = &two,
- },
-+#endif
-+#if defined CONFIG_TTY
-+ {
-+ .procname = "tiocsti_restrict",
-+ .data = &tiocsti_restrict,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax_sysadmin,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
- #endif
- {
- .procname = "device_sidechannel_restrict",
-diff --git a/security/Kconfig b/security/Kconfig
-index f3c995bd79cf..c8ea5a6ecce0 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -29,6 +29,19 @@ config SECURITY_PERF_EVENTS_RESTRICT
- perf_event_open syscall will be permitted unless it is
- changed.
-
-+config SECURITY_TIOCSTI_RESTRICT
-+ bool "Restrict unprivileged use of tiocsti command injection"
-+ default n
-+ help
-+ This enforces restrictions on unprivileged users injecting commands
-+ into other processes which share a tty session using the TIOCSTI
-+ ioctl. This option makes TIOCSTI use require CAP_SYS_ADMIN.
-+
-+ If this option is not selected, no restrictions will be enforced
-+ unless the tiocsti_restrict sysctl is explicitly set to (1).
-+
-+ If you are unsure how to answer this question, answer N.
-+
- config SECURITY
- bool "Enable different security models"
- depends on SYSFS
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch
deleted file mode 100644
index 91b69f34130d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From de6705ab90abfa7d2638503747f2e39bd2a6968a Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 23:36:14 -0400
-Subject: [PATCH 102/113] enable SECURITY_TIOCSTI_RESTRICT by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- security/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index c8ea5a6ecce0..615205c0113b 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -31,7 +31,7 @@ config SECURITY_PERF_EVENTS_RESTRICT
-
- config SECURITY_TIOCSTI_RESTRICT
- bool "Restrict unprivileged use of tiocsti command injection"
-- default n
-+ default y
- help
- This enforces restrictions on unprivileged users injecting commands
- into other processes which share a tty session using the TIOCSTI
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0103-disable-unprivileged-eBPF-access-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0103-disable-unprivileged-eBPF-access-by-default.patch
deleted file mode 100644
index 004b73121835..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0103-disable-unprivileged-eBPF-access-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 53965dd6981a73b1d92f428d2f952bf1b265f535 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Mon, 7 May 2018 20:37:07 +0200
-Subject: [PATCH 103/113] disable unprivileged eBPF access by default
-
----
- kernel/bpf/syscall.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
-index 9433ab9995cd..348c36273f1a 100644
---- a/kernel/bpf/syscall.c
-+++ b/kernel/bpf/syscall.c
-@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(map_idr_lock);
- static DEFINE_IDR(link_idr);
- static DEFINE_SPINLOCK(link_idr_lock);
-
--int sysctl_unprivileged_bpf_disabled __read_mostly;
-+int sysctl_unprivileged_bpf_disabled __read_mostly = 1;
-
- static const struct bpf_map_ops * const bpf_map_types[] = {
- #define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0104-enable-BPF-JIT-hardening-by-default-if-available.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0104-enable-BPF-JIT-hardening-by-default-if-available.patch
deleted file mode 100644
index 926435a4c3f9..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0104-enable-BPF-JIT-hardening-by-default-if-available.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 9bb1000bb74b15393f36de9291b3d930a51cf004 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Mon, 7 May 2018 20:37:55 +0200
-Subject: [PATCH 104/113] enable BPF JIT hardening by default (if available)
-
----
- kernel/bpf/core.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
-index 55454d2278b1..de02792dc2fc 100644
---- a/kernel/bpf/core.c
-+++ b/kernel/bpf/core.c
-@@ -524,7 +524,7 @@ void bpf_prog_kallsyms_del_all(struct bpf_prog *fp)
- /* All BPF JIT sysctl knobs here. */
- int bpf_jit_enable __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_DEFAULT_ON);
- int bpf_jit_kallsyms __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_DEFAULT_ON);
--int bpf_jit_harden __read_mostly;
-+int bpf_jit_harden __read_mostly = 2;
- long bpf_jit_limit __read_mostly;
-
- static void
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0105-enable-protected_-fifos-regular-by-default.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0105-enable-protected_-fifos-regular-by-default.patch
deleted file mode 100644
index d5b253dcabd8..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0105-enable-protected_-fifos-regular-by-default.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From fbd4dde75d88472ce6684656b08d571ebe39ec04 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Sun, 4 Nov 2018 18:48:53 +0100
-Subject: [PATCH 105/113] enable protected_{fifos,regular} by default
-
----
- fs/namei.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/fs/namei.c b/fs/namei.c
-index 59ff3ce21026..72f912c68975 100644
---- a/fs/namei.c
-+++ b/fs/namei.c
-@@ -934,8 +934,8 @@ static inline void put_link(struct nameidata *nd)
-
- int sysctl_protected_symlinks __read_mostly = 1;
- int sysctl_protected_hardlinks __read_mostly = 1;
--int sysctl_protected_fifos __read_mostly;
--int sysctl_protected_regular __read_mostly;
-+int sysctl_protected_fifos __read_mostly = 2;
-+int sysctl_protected_regular __read_mostly = 2;
-
- /**
- * may_follow_link - Check symlink following for unsafe situations
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch
deleted file mode 100644
index b67177ade4f4..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch
+++ /dev/null
@@ -1,129 +0,0 @@
-From ecdfd1bbfb546fbe3fc329f08f13f5b2b758995a Mon Sep 17 00:00:00 2001
-From: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Date: Mon, 6 May 2019 17:07:11 +0200
-Subject: [PATCH 106/113] modpost: Add
- CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_VERBOSE
-
-With 46c7dd56d541 ("modpost: always show verbose warning for section
-mismatch"), sec_mismatch_verbose was removed which would have printed
-errors for all writable function pointers during compilation if it
-hadn't been "#if 0"ed out for quite some time now.
-
-Let's introduce a new DEBUG_WRITABLE_FUNCTION_POINTERS_VERBOSE Kconfig
-option to cleanly control this linux-hardened functionality.
-
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- lib/Kconfig.debug | 3 +++
- scripts/Makefile.modpost | 1 +
- scripts/mod/modpost.c | 25 ++++++++++++++++---------
- 3 files changed, 20 insertions(+), 9 deletions(-)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index 4a1a32a059f4..5fce84adc315 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -374,6 +374,9 @@ config DEBUG_FORCE_FUNCTION_ALIGN_32B
-
- It is mainly for debug and performance tuning use.
-
-+config DEBUG_WRITABLE_FUNCTION_POINTERS_VERBOSE
-+ bool "Enable verbose reporting of writable function pointers"
-+
- #
- # Select this config option from the architecture Kconfig, if it
- # is preferred to always offer frame pointers as a config
-diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
-index f54b6ac37ac2..e53b3057d4cb 100644
---- a/scripts/Makefile.modpost
-+++ b/scripts/Makefile.modpost
-@@ -47,6 +47,7 @@ MODPOST = scripts/mod/modpost \
- $(if $(CONFIG_MODVERSIONS),-m) \
- $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
- $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
-+ $(if $(CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_VERBOSE),-f) \
- $(if $(KBUILD_MODPOST_WARN),-w) \
- -o $@
-
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index 50e9baefc4e7..2cbc4e8a6295 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -34,8 +34,9 @@ static int external_module = 0;
- static int warn_unresolved = 0;
- /* How a symbol is exported */
- static int sec_mismatch_count = 0;
--static int writable_fptr_count = 0;
- static int sec_mismatch_fatal = 0;
-+static int writable_fptr_count = 0;
-+static int writable_fptr_verbose = 0;
- /* ignore missing files */
- static int ignore_missing_files;
- /* If set to 1, only warn (instead of error) about missing ns imports */
-@@ -1466,10 +1467,13 @@ static void report_sec_mismatch(const char *modname,
- char *prl_from;
- char *prl_to;
-
-- if (mismatch->mismatch == DATA_TO_TEXT)
-+ if (mismatch->mismatch == DATA_TO_TEXT) {
- writable_fptr_count++;
-- else
-+ if (!writable_fptr_verbose)
-+ return;
-+ } else {
- sec_mismatch_count++;
-+ }
-
- get_pretty_name(from_is_func, &from, &from_p);
- get_pretty_name(to_is_func, &to, &to_p);
-@@ -1592,12 +1596,10 @@ static void report_sec_mismatch(const char *modname,
- "we should never get here.");
- break;
- case DATA_TO_TEXT:
--#if 0
- fprintf(stderr,
- "The %s %s:%s references\n"
- "the %s %s:%s%s\n",
- from, fromsec, fromsym, to, tosec, tosym, to_p);
--#endif
- break;
- }
- fprintf(stderr, "\n");
-@@ -2578,7 +2580,7 @@ int main(int argc, char **argv)
- struct dump_list *dump_read_start = NULL;
- struct dump_list **dump_read_iter = &dump_read_start;
-
-- while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) {
-+ while ((opt = getopt(argc, argv, "ei:fmnT:o:awENd:")) != -1) {
- switch (opt) {
- case 'e':
- external_module = 1;
-@@ -2589,6 +2591,9 @@ int main(int argc, char **argv)
- (*dump_read_iter)->file = optarg;
- dump_read_iter = &(*dump_read_iter)->next;
- break;
-+ case 'f':
-+ writable_fptr_verbose = 1;
-+ break;
- case 'm':
- modversions = 1;
- break;
-@@ -2689,9 +2694,11 @@ int main(int argc, char **argv)
- }
-
- free(buf.p);
-- if (writable_fptr_count)
-- warn("modpost: Found %d writable function pointer(s).\n",
-- writable_fptr_count);
-+ if (writable_fptr_count && !writable_fptr_verbose)
-+ warn("modpost: Found %d writable function pointer%s.\n"
-+ "To see full details build your kernel with:\n"
-+ "'make CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_VERBOSE=y'\n",
-+ writable_fptr_count, (writable_fptr_count == 1 ? "" : "s"));
-
- return err;
- }
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0107-mm-Fix-extra_latent_entropy.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0107-mm-Fix-extra_latent_entropy.patch
deleted file mode 100644
index fa0be65319bb..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0107-mm-Fix-extra_latent_entropy.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-From 1bba3073f24209ab48e1e9ea0721da8860a7a714 Mon Sep 17 00:00:00 2001
-From: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Date: Tue, 7 May 2019 11:46:21 +0200
-Subject: [PATCH 107/113] mm: Fix extra_latent_entropy
-
-Commit a9cd410a3d29 ("mm/page_alloc.c: memory hotplug: free pages as
-higher order") changed `static void __init __free_pages_boot_core()`
-into `void __free_pages_core()`, causing the following section mismatch
-warning at compile time:
-
- WARNING: vmlinux.o(.text+0x180fe4): Section mismatch in reference from the function __free_pages_core() to the variable .meminit.data:extra_latent_entropy
- The function __free_pages_core() references the variable __meminitdata extra_latent_entropy.
- This is often because __free_pages_core lacks a __meminitdata annotation or the annotation of extra_latent_entropy is wrong.
-
-This commit is an attempt at fixing this issue. I'm not sure it's OK as
-we are accessing pages that are still managed by the bootmem allocator.
-The prefetching part is not an issue as it only affects struct pages.
-
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
----
- mm/page_alloc.c | 38 ++++++++++++++++++++++----------------
- 1 file changed, 22 insertions(+), 16 deletions(-)
-
-diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index 965d49be78ed..cb7501769331 100644
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -1539,6 +1539,25 @@ static void __free_pages_ok(struct page *page, unsigned int order,
- local_irq_restore(flags);
- }
-
-+static void __init __gather_extra_latent_entropy(struct page *page,
-+ unsigned int nr_pages)
-+{
-+ if (extra_latent_entropy && !PageHighMem(page) && page_to_pfn(page) < 0x100000) {
-+ unsigned long hash = 0;
-+ size_t index, end = PAGE_SIZE * nr_pages / sizeof hash;
-+ const unsigned long *data = lowmem_page_address(page);
-+
-+ for (index = 0; index < end; index++)
-+ hash ^= hash + data[index];
-+#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
-+ latent_entropy ^= hash;
-+ add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy));
-+#else
-+ add_device_randomness((const void *)&hash, sizeof(hash));
-+#endif
-+ }
-+}
-+
- void __free_pages_core(struct page *page, unsigned int order)
- {
- unsigned int nr_pages = 1 << order;
-@@ -1558,22 +1577,6 @@ void __free_pages_core(struct page *page, unsigned int order)
- }
- __ClearPageReserved(p);
- set_page_count(p, 0);
--
-- if (extra_latent_entropy && !PageHighMem(page) && page_to_pfn(page) < 0x100000) {
-- unsigned long hash = 0;
-- size_t index, end = PAGE_SIZE * nr_pages / sizeof hash;
-- const unsigned long *data = lowmem_page_address(page);
--
-- for (index = 0; index < end; index++)
-- hash ^= hash + data[index];
--#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
-- latent_entropy ^= hash;
-- add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy));
--#else
-- add_device_randomness((const void *)&hash, sizeof(hash));
--#endif
-- }
--
- atomic_long_add(nr_pages, &page_zone(page)->managed_pages);
-
- /*
-@@ -1632,6 +1635,7 @@ void __init memblock_free_pages(struct page *page, unsigned long pfn,
- {
- if (early_page_uninitialised(pfn))
- return;
-+ __gather_extra_latent_entropy(page, 1 << order);
- __free_pages_core(page, order);
- }
-
-@@ -1723,6 +1727,7 @@ static void __init deferred_free_range(unsigned long pfn,
- if (nr_pages == pageblock_nr_pages &&
- (pfn & (pageblock_nr_pages - 1)) == 0) {
- set_pageblock_migratetype(page, MIGRATE_MOVABLE);
-+ __gather_extra_latent_entropy(page, 1 << pageblock_order);
- __free_pages_core(page, pageblock_order);
- return;
- }
-@@ -1730,6 +1735,7 @@ static void __init deferred_free_range(unsigned long pfn,
- for (i = 0; i < nr_pages; i++, page++, pfn++) {
- if ((pfn & (pageblock_nr_pages - 1)) == 0)
- set_pageblock_migratetype(page, MIGRATE_MOVABLE);
-+ __gather_extra_latent_entropy(page, 1);
- __free_pages_core(page, 0);
- }
- }
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0108-add-CONFIG-for-unprivileged_userfaultfd.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0108-add-CONFIG-for-unprivileged_userfaultfd.patch
deleted file mode 100644
index 24faee727e29..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0108-add-CONFIG-for-unprivileged_userfaultfd.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From 6703e6f3a33b514c317309e399ef121dcbf77720 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Wed, 2 Oct 2019 01:22:17 +0200
-Subject: [PATCH 108/113] add CONFIG for unprivileged_userfaultfd
-
-When disabled, unprivileged users will not be able to use the userfaultfd
-syscall. Userfaultfd provide attackers with a way to stall a kernel
-thread in the middle of memory accesses from userspace by initiating an
-access on an unmapped page. To avoid various heap grooming and heap
-spraying techniques for exploiting use-after-free flaws this should be
-disabled by default.
-
-This setting can be overridden at runtime via the
-vm.unprivileged_userfaultfd sysctl.
-
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- fs/userfaultfd.c | 4 ++++
- init/Kconfig | 17 +++++++++++++++++
- 2 files changed, 21 insertions(+)
-
-diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
-index 000b457ad087..06d35ecdcbc8 100644
---- a/fs/userfaultfd.c
-+++ b/fs/userfaultfd.c
-@@ -28,7 +28,11 @@
- #include <linux/security.h>
- #include <linux/hugetlb.h>
-
-+#ifdef CONFIG_USERFAULTFD_UNPRIVILEGED
- int sysctl_unprivileged_userfaultfd __read_mostly = 1;
-+#else
-+int sysctl_unprivileged_userfaultfd __read_mostly;
-+#endif
-
- static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
-
-diff --git a/init/Kconfig b/init/Kconfig
-index a7b5a4cb7939..2feea719cc25 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1745,6 +1745,23 @@ config USERFAULTFD
- Enable the userfaultfd() system call that allows to intercept and
- handle page faults in userland.
-
-+config USERFAULTFD_UNPRIVILEGED
-+ bool "Allow unprivileged users to use the userfaultfd syscall"
-+ depends on USERFAULTFD
-+ default n
-+ help
-+ When disabled, unprivileged users will not be able to use the userfaultfd
-+ syscall. Userfaultfd provide attackers with a way to stall a kernel
-+ thread in the middle of memory accesses from userspace by initiating an
-+ access on an unmapped page. To avoid various heap grooming and heap
-+ spraying techniques for exploiting use-after-free flaws this should be
-+ disabled by default.
-+
-+ This setting can be overridden at runtime via the
-+ vm.unprivileged_userfaultfd sysctl.
-+
-+ If unsure, say N.
-+
- config ARCH_HAS_MEMBARRIER_CALLBACKS
- bool
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch
deleted file mode 100644
index 51e144c1d45a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From 97f8e6d6060fdced726b7f7f344e78be66129cdf Mon Sep 17 00:00:00 2001
-From: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Date: Fri, 29 Nov 2019 16:27:14 +0100
-Subject: [PATCH 109/113] slub: Extend init_on_alloc to slab caches with
- constructors
-
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- mm/slab.h | 2 ++
- mm/slub.c | 23 ++++++++++++++++++-----
- 2 files changed, 20 insertions(+), 5 deletions(-)
-
-diff --git a/mm/slab.h b/mm/slab.h
-index 105dba485a7e..2138deacf719 100644
---- a/mm/slab.h
-+++ b/mm/slab.h
-@@ -630,8 +630,10 @@ static inline void cache_random_seq_destroy(struct kmem_cache *cachep) { }
- static inline bool slab_want_init_on_alloc(gfp_t flags, struct kmem_cache *c)
- {
- if (static_branch_unlikely(&init_on_alloc)) {
-+#ifndef CONFIG_SLUB
- if (c->ctor)
- return false;
-+#endif
- if (c->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON))
- return flags & __GFP_ZERO;
- return true;
-diff --git a/mm/slub.c b/mm/slub.c
-index dd68308c94a9..802f9051bc1a 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -1635,9 +1635,10 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- * need to show a valid freepointer to check_object().
- *
- * Note that doing this for all caches (not just ctor
-- * ones, which have s->offset != NULL)) causes a GPF,
-- * due to KASAN poisoning and the way set_freepointer()
-- * eventually dereferences the freepointer.
-+ * ones, which have s->offset >= object_size)) causes a
-+ * GPF, due to KASAN poisoning and the way
-+ * set_freepointer() eventually dereferences the
-+ * freepointer.
- */
- set_freepointer(s, object, NULL);
- }
-@@ -2955,8 +2956,14 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
- if (s->ctor)
- s->ctor(object);
- kasan_poison_object_data(s, object);
-- } else if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
-+ } else if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object) {
- memset(object, 0, s->object_size);
-+ if (s->ctor) {
-+ kasan_unpoison_object_data(s, object);
-+ s->ctor(object);
-+ kasan_poison_object_data(s, object);
-+ }
-+ }
-
- if (object) {
- check_canary(s, object, s->random_inactive);
-@@ -3416,8 +3423,14 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
- } else if (unlikely(slab_want_init_on_alloc(flags, s))) {
- int j;
-
-- for (j = 0; j < i; j++)
-+ for (j = 0; j < i; j++) {
- memset(p[j], 0, s->object_size);
-+ if (s->ctor) {
-+ kasan_unpoison_object_data(s, p[j]);
-+ s->ctor(p[j]);
-+ kasan_poison_object_data(s, p[j]);
-+ }
-+ }
- }
-
- for (k = 0; k < i; k++) {
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch
deleted file mode 100644
index 8be926e38809..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch
+++ /dev/null
@@ -1,151 +0,0 @@
-From de77132795adf97420e9b14c463d7cb2c188fd43 Mon Sep 17 00:00:00 2001
-From: madaidan <50278627+madaidan@users.noreply.github.com>
-Date: Sun, 9 Feb 2020 00:03:41 +0000
-Subject: [PATCH 110/113] net: tcp: add option to disable TCP simultaneous
- connect
-
-This is modified from Brad Spengler/PaX Team's code in the last public
-patch of grsecurity/PaX based on my understanding of the code. Changes
-or omissions from the original code are mine and don't reflect the
-original grsecurity/PaX code.
-
-TCP simultaneous connect adds a weakness in Linux's implementation of
-TCP that allows two clients to connect to each other without either
-entering a listening state. The weakness allows an attacker to easily
-prevent a client from connecting to a known server provided the source
-port for the connection is guessed correctly.
-
-As the weakness could be used to prevent an antivirus or IPS from
-fetching updates, or prevent an SSL gateway from fetching a CRL, it
-should be eliminated.
-
-This creates a net.ipv4.tcp_simult_connect sysctl that when disabled,
-disables TCP simultaneous connect.
-
-Reviewd-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Reviewd-by: Levente Polyak <levente@leventepolyak.net>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- Documentation/networking/ip-sysctl.rst | 18 ++++++++++++++++++
- include/net/tcp.h | 1 +
- net/ipv4/Kconfig | 23 +++++++++++++++++++++++
- net/ipv4/sysctl_net_ipv4.c | 9 +++++++++
- net/ipv4/tcp_input.c | 3 ++-
- 5 files changed, 53 insertions(+), 1 deletion(-)
-
-diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
-index 25e6673a085a..76f1892d65ed 100644
---- a/Documentation/networking/ip-sysctl.rst
-+++ b/Documentation/networking/ip-sysctl.rst
-@@ -665,6 +665,24 @@ tcp_comp_sack_nr - INTEGER
-
- Default : 44
-
-+tcp_simult_connect - BOOLEAN
-+ Enable TCP simultaneous connect that adds a weakness in Linux's strict
-+ implementation of TCP that allows two clients to connect to each other
-+ without either entering a listening state. The weakness allows an attacker
-+ to easily prevent a client from connecting to a known server provided the
-+ source port for the connection is guessed correctly.
-+
-+ As the weakness could be used to prevent an antivirus or IPS from fetching
-+ updates, or prevent an SSL gateway from fetching a CRL, it should be
-+ eliminated by disabling this option. Though Linux is one of few operating
-+ systems supporting simultaneous connect, it has no legitimate use in
-+ practice and is rarely supported by firewalls.
-+
-+ Disabling this may break TCP STUNT which is used by some applications for
-+ NAT traversal.
-+
-+ Default: Value of CONFIG_TCP_SIMULT_CONNECT_DEFAULT_ON
-+
- tcp_slow_start_after_idle - BOOLEAN
- If set, provide RFC2861 behavior and time out the congestion
- window after an idle period. An idle period is defined at
-diff --git a/include/net/tcp.h b/include/net/tcp.h
-index d4ef5bf94168..34d0d5438108 100644
---- a/include/net/tcp.h
-+++ b/include/net/tcp.h
-@@ -245,6 +245,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
- /* sysctl variables for tcp */
- extern int sysctl_tcp_max_orphans;
- extern long sysctl_tcp_mem[3];
-+extern int sysctl_tcp_simult_connect;
-
- #define TCP_RACK_LOSS_DETECTION 0x1 /* Use RACK to detect losses */
- #define TCP_RACK_STATIC_REO_WND 0x2 /* Use static RACK reo wnd */
-diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
-index 989e005bf698..d1584b4b39f9 100644
---- a/net/ipv4/Kconfig
-+++ b/net/ipv4/Kconfig
-@@ -743,3 +743,26 @@ config TCP_MD5SIG
- on the Internet.
-
- If unsure, say N.
-+
-+config TCP_SIMULT_CONNECT_DEFAULT_ON
-+ bool "Enable TCP simultaneous connect"
-+ help
-+ Enable TCP simultaneous connect that adds a weakness in Linux's strict
-+ implementation of TCP that allows two clients to connect to each other
-+ without either entering a listening state. The weakness allows an
-+ attacker to easily prevent a client from connecting to a known server
-+ provided the source port for the connection is guessed correctly.
-+
-+ As the weakness could be used to prevent an antivirus or IPS from
-+ fetching updates, or prevent an SSL gateway from fetching a CRL, it
-+ should be eliminated by disabling this option. Though Linux is one of
-+ few operating systems supporting simultaneous connect, it has no
-+ legitimate use in practice and is rarely supported by firewalls.
-+
-+ Disabling this may break TCP STUNT which is used by some applications
-+ for NAT traversal.
-+
-+ This setting can be overridden at runtime via the
-+ net.ipv4.tcp_simult_connect sysctl.
-+
-+ If unsure, say N.
-diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
-index 3e5f4f2e705e..791329c77dea 100644
---- a/net/ipv4/sysctl_net_ipv4.c
-+++ b/net/ipv4/sysctl_net_ipv4.c
-@@ -588,6 +588,15 @@ static struct ctl_table ipv4_table[] = {
- .mode = 0644,
- .proc_handler = proc_do_static_key,
- },
-+ {
-+ .procname = "tcp_simult_connect",
-+ .data = &sysctl_tcp_simult_connect,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
- { }
- };
-
-diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
-index 6bf066f924c1..e57673f42c6f 100644
---- a/net/ipv4/tcp_input.c
-+++ b/net/ipv4/tcp_input.c
-@@ -82,6 +82,7 @@
- #include <net/mptcp.h>
-
- int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
-+int sysctl_tcp_simult_connect __read_mostly = IS_ENABLED(CONFIG_TCP_SIMULT_CONNECT_DEFAULT_ON);
-
- #define FLAG_DATA 0x01 /* Incoming frame contained data. */
- #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
-@@ -6195,7 +6196,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
- tcp_paws_reject(&tp->rx_opt, 0))
- goto discard_and_undo;
-
-- if (th->syn) {
-+ if (th->syn && sysctl_tcp_simult_connect) {
- /* We see SYN without ACK. It is attempt of
- * simultaneous connect with crossed SYNs.
- * Particularly, it can be connect to self.
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch
deleted file mode 100644
index 27b8312f70f9..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch
+++ /dev/null
@@ -1,238 +0,0 @@
-From 70b68f8b02f0b7cba8336108c3726486bedf1a82 Mon Sep 17 00:00:00 2001
-From: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
-Date: Tue, 13 Oct 2020 19:18:48 +0200
-Subject: [PATCH 111/113] dccp: ccid: move timers to struct dccp_sock
-
-When dccps_hc_tx_ccid is freed, ccid timers may still trigger. The reason
-del_timer_sync can't be used is because this relies on keeping a reference
-to struct sock. But as we keep a pointer to dccps_hc_tx_ccid and free that
-during disconnect, the timer should really belong to struct dccp_sock.
-
-This addresses CVE-2020-16119.
-
-Fixes: 839a6094140a (net: dccp: Convert timers to use timer_setup())
-Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
-Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
----
- include/linux/dccp.h | 2 ++
- net/dccp/ccids/ccid2.c | 32 +++++++++++++++++++-------------
- net/dccp/ccids/ccid3.c | 30 ++++++++++++++++++++----------
- 3 files changed, 41 insertions(+), 23 deletions(-)
-
-diff --git a/include/linux/dccp.h b/include/linux/dccp.h
-index 07e547c02fd8..504afa1a4be6 100644
---- a/include/linux/dccp.h
-+++ b/include/linux/dccp.h
-@@ -259,6 +259,7 @@ struct dccp_ackvec;
- * @dccps_sync_scheduled - flag which signals "send out-of-band message soon"
- * @dccps_xmitlet - tasklet scheduled by the TX CCID to dequeue data packets
- * @dccps_xmit_timer - used by the TX CCID to delay sending (rate-based pacing)
-+ * @dccps_ccid_timer - used by the CCIDs
- * @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs)
- */
- struct dccp_sock {
-@@ -303,6 +304,7 @@ struct dccp_sock {
- __u8 dccps_sync_scheduled:1;
- struct tasklet_struct dccps_xmitlet;
- struct timer_list dccps_xmit_timer;
-+ struct timer_list dccps_ccid_timer;
- };
-
- static inline struct dccp_sock *dccp_sk(const struct sock *sk)
-diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
-index 3da1f77bd039..dbca1f1e2449 100644
---- a/net/dccp/ccids/ccid2.c
-+++ b/net/dccp/ccids/ccid2.c
-@@ -126,21 +126,26 @@ static void dccp_tasklet_schedule(struct sock *sk)
-
- static void ccid2_hc_tx_rto_expire(struct timer_list *t)
- {
-- struct ccid2_hc_tx_sock *hc = from_timer(hc, t, tx_rtotimer);
-- struct sock *sk = hc->sk;
-- const bool sender_was_blocked = ccid2_cwnd_network_limited(hc);
-+ struct dccp_sock *dp = from_timer(dp, t, dccps_ccid_timer);
-+ struct sock *sk = (struct sock *)dp;
-+ struct ccid2_hc_tx_sock *hc;
-+ bool sender_was_blocked;
-
- bh_lock_sock(sk);
-+
-+ if (inet_sk_state_load(sk) == DCCP_CLOSED)
-+ goto out;
-+
-+ hc = ccid_priv(dp->dccps_hc_tx_ccid);
-+ sender_was_blocked = ccid2_cwnd_network_limited(hc);
-+
- if (sock_owned_by_user(sk)) {
-- sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + HZ / 5);
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer, jiffies + HZ / 5);
- goto out;
- }
-
- ccid2_pr_debug("RTO_EXPIRE\n");
-
-- if (sk->sk_state == DCCP_CLOSED)
-- goto out;
--
- /* back-off timer */
- hc->tx_rto <<= 1;
- if (hc->tx_rto > DCCP_RTO_MAX)
-@@ -166,7 +171,7 @@ static void ccid2_hc_tx_rto_expire(struct timer_list *t)
- if (sender_was_blocked)
- dccp_tasklet_schedule(sk);
- /* restart backed-off timer */
-- sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer, jiffies + hc->tx_rto);
- out:
- bh_unlock_sock(sk);
- sock_put(sk);
-@@ -330,7 +335,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
- }
- #endif
-
-- sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer, jiffies + hc->tx_rto);
-
- #ifdef CONFIG_IP_DCCP_CCID2_DEBUG
- do {
-@@ -700,9 +705,9 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
-
- /* restart RTO timer if not all outstanding data has been acked */
- if (hc->tx_pipe == 0)
-- sk_stop_timer(sk, &hc->tx_rtotimer);
-+ sk_stop_timer(sk, &dp->dccps_ccid_timer);
- else
-- sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer, jiffies + hc->tx_rto);
- done:
- /* check if incoming Acks allow pending packets to be sent */
- if (sender_was_blocked && !ccid2_cwnd_network_limited(hc))
-@@ -737,17 +742,18 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
- hc->tx_last_cong = hc->tx_lsndtime = hc->tx_cwnd_stamp = ccid2_jiffies32;
- hc->tx_cwnd_used = 0;
- hc->sk = sk;
-- timer_setup(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire, 0);
-+ timer_setup(&dp->dccps_ccid_timer, ccid2_hc_tx_rto_expire, 0);
- INIT_LIST_HEAD(&hc->tx_av_chunks);
- return 0;
- }
-
- static void ccid2_hc_tx_exit(struct sock *sk)
- {
-+ struct dccp_sock *dp = dccp_sk(sk);
- struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
- int i;
-
-- sk_stop_timer(sk, &hc->tx_rtotimer);
-+ sk_stop_timer(sk, &dp->dccps_ccid_timer);
-
- for (i = 0; i < hc->tx_seqbufc; i++)
- kfree(hc->tx_seqbuf[i]);
-diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
-index b9ee1a4a8955..685f4d046c0d 100644
---- a/net/dccp/ccids/ccid3.c
-+++ b/net/dccp/ccids/ccid3.c
-@@ -184,17 +184,24 @@ static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hc,
-
- static void ccid3_hc_tx_no_feedback_timer(struct timer_list *t)
- {
-- struct ccid3_hc_tx_sock *hc = from_timer(hc, t, tx_no_feedback_timer);
-- struct sock *sk = hc->sk;
-+ struct dccp_sock *dp = from_timer(dp, t, dccps_ccid_timer);
-+ struct ccid3_hc_tx_sock *hc;
-+ struct sock *sk = (struct sock *)dp;
- unsigned long t_nfb = USEC_PER_SEC / 5;
-
- bh_lock_sock(sk);
-+
-+ if (inet_sk_state_load(sk) == DCCP_CLOSED)
-+ goto out;
-+
- if (sock_owned_by_user(sk)) {
- /* Try again later. */
- /* XXX: set some sensible MIB */
- goto restart_timer;
- }
-
-+ hc = ccid_priv(dp->dccps_hc_tx_ccid);
-+
- ccid3_pr_debug("%s(%p, state=%s) - entry\n", dccp_role(sk), sk,
- ccid3_tx_state_name(hc->tx_state));
-
-@@ -250,8 +257,8 @@ static void ccid3_hc_tx_no_feedback_timer(struct timer_list *t)
- t_nfb = max(hc->tx_t_rto, 2 * hc->tx_t_ipi);
-
- restart_timer:
-- sk_reset_timer(sk, &hc->tx_no_feedback_timer,
-- jiffies + usecs_to_jiffies(t_nfb));
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer,
-+ jiffies + usecs_to_jiffies(t_nfb));
- out:
- bh_unlock_sock(sk);
- sock_put(sk);
-@@ -280,7 +287,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
- return -EBADMSG;
-
- if (hc->tx_state == TFRC_SSTATE_NO_SENT) {
-- sk_reset_timer(sk, &hc->tx_no_feedback_timer, (jiffies +
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer, (jiffies +
- usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
- hc->tx_last_win_count = 0;
- hc->tx_t_last_win_count = now;
-@@ -354,6 +361,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, unsigned int len)
- static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
- {
- struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
-+ struct dccp_sock *dp = dccp_sk(sk);
- struct tfrc_tx_hist_entry *acked;
- ktime_t now;
- unsigned long t_nfb;
-@@ -420,7 +428,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
- (unsigned int)(hc->tx_x >> 6));
-
- /* unschedule no feedback timer */
-- sk_stop_timer(sk, &hc->tx_no_feedback_timer);
-+ sk_stop_timer(sk, &dp->dccps_ccid_timer);
-
- /*
- * As we have calculated new ipi, delta, t_nom it is possible
-@@ -445,8 +453,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
- "expire in %lu jiffies (%luus)\n",
- dccp_role(sk), sk, usecs_to_jiffies(t_nfb), t_nfb);
-
-- sk_reset_timer(sk, &hc->tx_no_feedback_timer,
-- jiffies + usecs_to_jiffies(t_nfb));
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer,
-+ jiffies + usecs_to_jiffies(t_nfb));
- }
-
- static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type,
-@@ -488,21 +496,23 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type,
-
- static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
- {
-+ struct dccp_sock *dp = dccp_sk(sk);
- struct ccid3_hc_tx_sock *hc = ccid_priv(ccid);
-
- hc->tx_state = TFRC_SSTATE_NO_SENT;
- hc->tx_hist = NULL;
- hc->sk = sk;
-- timer_setup(&hc->tx_no_feedback_timer,
-+ timer_setup(&dp->dccps_ccid_timer,
- ccid3_hc_tx_no_feedback_timer, 0);
- return 0;
- }
-
- static void ccid3_hc_tx_exit(struct sock *sk)
- {
-+ struct dccp_sock *dp = dccp_sk(sk);
- struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
-
-- sk_stop_timer(sk, &hc->tx_no_feedback_timer);
-+ sk_stop_timer(sk, &dp->dccps_ccid_timer);
- tfrc_tx_hist_purge(&hc->tx_hist);
- }
-
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch b/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch
deleted file mode 100644
index 67708033d230..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.13/hardened-patches/0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From a1369990ca622db871f12a9a6fc27f89f36ef1aa Mon Sep 17 00:00:00 2001
-From: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
-Date: Tue, 13 Oct 2020 19:18:49 +0200
-Subject: [PATCH 112/113] Revert "dccp: don't free ccid2_hc_tx_sock struct in
- dccp_disconnect()"
-
-This reverts commit 2677d20677314101293e6da0094ede7b5526d2b1.
-
-This fixes an issue that after disconnect, dccps_hc_tx_ccid will still be
-kept, allowing the socket to be reused as a listener socket, and the cloned
-socket will free its dccps_hc_tx_ccid, leading to a later use after free,
-when the listener socket is closed.
-
-This addresses CVE-2020-16119.
-
-Fixes: 2677d2067731 (dccp: don't free ccid2_hc_tx_sock struct in dccp_disconnect())
-Reported-by: Hadar Manor
-Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
-Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
----
- net/dccp/proto.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/net/dccp/proto.c b/net/dccp/proto.c
-index 6d705d90c614..359e848dba6c 100644
---- a/net/dccp/proto.c
-+++ b/net/dccp/proto.c
-@@ -279,7 +279,9 @@ int dccp_disconnect(struct sock *sk, int flags)
-
- dccp_clear_xmit_timers(sk);
- ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
-+ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
- dp->dccps_hc_rx_ccid = NULL;
-+ dp->dccps_hc_tx_ccid = NULL;
-
- __skb_queue_purge(&sk->sk_receive_queue);
- __skb_queue_purge(&sk->sk_write_queue);
---
-2.30.0
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0001-ctf-generate-CTF-information-for-the-kernel.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0001-ctf-generate-CTF-information-for-the-kernel.patch
deleted file mode 100644
index 2eda4541a94c..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0001-ctf-generate-CTF-information-for-the-kernel.patch
+++ /dev/null
@@ -1,7297 +0,0 @@
-From ee291dd05f9c4904f1c5a110d22cf0c3a5580df6 Mon Sep 17 00:00:00 2001
-From: Nick Alcock <nick.alcock@oracle.com>
-Date: Wed, 14 Nov 2018 19:42:21 +0000
-Subject: [PATCH 01/19] ctf: generate CTF information for the kernel
-
-This introduces a new tool, dwarf2ctf, which runs whenever 'make ctf' is
-run, extracting information on the kernel's types and global variables
-from the DWARF-format debug information in the kernel build tree,
-deduplicating it, and emitting it in Sun's Compact Type Format into a
-mmappable type archive named vmlinux.ctfa, which is installed at 'make
-install' time into /lib/modules/$(uname -r)/kernel/. Out-of-tree
-modules cannot participate in this mechanism since the file is already
-written: CTF information for such modules is instead linked into such
-modules at build time as new sections named .SUNW_ctf (as a result, most
-of the build-time machinery for this is in scripts/Makefile.modpost).
-Care should be taken not to strip such sections into debug RPMs (they
-are small enough that this should not be a problem).
-
-Within the ctfa file, the type information is divided into a shared
-repository, containing all types used by more than one module, CTF for
-the core kernel, and separate CTF for each module built, whether or not
-this module has been compiled in or not: if a file *could* be built as a
-module, it will be considered to be a module from the perspective of CTF
-file emission (and kallmodsyms: see the next commit). This ensures that
-external consumers such as DTrace always find types for a given module
-in the same place, regardless of the local kernel configuration, as long
-as that module is present at all, assisting in portability of D scripts
-between installations. The ctf_ar tool in libdtrace-ctf can be used to
-inspect ctfa files, and the ctf_dump tool can be used to look at the ctf
-files they contain.
-
-This process needs a pair of new files, objects.builtin (which lists all
-object files that are unconditionally built into the kernel and cannot
-be built as modules) and modules_thick.builtin, which maps from the thin
-archives that make up built-in modules to their constituent object
-files. Taken together, these files let dwarf2ctf determine whether a
-given object file linked into vmlinux.o is part of a module, and if so,
-which one.
-
-There is a single manually-maintained blacklist of structure members
-dwarf2ctf cannot handle in scripts/dwarf2ctf/member.blacklist: this is
-used to identify structure members which have different definitions in
-different object files even though they are defined in the same location
-in the same source file, usually due to preprocessor magic. (Currently,
-the only item in this list is present for example purposes only, since
-the file in question was recently removed from the kernel: dwarf2ctf can
-these days identify most members needing blacklisting automatically, and
-will fail with an error if it needs more help. It is quite possible that
-dwarf2ctf will fail on make allyesconfig kernel configurations and other
-extreme cases: I hope to track all such bugs down in time.)
-
-The documentation for dwarf2ctf is currently somewhat outdated: an
-update is planned. It remains largely accurate except for some details
-of the deduplication pass.
-
-This introduces new kernel build-time dependencies on elfutils, zlib,
-glib, and the new libdtrace-ctf package (shared with DTrace userspace).
-No new runtime dependencies are introduced.
-
-v5.6: retain the tristate machinery and scripts/Makefile.modbuiltin,
- since there appears to be no other way to get modules_thick.builtin
- (or anything like it) generated.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
----
- .gitignore | 3 +
- Documentation/dontdiff | 1 +
- Documentation/dwarf2ctf | 1054 ++++++
- Documentation/kbuild/kconfig.rst | 5 +
- Documentation/process/changes.rst | 23 +-
- Makefile | 72 +-
- lib/Kconfig | 12 +
- scripts/Kbuild.include | 6 +
- scripts/Makefile | 1 +
- scripts/Makefile.modbuiltin | 60 +
- scripts/Makefile.modfinal | 141 +-
- scripts/dwarf2ctf/.gitignore | 1 +
- scripts/dwarf2ctf/Makefile | 10 +
- scripts/dwarf2ctf/dwarf2ctf.c | 4962 ++++++++++++++++++++++++++++
- scripts/dwarf2ctf/eu_simple.c | 2 +
- scripts/dwarf2ctf/member.blacklist | 1 +
- scripts/eu_simple.c | 356 ++
- scripts/eu_simple.h | 91 +
- scripts/kconfig/confdata.c | 41 +-
- scripts/move-if-change | 8 +
- scripts/package/mkspec | 12 +
- 21 files changed, 6851 insertions(+), 11 deletions(-)
- create mode 100644 Documentation/dwarf2ctf
- create mode 100644 scripts/Makefile.modbuiltin
- create mode 100644 scripts/dwarf2ctf/.gitignore
- create mode 100644 scripts/dwarf2ctf/Makefile
- create mode 100644 scripts/dwarf2ctf/dwarf2ctf.c
- create mode 100644 scripts/dwarf2ctf/eu_simple.c
- create mode 100644 scripts/dwarf2ctf/member.blacklist
- create mode 100644 scripts/eu_simple.c
- create mode 100644 scripts/eu_simple.h
- create mode 100755 scripts/move-if-change
-
-diff --git a/.gitignore b/.gitignore
-index d01cda8e11779a2fa3e3333fd176e2e77e02fd21..1c10cd7ce03399a97367d56dbefd66dea1823859 100644
---- a/.gitignore
-+++ b/.gitignore
-@@ -48,6 +48,8 @@
- Module.symvers
- modules.builtin
- modules.order
-+modules_thick.builtin
-+objects.builtin
-
- #
- # Top-level generic files
-@@ -58,6 +60,7 @@ modules.order
- /vmlinux
- /vmlinux.32
- /vmlinux.symvers
-+/vmlinux.ctfa
- /vmlinux-gdb.py
- /vmlinuz
- /System.map
-diff --git a/Documentation/dontdiff b/Documentation/dontdiff
-index e361fc95ca293d80434ee0cdfae309046c17d612..a763d0fb892edf3e0cfddc1670f52963eaad5a36 100644
---- a/Documentation/dontdiff
-+++ b/Documentation/dontdiff
-@@ -181,6 +181,7 @@ modpost
- modules.builtin
- modules.builtin.modinfo
- modules.nsdeps
-+modules_thick.builtin
- modules.order
- modversions.h*
- nconf
-diff --git a/Documentation/dwarf2ctf b/Documentation/dwarf2ctf
-new file mode 100644
-index 0000000000000000000000000000000000000000..5cc445fbd227cbea527b593b2f16775430ee5f52
---- /dev/null
-+++ b/Documentation/dwarf2ctf
-@@ -0,0 +1,1054 @@
-+dwarf2ctf, a type encoder for the Linux kernel
-+=========
-+
-+Many kernel-level debugging and tracing systems need access to the kernel's type
-+information. Since C doesn't support any form of introspection, the data must
-+be extracted in some other way: here, we extract it from the DWARF debugging
-+information generated by the compiler. Unfortunately, this information is very
-+voluminous (just the type information alone adds up to a couple of hundred
-+megabytes in a 'make allyesconfig' kernel): even if users are happy to spend the
-+disk space, the time and memory required to read much of this information in is
-+likely to be prohibitive.
-+
-+This problem is not new -- back in 2004, Sun had the same problem when
-+attempting to give DTrace a view of the type information in the Solaris kernel.
-+Their solution was the Compact ANSI-C Type Format (CTF), a highly compacted
-+representation of C types suitable for debuggers and tracers. They combined
-+this with a highly efficient tool for converting DWARF2 types to CTF, and hacks
-+in the Solaris kernel causing the kernel itself to emit CTF data for its own
-+types.
-+
-+Unfortunately while this tool may be highly efficient it is not adequate for the
-+Linux kernel. It treats every ELF object as an independent entity with an
-+independent set of types -- perfectly all right for the Solaris kernel with a
-+few hundred modules maximum, but very much not for Linux, where distro kernels
-+often compile in thousands of modules. Ideally, we would like to treat all
-+kernel modules, built-in or not, the same way, sharing and deduplicating all
-+globally-visible types across the entire set of visible modules and recording
-+each precisely once.
-+
-+We also want to collect descriptions of global variables and emit descriptions
-+of their name->type mapping as well, since the kernel has no easily accessible
-+ELF section we can extract this information from at runtime (kernel modules must
-+be accessible at runtime for modern Linux systems to work, but the kernel itself
-+could have come from over the network or off a USB key or from a non-mounted
-+partition or an EFI boot partition or who knows where, and could have any name
-+even if it is accessible: so tracing tools should not rely on being able to look
-+inside the kernel image).
-+
-+We do all this with dwarf2ctf, a CTF generation tool that reads in DWARF from a
-+set of object files (usually, every object file in the kernel and all modules)
-+and fills a directory with compressed files containing CTF representations of
-+the types in those object files: the kernel build system regenerates these as
-+necessary and links them directly into kernel modules.
-+
-+Caveats: It is somewhat specific to the form of DWARF output emitted by GCC, and
-+doesn't yet support DWARF-4 type signatures or compressed DWARF at all.
-+
-+We'll look at each part of this system in turn, from the top down, starting with
-+using the kernel type information dwarf2ctf produces in other programs.
-+
-+
-+Using dwarf2ctf output
-+----------------------
-+
-+Using this data is fairly simple. Once you've read the CTF sections from the
-+kernel modules and inflated them (or ignored them if they are empty or, as just
-+mentioned, one byte long), you simply need to look at the ctf_parent_name() for
-+each module, and if it is set to "ctf", call ctf_import() to set the parent of
-+this module to the CTF data you have read from the .ctf.shared_ctf section in
-+the ctf.ko kernel module. The core kernel's types are stored in the
-+.ctf.vmlinux section in the same kernel module, and all built-in kernel modules
-+have their types in .ctf.$module_name. Non-built-in kernel modules just have a
-+.ctf section containing their types, which again might need their parent set to
-+"shared_ctf". (Out-of-tree kernel modules will have no such parent.)
-+
-+Once you've set up the parenthood relationships you can call ctf_close() on the
-+shared type repository and forget about it entirely: it will be refcounted and
-+destroyed when all its children are closed.
-+
-+
-+You should end up with a family of CTF files, one per kernel module built-in or
-+not and one for the core kernel, freely usable for whatever purpose you need.
-+
-+
-+Invocation and build-system connections
-+----------
-+
-+dwarf2ctf's command-line syntax emphasises simplicity over compactness. Linux
-+has nearly-infinitely-long command lines these days, so we can take advantage of
-+this.
-+
-+Two syntaxes are supported. The first shares types across multiple modules and
-+the core kernel; the second is used for out-of-tree module building, and avoids
-+either sharing anything at all across modules or depending on the set of shared
-+types defined for the core kernel.
-+
-+
-+dwarf2ctf outputdir objects.builtin modules.builtin dedup.blacklist \
-+ vmlinux.o module.o ...
-+dwarf2ctf outputdir -e module.o ...
-+
-+where:
-+
-+ - 'outputdir' is the possibly-relative path to a directory in which the
-+ generated CTF files get placed.
-+ - 'objects.builtin' is the name of the file containing the object files that
-+ correspond to always-built-in kernel code (that cannot be built as modules).
-+ - 'modules.builtin' is the name of the file containing the names of
-+ kernel modules presently built in to the kernel.
-+ - 'dedup.blacklist' is a blacklist of modules that should never participate
-+ in deduplication: see 'Duplicate type detection' below.
-+ - the .o filenames are the names of object files comprising the kernel and/or
-+ modules: you can feed in whole modules at once (before linking with .mod.o).
-+ This list is often very, very long (I have seen command-lines in excess of
-+ 60Kb).
-+
-+dwarf2ctf's output consists of a series of gzip-compressed .ctf.new files in the
-+outputdir, which the makefile compares with and if necessary moves over the top
-+of .ctf files with the same basename, so as to avoid relinking things if
-+dwarf2ctf has written out content identical to what it wrote last time it ran.
-+These fall into several classes, partitioned according to the contents of
-+objects.builtin and modules.builtin:
-+
-+ - shared_ctf.builtin.ctf: The shared type repository. Types shared by more
-+ than one of the files below go here.
-+ libdtrace-ctf). See 'Using dwarf2ctf output' below regarding use of this
-+ data.
-+ - vmlinux.builtin.ctf: Types in the core kernel, that cannot be built in to
-+ modules, go here.
-+ - *.builtin.ctf: One of these is generated for the types in each module that
-+ is presently built in to the kernel.
-+ - *.mod.ctf: One of these is generated for each .ko.
-+
-+All the files in the first three classes are linked into the ctf.ko module under
-+various names, an empty module containing nothing but CTF data.
-+
-+
-+A lengthy section of Makefile.modpost, and a short section of the toplevel
-+Makefile, is dedicated to creating these files, and to linking them into the
-+kernel modules. The dependency graph related to dwarf2ctf output is quite
-+complex: modules and objects (ld -r'ed *.o files) are processed by dwarf2ctf to
-+produce a number of files in the .ctf directory, and the final modules depend on
-+the relevant ctf files. The .mod.ctf's go into the .ko's with the same stem
-+name, but ctf.ko receives content from all the CTF files corresponding to
-+built-in modules, and until dwarf2ctf runs and creates those files we cannot
-+tell what those CTF files will be, though we do have a wildcard that matches
-+them all.
-+[
-+GNU Make's 'secondary expansion' feature comes to the rescue here: we can
-+compute a list of expected CTF filenames at runtime, given the names of the
-+modules we are linking in. For the builtin modules, we cheat and touch a stamp
-+file after moving any .ctf.new files back over a .ctf file, then depend on that
-+to see if ctf.ko needs to be relinked.
-+
-+The actual incorporation of the CTF data into the kernel modules happens before
-+module signing (if signing is active), by calling objcopy --add-section on the
-+module in question. This too has some knotty corners.
-+
-+First of all, the module linkage process normally links a module using all the
-+prerequisites of the module's target -- but we have designated all the CTF files
-+as prerequisites of the module's target, and we don't want to link them directly
-+in using ld(1), since they aren't object files. So we have to filter them out in
-+the link line.
-+
-+Secondly, those modules which have no CTF files should acquire empty CTF
-+sections to indicate their lack of unique types -- but objcopy in binutils 2.20
-+and below silently exits if asked to --add-section an empty file. So we use dd
-+to generate a file with a one-byte null in it instead, and teach the users of
-+CTF sections to treat a one-byte-long 'CTF' section as if it were empty.
-+
-+
-+Overview of dwarf2ctf operation
-+--------
-+
-+There are four phases to dwarf2ctf operation: initialization, duplicate type
-+detection, CTF construction, and writeout. Some of these phases can repeat.
-+All but the last phase consists purely of sucking data from object files into
-+GHashTables in memory. (The last two phases could potentially be combined,
-+shrinking the size of one hash and saving memory, but the hash that is shrunk is
-+by no means the largest one, so the extra complexity is probably not worth it.)
-+
-+dwarf2ctf uses several other libraries to do this:
-+
-+ - elfutils, used for DWARF parsing. We could potentially write our own
-+ DWARF parser, but elfutils works and is tested.
-+
-+ - glib, used for the GHashTable. The rest of the kernel uses roll-your-own
-+ hash tables, but dwarf2ctf makes heavy demands of its hashtables: they must
-+ be expanding hashes capable of efficiently storing hundreds of thousands of
-+ items, with amortized log(N) lookup time, and they must support deletion
-+ (though it need not be particularly efficient deletion). This rules out
-+ simple fixed-size bucket hashes like the ones used in other parts of the
-+ kernel build system: GHashTable is already implemented, and works.
-+
-+ - zlib, used to compress the CTF information.
-+
-+ - libdtrace-ctf, which both reads and writes the CTF data. This is a port of
-+ the Solaris CTF library, GPLed and with additional support for the storage
-+ of name->type mappings (meant to represent variables) akin to its existing
-+ ELF symbol->type mappings.
-+
-+dwarf2ctf has a good few important data structures, described at the top of
-+scripts/dwarf2ctf/dwarf2ctf.c.
-+
-+dwarf2ctf has its own trace facility, implemented via the dw_ctf_trace() macro
-+and enabled by compiling with -DDEBUG and setting DWARF2CTF_TRACE in the
-+environment. (The first step is required because some very numerous data
-+structures are greatly expanded when debugging is turned on, which would waste
-+memory if it were done all the time). This produces a huge volume of trace
-+output, several gigabytes when run over an allyesconfig kernel.
-+
-+
-+Unless you're interested in how dwarf2ctf works internally, you can stop reading
-+here. If you are interested, now is a good time to read the comments above
-+main() in scripts/dwarf2ctf/dwarf2ctf.c, which briefly describe dwarf2ctf's data
-+structures and functions.
-+
-+
-+Flow of Control
-+---------------
-+
-+The /* C comments */ point to other sections of this document,
-+
-+Functions named in the /* Utilities */ section of dwarf2ctf.c are not mentioned
-+here for simplicity's sake.
-+
-+[C]: Callback
-+[R]: recursive
-+[1]: Numbers: Mutually-recursive loop
-+|: Several functions which all call the same functions
-+->: Call from array of callbacks (filter_ctf_*() omitted as uninteresting)
-+
-+main()
-+ /* See 'Initialization' */
-+ init_assembly_tab()
-+ init_builtin()
-+ init_dedup_blacklist()
-+ init_member_blacklist()
-+ run()
-+ init_tu_to_modules()
-+ init_ctf_table()
-+
-+ /* Duplicate detection */
-+
-+ scan_duplicates()
-+ process_file() /* Toplevel DWARF walkers */
-+[C] detect_duplicates_init()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] detect_duplicates()
-+[ 1] mark_shared()
-+[R] type_id() /* Type IDs */
-+[C1] mark_shared()
-+[R] mark_seen_contained()
-+[C] detect_duplicates_done()
-+
-+ process_file()
-+[C] detect_duplicates_init()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] detect_duplicates_alias_fixup()
-+[R] type_id()
-+[C] is_named_struct_union_enum()
-+[R] type_id()
-+[C] detect_duplicates_alias_fixup_internal()
-+ mark_shared() (see above)
-+[C] detect_duplicates_done()
-+
-+ /* CTF construction */
-+
-+ process_file()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] construct_ctf()
-+[ 2] construct_ctf_id()
-+[R3] die_to_ctf()
-+ assembly_tab[]
-+[C] -> assemble_ctf_base()
-+ -> assemble_ctf_pointer()
-+ | assemble_ctf_array()
-+ | assemble_ctf_array_dimension()
-+ | assemble_ctf_typedef()
-+ | assemble_ctf_cvr_qual()
-+ | assemble_ctf_variable()
-+ lookup_ctf_type()
-+[ 2] construct_ctf_id()
-+ -> assemble_ctf_enumeration()
-+ -> assemble_ctf_enumerator()
-+ -> assemble_ctf_struct_union()
-+ -> assemble_ctf_su_member()
-+[ 3] die_to_ctf()
-+[ 2] construct_ctf_id()
-+
-+ write_types()
-+
-+Initialization
-+--------------
-+
-+ init_assembly_tab()
-+ init_builtin()
-+ init_dedup_blacklist()
-+ run()
-+ init_tu_to_modules()
-+ init_ctf_table()
-+
-+This happens at the top of main() and run(), and in various functions named
-+init_*(). Of these, init_assembly_tab() and init_builtin() serve only to turn
-+various static arrays and files mentioned on the command line into more useful
-+internal representations (e.g. the assembly filter array of structures is turned
-+into a pair of arrays indexed by DWARF tag), and the blacklisting functions are
-+described in the section on duplicate type detection below.
-+
-+init_ctf_table(), called both at initialization time and later during CTF
-+assembly when new CTF files are found to be needed, creates a new CTF file in
-+memory and either marks it as a child of the shared type repository, or (if it
-+*is* the shared type repository, or deduplication is off and there is only one
-+CTF file being processed and no shared type repository at all) creates a few
-+types in it which CTF has representations of but DWARF does not: a void type,
-+and a generic catchall pointer-to-function-returning-int.
-+
-+That leaves init_tu_to_modules(). This walks over all the top-level
-+compile_unit DIEs in the DWARF debugging information in every object file
-+mentioned in the list of modules and built-in modules, constructing a mapping
-+from translation unit name back to the name of the kernel module it comes from,
-+even if that module is built in to the kernel. This is normally the same as the
-+filename (sans extension), but for built-in kernel modules, the name comes from
-+the modules.builtin file's entry for the translation unit instead, so that the
-+output can land in a .builtin.ctf file rather than being jammed into
-+vmlinux.builtin.ctf with the core kernel's types.
-+
-+This means that dwarf2ctf can operate in terms of the kernel module a type is
-+contained within rather than having to think about the mapping between object
-+file name, translation unit name and module name all the time.
-+
-+
-+Toplevel DWARF walkers
-+----------------------
-+
-+ process_file()
-+[C] (per-TU initialization callback)
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] (per-DIE callback)
-+[C] (per-TU cleanup callback)
-+
-+All routines in dwarf2ctf other than initialization and writeout are DWARF
-+walkers: i.e., they walk over all DWARF DIEs in all object files specified on
-+the command line and do something with every DIE. This job is done by
-+process_file() and its helper process_tu_func(), which not only digs out the
-+corresponding (built-in or non-built-in) module name corresponding to each
-+object file, but also detects and skips translation units it has handled before
-+(in case they are incrementally linked into multiple object files) and allows
-+callbacks to be invoked at the start and end of each translation unit.
-+
-+Even though dwarf2ctf only cares about top-level types, in some situations DWARF
-+can emit top-level types with references to a non-top-level type: if all
-+occurrences of the top-level type are an opaque structure, and the only
-+non-opaque definition is inside a function, references in the same translation
-+unit as the non-opaque definition will point to the definition inside the
-+function (and references outside the translation unit will not point at any
-+definition). Thus, if we want to catch all nuances of globally-visible types,
-+we have to scan types inside functions and lexical blocks inside functions too.
-+
-+To avoid generating a vast number of unnecessary type definitions, the 'assembly
-+table' which describes how to construct a CTF type given a DWARF DIE also
-+contains a description of a set of filters which are passed the current DIE and
-+its parent: if they return false, the DIE is skipped and never passed to the
-+callback function. We also avoid calling the callback for any DWARF DIE whose
-+tag doesn't appear in the assembly table at all: there's no point doing
-+duplicate detection or anything else for a DWARF DIE we won't be generating CTF
-+from. There are currently two filters defined: filter_ctf_file_scope(), which
-+is called for every DWARF DIE whose tag is one we never expect to see a
-+reference to if it is inside a function (except if they relate to a structure or
-+union, as above), and filter_ctf_uninteresting(), which is called for variables
-+to see if they are worthy of recording (top-level named variables with external
-+linkage not part of the internal workings of macros only).
-+
-+
-+Type IDs
-+--------
-+
-+[R] type_id()
-+[C] (optional per-type callback)
-+
-+The only thing dwarf2ctf does which the Sun tool does not is the detection of
-+duplicate and shared types, both within individual kernel modules and across
-+modules. Our ultimate goal is that a type that appears in the source code once
-+appears in the CTF output once as well. This goal has mostly been attained,
-+except for out-of-tree modules, where cross-module type sharing must be disabled
-+to avoid requiring rebuilds of the module whenever the core kernel is rebuilt.
-+
-+The core of this is the concept of a *type ID* and the function type_id() which
-+computes it. A type ID is an identifier for a type which precisely represents
-+that type and only that type. Doing this for types in different headers or at
-+different scopes with the same name without needing to encode knowledge of C
-+scoping rules into dwarf2ctf is an interesting proposition: we can use the line
-+number and filename info provided by DWARF in most user-specified types to help.
-+
-+A type ID is a recursively-constructed string of the following form (fixed
-+elements represented by {}, optional elements by []):
-+
-+//[filename]//[line number]//{type string}
-+
-+Types are *based* upon other types iff they have a DW_AT_type attribute pointing
-+to some other type. All types based upon other types have a type ID that is the
-+type ID of the type upon which they are based, with additional information
-+specific to this type appended to it. The filename and line number is only
-+added for those types which are not based upon other types and which have a
-+filename and line number in the DWARF (lots don't, e.g. base types): the
-+filename is canonicalized with realpath(), though since this is quite slow and
-+type_id() is called a lot, the mapping from DWARF filename to realpath() result
-+is cached. Types that have no filename or line number start with '////'.
-+
-+We use // to separate the filename and line number elements because this is the
-+shortest string other than NUL that cannot appear in a canonicalized POSIX
-+pathname (ignoring Pyramid, Cygwin and other strange systems that actually
-+return // in the result of realpath(): Linux doesn't use it and that's all that
-+matters. Should it start to use it, we can switch delimiter to ///.)
-+
-+Function pointers are not represented (or, rather, are all mapped to the same
-+type ID, the generic catchall function-pointer type mentioned above); array
-+dimensions are represented by [index-type dimension], or [] for flexible array
-+members. Structure members are not represented, since they are not types, but
-+the types of their members *are* represented, as are nested structures (the line
-+number and filename serving, as ever, to disambiguate them from other structures
-+with the same name declared nested inside different structures).
-+
-+The following are some examples of valid type IDs (assuming the kernel source
-+tree is, implausibly, located at /k/, just off the root directory: comments on
-+individual types done /* like C */; the last example is broken across lines for
-+formatting's sake):
-+
-+//fp//* # a pointer to a function, any function
-+////long int
-+////char []
-+////unsigned int typedef __kernel_uid_t typedef __kernel_uid32_t
-+//fp//* typedef __signalfn_t * typedef __sighandler_t
-+////struct nsproxy /* an opaque type */
-+////struct nsproxy * # /* pointer to it */
-+////long unsigned int typedef u64 volatile
-+////long unsigned int volatile const * const
-+////long unsigned int typedef sector_t [////long unsigned int 511]
-+/k/include/linux/types.h//222//struct list_head
-+/k/include/linux/types.h//222//struct list_head *
-+/k/include/linux/types.h//222//struct list_head [////long unsigned int 5]
-+/k/include/linux/types.h//217//struct /* no struct tag */
-+/k/include/linux/types.h//217//struct typedef atomic64_t
-+/k/include/linux/mm_types.h//34//struct page * typedef pgtable_t
-+/k/fs/eventpoll.c//122//struct nested_calls
-+/k/include/linux/sysctl.h//1016//struct ctl_table typedef ctl_table
-+ [////long unsigned int 4] var inotify_table /* A global variable */
-+
-+This scheme means that cv-quals and other modifiers applied to other types are
-+always merged: if there are a dozen typedefs for a single type 'foo' with the
-+same name declared in the same place, they all end up with the same type ID and
-+are only emitted into the CTF once.
-+
-+The type_id() function can also accept a callback, which is called as the
-+recursion unwinds, from base type up to derived type: so it might be called for
-+"////unsigned int", then for "////unsigned int typedef __kernel_uid_t", and so
-+on up to the DIE that was originally passed in. Because type_id() returns a
-+dynamically-allocated string, calls to type_id() made purely for the sake of
-+invoking a callback are normally of the peculiar form "free(type_id(...))".
-+
-+type_id() is a very hot spot, so syscall results are cached in it (such as
-+realpath(), as mentioned above), and when string appending is done, it is done
-+all at once where possible, via str_appendn(), which calls realloc() only once
-+no matter the number of strings being appended.
-+
-+Lots of core data structures in dwarf2ctf consist of hashes mapping type IDs to
-+something else (predominantly CTF file/ID pairs and module names). It would
-+be possible to map from hashes of type IDs, saving some memory, but this would
-+impair debugging so is not yet implemented. (If it is implemented, it should
-+probably be implemented only when DEBUG is not defined.)
-+
-+
-+Duplicate detection
-+-------------------
-+
-+ scan_duplicates()
-+ process_file() /* Toplevel DWARF walkers */
-+[C] detect_duplicates_init()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] detect_duplicates()
-+[ 1] mark_shared()
-+[R] type_id() /* Type IDs */
-+[C1] mark_shared()
-+[ 4] type_id()
-+[ 4] detect_duplicates_typeid()
-+[ 4] detect_duplicates()
-+[R] mark_seen_contained()
-+ member_blacklisted()
-+[C] detect_duplicates_done()
-+
-+ process_file()
-+[C] detect_duplicates_init()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] detect_duplicates_alias_fixup()
-+[R] type_id()
-+[C] is_named_struct_union_enum()
-+[R] type_id()
-+[C] detect_duplicates_alias_fixup_internal()
-+ mark_shared() (see above)
-+[C] detect_duplicates_done()
-+
-+The job of the duplicate detection pass is to fill out the id_to_module hash,
-+which maps type IDs to the module they appear in, with the two special cases
-+that types that appear only in the core kernel are said to appear in the module
-+'vmlinux', and types that appear in more than one module (or in a module and in
-+the core kernel) are said to appear in the module 'shared_ctf', the shared type
-+repository. This is quite a tricky multi-pass process, because we must ensure
-+that the shared type repository is self-contained: all types in the repository
-+must not reference any types outside the repository.
-+
-+Detecting duplicates itself is easy: we consider two types duplicates if they
-+have the same type ID: if they both reside in the same module, the resulting
-+type resides in that module too. However, detecting shared types is harder.
-+We consider that a type belongs in the shared module if any of these conditions
-+is true:
-+
-+ - the type appears multiple times in different modules
-+ - a type for which this type is a base type is shared
-+ - the type is referenced by a structure or union member, and the structure
-+ or union is shared
-+ - the type is a non-opaque type with an opaque variant ('struct foo'), or
-+ vice versa, and either of these variants is shared: these two types will
-+ get different type IDs, so explicit checking is necessary
-+
-+Note that we do *not* consider a type to belong in the shared module merely if
-+*it* has a base type which is shared: indeed, this is the common case for
-+unshared types (even unshared structures tend to have fields of shared types
-+like int).
-+
-+It should be fairly easy to see that sharedness is a contagious property:
-+e.g. if you mark a structure as shared, and one of its members is an
-+otherwise-unshared opaque pointer to a structure, you have to mark that as
-+shared: this causes the non-opaque definition of the structure, and all *its*
-+members, to be shared, and so on. So since dwarf2ctf does not track the members
-+of structures itself (not until the CTF generation phase, anyway), this means
-+walking over the DWARF DIEs multiple times, checking for sharedness over and
-+over until we are done.
-+
-+We partition the problem into two parts, both of which are carried out by
-+process_file() callback functions: detect_duplicates() and
-+detect_duplicates_alias_fixup().
-+
-+
-+detect_duplicates() is called first, once for every DIE in the kernel (via
-+process_file()). This identifies types that are duplicated but not shared, and
-+identifies shared types without consideration of opaque struct/union aliasing.
-+It also flags types that have been seen only once as 'seen': this is checked
-+much later on by the CTF construction phase, since construction of CTF for
-+any type which has not been inspected by the deduplicator is a sign of a bug in
-+the deduplicator.
-+
-+This has several subtleties.
-+
-+If we are running for an out-of-tree module, we must still identify types as
-+duplicated within the module, but must never mark them as shared: out-of-tree
-+modules cannot contribute to the shared type repository nor even use types in
-+it, since they are rebuilt independently from the kernel proper and thus cannot
-+depend on a type currently in the repository remaining there (e.g. perhaps it
-+has only two users, both in modules, and the kernel is rebuilt to not build one
-+of those modules anymore: this should not require rebuilding of any out-of-tree
-+modules).
-+
-+If we mark a structure or union type as seen, we must mark aggregate types that
-+appear directly within that type's DIE as seen as well. This is done by the
-+recursive function mark_seen_contained(). You might wonder what the point of it
-+is: such types surely cannot appear anywhere else, and any duplication will
-+precisely match the duplication of the containing type. The answer is that they
-+can still be referenced as the type of structure members of their containing
-+structure, e.g. in
-+
-+struct foo {
-+ struct bar {
-+ } *baz;
-+ struct bar wombat[16];
-+};
-+
-+Here, a reference to 'struct bar' appears in 'struct foo', and CTF is
-+constructed for it, even though it is not a top-level DIE. In GCC 4.8+, a
-+reference to the 16-element array-of-struct-bar can also appear in 'struct foo':
-+in fact almost anything can appear in there if used nowhere else in the
-+translation unit, even base types. So we look for the appearance of anything
-+which we can assemble into CTF (anything in the assembly_tab) other than
-+members, since members cannot be used as the type of anything else, and mark
-+them all as seen in this module. (Nearly everything in a structure or union is
-+a member, so this ends up skipping almost but not quite everything.)
-+
-+
-+If we find that a type has appeared more than once in different kernel modules
-+(or in a module and in the core kernel), we must mark it as shared. This is
-+done via mark_shared(), which is both a function that can be directly called
-+(e.g. from detect_duplicates()) and a type_id() callback. If it is called
-+directly, it immediately reinvokes itself as a type_id() callback, which calls
-+it for the base type of the type in question and then for all qualifiers up the
-+type ID stack, marking them all as shared if they weren't already.
-+
-+If a structure or union is marked as shared, the types of its members are also
-+marked as shared via a recursive call (even if they have already been so marked:
-+just because this structure is of a type we've already seen, in a location we've
-+already seen, doesn't mean that someone might not have legitimately used
-+#defines to add extra members to the end of it, and we need to mark them as
-+shared too). We track structures that have been seen in this translation unit
-+and avoid recursing into them, to avoid an infinite loop in cases like this:
-+
-+struct one;
-+struct two {
-+ struct one *foo;
-+};
-+
-+struct one {
-+ struct two *foo;
-+}
-+
-+The types being pointers does not help here -- the marking of 'struct one *' as
-+shared will automatically mark 'struct one' as shared too, because otherwise we
-+might have a structure in the shared type repository whose members' types
-+could not be found there.
-+
-+
-+The second pass is the 'alias fixup' pass, implemented by
-+detect_duplicates_alias_fixup(). This pass serves to detect unshared opaque
-+types whose non-opaque equivalents are shared, and vice versa. It is executed
-+repeatedly until no types have been marked as shared for an entire iteration,
-+but is considerably faster per iteration than the first pass, which often
-+consumes more than half of dwarf2ctf's total runtime. We work in one direction
-+only, looking for non-opaque structures, unions or enums which have structure
-+tags. (Structures without tags cannot have opaque variants, and structures
-+which are opaque will have non-opaque cousins somewhere, or can be emitted to
-+the CTF as an opaque structure harmlessly since they truly have no members and
-+are probably manipulated only via casts.)
-+
-+We identify structures, unions or enums with tags via the type_id() callback
-+is_named_struct_union_enum(), but cannot determine if something is an opaque
-+structure at this stage. Instead, we do that after the callback, checking to
-+see if the first four characters of the type ID are "////": this relies on the
-+fact that GCC never gives opaque structures line numbers in DWARF. We do the
-+actual checking and marking of each non-opaque structure using
-+detect_duplicates_alias_fixup_internal(), which is yet another type_id()
-+callback.
-+
-+This function directly synthesises the name which this structure's opaque cousin
-+would have, if it existed, by stripping off the line number and filename and
-+replacing them with '////', and sees if either of these types have been marked
-+as shared while the other has not. If the opaque type is shared, the non-opaque
-+variant can be marked shared using the same recursive mark_shared() function as
-+before (thus marking the types of all its members and types it depends upon as
-+shared too). If it is the opaque type that needs marking shared, this will not
-+work, since mark_shared() takes a DWARF DIE, and we don't have one for the
-+opaque type, just a faked-up type ID. However, since an opaque type doesn't
-+have any members that need recursively tracing, we don't need access to its
-+DWARF DIE to figure them out, and can just mark it as shared directly, via an
-+insert into the id_to_module hash.
-+
-+Since this function is a type_id() callback, it is called not just for
-+structures but for types based on them (e.g. in type_id form, "struct foo const
-+* [43] volatile *"); at every level of this declarator stack, a shared opaque
-+base type will contaminate its non-opaque cousins with sharedness, and vice
-+versa. This handles situations in which, say, the opaque version of "struct foo
-+const * [43]" was used by more than one module and was marked as shared: the
-+marking process will have marked the opaque versions of "struct foo const *
-+[43]", "struct foo const *", "struct foo const" and "struct foo" as shared, but
-+will not have touched any non-opaque versions of these types which may exist
-+until this routine runs. It also handles typedefs to structures with no need
-+for any extra code.
-+
-+This whole alias fixup process needs to be repeated, because whenever a
-+non-opaque type is marked as shared and its member's types traced and marked
-+shared, *those* may themselves be structure types with corresponding opaque or
-+non-opaque variants, and when they are opaque types the non-opaque variant that
-+alias fixup works from may already have passed under the DWARF walker's gaze: so
-+another pass over the kernel's DWARF is necessary to be sure we catch it.
-+mark_shared() thus sets a flag that scan_duplicates() recognizes and uses to
-+trigger another run through the alias fixup pass.
-+
-+
-+There are a very few modules that this algorithm doesn't work for. One example
-+is snd-ens1371, which reads, in toto
-+
-+#define CHIP1371
-+#include "ens1370.c"
-+
-+and ens1370.c (itself a distinct kernel module) then defines a 'struct ensoniq'
-+whose members vary depending on whether CHIP1371 is defined. Obviously, it is
-+impossible to share any such types between kernel modules even though their
-+names are the same and they are defined in the same place in the same source
-+file in both cases. But this sort of trickery is very rare, so we simply
-+implement a 'deduplication blacklist' of modules which will not introduce new
-+types into the shared CTF repository, and who do not participate in alias fixup
-+detection either. Detecting these cases in order to blacklist them is harder:
-+no automated system has yet been implemented, although instances where #defines
-+of this nature introduce new types that are then used by later members will
-+cause assertion failures inside dwarf2ctf which might be a clue. So it is
-+possible that some examples have been missed. (The blacklist only applies to
-+cases where structure members change within a single kernel build, so cases
-+where structures have members whose presence depends on CONFIG_* values are
-+quite all right, as are cases where #defines are introduced by one translation
-+that #includes another that then goes on to define whole new structures: it is
-+only cases where modules #define something that changes the definition of
-+individual possibly-shared types that will need blacklisting.)
-+
-+
-+There are a few even worse cases where a single structure is defined with
-+different members in different translation units within a single module. In
-+this case we can do nothing at all, since our output representation describes
-+only a single type per module: we implement a 'member blacklist' which bans
-+emission of affected members entirely, leaving a description of a structure with
-+an undescribed hole in it.
-+
-+
-+CTF construction
-+----------------
-+
-+ process_file()
-+[R] process_tu_func()
-+[C] assembly_filter_tab[]
-+[C] construct_ctf()
-+[ 2] construct_ctf_id()
-+[R3] die_to_ctf()
-+ assembly_tab[]
-+[C] -> assemble_ctf_base()
-+ -> assemble_ctf_pointer()
-+ | assemble_ctf_array()
-+ | assemble_ctf_array_dimension()
-+ | assemble_ctf_typedef()
-+ | assemble_ctf_cvr_qual()
-+ | assemble_ctf_variable()
-+ lookup_ctf_type()
-+[ 2] construct_ctf_id()
-+ -> assemble_ctf_enumeration()
-+ -> assemble_ctf_enumerator()
-+ -> assemble_ctf_struct_union()
-+ -> assemble_ctf_su_member()
-+ member_blacklisted()
-+[ 3] die_to_ctf()
-+[ 2] construct_ctf_id()
-+[C] cleanup_sou_member_count()
-+
-+The next stage after the detection of duplicate and cross-module shared types is
-+to generate CTF. We generate all CTF at once before emitting it: this is
-+potentially somewhat wasteful of memory, but in practice has not proved to be a
-+problem: substantially less memory is used than is used by other parts of the
-+kernel build, unless -DDEBUG is enabled. Its job is to look through the
-+kernel's type DWARF (via process_file(), as usual) and create CTF for every
-+file-or-global-scope type and every externally-visible variable in the CTF file
-+in which the duplicate detection pass has said that type should appear.
-+(Variables are treated exactly like types: it just so happens that they are
-+never shared because no type or variable can depend upon them, so they always go
-+directly into the appropriate module and never into the shared type repository.)
-+
-+At this stage, the 'CTF files' are not actually files but rather ctf_file_t
-+structures maintained by libdtrace-ctf and tracked in the per_module hash, along
-+with other information which varies by module name. We track every single
-+individual type in the CTF file in the id_to_type hash, which maps type IDs to
-+pairs of (CTF file ID, ctf type ID): this lets us use the type IDs described
-+above when considering cross-references within CTF files (e.g. from one CTF type
-+to a type it depends upon).
-+
-+The most important functions in this phase are:
-+
-+ - construct_ctf_id(), the top-level process_file() callback which is given a
-+ DWARF DIE, looks in module_to_ctf_file for the CTF file where this type
-+ should land (creating it if necessary), makes sure a type with this type ID
-+ has not already been created there, calls die_to_ctf() to create the CTF,
-+ notes where it was created in id_to_type, and handles errors.
-+
-+ - die_to_ctf(), a recursive function which calls the assembly function for the
-+ DIE it is given and all its immediate children, with special-case handling
-+ for tagged structures and unions. If you want to create a type but not note
-+ where it was created for future lookups by lookup_ctf_type(), this is what to
-+ call. (This is only done currently for unnamed structures/unions.)
-+
-+ - lookup_ctf_type(), which is called by CTF assembly functions for those
-+ types that depend upon other types: it calls construct_ctf_id() again
-+ to construct the type, and double-checks that all such types appear
-+ either in the module we are constructing types for, or in the shared CTF
-+ module. CTF represents all function pointers the same way, and has a
-+ special type ID for 'void', so we special-case both of these cases.
-+
-+These functions are mostly straightforward (though highly recursive, with all
-+three plus CTF construction functions participating in loop 2 above,
-+die_to_ctf() calling itself directly, and even one situation, the
-+already-mentioned unnamed structures/unions, in which die_to_ctf() is directly
-+called back by a CTF construction function, in loop 3 above.)
-+
-+
-+There are a few subtleties, though. Firstly, error handling. We consider that
-+errors that will lead to unusable CTF are fatal: mostly, these are errors where
-+a bug in the deduplicator has failed to trace types correctly and has left at
-+least one type in the shared module depending on a type in a non-shared module,
-+or has failed to mark a type as shared at all. In all these cases, you'll
-+eventually get an error from lookup_ctf_type() of the general form
-+
-+blah.c:413:foo_t: Internal error: lookup of flob found in different file.
-+
-+The first two parts of this error are the translation unit and line number the
-+type being assembled (usually a structure or union) was found in: foo_t is the
-+name of the type being assembled. The type of the structure being looked up
-+appears nowhere, because we don't know it, but the name of the member is given
-+("flob" above, or "(unnamed)" if we don't know it). If you want more
-+information, you can pass -DDEBUG to the compilation of dwarf2ctf.c in
-+scripts/dwarf2ctf/Makefile, and rerun dwarf2ctf, and you'll get the module and
-+filename in which both the originating and the target types appear. In order to
-+actually track down the bug you'll probably have to run dwarf2ctf with
-+DWARF2CTF_TRACE set in the environment, and look at the place where the target
-+type was deduplicated, and try to figure out why the deduplicator didn't trace
-+the reference to the type in foo_t correctly.
-+
-+There is another kind of error, though: a failure to assemble a single type,
-+perhaps because DWARF was emitted that we don't know how to understand (this is
-+particularly likely in structure assembly, where we are highly dependent on the
-+form of the DWARF that GCC happens to emit for DW_AT_member_location). We pass
-+an 'enum skip_type' around, which has three possible values, one of which is
-+SKIP_ABORT. Before each type is assembled, we call ctf_snapshot() to take a
-+snapshot of the variable-plus-type set in the CTF file we're working over. If a
-+SKIP_ABORT propagates up to construct_ctf_id(), we call ctf_rollback(), which
-+throws away every type constructed since the last ctf_snapshot() -- i.e., the
-+specific erroneous type we've just been working on. (We might have emitted some
-+parts of it and then failed, so we should try to clean up).
-+
-+A SKIP_ABORT is not fatal unless DEBUG is defined: its only effect is to omit
-+one single type from the resulting CTF, which is probably still usable.
-+
-+libdtrace-ctf causes additional problems here. It can only see the types we
-+added once the notably expensive function ctf_update() is called. This takes
-+the in-memory structures and serializes them (all of them, every time). This
-+only affects libctf when structure and union members are added: libctf needs to
-+know the sizes and alignments of the types of those members, which might quite
-+possibly just have been added, e.g. if this structure contains a pointer to its
-+own structure tag. So, when we insert a member in assemble_ctf_su_member(), we
-+note a bad type-ID error and do a ctf_update() on the file we're working over
-+and try again: even then that can fail if the type was added to the shared
-+repository, so we do a ctf_update() on *that* and try again, and only if that
-+fails do we declare a SKIP_ABORT error. (We check the shared repository last
-+because it is very large, so takes longer to serialize than other CTF files do).
-+
-+The need to keep the number of calls to ctf_update() down means we must avoid
-+all access to the CTF types we are assembling if we can possibly get at the same
-+data another way. Hence the member_counts hash, a member of the per_module
-+state, which tracks the number of members in structures with a given C-style
-+name and their CTF IDs. This structure allows us to handle the (valid) C idiom
-+of redeclaring the same structure with a different number of members, merging
-+the definitions across translation units and discarding them (iff the structure
-+was unshared) when we transition into a new module, without ever having to
-+consult the CTF to see how many members we put into it. (We have to use the
-+C-style name here, because by definition the type IDs of such redeclared
-+structures will be different, since a type ID contains a line number and
-+translation unit name.)
-+
-+
-+There's more error-handling complexity inside die_to_ctf(), where errors from
-+libdtrace-ctf are actually reported (there may be multiple of them for a single
-+type, e.g. if we are assembling a structure and several members somehow refer to
-+a type we do not know about).
-+
-+die_to_ctf() itself has the sort of parameter list that can make people swear
-+off C for life. It is largely explained in the description of ctf_assembly_fun.
-+Most parts of it are hardly used in the function itself, just passed down to CTF
-+assembly functions.
-+
-+Finally, we must note the override flag. Both die_to_ctf() and
-+construct_ctf_id() return a CTF ID. This is thrown away by the DWARF walking
-+code (the function construct_ctf() exists just for that purpose), but when
-+called by lookup_ctf_type(), this CTF ID is taken to be the single ID of the CTF
-+type that's just been assembled. Normally this is the same as the CTF ID
-+returned by the CTF assembly function for the top-level DWARF DIE, but there are
-+a few structures for which we want to return the result of some other CTF
-+assembly function.
-+
-+The only currently-existing example is array dimensions, which DWARF represents
-+as a typed array DIE whose child is a dimension, but which CTF represents as an
-+array-with-dimensions that you can't change afterwards. We can't assemble an
-+'array' at the top level because we don't know how big it is, but we have to
-+track the type recorded there somehow. We handle this by having
-+assemble_ctf_array(), the assembly function for the top-level DW_TAG_array_type
-+DIE, simply look up the type of the array's members and return its ID as if it
-+had just constructed it, after which assemble_ctf_array_dimension(), the
-+assembly function for DW_TAG_subrange_type, actually constructs the array,
-+wrapping it around the CTF 'ID' 'assembled' by the parent and setting the
-+override flag to make sure that this is what is really recorded.
-+
-+
-+CTF construction functions
-+--------------------------
-+
-+Each CTF construction function takes a single DWARF DIE and turns it into CTF,
-+somehow. They are laid out in the assembly table described in 'toplevel DWARF
-+walkers' above. They all start the same way, with a series of CTF_DW_ENFORCE or
-+CTF_DW_ENFORCE_NOT assertions. These guard against corrupted DWARF missing some
-+of the attributes we need, or DWARF containing attributes which indicate that we
-+can't handle the content (e.g. DW_AT_signature or DW_AT_specification on
-+structures, which would both indicate this is DWARF 4, which we can't handle
-+yet.)
-+
-+We'll go through these functions one by one, pointing out anything that
-+maintainers should be aware of.
-+
-+
-+assemble_ctf_base() assembles all integral base types (DW_TAG_base_type) and
-+transforms them into the corresponding CTF type. The functions we need to call
-+for this in the CTF API all have the same type signature but have different
-+names; CTF also distinguishes between the various differently-sized
-+floating-point types, so we must figure out from the type size which type a
-+given DWARF base type is referring to. We map from DWARF encoding to a triple
-+of (CTF addition function, CTF integral type, type size) where the latter is
-+optional and depends on the size of the DWARF type we are encoding and the size
-+of various floating_point types on the current system. (This does mean that
-+cross-compilation using dwarf2ctf is likely to fail fairly often: we need
-+machinery to determine the sizeof() types on the target system before that can
-+function.)
-+
-+This sizeof()-based search procedure is why we do not currently support
-+DW_AT_bit_size for base types: we could easily support it for sizes modulo 8,
-+but GCC happens to emit DW_AT_byte_size in this case. In C DW_AT_bit_size is
-+likely to be emitted only for bitfields in structures anyway, not for base
-+types.
-+
-+
-+assemble_ctf_pointer() and assemble_ctf_typedef() are trivial: look up the
-+associated type with lookup_ctf_type() and assemble the appropriate thing.
-+assemble_ctf_cvr_qual() is almost as trivial, but has to figure out which of
-+const, volatile or restrict it was called for and call the corresponding CTF API
-+function. assemble_ctf_enumeration() and assemble_ctf_enumerator() are quite
-+simple too.
-+
-+
-+assemble_ctf_variable() has a couple of extra complexities: we unconditionally
-+set the skip parameter to SKIP_SKIP, suppressing recursion into containing DIEs,
-+since we already know we won't care about any of them. Also, while the
-+deduplication pass unifies opaque and non-opaque structures into the same type,
-+it never makes sure that variables declared in the same header by translation
-+units which have opaque versus non-opaque structures in scope are deduplicated.
-+e.g. you could well end up with these two type IDs, depending on whether
-+<linux/pid_namespace.h> was included before <linux/pid.h> in a given translation
-+unit:
-+
-+////struct pid_namespace var init_pid_ns
-+/path/to/kernel/include/linux/pid_namespace.h//19//struct pid_namespace var init_pid_ns
-+
-+These variables both refer to the same type, but deduplicating them would
-+require an additional deduplication pass. Since variables are always terminal
-+and nothing can refer to them, nothing will ever look up any of those type IDs
-+(since the only thing that looks up type IDs is code that is searching for type
-+that other types depend on). So we don't care about this duplication and
-+running an additional deduplication pass to eliminate it would slow down
-+dwarf2ctf to no good end. It's better just to ignore duplicate errors from
-+ctf_add_variable().
-+
-+
-+assemble_ctf_array() and assemble_ctf_array_dimension() we talked about
-+above. One last subtlety remains, which is that figuring out the actual
-+dimensionality of an array is complicated enough that it has been hived off into
-+a private_subrange_dimension() function, called both from here and from
-+type_id(). Arrays with neither a DW_AT_upper_bound nor a DW_AT_count, and
-+arrays without an indexing type, are best considered flexible arrays; arrays
-+whose upper bound or count is not unsigned or signed integral data are also
-+flexible (perhaps they're using a full-blown location list, but we can't encode
-+that in CTF so we treat it as flexible); and if an upper bound is used, we want
-+to add one to its value before treating it as a count of elements.
-+
-+
-+This leaves structure/union assembly, both of which are assembled by the same
-+pair of functions, assemble_ctf_struct_union for the type itself and
-+assemble_ctf_su_member() for the individual members. As with
-+assemble_ctf_cvr_qual(), we have to look at the tag to figure out which CTF
-+function to use to do the assembly, but we have an extra constraint: it is
-+perfectly idiomatic C to declare a structure repeatedly with a different number
-+of members every time. This is perfectly permissible as long as the leading
-+portions of all declarations match. We do not verify this (we hope that the
-+compiler will diagnose it, which it will unless the conflicting declarations
-+cross modules), though perhaps we should: we simply look up the structure in the
-+CTF and the DWARF and skip assembly of the structure members via SKIP_SKIP if
-+the already-assembled structure has at least as many members as the current one.
-+
-+assemble_ctf_su_member() is by far the most complex of the assembly functions.
-+It has to handle members that already exist, members that need assembly, members
-+that correspond to unnamed structure members, numerous different ways of
-+representing structure offsets and members with no offset at all.
-+
-+The offset computation is quite laborious and by no means complete: a complete
-+implementation would require an interpreter for DWARF location lists, which is
-+total overkill given that in DWARF2 GCC emits a totally stereotyped location
-+list, and in DWARF3+ we don't need location list parsing at all. CTF wants an
-+offset in bits.
-+
-+We have five cases:
-+ - for DW_AT_data_bit_offset, we just use the offset unchanged.
-+
-+ - for DW_AT_data_member_location with an integral form (data2, data4, data8,
-+ udata, or sdata) we just look it up and multiply it by eight, adding the
-+ parent's DW_AT_bit_offset to handle structures nested inside other
-+ structures.
-+
-+ - for DW_AT_data_member_location with a block form, we make sure that the list
-+ is of one particular simple form (DW_OP_plus_uconst and a constant value in
-+ bytes), and abort assembly otherwise. The only case I know of where this
-+ test will trip is C++ virtual bases: if people are using C++ code with
-+ virtual bases inside the kernel they deserve sympathy, but probably not
-+ support in the code. CTF can't represent C++ types in any case.
-+
-+ - for expression location lists, or anything else that we don't understand, we
-+ simply die (we could simply skip the type, but this seems serious enough that
-+ dying is warranted).
-+
-+ - with none of these present, we have no offset: the member is at the same
-+ location as the start of the structure.
-+
-+But where is the 'start of the structure'? That depends on whether this is an
-+unnamed struct/union member (usually a union). If it is, we want to fold all
-+its members directly into the parent structure, with their offsets increased by
-+the offset of the unnamed member as a whole. This is done by directly calling
-+die_to_ctf() with the first child of the anonymous member's type and with all
-+other parameters set as if the parent DIE was the current structure, thus
-+fooling die_to_ctf() into believing that these members are members of the
-+current structure, not of the anonymous one. The offset-increasing magic is
-+done via the parent_bias parameter to die_to_ctf() and all the CTF construction
-+functions: it is ignored by all of them except for assemble_ctf_su_member()
-+itself, which adds the parent bias onto the normally-computed offset, and is
-+otherwise passed down unchanged to all children. This means that even this
-+terribly contrived case works:
-+
-+struct horror {
-+ int spacer;
-+ union {
-+ struct {
-+ int spacer;
-+ struct {
-+ int foo;
-+ int bar;
-+ } b;
-+ } a;
-+ };
-+};
-+
-+In this situation, horror.a.b.bar may have:
-+
-+ - a nonzero parent_bias due to the offset of the anonymous union in 'struct
-+ horror'
-+ - a nonzero offset due to the offset of 'bar' in its containing structure
-+ - if DW_AT_data_member_location with integral form is used, a nonzero
-+ DW_AT_bit_offset of 'b' in 'a'
-+
-+If this is not an anonymous union, we are dealing with only one member: we look
-+up its type and add it reasonably conventionally via ctf_add_member_offset().
-+Even here there are subtleties: we use construct_ctf_id() directly rather than
-+via lookup_ctf_type() so we can get a better error message on failure, and we
-+ignore any duplicate-member errors because this is probably a sign that this
-+structure has already been encountered and we are working through another
-+instance of it with more members.
-+
-+
-+Writeout
-+--------
-+
-+ write_types()
-+
-+This couldn't really be simpler, as the trivial call graph shows. We create an
-+output directory with the requested name, then work over the entire
-+module_to_ctf_file hash, writing out every CTF file into a new suitably-named
-+file via zlib's compressed file I/O functions.
-diff --git a/Documentation/kbuild/kconfig.rst b/Documentation/kbuild/kconfig.rst
-index dce6801d66c9b5e575ad9c4b4e8a557181bf7e8f..a9a855f894b3fad08f7ef89fff31fd7c626819eb 100644
---- a/Documentation/kbuild/kconfig.rst
-+++ b/Documentation/kbuild/kconfig.rst
-@@ -154,6 +154,11 @@ KCONFIG_AUTOCONFIG
- This environment variable can be set to specify the path & name of the
- "auto.conf" file. Its default value is "include/config/auto.conf".
-
-+KCONFIG_TRISTATE
-+----------------
-+This environment variable can be set to specify the path & name of the
-+"tristate.conf" file. Its default value is "include/config/tristate.conf".
-+
- KCONFIG_AUTOHEADER
- ------------------
- This environment variable can be set to specify the path & name of the
-diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst
-index dac17711dc1123c5996c5468086168a8c55f126a..1bce2aab4109241ecfd4fd48ca57506256dea101 100644
---- a/Documentation/process/changes.rst
-+++ b/Documentation/process/changes.rst
-@@ -56,9 +56,14 @@ iptables 1.4.2 iptables -V
- openssl & libcrypto 1.0.0 openssl version
- bc 1.06.95 bc --version
- Sphinx\ [#f1]_ 1.3 sphinx-build --version
-+elfutils\ [#f2]_ 0.156 eu-readelf --version
-+pkg-config\ [#f2]_ 0.16 pkg-config --version
-+glib\ [#f2]_ 2.x pkg-config --exists glib-2.0 && echo present
-+libdtrace-ctf\ [#f2]_ 1.1
- ====================== =============== ========================================
-
- .. [#f1] Sphinx is needed only to build the Kernel documentation
-+.. [#f2] This is needed at build-time when CTF or DTrace are enabled
-
- Kernel compilation
- ******************
-@@ -94,7 +99,8 @@ pkg-config
- The build system, as of 4.18, requires pkg-config to check for installed
- kconfig tools and to determine flags settings for use in
- 'make {g,x}config'. Previously pkg-config was being used but not
--verified or documented.
-+verified or documented. dwarf2ctf also relies on it during 'make ctf' and
-+while building out-of-tree modules with CONFIG_CTF enabled.
-
- Flex
- ----
-@@ -371,6 +377,21 @@ OpenSSL
-
- - <https://www.openssl.org/>
-
-+elfutils
-+--------
-+
-+- <https://fedorahosted.org/elfutils/>
-+
-+glib 2.x
-+--------
-+
-+- <http://www.gtk.org/>
-+
-+libdtrace-ctf
-+-------------
-+
-+- <https://oss.oracle.com/git/?p=libdtrace-ctf.git>
-+
- System utilities
- ****************
-
-diff --git a/Makefile b/Makefile
-index a6b2e64bcf6c786be1bb38ff9b593c7c3f838e0a..e94e5bfc9c4f5d9c64c08c83d877c2c9394bc2c7 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1166,7 +1166,7 @@ cmd_link-vmlinux = \
- $(CONFIG_SHELL) $< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)"; \
- $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
-
--vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE
-+vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) modules_thick.builtin FORCE
- +$(call if_changed,link-vmlinux)
-
- targets := vmlinux
-@@ -1406,6 +1406,45 @@ modules.order: $(subdir-modorder) FORCE
-
- targets += modules.order
-
-+ifneq (CONFIG_CTF@,'@')
-+
-+# We need to force everything to be built, since we need the .o files below.
-+KBUILD_BUILTIN := 1
-+
-+# This contains all the object files that are built directly into the
-+# kernel (including built-in modules), for consumption by dwarf2ctf in
-+# Makefile.modpost.
-+# This is made doubly annoying by the presence of '.o' files which are actually
-+# thin ar archives, and the need to support file(1) versions too old to
-+# recognize them as archives at all. (So we assume that everything that is not
-+# an ELF object is an archive.)
-+ifeq ($(SRCARCH),x86)
-+objects.builtin: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),bzImage) FORCE
-+else
-+objects.builtin: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) FORCE
-+endif
-+ @echo $(KBUILD_VMLINUX_OBJS) | \
-+ tr " " "\n" | grep "\.o$$" | xargs -r file | \
-+ grep ELF | cut -d: -f1 > objects.builtin
-+ @for archive in $$(echo $(KBUILD_VMLINUX_OBJS) |\
-+ tr " " "\n" | xargs -r file | grep -v ELF | cut -d: -f1); do \
-+ $(AR) t "$$archive" >> objects.builtin; \
-+ done
-+
-+ctf: vmlinux.ctfa
-+PHONY += ctf
-+
-+# Making CTF needs the builtin files unless out-of-tree.
-+ifeq ($(KBUILD_EXTMOD),)
-+vmlinux.ctfa: modules_thick.builtin objects.builtin
-+endif
-+vmlinux.ctfa:
-+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal vmlinux.ctfa
-+else
-+PHONY += objects.builtin
-+objects.builtin:
-+endif
-+
- # Target to prepare building external modules
- PHONY += modules_prepare
- modules_prepare: prepare
-@@ -1428,6 +1467,9 @@ _modinst_:
- @sed 's:^:kernel/:' modules.order > $(MODLIB)/modules.order
- @cp -f modules.builtin $(MODLIB)/
- @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/
-+ @if [ -f $(objtree)/vmlinux.ctfa ] ; then \
-+ cp -f $(objtree)/vmlinux.ctfa $(MODLIB)/kernel ; \
-+ fi
- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
-
- # This depmod is only for convenience to give the initial
-@@ -1459,6 +1501,23 @@ modules modules_install:
-
- endif # CONFIG_MODULES
-
-+# modules_thick.builtin maps from kernel modules (or rather the object file
-+# names they would have had had they not been built in) to their constituent
-+# object files: dwarf2ctf uses this to determine which modules any given object
-+# file is part of. (We cannot eliminate the slight redundancy here without
-+# double-expansion.)
-+
-+modthickbuiltin-dirs := $(addprefix _modthickbuiltin_, $(build-dirs))
-+
-+modules_thick.builtin: $(modthickbuiltin-dirs)
-+ $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(build-dirs)) > $@
-+
-+PHONY += $(modthickbuiltin-dirs)
-+# tristate.conf is not included from this Makefile. Add it as a prerequisite
-+# here to make it self-healing in case somebody accidentally removes it.
-+$(modthickbuiltin-dirs): include/config/tristate.conf
-+ $(Q)$(MAKE) $(modbuiltin)=$(patsubst _modthickbuiltin_%,%,$@) builtin-file=modules_thick.builtin
-+
- ###
- # Cleaning is done on three levels.
- # make clean Delete most generated files
-@@ -1467,9 +1526,10 @@ endif # CONFIG_MODULES
- # make distclean Remove editor backup files, patch leftover files and the like
-
- # Directories & files removed with 'make clean'
--CLEAN_FILES += include/ksym vmlinux.symvers \
-- modules.builtin modules.builtin.modinfo modules.nsdeps \
-- compile_commands.json
-+CLEAN_FILES += include/ksym .ctf vmlinux.symvers \
-+ modules.builtin modules.builtin.modinfo objects.builtin \
-+ modules.nsdeps compile_commands.json \
-+ .ctf.filelist .ctf.filelist.raw
-
- # Directories & files removed with 'make mrproper'
- MRPROPER_FILES += include/config include/generated \
-@@ -1564,6 +1624,8 @@ help:
- @echo ' (requires a recent binutils and recent build (System.map))'
- @echo ' dir/file.ko - Build module including final link'
- @echo ' modules_prepare - Set up for building external modules'
-+ @echo ' ctf - Generate CTF type information for DTrace, installed by '
-+ @echo ' make modules_install'
- @echo ' tags/TAGS - Generate tags file for editors'
- @echo ' cscope - Generate cscope index'
- @echo ' gtags - Generate GNU GLOBAL index'
-@@ -1825,7 +1887,7 @@ clean: $(clean-dirs)
- -o -name '*.symtypes' -o -name 'modules.order' \
- -o -name '.tmp_*.o.*' \
- -o -name '*.c.[012]*.*' \
-- -o -name '*.ll' \
-+ -o -name '*.ll' -o -name '*.ctfa' \
- -o -name '*.gcno' \) -type f -print | xargs rm -f
-
- # Generate tags for editors
-diff --git a/lib/Kconfig b/lib/Kconfig
-index b46a9fd122c81acabd888e8b250e78be4f575ef6..e2906daac926dc0b9f5342b37d521670015d7841 100644
---- a/lib/Kconfig
-+++ b/lib/Kconfig
-@@ -582,6 +582,18 @@ config DIMLIB
- #
- config LIBFDT
- bool
-+#
-+# CTF support is select'ed if needed
-+#
-+config CTF
-+ bool "Compact Type Format generation"
-+ default n
-+ select STRIP_ASM_SYMS
-+ depends on DEBUG_INFO && !DEBUG_INFO_REDUCED && !DEBUG_INFO_SPLIT && !DEBUG_INFO_DWARF4 && DTRACE
-+ help
-+ Emit a compact, compressed description of the kernel's datatypes and
-+ global variables into the vmlinux.ctfa archive (for in-tree modules)
-+ or into .ctf sections in kernel modules (for out-of-tree modules).
-
- config OID_REGISTRY
- tristate
-diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
-index 08e011175b4c879852a2cc203ea0b2ccf4ce8cfc..d3c6f0f56e6538b4383dea122f4f3ab687f5938b 100644
---- a/scripts/Kbuild.include
-+++ b/scripts/Kbuild.include
-@@ -157,6 +157,12 @@ ld-ifversion = $(shell [ $(ld-version) $(1) $(2) ] && echo $(3) || echo $(4))
- # $(Q)$(MAKE) $(build)=dir
- build := -f $(srctree)/scripts/Makefile.build obj
-
-+###
-+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj=
-+# Usage:
-+# $(Q)$(MAKE) $(modbuiltin)=dir
-+modbuiltin := -f $(srctree)/scripts/Makefile.modbuiltin obj
-+
- ###
- # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj=
- # Usage:
-diff --git a/scripts/Makefile b/scripts/Makefile
-index b5418ec587fbd2cd6ca6896b8868b93f12e59ef3..041bcf48cc5c7613d072cf50eae142a21d31153e 100644
---- a/scripts/Makefile
-+++ b/scripts/Makefile
-@@ -34,6 +34,7 @@ targets += module.lds
-
- subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
- subdir-$(CONFIG_MODVERSIONS) += genksyms
-+subdir-$(CONFIG_CTF) += dwarf2ctf
- subdir-$(CONFIG_SECURITY_SELINUX) += selinux
-
- # Let clean descend into subdirs
-diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin
-new file mode 100644
-index 0000000000000000000000000000000000000000..f2c085e8640fbe9d245fb91713c31379f10bcb59
---- /dev/null
-+++ b/scripts/Makefile.modbuiltin
-@@ -0,0 +1,60 @@
-+# SPDX-License-Identifier: GPL-2.0
-+# ==========================================================================
-+# Generating modules_thick.builtin
-+# ==========================================================================
-+
-+src := $(obj)
-+
-+PHONY := __modbuiltin
-+__modbuiltin:
-+
-+include include/config/auto.conf
-+# tristate.conf sets tristate variables to uppercase 'Y' or 'M'
-+# That way, we get the list of built-in modules in obj-Y
-+include include/config/tristate.conf
-+
-+include scripts/Kbuild.include
-+
-+ifdef building_out_of_srctree
-+# Create output directory if not already present
-+_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
-+endif
-+
-+# The filename Kbuild has precedence over Makefile
-+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
-+kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
-+include $(kbuild-file)
-+
-+include scripts/Makefile.lib
-+__subdir-Y := $(patsubst %/,%,$(filter %/, $(obj-Y)))
-+subdir-Y += $(__subdir-Y)
-+subdir-ym := $(sort $(subdir-y) $(subdir-Y) $(subdir-m))
-+subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
-+pathobj-Y := $(addprefix $(obj)/,$(obj-Y))
-+
-+modthickbuiltin-subdirs := $(patsubst %,%/modules_thick.builtin, $(subdir-ym))
-+modthickbuiltin-target := $(obj)/modules_thick.builtin
-+
-+__modbuiltin: $(obj)/$(builtin-file) $(subdir-ym)
-+ @:
-+
-+$(modthickbuiltin-target): $(subdir-ym) FORCE
-+ $(Q) $(foreach mod-o, $(filter %.o,$(obj-Y)),\
-+ printf "%s:" $(addprefix $(obj)/,$(mod-o)) >> $@; \
-+ printf " %s" $(sort $(strip $(addprefix $(obj)/,$($(mod-o:.o=-objs)) \
-+ $($(mod-o:.o=-y)) $($(mod-o:.o=-Y))))) >> $@; \
-+ printf "\n" >> $@; ) \
-+ cat /dev/null $(modthickbuiltin-subdirs) >> $@;
-+
-+PHONY += FORCE
-+
-+FORCE:
-+
-+# Descending
-+# ---------------------------------------------------------------------------
-+
-+PHONY += $(subdir-ym)
-+$(subdir-ym):
-+ $(Q)$(MAKE) $(modbuiltin)=$@ builtin-file=$(builtin-file)
-+
-+.PHONY: $(PHONY)
-diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
-index ae01baf96f4e8038583d994df2348a0b53b8a565..920545d75da9b3248ef47ff1cdc81c981d3637ba 100644
---- a/scripts/Makefile.modfinal
-+++ b/scripts/Makefile.modfinal
-@@ -1,11 +1,21 @@
- # SPDX-License-Identifier: GPL-2.0-only
- # ===========================================================================
--# Module final link
-+# Module final link and CTF generation
- # ===========================================================================
-+# 1) compile all <module>.mod.c files
-+# 2) for external modules, generate CTF for the module (there is an extra,
-+# externally-invoked target that does this for the entire kernel but does
-+# not invoke the rst of the module-building process)
-+# 3) final link of the module to a <module.ko> file
-+
-+# We need secondary expansion for 'module-ctfs-modular-prereq', below.
-+
-+.SECONDEXPANSION:
-
- PHONY := __modfinal
- __modfinal:
-
-+include include/config/auto.conf
- include $(srctree)/scripts/Kbuild.include
-
- # for c_flags
-@@ -27,16 +37,141 @@ quiet_cmd_cc_o_c = CC [M] $@
- %.mod.o: %.mod.c FORCE
- $(call if_changed_dep,cc_o_c)
-
-+# Generate CTF for the entire kernel, or for the module alone if this is a
-+# build of an external module.
-+
-+# These are overridden below for standalone modules only.
-+module-ctfs-modular-prereq =
-+module-ctfs-modular =
-+module-ctf-flags =
-+cmd_touch_ctf =
-+ctf-dir = ///.nonexistent
-+cmd-touch-ctf = @:
-+
-+ifdef CONFIG_CTF
-+
-+# This is quite tricky. If called for non-external-modules, dwarf2ctf needs to
-+# be told about all the built-in objects as well as all the external modules --
-+# but Makefile.modpost only knows about the latter. So the toplevel makefile
-+# emits the names of the built-in objects into a temporary file, which is
-+# then catted and its contents used as prerequisites by this rule.
-+#
-+# We write the names of the object files to be scanned for CTF content into a
-+# file, then use that, to avoid hitting command-line length limits.
-+
-+ifeq ($(KBUILD_EXTMOD),)
-+ctf-dir-mk :=
-+quiet_cmd_ctf = CTFA
-+ cmd_ctf = scripts/dwarf2ctf/dwarf2ctf vmlinux.ctfa $(srctree) objects.builtin modules_thick.builtin $(srctree)/scripts/dwarf2ctf/member.blacklist $(ctf-filelist)
-+ctf-builtins := objects.builtin
-+ctf-builtins-prereq := $(ctf-builtins)
-+ ctf-modules := $(shell find . -name '*.ko' -print)
-+ctf-filelist := .ctf.filelist
-+ctf-filelist-raw := .ctf.filelist.raw
-+ctf-stamp :=
-+
-+else
-+ctf-dir := $(KBUILD_EXTMOD)/.ctf
-+ctf-dir-mk := $(ctf-dir)
-+quiet_cmd_ctf = CTF
-+ cmd_ctf = scripts/dwarf2ctf/dwarf2ctf $(ctf-dir) -e $(ctf-filelist)
-+ctf-builtins := ////.no-builtins
-+ctf-builtins-prereq :=
-+ctf-modules := $(modules:.ko=.o)
-+ctf-filelist := $(ctf-dir)/$(notdir $(M)-extmod).ctf.filelist
-+ctf-filelist-raw := $(ctf-dir)/$(notdir $(M)-extmod).ctf.filelist.raw
-+ctf-stamp = $(ctf-dir)/$(notdir $(M)-extmod).stamp
-+
-+# All the modules' CTF depends on the stamp file.
-+
-+all-module-ctfs = $(addprefix $(ctf-dir)/,$(notdir $(modules:.ko=.mod.ctf)))
-+$(all-module-ctfs): $(ctf-stamp)
-+
-+endif
-+
-+# Split a list up like shell xargs does.
-+define xargs =
-+$(1) $(wordlist 1,1024,$(2))
-+$(if $(word 1025,$(2)),$(call xargs,$(1),$(wordlist 1025,$(words $(2)),$(2))))
-+endef
-+
-+$(ctf-filelist-raw): $(ctf-builtins-prereq) $(ctf-modules)
-+ @rm -f $(ctf-filelist-raw);
-+ @if [ -n "$(ctf-dir-mk)" ]; then \
-+ mkdir -p "$(ctf-dir-mk)"; \
-+ fi
-+ $(call xargs,@printf "%s\n" >> $(ctf-filelist-raw),$^)
-+ @touch $(ctf-filelist-raw)
-+
-+$(ctf-filelist): $(ctf-filelist-raw)
-+ @rm -f $(ctf-filelist);
-+ @cat $(ctf-filelist-raw) | while read -r obj; do \
-+ case $$obj in \
-+ $(ctf-builtins)) cat $$obj >> $(ctf-filelist);; \
-+ *.a) ar t $$obj > $(ctf-filelist);; \
-+ *.builtin) cat $$obj >> $(ctf-filelist);; \
-+ *) echo "$$obj" >> $(ctf-filelist);; \
-+ esac; \
-+ done
-+ @touch $(ctf-filelist)
-+
-+ifeq ($(KBUILD_EXTMOD),)
-+# The CTF depends on the output CTF file list, and that depends
-+# on the .ko files for the modules.
-+vmlinux.ctfa: $(ctf-filelist)
-+ $(call if_changed,ctf)
-+else
-+
-+# The CTF depends on the output CTF file list, and that depends
-+# on the .o files for the modules
-+$(ctf-stamp): $(ctf-filelist)
-+ $(call if_changed,ctf)
-+ @shopt -s nullglob; \
-+ for name in $(ctf-dir)/*.ctf.new; do \
-+ $(srctree)/scripts/move-if-change $$name $${name%.new}; \
-+ done; \
-+ touch $(ctf-stamp)
-+
-+# Expands to the names of the CTF files to be incorporated into this module.
-+# The former is used in prerequisite lists, thanks to secondary expansion.
-+
-+module-ctfs-modular-prereq = $$(addprefix $(ctf-dir)/,$$(notdir $$*.mod.ctf))
-+module-ctfs-modular = $(addprefix $(ctf-dir)/,$(notdir $*.mod.ctf))
-+
-+# Expands to the name of a CTF file, given a target of a module name given to
-+# one of the link rules below.
-+
-+ctf-module-name = $(addprefix $(ctf-dir)/,$(notdir $(basename $@)).mod.ctf)
-+
-+# An objcopy --add-section argument to add the CTF section to a standalone
-+# module.
-+
-+module-ctf-flags = --add-section .ctf=$(ctf-module-name)
-+
-+# We have to put content in our dummy no-CTF files because --add-section
-+# in binutils 2.20 silently fails if asked to add an empty file as a section.
-+
-+cmd_touch_ctf = @for name in $(filter $(ctf-dir)/%,$(module-ctfs-modular)); do \
-+ test -f $$name || dd if=/dev/zero of=$$name bs=1 count=1 2>/dev/null; \
-+ done
-+
-+endif # KBUILD_EXTMOD
-+
-+endif # !CONFIG_CTF
-+
- ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
-
- quiet_cmd_ld_ko_o = LD [M] $@
- cmd_ld_ko_o = \
- $(LD) -r $(KBUILD_LDFLAGS) \
- $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
-- -T scripts/module.lds -o $@ $(filter %.o, $^); \
-+ -T scripts/module.lds $(LDFLAGS_$(modname)) -o $@.tmp \
-+ $(patsubst $(ctf-dir)/%,,$(filter %.o, $^)) && \
-+ $(OBJCOPY) $(module-ctf-flags) $@.tmp $@ && rm -f $@.tmp ; \
- $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
-
--$(modules): %.ko: %.o %.mod.o scripts/module.lds FORCE
-+$(modules): %.ko: %.o %.mod.o scripts/module.lds $(module-ctfs-modular-prereq) FORCE
-+ $(call cmd_touch_ctf)
- +$(call if_changed,ld_ko_o)
-
- targets += $(modules) $(modules:.ko=.mod.o)
-diff --git a/scripts/dwarf2ctf/.gitignore b/scripts/dwarf2ctf/.gitignore
-new file mode 100644
-index 0000000000000000000000000000000000000000..e37b47cf30280844fdb1c4bcfa512fa854f3636c
---- /dev/null
-+++ b/scripts/dwarf2ctf/.gitignore
-@@ -0,0 +1 @@
-+dwarf2ctf
-diff --git a/scripts/dwarf2ctf/Makefile b/scripts/dwarf2ctf/Makefile
-new file mode 100644
-index 0000000000000000000000000000000000000000..2b40419add316fd20f7171b4b9415ca8550cd50a
---- /dev/null
-+++ b/scripts/dwarf2ctf/Makefile
-@@ -0,0 +1,10 @@
-+ifdef CONFIG_CTF
-+hostprogs-always-$(CONFIG_CTF) := dwarf2ctf
-+
-+dwarf2ctf-objs := dwarf2ctf.o eu_simple.o
-+
-+HOSTCFLAGS_eu_simple.o := -I$(srctree)/scripts
-+HOSTCFLAGS_dwarf2ctf.o := $(shell pkg-config --cflags glib-2.0) -I$(srctree)/scripts
-+
-+HOSTLDLIBS_dwarf2ctf := -ldtrace-ctf -lelf -ldw $(shell pkg-config --libs glib-2.0) -lz
-+endif
-diff --git a/scripts/dwarf2ctf/dwarf2ctf.c b/scripts/dwarf2ctf/dwarf2ctf.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..ecd430174442c7882236de086d5d9160ac1974e9
---- /dev/null
-+++ b/scripts/dwarf2ctf/dwarf2ctf.c
-@@ -0,0 +1,4962 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * dwarf2ctf.c: Read in DWARF[23] debugging information from some set of ELF
-+ * files, and generate CTF in correspondingly-named files, or in a single
-+ * representation meant for mmapping.
-+ *
-+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#define _GNU_SOURCE 1
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <stddef.h>
-+#include <sys/stat.h>
-+#include <sys/types.h>
-+#include <fcntl.h>
-+#include <limits.h>
-+#include <endian.h>
-+#include <unistd.h>
-+
-+#include <libelf.h>
-+#include <dwarf.h>
-+#include <elfutils/libdwfl.h>
-+#include <elfutils/libdw.h>
-+#include <elfutils/version.h>
-+#include <sys/ctf_api.h>
-+#include <glib.h>
-+
-+#include <eu_simple.h>
-+
-+#ifndef PATH_MAX
-+#define PATH_MAX 1024
-+#endif
-+
-+#define __unused__ __attribute__((__unused__))
-+
-+/*
-+ * If non-NULL, tracing is on.
-+ */
-+static const char *trace;
-+
-+/*
-+ * Trace something.
-+ */
-+#ifdef DEBUG
-+#define dw_ctf_trace(format, ...) do { \
-+ if (trace) \
-+ fprintf(stderr, (format), ## __VA_ARGS__); \
-+} while (0)
-+#else
-+#define dw_ctf_trace(format, ...)
-+#endif
-+
-+/*
-+ * Run dwarf2ctf over a single object file or set thereof.
-+ *
-+ * output_dir is the directory into which the CTF goes, if 'standalone', or the
-+ * CTF archive file name otherwise.
-+ */
-+static void run(char *output, int standalone);
-+
-+/*
-+ * Whether we are deduplicating. We do not deduplicate if run over external
-+ * modules.
-+ */
-+static int deduplicating;
-+
-+/*
-+ * A fully descriptive CTF type ID: both file and type ID in one place.
-+ */
-+struct ctf_full_id {
-+ ctf_file_t *ctf_file;
-+ ctf_id_t ctf_id;
-+#ifdef DEBUG
-+ char module_name[PATH_MAX];
-+ char file_name[PATH_MAX];
-+#endif
-+};
-+
-+/*
-+ * A hash mapping 'atoms' (almost entirely type IDs) to nothing.
-+ */
-+static GHashTable *atoms;
-+
-+/*
-+ * A mapping from the type ID of a DIE (see type_id()) to ctf_full_id_t's
-+ * describing the type with that ID. The type ID is an atom.
-+ *
-+ * This is used to look up types regardless of which CTF file they may reside
-+ * in. Not the same as a DWARF4 type signature because we must encode scope
-+ * information which DWARF4 can encode in its DIE refs.
-+ *
-+ * (TODO: store a hash of the ID rather than the ID itself, to save memory.
-+ * Makes debugging slightly harder though.)
-+ */
-+static GHashTable *id_to_type;
-+
-+/*
-+ * A mapping from the type ID of a DIE (an atom) to the name of the module (and
-+ * thus CTF table) incorporating that type. (Modules in this context, and
-+ * throughout dwarf2ctf, are DTrace modules: a name without suffix or path.)
-+ *
-+ * This is used to merge types identical across modules (e.g. those in global
-+ * header files).
-+ */
-+static GHashTable *id_to_module;
-+
-+/*
-+ * Module-specific state. The module named 'vmlinux' is that corresponding to
-+ * the types in always-built-in translation units; the module named 'shared_ctf'
-+ * (not appearing in this mapping) is that corresponding to types shared between
-+ * more than one module (even between two currently-built-in modules: we do not
-+ * distinguish at this level between built-in modules and non-built-in modules.)
-+ */
-+static GHashTable *per_module;
-+
-+/*
-+ * The data structure that per_module maps module names to.
-+ */
-+struct per_module {
-+ /*
-+ * The CTF file containing the types in this module.
-+ */
-+ ctf_file_t *ctf_file;
-+
-+ /*
-+ * A hash from a "CTF-form" structure name (in the form 's/u NAME') to
-+ * a struct ctf_memb_count (see below).
-+ */
-+ GHashTable *member_counts;
-+};
-+
-+/*
-+ * A count associating a type ID relating to a structure or union with a count
-+ * of members in that structure.
-+ */
-+struct ctf_memb_count {
-+ ctf_id_t ctf_id;
-+ size_t count;
-+};
-+
-+/*
-+ * A mapping from the absolute pathname of a TU to a hashtable mapping
-+ * DIE offsets of child DIEs to DIE offsets of parents. Populated on first
-+ * iteration. Contains only those DIEs that we know are necessary for other
-+ * functions' use of this structure, to keep memory usage down.
-+ */
-+static GHashTable *fn_to_die_to_parent;
-+
-+/*
-+ * Get a ctf_file out of the per_module hash for a given module.
-+ */
-+static ctf_file_t *lookup_ctf_file(const char *module_name);
-+
-+/*
-+ * The names of the object files to run over. Except in -e mode, this comes
-+ * straight from the module filelist passed in.
-+ */
-+static char **object_names;
-+static size_t object_names_cnt;
-+
-+/*
-+ * Populate the object_names list from the module filelist.
-+ */
-+static void init_object_names(const char *object_names_file);
-+
-+/*
-+ * Populate and object_to_module from the objects.builtin and modules.builtin
-+ * file.
-+ */
-+static void init_builtin(const char *builtin_objects_file,
-+ const char *builtin_module_file);
-+
-+/*
-+ * The member blacklist bans fields with specific names in specifically named
-+ * structures, declared in specific source files, from being emitted. The
-+ * mapping is from absolute source file name:structure.member to NULL (this is
-+ * safe because type names cannot contain a colon, and structure names cannot
-+ * contain a period).
-+ */
-+static GHashTable *member_blacklist;
-+
-+/*
-+ * Populate the member blacklist from the member_blacklist file.
-+ */
-+static void init_member_blacklist(const char *member_blacklist_file,
-+ const char *srcdir);
-+
-+/*
-+ * Return 1 if a given DWARF DIE, which must be a DW_TAG_member, appears in the
-+ * member blacklist.
-+ */
-+static int member_blacklisted(Dwarf_Die *die, Dwarf_Die *parent_die);
-+
-+/*
-+ * The variable blacklist, like the others, is an automatically-maintained
-+ * blacklist giving variables in specific modules which should not be emitted.
-+ * (These are variables whose names are ambiguous within a module, and may
-+ * appear multiple times in /proc/kallmodsyms, identical but for address and
-+ * thus indistinguishable.)
-+ *
-+ * The mapping is from module`variable to NULL (safe because variable names
-+ * cannot begin with a backtick, and even if they could DTrace's notation could
-+ * not reference such variables).
-+ */
-+static GHashTable *variable_blacklist;
-+
-+/*
-+ * A mapping from object file name to the name of the module that translation
-+ * unit is part of.
-+ *
-+ * Actual, real, on-disk .ko modules do not appear here, because the translation
-+ * is trivial for them.
-+ */
-+static GHashTable *object_to_module;
-+
-+/*
-+ * Initialize a CTF type table, and possibly fill it with those special types
-+ * that appear in CTF but not in DWARF (such as 'void'). (This filling happens
-+ * only for the type table named "shared_ctf", unless deduplication is turned
-+ * off.)
-+ *
-+ * If this is a local type table, and deduplication is active, make the global
-+ * type table its parent.
-+ */
-+static void init_ctf_table(const char *module_name);
-+
-+/*
-+ * A few useful singleton CTF type IDs in the global type table: a void pointer
-+ * and a function pointer. Constructed by init_ctf_table().
-+ */
-+static ctf_id_t ctf_void_type;
-+static ctf_id_t ctf_funcptr_type;
-+
-+/*
-+ * Initialize the child->parent DIE mapping for a single file.
-+ */
-+static void init_parent_die(const char *file_name, Dwfl *dwfl);
-+
-+/*
-+ * Initialize one layer of a child->parent mapping.
-+ */
-+static int init_parent_die_internal(const char *file_name,
-+ GHashTable *offs, Dwarf_Die *parent,
-+ int depth, int found_subprogram);
-+
-+/*
-+ * Override the presence and value of FORM_u/sdata attributes on DWARF DIEs,
-+ * either adding to it, or replacing it.
-+ *
-+ * (Used so that a caller of construct_ctf_id() that wants a type to be created
-+ * can override aspects of that type.)
-+ *
-+ * The 'chain', if set, causes the various private_*() functions that handle
-+ * overrides to look back along the chain to find a suitable attribute. The
-+ * chain must be set on the last element in the array. The search for
-+ * attributes terminates at the first match.
-+ *
-+ * Note: this is not a particularly generic implementation: a better approach
-+ * would be to keep walking the chain on DIE_OVERRIDE_ADD, and keep adding until
-+ * we are done: but we have only one user of ADD, and it implements the addition
-+ * itself because it is adding to a value from a different DIE: so this added
-+ * generality is not needed yet.
-+ */
-+struct die_override {
-+ int tag;
-+ int attribute;
-+ enum { DIE_OVERRIDE_REPLACE, DIE_OVERRIDE_ADD } op;
-+ Dwarf_Sword value;
-+ struct die_override *chain;
-+};
-+
-+/*
-+ * Compute the type ID of a DWARF DIE (with possibly-overridden attributes) and
-+ * return it in a new dynamically-allocated string.
-+ *
-+ * Optionally, call a callback with the computed ID once we know it (this is a
-+ * recursive process, so the callback can be called multiple times as the ID
-+ * is built up).
-+ *
-+ * An ID of NULL indicates that this DIE has no ID and need not be considered.
-+ */
-+static char *type_id(Dwarf_Die *die, struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data) __attribute__((__warn_unused_result__));
-+
-+/*
-+ * Internal: allows flags to be passed to affect one (and only one) type ID
-+ * recursion, without affecting other type_id()s launched from the 'fun'.
-+ */
-+static char *type_id_internal(Dwarf_Die *die,
-+ struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data,
-+ int flags);
-+
-+/*
-+ * Internal: generate the type ID for a type DIE.
-+ *
-+ * If there are no overrides, look for a bit_size and bit_offset and pass them
-+ * down as well.
-+ */
-+static char *type_id_type_die(Dwarf_Die *die,
-+ Dwarf_Die *type_die,
-+ struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data);
-+
-+/*
-+ * Convert 'long unsigned int' to 'sizetype'. Internal use within type_id().
-+ */
-+#define TI_COLLAPSE_SIZETYPE 0x1
-+
-+/*
-+ * Process a file, calling the dwarf_process function for every type found
-+ * therein (even types in functions). Optionally call tu_init() at the start of
-+ * each translation unit, and tu_done() at the end.
-+ */
-+static void process_file(const char *file_name,
-+ void (*dwarf_process)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ void *data),
-+ void (*tu_init)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *tu_die,
-+ void *data),
-+ void (*tu_done)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *tu_die,
-+ void *data),
-+ void *data);
-+
-+/*
-+ * process_file() helper, walking over the top level and picking up types
-+ * therein.
-+ */
-+static void process_tu_func(const char *module_name,
-+ const char *file_name,
-+ Dwarf *dwarf,
-+ Dwarf_Die *parent_die,
-+ Dwarf_Die *die,
-+ void (*dwarf_process)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ void *data),
-+ void *data);
-+
-+/*
-+ * Records the type ID of interesting types, the files they are contained in,
-+ * and their DWARF offset, so they can be found rapidly.
-+ *
-+ * Used to avoid rescanning files that can contain no duplicates.
-+ */
-+struct dedup_id_file {
-+ char *file_name;
-+ char *id;
-+ Dwarf_Off dieoff;
-+};
-+
-+/*
-+ * The structure used as the data argument for dedup() and
-+ * dedup_alias_fixup().
-+ *
-+ * structs_seen tracks the IDs of structures marked as duplicates within a given
-+ * translation unit, in order that recursion terminates if two such structures
-+ * have pointers to each other.
-+ *
-+ * vars_seen tracks variables seen in this module, mapping from unadorned name
-+ * to a non-NULL pointer (for static, non-'external') or NULL (for non-static or
-+ * 'extern'). If a static variable coexists with any other variable with the
-+ * same name, static or not, the variable is blacklisted. (Non-static
-+ * coexistence is fine, because they are just different references to the same
-+ * variable). Note that management of this variable is a little annoying
-+ * because it varies by module, not by TU, so we can't use tu_init/tu_done to
-+ * manage its lifetime.
-+ *
-+ * named_structs tracks type IDs and contained modules for every type that may
-+ * contain undetected duplicates and thus may require rescanning.
-+ *
-+ * dwfl and dwfl_file_name identify the opened DWARF file (if any) during the
-+ * second duplicates detection pass.
-+ *
-+ * repeat_detection is set by each phase if it considers that another round of
-+ * alias fixup detection is needed.
-+ */
-+struct dedup_state {
-+ const char *file_name;
-+ const char *module_name;
-+ GHashTable *structs_seen;
-+ GList *named_structs;
-+ GHashTable *vars_seen;
-+ char *dwfl_file_name;
-+ Dwarf *dwarf;
-+ Dwfl *dwfl;
-+ int repeat_detection;
-+};
-+
-+/*
-+ * Scan and identify duplicates across the entire set of object files.
-+ */
-+static void scan_dups(void);
-+
-+/*
-+ * Recursively detect duplicate types and types referenced by them, and
-+ * determine which CTF file they should be located in, and request a
-+ * dedup_alias_fixup() pass if any structures are shared.
-+ * Determine the mapping from translation unit name to module name.
-+ */
-+static void dedup(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die, void *data);
-+
-+/*
-+ * Do the underlying marking of a DIE as shared, iff need be. (No variable
-+ * blacklisting, non-opaque structure checks, or anything else needed only by
-+ * top-level DIEs.)
-+ *
-+ * This function may be called multiple times for overridden DIEs that are
-+ * dependent types of bitfields.
-+ */
-+static void dedup_mark_inner_die(const char *module_name, Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data);
-+
-+/*
-+ * Note in the dedup_id_file list that we will rescan a DIE in a later duplicate
-+ * detection pass.
-+ *
-+ * A type_id() callback.
-+ */
-+static void dedup_will_rescan(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data);
-+
-+/*
-+ * Note the variable referenced by this DIE in vars_seen: blacklist it if an
-+ * entry for this variable already exists in vars_seen and this instance is
-+ * static, or if a static entry already exists in vars_seen, whether this
-+ * instance is static or not.
-+ */
-+static void dedup_blacklist_var_dups(Dwarf_Die *die,
-+ struct dedup_state *state);
-+
-+/*
-+ * Detect duplicates and mark seen types for a given type, via a type_id()
-+ * callback: used to detect dependent types (particularly those at child-DIE
-+ * level) as duplicates.
-+ */
-+static void dedup_typeid(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data);
-+
-+/*
-+ * Mark any aggregates contained within a particular type DIE as seen. This is
-+ * needed since even nameless aggregates contained within other aggregates can
-+ * be used as the type of members of the outer aggregate (though they cannot
-+ * possibly be found in a module different from that of their containing
-+ * aggregate, any more than a structure member can).
-+ */
-+static void mark_seen_contained(Dwarf_Die *die, const char *module_name,
-+ struct die_override *overrides, void *data);
-+
-+/*
-+ * Determine if some type (whose ultimate base type is an non-opaque structure,
-+ * alias, or enum) has an opaque equivalent which is shared, and mark it and
-+ * all its bases as shared too if so.
-+ *
-+ * A list_filter() filter function.
-+ */
-+static int dedup_alias_fixup(void *id_file_data, void *data);
-+
-+/*
-+ * Mark a basic type shared by name and intern it in all relevant hashes. (Used
-+ * for marking basic types we don't have a DIE for.)
-+ */
-+static void mark_shared_by_name(ctf_file_t *ctf, ctf_id_t ctf_id,
-+ const char *name);
-+
-+/*
-+ * Determine if a type is a named struct, union, or enum.
-+ *
-+ * A type_id() callback.
-+ */
-+static void is_named_struct_union_enum(Dwarf_Die *die, const char *unused,
-+ struct die_override *overrides,
-+ void *data);
-+
-+/*
-+ * Set up state for dedup(). A tu_init() callback.
-+ */
-+static void dedup_tu_init(const char *module_name, const char *file_name,
-+ Dwarf_Die *tu_die, void *data);
-+
-+/*
-+ * Free state for dedup(). A tu_done() callback.
-+ */
-+static void dedup_tu_done(const char *module_name, const char *file_name,
-+ Dwarf_Die *tu_die, void *data);
-+
-+/*
-+ * Free DWARF state for dedup().
-+ */
-+static void dedup_dwarf_free(struct dedup_state *state);
-+
-+/*
-+ * Determine if a type is duplicated and needs sharing.
-+ */
-+enum needs_sharing { NS_NOT_SHARED, NS_NO_MARKING, NS_NEEDS_SHARING };
-+static enum needs_sharing type_needs_sharing(const char *module_name,
-+ const char *id);
-+
-+/*
-+ * Mark a type (optionally, with an already-known ID) as duplicated and located
-+ * in the shared CTF table.
-+ *
-+ * A type_id() callback (though also called directly).
-+ */
-+static void mark_shared(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data);
-+
-+/*
-+ * Construct CTF out of each type.
-+ */
-+static void construct_ctf(const char *module_name, const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ void *unused __unused__);
-+
-+/*
-+ * Write out the CTF files from the per_module->ctf_file into files in the
-+ * output directory (if standalone), or into the output file (otherwise).
-+ */
-+static void write_types(char *output, int standalone);
-+
-+/*
-+ * Construct CTF out of each type and return that type's ID and file.
-+ */
-+static struct ctf_full_id *construct_ctf_id(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ struct die_override *overrides);
-+
-+/*
-+ * Things to do after a CTF recursion step.
-+ */
-+enum skip_type { SKIP_CONTINUE = 0, SKIP_SKIP, SKIP_ABORT };
-+
-+/*
-+ * Recursive over a given DWARF DIE and its children andconstruct CTF out of it.
-+ *
-+ * Most parameters are shared with the ctf_assembly_fun: see the comment below.
-+ */
-+static ctf_id_t die_to_ctf(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die,
-+ ctf_file_t *ctf, ctf_id_t parent_ctf_id,
-+ struct die_override *overrides, int top_level_type,
-+ int backwards, enum skip_type *skip, int *replace,
-+ const char *id);
-+
-+/*
-+ * Return the next DIE, if that DIE needs to be emitted before this one.
-+ */
-+static Dwarf_Die *die_emit_next_backwards(Dwarf_Die *next, Dwarf_Die *die,
-+ struct die_override *overrides);
-+
-+/*
-+ * Look up a type through its reference: return its ctf_id_t, or
-+ * recursively construct it if need be.
-+ *
-+ * Must be called on a DIE with a type attribute.
-+ */
-+static ctf_id_t lookup_ctf_type(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, ctf_file_t *ctf,
-+ struct die_override *overrides,
-+ const char *locerrstr);
-+
-+/*
-+ * Assemble a given DIE and its children into CTF in some fashion, returning the
-+ * ID of the top-level piece of generated CTF (only relevant for aggregates).
-+ *
-+ * The parent_ctf_id is the ID of the CTF entity that was or is being generated
-+ * from the enclosing DWARF DIE, or 0 if population succeeded but did not yield
-+ * a type ID (e.g. for variable assembly), or -1 on error. The parent_die is
-+ * the parent of the current DWARF DIE, and is always populated (even if just
-+ * with the CU's DIE). The parent_ctf_id is always in the same CTF file as the
-+ * ctf_id, just as the parent DWARF DIE is always in the same DWARF CU: this is
-+ * lexical scope, not dynamic, so referenced types themselves located at the top
-+ * level have the CU as their parent.
-+ *
-+ * Returning an error value (see below) indicates that no CTF was generated from
-+ * this DWARF DIE.
-+ *
-+ * Setting skip to SKIP_ABORT indicates that the translation of this entity
-+ * failed, and the entire top-level type of which it is a part should be
-+ * skipped. Setting it to SKIP_SKIP indicates that this entity does not need to
-+ * be translated (perhaps because it already exists), so recursion into
-+ * sub-entities can be skipped, but translation of the containing type should
-+ * continue. Setting it to SKIP_CONTINUE indicates no error.
-+ *
-+ * Setting 'replace' to 1 in a child DIE indicates that this type should
-+ * entirely *replace* its parent's type (generally because it has wrapped it up
-+ * in something). This replacemenu takes immediate effect for later children of
-+ * the same DIE.
-+ *
-+ * die_to_ctf() calls these functions repeatedly for every child of the
-+ * requested DIE: the CTF ID eventually returned is whatever ID is returned by
-+ * the last such function, and parent_ctf_id is repeatedly replaced with the ID
-+ * returned by the last assembly function. Thus, assembly functions that
-+ * augment an already-present ctf_id should return parent_ctf_id: assembly
-+ * functions that wrap it in a new ctf_id referring to the parent_ctf_id should
-+ * return the new ID. (Assembly functions should never entirely disregard the
-+ * parent_ctf_id.)
-+ */
-+typedef ctf_id_t (*ctf_assembly_fun)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace);
-+
-+#define ASSEMBLY_FUN(name) \
-+ static ctf_id_t assemble_ctf_##name(const char *module_name, \
-+ const char *file_name, \
-+ Dwarf_Die *die, \
-+ Dwarf_Die *parent_die, \
-+ ctf_file_t *ctf, \
-+ ctf_id_t parent_ctf_id, \
-+ const char *locerrstr, \
-+ struct die_override *overrides, \
-+ int top_level_type, \
-+ enum skip_type *skip, \
-+ int *replace)
-+
-+/*
-+ * Defined assembly functions.
-+ */
-+ASSEMBLY_FUN(base);
-+ASSEMBLY_FUN(array);
-+ASSEMBLY_FUN(array_dimension);
-+ASSEMBLY_FUN(cvr_qual);
-+ASSEMBLY_FUN(enumeration);
-+ASSEMBLY_FUN(enumerator);
-+ASSEMBLY_FUN(pointer);
-+ASSEMBLY_FUN(struct_union);
-+ASSEMBLY_FUN(su_member);
-+ASSEMBLY_FUN(typedef);
-+ASSEMBLY_FUN(variable);
-+
-+/*
-+ * An assembly filter is an optional function called with the DIE and parent DIE
-+ * of a top-level type alone, before calling down into the process_file()
-+ * processing function: it can be used to rapidly determine that this DIE is not
-+ * worth processing. (It should return 0 in this case, and nonzero otherwise.)
-+ */
-+typedef int (*ctf_assembly_filter_fun)(const char *file_name,
-+ Dwarf *dwarf,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die);
-+
-+/*
-+ * A CTF assembly filter function which excludes all types not at the global
-+ * scope (i.e. whose immediate parent is not a CU DIE) and which does not have a
-+ * structure or union as its ultimate dependent type. (All structures and
-+ * unions and everything dependent on them must be recorded, even inside
-+ * functions, because GCC may emit references to the opaque variants of those
-+ * types from file scope.)
-+ */
-+static int filter_ctf_file_scope(const char *file_name,
-+ Dwarf *dwarf,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die);
-+
-+/*
-+ * A CTF assembly filter function which excludes all names not at the global
-+ * scope, all static symbols, and all names whose names are unlikely to be
-+ * interesting. (DTrace userspace contains a similar list, but the two lists
-+ * need not be in sync.)
-+ */
-+static int filter_ctf_uninteresting(const char *file_name,
-+ Dwarf *dwarf,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die);
-+
-+/*
-+ * Error return values from CTF assembly functions. These differ only in that
-+ * die_to_ctf() reports the ctf_errmsg() if CTF_NO_ERROR_REPORTED is returned,
-+ * but says nothing in the CTF_ERROR_REPORTED case.
-+ */
-+#define CTF_NO_ERROR_REPORTED CTF_ERR
-+#define CTF_ERROR_REPORTED (-2L)
-+
-+/*
-+ * The total number of type errors encountered.
-+ */
-+static long num_errors;
-+
-+/*
-+ * A mapping from DW_TAG_* to functions which assemble this DW_TAG_* and
-+ * possibly its children into the passed CTF. This table is not used
-+ * directly, but rather assembled into a lookup table.
-+ */
-+static struct assembly_tab_t
-+{
-+ int tag;
-+ ctf_assembly_filter_fun filter;
-+ ctf_assembly_fun fun;
-+} assembly_tab_init[] =
-+{{ DW_TAG_base_type, filter_ctf_file_scope, assemble_ctf_base },
-+ { DW_TAG_array_type, filter_ctf_file_scope, assemble_ctf_array },
-+ { DW_TAG_subrange_type, NULL, assemble_ctf_array_dimension },
-+ { DW_TAG_const_type, filter_ctf_file_scope, assemble_ctf_cvr_qual },
-+ { DW_TAG_restrict_type, filter_ctf_file_scope, assemble_ctf_cvr_qual },
-+ { DW_TAG_enumeration_type, NULL, assemble_ctf_enumeration },
-+ { DW_TAG_enumerator, NULL, assemble_ctf_enumerator },
-+ { DW_TAG_pointer_type, filter_ctf_file_scope, assemble_ctf_pointer },
-+ { DW_TAG_structure_type, NULL, assemble_ctf_struct_union },
-+ { DW_TAG_union_type, NULL, assemble_ctf_struct_union },
-+ { DW_TAG_member, NULL, assemble_ctf_su_member },
-+ { DW_TAG_typedef, NULL, assemble_ctf_typedef },
-+ { DW_TAG_variable, filter_ctf_uninteresting, assemble_ctf_variable },
-+ { DW_TAG_volatile_type, filter_ctf_file_scope, assemble_ctf_cvr_qual },
-+ { 0, NULL }};
-+
-+/*
-+ * The CTF assembly and filter lookup tables, in constructed form.
-+ */
-+static ctf_assembly_fun *assembly_tab;
-+static ctf_assembly_filter_fun *assembly_filter_tab;
-+static size_t assembly_len;
-+
-+/*
-+ * Populate the assembly_tab and assembly_filter_tab from the assembly_tab_init.
-+ */
-+static void init_assembly_tab(void);
-+
-+/*
-+ * A mapping from sizeof() to CTF type encoding.
-+ */
-+struct type_encoding_tab {
-+ size_t size;
-+ int ctf_encoding;
-+};
-+
-+/*
-+ * Given a type encoding table, and a size, return the CTF encoding for that
-+ * type, or 0 if none.
-+ */
-+static int find_ctf_encoding(struct type_encoding_tab *type_tab, size_t size);
-+
-+/*
-+ * Count the number of members of a DWARF aggregate.
-+ */
-+static long count_dwarf_members(Dwarf_Die *die);
-+
-+/*
-+ * Given a DIE that may contain a type attribute, look up the target of that
-+ * attribute and return it, or NULL if none.
-+ */
-+static Dwarf_Die *private_dwarf_type(Dwarf_Die *die, Dwarf_Die *target_die);
-+
-+/*
-+ * Check for existence of an attribute in a DIE, chasing through
-+ * DW_AT_specification if need be.
-+ */
-+static inline int private_dwarf_hasattr(Dwarf_Die *die,
-+ unsigned int search_name);
-+
-+/*
-+ * Return a DIE attribute, chasing through DW_AT_specification if need be.
-+ */
-+static inline Dwarf_Attribute *private_dwarf_attr(Dwarf_Die *die,
-+ unsigned int search_name,
-+ Dwarf_Attribute *result);
-+
-+/*
-+ * Given a DIE that contains a udata attribute, look up that attribute and
-+ * return its value (optionally overridden or modified by the die_overrides).
-+ */
-+static inline Dwarf_Word private_dwarf_udata(Dwarf_Die *die, int attribute,
-+ struct die_override *overrides);
-+
-+/*
-+ * Given a DIE, return its byte size, if known and interpretable, or -1
-+ * otherwise.
-+ */
-+static inline long long private_dwarf_size(Dwarf_Die *die);
-+
-+/*
-+ * Find an override in an override list.
-+ */
-+static struct die_override *
-+private_find_override(Dwarf_Die *die,
-+ int attribute,
-+ struct die_override *overrides);
-+
-+/*
-+ * Determine the dimensions of an array subrange, or 0 if variable.
-+ */
-+static Dwarf_Word private_subrange_dimensions(Dwarf_Die *die);
-+
-+/*
-+ * A string appender working on dynamic strings.
-+ */
-+static char *str_append(char *s, const char *append)
-+ __attribute__((__warn_unused_result__));
-+
-+/*
-+ * A vararg string appender.
-+ */
-+static char *str_appendn(char *s, ...)
-+ __attribute__((__warn_unused_result__, sentinel));
-+
-+/*
-+ * An error-checking strdup().
-+ */
-+static char *xstrdup(const char *s) __attribute__((__nonnull__,
-+ __warn_unused_result__,
-+ __malloc__));
-+
-+/*
-+ * Filter a GList, calling a predicate on it and removing all elements for which
-+ * the predicate returns true, calling the free_func on them if set.
-+ */
-+typedef int (*filter_pred_fun) (void *element, void *data);
-+static GList *list_filter(GList *list, filter_pred_fun fun,
-+ GDestroyNotify free_func, void *data);
-+
-+/*
-+ * Intern an atom in the atoms table and return it, or free it and return the
-+ * existing atom if one is already interned. (Despite the type signature, this
-+ * return value is constant and should not be freed.)
-+ */
-+static void *intern(char *atom);
-+
-+/*
-+ * Figure out the (pathless, suffixless) module name for a given module file (.o
-+ * or .ko), and return it in a new dynamically allocated string.
-+ *
-+ * Takes the object_to_module mapping into account.
-+ */
-+static char *fn_to_module(const char *file_name);
-+
-+/*
-+ * Determine, and cache, absolute filenames.
-+ */
-+static const char *abs_file_name(const char *file_name);
-+
-+/*
-+ * Determine absolute filenames relative to some other directory: do not cache
-+ * them. It is the caller's responsibility to free them.
-+ */
-+static char *rel_abs_file_name(const char *file_name, const char *relative_to);
-+
-+/*
-+ * Free a per_module's contents.
-+ */
-+static void private_per_module_free(void *per_module);
-+
-+/*
-+ * Free a dedup_id_file's contents.
-+ */
-+static void free_dups_id_file(void *id_file);
-+
-+/*
-+ * Free a fn_to_die_to_parent subhash.
-+ */
-+static void private_fn_die_parent_free(void *ptr);
-+
-+/*
-+ * dwarf_dieoffset() with a return type better for printf().
-+ */
-+#define DIEOFFSET(die) (unsigned long) dwarf_dieoffset((die))
-+
-+/*
-+ * A line-shortener with a kernel-familiar name for fprintfing to stderr.
-+ */
-+#define pr_err(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
-+
-+/* Initialization. */
-+
-+int main(int argc, char *argv[])
-+{
-+ char *output;
-+
-+ trace = getenv("DWARF2CTF_TRACE");
-+
-+ if ((argc != 4 && argc != 7) ||
-+ (argc == 4 && strcmp(argv[2], "-e") != 0)) {
-+ pr_err("Syntax: dwarf2ctf output-file srcdir objects.builtin\n");
-+ pr_err(" modules.builtin member.blacklist filelist\n");
-+ pr_err(" or dwarf2ctf output-dir -e filelist\n"
-+ "for external module use\n");
-+ exit(1);
-+ }
-+
-+ output = argv[1];
-+
-+ elf_version(EV_CURRENT);
-+
-+ if (elf_errno()) {
-+ pr_err("Version synchronization fault: %s\n",
-+ elf_errmsg(elf_errno()));
-+ exit(1);
-+ }
-+
-+ init_assembly_tab();
-+ object_to_module = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ free, free);
-+
-+ /*
-+ * When not building an external module, we run over all the arguments
-+ * at once, deduplicating them. In external-module mode, we act as if
-+ * independently invoked with every argument.
-+ */
-+ if (strcmp(argv[2], "-e") != 0) {
-+ const char *srcdir;
-+ char *builtin_objects_file;
-+ char *builtin_module_file;
-+ char *member_blacklist_file;
-+
-+ srcdir = argv[2];
-+ builtin_objects_file = argv[3];
-+ builtin_module_file = argv[4];
-+ member_blacklist_file = argv[5];
-+ deduplicating = 1;
-+
-+ init_builtin(builtin_objects_file, builtin_module_file);
-+ init_member_blacklist(member_blacklist_file, srcdir);
-+ init_object_names(argv[6]);
-+
-+ run(output, 0);
-+ } else {
-+ char *single_object_name;
-+ char **all_object_names;
-+ size_t all_object_names_cnt;
-+ size_t i;
-+
-+ deduplicating = 0;
-+ init_object_names(argv[3]);
-+
-+ /*
-+ * Repeatedly populate object_names with one object name, and
-+ * call run() with that.
-+ */
-+ all_object_names = object_names;
-+ all_object_names_cnt = object_names_cnt;
-+ object_names = &single_object_name;
-+ object_names_cnt = 1;
-+
-+ for (i = 0; i < all_object_names_cnt; i++) {
-+ single_object_name = all_object_names[i];
-+
-+ run(output, 1);
-+ }
-+ }
-+
-+ g_hash_table_destroy(object_to_module);
-+
-+ if (num_errors > 0)
-+ pr_err("%li CTF construction errors.\n", num_errors);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Run dwarf2ctf over a single object file or set thereof.
-+ *
-+ * output is the directory into which the CTF goes, if 'standalone', or the
-+ * CTF archive file name otherwise.
-+ */
-+static void run(char *output, int standalone)
-+{
-+ size_t i;
-+
-+ /*
-+ * Create all the hashes, assemble the translation unit->module list for
-+ * builtin modules, and create the shared CTF file if deduplicating.
-+ */
-+
-+ atoms = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
-+ id_to_type = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ NULL, free);
-+ id_to_module = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ NULL, free);
-+ per_module = g_hash_table_new_full(g_str_hash, g_str_equal, free,
-+ private_per_module_free);
-+ variable_blacklist = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ free, free);
-+ fn_to_die_to_parent = g_hash_table_new_full(g_str_hash,
-+ g_str_equal, free,
-+ private_fn_die_parent_free);
-+
-+ dw_ctf_trace("Initializing...\n");
-+
-+ if (deduplicating)
-+ init_ctf_table("shared_ctf");
-+
-+ scan_dups();
-+
-+ /*
-+ * Now construct CTF out of the types.
-+ */
-+ dw_ctf_trace("CTF construction.\n");
-+ for (i = 0; i < object_names_cnt; i++)
-+ process_file(object_names[i], construct_ctf, NULL, NULL, NULL);
-+
-+ /*
-+ * Finally, emit the types into their .ctf files, and generate the
-+ * necessary linker scripts.
-+ */
-+ dw_ctf_trace("Writeout.\n");
-+ write_types(output, standalone);
-+
-+ g_hash_table_destroy(id_to_type);
-+ g_hash_table_destroy(id_to_module);
-+ g_hash_table_destroy(per_module);
-+ g_hash_table_destroy(variable_blacklist);
-+ g_hash_table_destroy(fn_to_die_to_parent);
-+ g_hash_table_destroy(atoms);
-+}
-+
-+/*
-+ * Populate the object_names list from the module filelist.
-+ */
-+static void init_object_names(const char *object_names_file)
-+{
-+ FILE *f;
-+ char *line = NULL;
-+ size_t line_size = 0;
-+
-+ f = fopen(object_names_file, "r");
-+ if (f == NULL) {
-+ pr_err("Cannot open object names file %s: %s\n",
-+ object_names_file, strerror(errno));
-+ exit(1);
-+ }
-+
-+ /*
-+ * This needs no massaging other than linefeed removal, just reading and
-+ * stashing.
-+ */
-+
-+ while (getline(&line, &line_size, f) >= 0) {
-+ size_t len = strlen(line);
-+
-+ if (len == 0)
-+ continue;
-+
-+ if (line[len-1] == '\n')
-+ line[len-1] = '\0';
-+
-+ object_names = realloc(object_names,
-+ ++object_names_cnt *
-+ sizeof(char *));
-+
-+ if (object_names == NULL) {
-+ pr_err("Out of memory reading %s\n", object_names_file);
-+ exit(1);
-+ }
-+
-+ object_names[object_names_cnt-1] = xstrdup(line);
-+ }
-+ free(line);
-+
-+ if (ferror(f)) {
-+ pr_err("Error reading from %s: %s\n", object_names_file,
-+ strerror(errno));
-+ exit(1);
-+ }
-+
-+ fclose(f);
-+}
-+
-+/*
-+ * Populate object_to_module from the objects.builtin and modules.builtin file.
-+ */
-+static void init_builtin(const char *builtin_objects_file,
-+ const char *builtin_module_file)
-+{
-+ FILE *f;
-+ struct modules_thick_iter *i;
-+ char *line = NULL;
-+ size_t line_size = 0;
-+ char *module_name = NULL;
-+ char **paths;
-+
-+ /*
-+ * Iterate over all modules in modules_thick.builtin and add each to
-+ * object_to_module.
-+ */
-+ i = modules_thick_iter_new(builtin_module_file);
-+ if (i == NULL) {
-+ pr_err("Cannot iterate over builtin module file.\n");
-+ exit(1);
-+ }
-+
-+ while ((paths = modules_thick_iter_next(i, &module_name)) != NULL) {
-+ size_t j;
-+
-+ for (j = 0; paths[j] != NULL; j++) {
-+ dw_ctf_trace("noting built-in module mapping %s -> %s\n",
-+ module_name, paths[j]);
-+ g_hash_table_replace(object_to_module,
-+ strdup(paths[j]),
-+ xstrdup(module_name));
-+ }
-+ free(paths);
-+ }
-+ free(module_name);
-+ modules_thick_iter_free(i);
-+
-+ f = fopen(builtin_objects_file, "r");
-+ if (f == NULL) {
-+ pr_err("Cannot open builtin objects file %s: %s\n",
-+ builtin_objects_file, strerror(errno));
-+ exit(1);
-+ }
-+
-+ /*
-+ * Those entries in builtin.objects that are not already known are
-+ * unconditionally-built-in object files.
-+ */
-+ while (getline(&line, &line_size, f) >= 0) {
-+ size_t len = strlen(line);
-+
-+ if (len == 0)
-+ continue;
-+
-+ if (line[len-1] == '\n')
-+ line[len-1] = '\0';
-+
-+ if (!g_hash_table_lookup(object_to_module, line))
-+ g_hash_table_replace(object_to_module, xstrdup(line),
-+ xstrdup("vmlinux"));
-+ }
-+
-+ if (ferror(f)) {
-+ pr_err("Error reading from %s: %s\n", builtin_objects_file,
-+ strerror(errno));
-+ exit(1);
-+ }
-+
-+ free(line);
-+ fclose(f);
-+}
-+
-+/*
-+ * Translate the assembly lookup table into the assembly_tab and
-+ * assembly_filter_tab arrays.
-+ */
-+static void init_assembly_tab(void)
-+{
-+ struct assembly_tab_t *walk;
-+
-+ for (walk = assembly_tab_init; walk->fun != NULL; walk++) {
-+ if (assembly_len < walk->tag)
-+ assembly_len = walk->tag;
-+ }
-+ assembly_len++;
-+
-+ assembly_tab = calloc(sizeof(ctf_assembly_fun *), assembly_len);
-+ assembly_filter_tab = calloc(sizeof(ctf_assembly_filter_fun *),
-+ assembly_len);
-+ if ((assembly_tab == NULL) || (assembly_filter_tab == NULL)) {
-+ pr_err("Out of memory allocating assembly table\n");
-+ exit(1);
-+ }
-+
-+ for (walk = assembly_tab_init; walk->fun != NULL; walk++) {
-+ assembly_tab[walk->tag] = walk->fun;
-+ assembly_filter_tab[walk->tag] = walk->filter;
-+ }
-+}
-+
-+/*
-+ * Populate the member blacklist from the member_blacklist file.
-+ */
-+static void init_member_blacklist(const char *member_blacklist_file,
-+ const char *srcdir)
-+{
-+ FILE *f;
-+ char *line = NULL;
-+ size_t line_num = 0;
-+ size_t line_size = 0;
-+
-+ /*
-+ * Not having a member blacklist is not an error.
-+ */
-+ f = fopen(member_blacklist_file, "r");
-+ if (f == NULL)
-+ return;
-+
-+ member_blacklist = g_hash_table_new(g_str_hash, g_str_equal);
-+
-+ while (getline(&line, &line_size, f) >= 0) {
-+ size_t len = strlen(line);
-+ char *last_colon;
-+ const char *last_dot;
-+ char *absolutized;
-+
-+ line_num++;
-+
-+ if (len == 0)
-+ continue;
-+
-+ if (line[len-1] == '\n')
-+ line[len-1] = '\0';
-+
-+ last_colon = strrchr(line, ':');
-+ last_dot = strrchr(last_colon + 1, '.');
-+ if (!last_colon || !last_dot) {
-+ pr_err("Syntax error on line %li of %s.\n"
-+ "Syntax: filename:structure.member.\n",
-+ line_num, member_blacklist_file);
-+ continue;
-+ }
-+
-+ *last_colon = '\0';
-+ last_colon++;
-+ absolutized = rel_abs_file_name(line, srcdir);
-+ absolutized = str_appendn(absolutized, ":", last_colon, NULL);
-+
-+ g_hash_table_insert(member_blacklist, absolutized, NULL);
-+ }
-+ free(line);
-+
-+ if (ferror(f)) {
-+ pr_err("Error reading from %s: %s\n", member_blacklist_file,
-+ strerror(errno));
-+ exit(1);
-+ }
-+
-+ fclose(f);
-+}
-+
-+/*
-+ * Return 1 if a given DWARF DIE, which must be a DW_TAG_member, appears in the
-+ * member blacklist.
-+ */
-+static int member_blacklisted(Dwarf_Die *die, Dwarf_Die *parent_die)
-+{
-+ const char *fname = dwarf_decl_file(die);
-+ char *id;
-+ int blacklisted = 0;
-+
-+ /*
-+ * If there is no member blacklist, do nothing.
-+ */
-+ if (!member_blacklist)
-+ return 0;
-+
-+ /*
-+ * Unnamed structure and union members cannot be blacklisted, for now.
-+ */
-+ if ((dwarf_diename(parent_die) == NULL) ||
-+ (dwarf_diename(die) == NULL))
-+ return 0;
-+
-+ /*
-+ * The compiler can define its own structures, which appear in no
-+ * decl_file.
-+ *
-+ * We can't blacklist them with this mechanism, so skip them.
-+ */
-+ if (__builtin_expect(fname == NULL, 0))
-+ return 0;
-+
-+ fname = abs_file_name(fname);
-+
-+ if (dwarf_tag(die) != DW_TAG_member ||
-+ (dwarf_tag(parent_die) != DW_TAG_structure_type &&
-+ dwarf_tag(parent_die) != DW_TAG_union_type)) {
-+ pr_err("Warning: member_blacklisted() called on "
-+ "%s:%s.%s at offset %li, which is not a structure member.\n",
-+ fname, dwarf_diename(parent_die), dwarf_diename(die),
-+ DIEOFFSET(die));
-+ return 0;
-+ }
-+
-+ id = xstrdup(fname);
-+ id = str_appendn(id, ":", dwarf_diename(parent_die), ".",
-+ dwarf_diename(die), NULL);
-+
-+ if (g_hash_table_lookup_extended(member_blacklist, id, NULL, NULL))
-+ blacklisted = 1;
-+
-+ free(id);
-+ return blacklisted;
-+}
-+
-+/*
-+ * Initialize a CTF type table, and possibly fill it with those special types
-+ * that appear in CTF but not in DWARF (such as 'void'). (This filling happens
-+ * only for the type table named "shared_ctf", unless deduplication is turned
-+ * off.)
-+ *
-+ * If this is a local type table, and deduplication is active, make the global
-+ * type table its parent.
-+ */
-+static void init_ctf_table(const char *module_name)
-+{
-+ ctf_file_t *ctf_file;
-+ struct per_module *new_per_mod;
-+ int ctf_err;
-+
-+ ctf_file = ctf_create(&ctf_err);
-+ if (ctf_file == NULL) {
-+ pr_err("Cannot create CTF file: %s\n", strerror(ctf_err));
-+ exit(1);
-+ }
-+ new_per_mod = malloc(sizeof(struct per_module));
-+ if (new_per_mod == NULL) {
-+ pr_err("Out of memory allocating per-module CTF info\n");
-+ exit(1);
-+ }
-+
-+ new_per_mod->ctf_file = ctf_file;
-+ new_per_mod->member_counts = g_hash_table_new_full(g_str_hash,
-+ g_str_equal,
-+ free, free);
-+ g_hash_table_replace(per_module, xstrdup(module_name), new_per_mod);
-+
-+ dw_ctf_trace("Initializing module: %s\n", module_name);
-+ if ((strcmp(module_name, "shared_ctf") == 0) ||
-+ !deduplicating) {
-+ ctf_encoding_t void_encoding = { CTF_INT_SIGNED, 0, 0 };
-+ ctf_encoding_t int_encoding = { CTF_INT_SIGNED, 0,
-+ sizeof(int) * 8 };
-+ ctf_id_t int_type;
-+ ctf_id_t func_type;
-+ ctf_funcinfo_t func_info;
-+
-+ /*
-+ * Global types module, or deduplication is disabled. Add a
-+ * type for 'void *' to point to, and a type for the return
-+ * value of pointers to functions: then add the (single,
-+ * universal) pointer-to-function value.
-+ */
-+ ctf_void_type = ctf_add_integer(ctf_file, CTF_ADD_ROOT,
-+ "void", &void_encoding);
-+ int_type = ctf_add_integer(ctf_file, CTF_ADD_ROOT, "int",
-+ &int_encoding);
-+ mark_shared_by_name(ctf_file, ctf_void_type, "void");
-+ mark_shared_by_name(ctf_file, int_type, "int");
-+
-+ func_info.ctc_return = int_type;
-+ func_info.ctc_argc = 0;
-+ func_info.ctc_flags = 0;
-+ func_type = ctf_add_function(ctf_file, CTF_ADD_ROOT,
-+ &func_info, NULL);
-+ ctf_funcptr_type = ctf_add_pointer(ctf_file, CTF_ADD_ROOT,
-+ func_type);
-+
-+ if (ctf_update(ctf_file) < 0) {
-+ pr_err("Cannot initialize shared CTF file: %s\n",
-+ ctf_errmsg(ctf_errno(ctf_file)));
-+ exit(1);
-+ }
-+ } else {
-+ /*
-+ * Local types module with deduplication enabled: point the
-+ * parent at the global CTF file, which must exist by this
-+ * point.
-+ */
-+ if (ctf_import(ctf_file, lookup_ctf_file("shared_ctf")) < 0) {
-+ pr_err("Cannot set parent of CTF file for module %s: %s\n",
-+ module_name, ctf_errmsg(ctf_errno(ctf_file)));
-+ exit(1);
-+ }
-+ ctf_parent_name_set(ctf_file, "shared_ctf");
-+ }
-+
-+ dw_ctf_trace("Created CTF file for module %s: %p\n",
-+ module_name, ctf_file);
-+}
-+
-+/* DWARF walkers. */
-+
-+/*
-+ * Initialize the child->parent DIE mapping for a single file.
-+ */
-+static void init_parent_die(const char *file_name, Dwfl *dwfl)
-+{
-+ GHashTable *offs;
-+ Dwarf_Die *tu_die = NULL;
-+ Dwarf_Addr junk;
-+
-+ offs = g_hash_table_new(g_direct_hash, g_direct_equal);
-+ if (offs == NULL) {
-+ pr_err("Out of memory creating DIE offset hash\n");
-+ exit(1);
-+ }
-+
-+ while ((tu_die = dwfl_nextcu(dwfl, tu_die, &junk)) != NULL) {
-+ init_parent_die_internal(file_name, offs, tu_die, 0, 0);
-+ }
-+
-+ g_hash_table_insert(fn_to_die_to_parent,
-+ strdup(abs_file_name(file_name)), offs);
-+}
-+
-+/*
-+ * Initialize one layer of a child->parent mapping.
-+ *
-+ * We traverse children of top-level subprograms hunting for anything we know
-+ * how to emit, and record parent->child mappings for all intermediate DIEs.
-+ */
-+static int init_parent_die_internal(const char *file_name,
-+ GHashTable *offs, Dwarf_Die *parent,
-+ int depth, int found_subprogram)
-+{
-+ Dwarf_Die child;
-+ int sib_ret;
-+ Dwarf_Off parent_offset;
-+ const char *err;
-+ int add_parent = 0;
-+
-+ if (dwarf_tag(parent) == DW_TAG_subprogram)
-+ found_subprogram = 1;
-+
-+ switch (dwarf_child(parent, &child)) {
-+ case -1:
-+ err = "child DIEs";
-+ goto err;
-+ case 1: /* This DIE has no children */
-+ goto out;
-+ }
-+
-+ parent_offset = dwarf_dieoffset(parent);
-+
-+ do {
-+ int add_child = 0;
-+
-+ /*
-+ * Add links from the parent to all children for which a
-+ * recursive call says they should be added, and note that we
-+ * should add links to the parent too. Always look down to
-+ * depth 2, since the topmost level is always
-+ * DW_TAG_compile_unit, and we are interested in
-+ * DW_TAG_subprograms one level below that.
-+ */
-+ if (found_subprogram || depth < 2)
-+ add_child = init_parent_die_internal(file_name, offs,
-+ &child, depth+1,
-+ found_subprogram);
-+
-+ if (add_child) {
-+ g_hash_table_insert(offs,
-+ GUINT_TO_POINTER(dwarf_dieoffset(&child)),
-+ GUINT_TO_POINTER(parent_offset));
-+ add_parent = 1;
-+ }
-+ } while ((sib_ret = dwarf_siblingof (&child, &child)) == 0);
-+
-+ if (sib_ret == -1) {
-+ err = "sibling DIEs";
-+ goto err;
-+ }
-+
-+out:
-+ /*
-+ * Emit a link for the next level up if we're under a subprogram and
-+ * either we emitted a child link or the parent is itself something we
-+ * know how to emit (and thus might possibly appear in a type DIE we
-+ * care about).
-+ */
-+ return (found_subprogram &&
-+ (add_parent ||
-+ (dwarf_tag(parent) < assembly_len &&
-+ assembly_tab[dwarf_tag(parent)] != NULL)));
-+err:
-+ pr_err("Cannot fetch %s of DIE at offset %lu in %s: %s\n",
-+ err, DIEOFFSET(parent), file_name,
-+ dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * Type ID computation.
-+ *
-+ * A type ID is a constant, recursively-constructed, dynamically-allocated
-+ * string describing a given DWARF DIE in such a way that any DWARF file
-+ * containing the same type will have the same type ID. (It even works for
-+ * variables! Variables of the same name and referring to the same type have
-+ * the same ID...)
-+ *
-+ * Optionally, call a callback with the computed ID once we know it (this is a
-+ * recursive process, so the callback can be called multiple times as the ID is
-+ * built up).
-+ *
-+ * An ID of NULL indicates that this DIE has no ID and need not be considered.
-+ *
-+ * It is probably an error for two DWARF DIEs representing top-level types to
-+ * return the same ID, but for certain other DIEs (notably those representing
-+ * the members of structures or unions), it is expected that they return the
-+ * same ID as their type DIE.
-+ *
-+ * This function is the hottest hot spot in dwarf2ctf, so is somewhat
-+ * aggressively optimized.
-+ *
-+ * The "overrides" allow the overriding of DWARF attributes, so that the
-+ * machinery notices different DWARF from what actually appears in the
-+ * debuginfo, so that the CTF that is emitted is suitably modified (and possibly
-+ * duplicated). This is mostly used by type_id() to generate different IDs for
-+ * dependent types of bitfields, but can be used for other purposes too, such as
-+ * adjusting the offsets of types in unnamed structures, etc. Overrides are
-+ * passed down if provided: overrides relating to bitfields are only applied by
-+ * type_id() if no other overrides are provided.
-+ *
-+ * In general, you do not need to pass overrides down if you know you will only
-+ * be called directly on top-level DIEs, but otherwise, you should do so.
-+ */
-+static char *type_id(Dwarf_Die *die,
-+ struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data)
-+{
-+ return type_id_internal(die, overrides, fun, data, 0);
-+}
-+
-+/*
-+ * Internal: generate the type ID for a type DIE.
-+ *
-+ * If there are no overrides, look for a bit_size and bit_offset and pass them
-+ * down as well.
-+ */
-+static char *type_id_type_die(Dwarf_Die *die,
-+ Dwarf_Die *type_die,
-+ struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data)
-+{
-+ char *id;
-+
-+ /*
-+ * bit_size and bit_offset go together: we can assume that if a member
-+ * has the one, it has the other.
-+ */
-+
-+ if (private_dwarf_hasattr(die, DW_AT_bit_size)) {
-+ Dwarf_Word size;
-+ Dwarf_Word offset;
-+
-+ size = private_dwarf_udata(die, DW_AT_bit_size, NULL);
-+ offset = private_dwarf_udata(die, DW_AT_bit_offset, NULL);
-+ struct die_override o[] = {
-+ { DW_TAG_base_type,
-+ DW_AT_bit_size,
-+ DIE_OVERRIDE_REPLACE,
-+ size, NULL },
-+ { DW_TAG_base_type,
-+ DW_AT_bit_offset,
-+ DIE_OVERRIDE_REPLACE,
-+ offset, overrides },
-+ {0}
-+ };
-+ id = type_id(type_die, o, fun, data);
-+ } else
-+ id = type_id(type_die, overrides, fun, data);
-+ return id;
-+}
-+
-+/*
-+ * Internal: allows flags to be passed to affect one (and only one) type ID
-+ * recursion, without affecting other type_id()s launched from the 'fun'.
-+ */
-+static char *type_id_internal(Dwarf_Die *die,
-+ struct die_override *overrides,
-+ void (*fun)(Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data),
-+ void *data,
-+ int flags)
-+{
-+ char *id = NULL;
-+ int no_type_id = 0;
-+ int decorated = 1;
-+
-+ /*
-+ * The ID of a null pointer is NULL.
-+ */
-+ if (die == NULL)
-+ return NULL;
-+
-+ /*
-+ * The ID of a function pointer is '//fp//', as a special case,
-+ * with no location or overrides, ever.
-+ */
-+ if (dwarf_tag(die) == DW_TAG_subroutine_type) {
-+ id = xstrdup("//fp//");
-+ if (fun)
-+ fun(die, id, NULL, data);
-+ return id;
-+ }
-+
-+ /*
-+ * If we have a type DIE, generate it first, passing any overrides down.
-+ * (Base types and enumerations don't have a type DIE that CTF can
-+ * encode the type of in any useful fashion.)
-+ *
-+ * Otherwise, note the location of this DIE, providing scoping
-+ * information for all types based upon this one. Location elements are
-+ * separated by //, an element impossible in a Linux path. The
-+ * blacklist type prefix (if set) follows this (which is a name which,
-+ * while not impossible in a Linux path, is very unlikely.)
-+ *
-+ * Array dimensions get none of this: they must be contained within
-+ * another DIE, so will always have a location attached via that DIE,
-+ * and get their type chased further down (so as to arrange that they
-+ * appear inside an [].)
-+ */
-+ if (dwarf_tag(die) != DW_TAG_subrange_type) {
-+ if ((dwarf_tag(die) != DW_TAG_base_type) &&
-+ (dwarf_tag(die) != DW_TAG_enumeration_type)) {
-+ Dwarf_Die type_die;
-+ Dwarf_Die *diep = private_dwarf_type(die, &type_die);
-+
-+ if (diep)
-+ id = type_id_type_die(die, diep, overrides,
-+ fun, data);
-+ }
-+
-+ /*
-+ * Location information. We use cached realpath() results, and
-+ * call str_appendn() only once, minimizing the number of
-+ * strlen()s.
-+ */
-+ if (id == NULL) {
-+ const char *decl_file_name = dwarf_decl_file(die);
-+ int decl_line_num;
-+ const char *fname = "";
-+ char line_num[21] = ""; /* > than 2^64's digit count */
-+
-+ no_type_id = 1;
-+ if (decl_file_name != NULL)
-+ fname = abs_file_name(decl_file_name);
-+
-+ if (dwarf_decl_line(die, &decl_line_num) >= 0) {
-+ snprintf(line_num, sizeof(line_num), "%i",
-+ decl_line_num);
-+ }
-+ id = str_appendn(id, fname, "//", line_num, "//", NULL);
-+ }
-+ }
-+
-+ /*
-+ * We implement this via a switch statement, rather than a jump table
-+ * like the assembly_tab, simply because most cases are so small that
-+ * splitting them into separate functions would do more harm than good
-+ * to readability.
-+ *
-+ * WARNING: The spaces in the strings in this switch statement are not
-+ * just for appearance: types with spaces in their names are impossible
-+ * in C. If you move those spaces around for appearance's sake, please
-+ * adjust mark_shared_by_name and dedup_alias_fixup(), which
-+ * construct the IDs of basic types, structures, and unions by hand.
-+ */
-+ switch (dwarf_tag(die)) {
-+ case DW_TAG_base_type: {
-+ Dwarf_Word bit_size = -1;
-+ Dwarf_Word type_size = -1;
-+ Dwarf_Word bit_offset = -1;
-+ const char *diename = dwarf_diename(die);
-+
-+ if ((flags & TI_COLLAPSE_SIZETYPE) &&
-+ (strcmp(diename, "long unsigned int") == 0))
-+ diename = "sizetype";
-+
-+ /*
-+ * CTF encodes the size and bitwise-offset of bit-fields in the
-+ * base type, so it must be stored once for each size, even if
-+ * it only appears once for all sizes in the DWARF.
-+ */
-+ if (private_dwarf_hasattr(die, DW_AT_bit_size) ||
-+ private_find_override(die, DW_AT_bit_size,
-+ overrides))
-+ bit_size = private_dwarf_udata(die, DW_AT_bit_size,
-+ overrides);
-+ if (private_dwarf_hasattr(die, DW_AT_bit_offset) ||
-+ private_find_override(die, DW_AT_bit_offset,
-+ overrides))
-+ bit_offset = private_dwarf_udata(die, DW_AT_bit_offset,
-+ overrides);
-+
-+ /*
-+ * Bitfields that occupy their entire containing type are not
-+ * bitfields, but just redundant DWARF. GCC emits these now and
-+ * again, but the dups would trip CTF consistency checks, so
-+ * must be skipped.
-+ */
-+ if (bit_size > -1) {
-+ /*
-+ * This "may be omitted" in DWARF, but GCC doesn't:
-+ * bitfields always get both. (See
-+ * gcc/dwarf2out.c:gen_field_die().)
-+ */
-+ type_size = private_dwarf_udata(die, DW_AT_bit_size,
-+ overrides);
-+ }
-+ if (bit_size != type_size) {
-+ char bitsize[22]; /* > 2^64's digit count */
-+ char bitoffset[22]; /* > 2^64's digit count */
-+
-+ snprintf(bitsize, sizeof(bitsize), "%li", bit_size);
-+ id = str_appendn(id, diename, ":", bitsize, NULL);
-+ if (bit_offset != -1) {
-+ snprintf(bitoffset, sizeof(bitoffset), "%li",
-+ bit_offset);
-+ id = str_appendn(id, ":", bitoffset, NULL);
-+ }
-+ id = str_append(id, " ");
-+ } else {
-+ /*
-+ * Ordinary (non-bit-field) base type.
-+ */
-+ id = str_appendn(id, diename, " ", NULL);
-+ }
-+ break;
-+ }
-+ case DW_TAG_enumeration_type:
-+ id = str_appendn(id, "enum ", dwarf_diename(die), " ", NULL);
-+ break;
-+ case DW_TAG_structure_type:
-+ case DW_TAG_union_type: {
-+ /*
-+ * Incorporate the unaligned sizeof() the structure, if
-+ * statically known (the offset of the last member in the DWARF)
-+ * so that most structures which are redefined on the fly by
-+ * preprocessor defines are disambiguated despite being defined
-+ * in the same place.
-+ *
-+ * Only do this if this is a non-opaque structure/union
-+ * definition: opaque definitions cannot have a size, but if
-+ * they do by some mischance get one, notating it will mess up
-+ * the several other places that manually construct opaque
-+ * structure identifiers (and cannot incorporate a size, since
-+ * they don't know it).
-+ */
-+ const char *sou;
-+
-+ if (strncmp(id, "////", 4) != 0) {
-+ long long size;
-+ char byte_size[24];
-+
-+ size = private_dwarf_size(die);
-+ if (size > -1) {
-+ sprintf(byte_size, "%lli", size);
-+ id = str_appendn(id, byte_size, "//", NULL);
-+ }
-+ }
-+
-+ if (dwarf_tag(die) == DW_TAG_union_type)
-+ sou = "union ";
-+ else
-+ sou = "struct ";
-+
-+ id = str_appendn(id, sou, dwarf_diename(die), " ", NULL);
-+ break;
-+ }
-+ case DW_TAG_variable:
-+ id = str_appendn(id, "var ", dwarf_diename(die), " ", NULL);
-+ break;
-+ case DW_TAG_typedef:
-+ id = str_appendn(id, "typedef ", dwarf_diename(die), " ", NULL);
-+ break;
-+ case DW_TAG_const_type:
-+ id = str_append(id, "const ");
-+ break;
-+ case DW_TAG_restrict_type:
-+ id = str_append(id, "restrict ");
-+ break;
-+ case DW_TAG_volatile_type:
-+ id = str_append(id, "volatile ");
-+ break;
-+ case DW_TAG_pointer_type:
-+ if (no_type_id)
-+ id = str_append(id, "void ");
-+ id = str_append(id, "* ");
-+ break;
-+
-+ case DW_TAG_array_type: {
-+ /*
-+ * No explicit notation: all done per-dimension: so recurse to
-+ * those.
-+ */
-+
-+ int sib_ret;
-+ int dimens = 0;
-+ Dwarf_Die dim_die;
-+
-+ switch (dwarf_child(die, &dim_die)) {
-+ case -1:
-+ pr_err("Corrupt DWARF: Cannot get array dimensions: %s\n",
-+ dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+ case 1: /* No dimensions. */
-+ id = str_append(id, "[] ");
-+ break;
-+ default:
-+ dimens = 1;
-+ }
-+
-+ if (!dimens)
-+ break;
-+
-+ do {
-+ char *sub_id = type_id_internal(&dim_die, overrides,
-+ fun, data,
-+ TI_COLLAPSE_SIZETYPE);
-+ id = str_append(id, sub_id);
-+ free(sub_id);
-+ } while ((sib_ret = dwarf_siblingof(&dim_die, &dim_die)) == 0);
-+
-+ if (sib_ret == -1) {
-+ pr_err("Corrupt DWARF: Cannot get array dimensions: %s\n",
-+ dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+ }
-+ break;
-+ }
-+ case DW_TAG_subrange_type: {
-+ Dwarf_Word nelems = private_subrange_dimensions(die);
-+
-+ id = str_append(id, "[");
-+
-+ if (nelems > 0) {
-+ Dwarf_Die type_die;
-+ char elems[22]; /* bigger than 2^64's digit count */
-+ char *sub_id = type_id_internal(private_dwarf_type(die, &type_die),
-+ overrides, fun, data,
-+ TI_COLLAPSE_SIZETYPE);
-+
-+ snprintf(elems, sizeof(elems), " %li", nelems);
-+ id = str_appendn(id, sub_id, elems, NULL);
-+ free(sub_id);
-+ }
-+ id = str_append(id, "] ");
-+ break;
-+ }
-+ default:
-+ /*
-+ * Some tags (e.g. structure members) get the same ID as their
-+ * associated type. We don't need to call the hook function
-+ * again for such tags.
-+ */
-+ decorated = 0;
-+ }
-+
-+ if (fun && decorated)
-+ fun(die, id, overrides, data);
-+
-+ return id;
-+}
-+
-+/*
-+ * Process a file, calling the dwarf_process function for every top-level type
-+ * found therein. Optionally call tu_init() at the start of each translation
-+ * unit, and tu_done() at the end.
-+ */
-+static void process_file(const char *file_name,
-+ void (*dwarf_process)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ void *data),
-+ void (*tu_init)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *tu_die,
-+ void *data),
-+ void (*tu_done)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *tu_die,
-+ void *data),
-+ void *data)
-+{
-+ const char *err;
-+ char *fn_module_name = fn_to_module(file_name);
-+ const char *module_name = fn_module_name;
-+
-+ Dwfl_Module *mod;
-+ Dwfl *dwfl;
-+ Dwarf *dwarf;
-+ GHashTable *seen_before = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ free, free);
-+ Dwarf_Die *tu_die = NULL;
-+ Dwarf_Addr junk;
-+
-+ if (seen_before == NULL) {
-+ pr_err("Out of memory creating seen_before hash\n");
-+ exit(1);
-+ }
-+
-+ dwfl = simple_dwfl_new(file_name, &mod);
-+ dwarf = dwfl_module_getdwarf(mod, &junk);
-+
-+ /*
-+ * On first traversal, make sure the DIE parent mapping is populated,
-+ * so that filter_ctf_file_scope can use it.
-+ */
-+ if (!g_hash_table_lookup_extended(fn_to_die_to_parent,
-+ abs_file_name(file_name),
-+ NULL, NULL))
-+ init_parent_die(file_name, dwfl);
-+
-+ while ((tu_die = dwfl_nextcu(dwfl, tu_die, &junk)) != NULL) {
-+ const char *tu_name;
-+
-+ if (dwarf_tag(tu_die) != DW_TAG_compile_unit) {
-+ err = "Malformed DWARF: non-compile_unit at top level";
-+ goto fail;
-+ }
-+
-+ tu_name = dwarf_diename(tu_die);
-+
-+ dw_ctf_trace("Processing %s\n", tu_name);
-+
-+ /*
-+ * If we have seen this TU before, skip it. We assume that
-+ * types in multiple identical TUs are always entirely
-+ * identical. This lets us skip cases where the same object
-+ * file is linked in multiple places without scanning every type
-+ * in it. (Note: this may be inaccurate if a TU is built
-+ * repeatedly with different #defines in force. I hope this
-+ * cannot happen, but if it does, a workaround a-la libtool is
-+ * simple: rename or symlink the TU for such repeated builds.)
-+ *
-+ * Otherwise, note the name of the module to which this TU maps,
-+ * if it is not already known: otherwise, extract that name.
-+ *
-+ * This is purely an optimization: it breaks somewhat for
-+ * multifile modules but this has no effect but a slight
-+ * slowdown.
-+ */
-+ if (g_hash_table_lookup_extended(seen_before, tu_name,
-+ NULL, NULL))
-+ continue;
-+
-+ g_hash_table_replace(seen_before, xstrdup(tu_name), NULL);
-+
-+ /*
-+ * We are only interested in top-level definitions within each
-+ * TU.
-+ */
-+ Dwarf_Die die;
-+
-+ switch (dwarf_child(tu_die, &die)) {
-+ case -1:
-+ err = "fetch first child of TU";
-+ goto fail;
-+ case 1: /* No DIEs at all in this TU */
-+ continue;
-+ default: /* Child DIEs exist. */
-+ break;
-+ }
-+
-+ if (tu_init != NULL)
-+ tu_init(module_name, file_name, tu_die, data);
-+
-+ process_tu_func(module_name, file_name, dwarf, tu_die, &die,
-+ dwarf_process, data);
-+
-+ if (tu_done != NULL)
-+ tu_done(module_name, file_name, tu_die, data);
-+ }
-+
-+ free(fn_module_name);
-+ simple_dwfl_free(dwfl);
-+ g_hash_table_destroy(seen_before);
-+
-+ return;
-+
-+ fail:
-+ pr_err("Cannot %s for %s: %s\n", err, module_name,
-+ dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * process_file() helper, walking over the top level and picking up types
-+ * therein.
-+ */
-+static void process_tu_func(const char *module_name,
-+ const char *file_name,
-+ Dwarf *dwarf,
-+ Dwarf_Die *parent_die,
-+ Dwarf_Die *die,
-+ void (*dwarf_process)(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ void *data),
-+ void *data)
-+{
-+ const char *err;
-+ int sib_ret;
-+
-+ /*
-+ * We are only interested in definitions for which we can (eventually)
-+ * emit CTF: call the processing function for all such.
-+ */
-+ do {
-+ if ((dwarf_tag(die) < assembly_len) &&
-+ (assembly_filter_tab[dwarf_tag(die)] == NULL ||
-+ assembly_filter_tab[dwarf_tag(die)](file_name, dwarf, die,
-+ parent_die)) &&
-+ (assembly_tab[dwarf_tag(die)] != NULL))
-+ dwarf_process(module_name, file_name, die,
-+ parent_die, data);
-+ } while ((sib_ret = dwarf_siblingof(die, die)) == 0);
-+
-+ if (sib_ret == -1) {
-+ err = "fetch sibling";
-+ goto fail;
-+ }
-+
-+ return;
-+ fail:
-+ pr_err("Cannot %s for %s: %s\n", err, module_name,
-+ dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+}
-+
-+/* Duplicate detection. */
-+
-+/*
-+ * Scan and identify duplicates across the entire set of object files.
-+ */
-+static void scan_dups(void)
-+{
-+ size_t i;
-+
-+ /*
-+ * First, determine which types are referenced by more than one
-+ * translation unit, and construct the mapping from translation unit to
-+ * non-builtin module name.
-+ *
-+ * The first pass detects duplicated types in need of sharing, without
-+ * considering opaque/transparent structure/union aliasing. It requests
-+ * an alias detection pass if any structures, or typedefs to them, are
-+ * newly marked as shared.
-+ *
-+ * We must do this even when deduplication is disabled, because we need
-+ * the TU->module-name mapping, even if in this case it is trivial.
-+ */
-+
-+ struct dedup_state state = {0};
-+
-+ dw_ctf_trace("Duplicate detection: primary pass.\n");
-+
-+ /*
-+ * This is merely flushed between TUs, not recreated: we create it here.
-+ */
-+ state.vars_seen = g_hash_table_new_full(g_str_hash,
-+ g_str_equal,
-+ free, NULL);
-+
-+ for (i = 0; i < object_names_cnt; i++)
-+ process_file(object_names[i], dedup,
-+ dedup_tu_init, dedup_tu_done, &state);
-+
-+ if ((!state.repeat_detection) || !deduplicating)
-+ goto out;
-+
-+ do {
-+ /*
-+ * The second pass recognizes that opaque structures must be
-+ * shared if the transparent equivalents are, and vice versa,
-+ * and re-traces all transparent types that need sharing.
-+ *
-+ * It requests another alias detection pass if any non-opaque
-+ * structures are newly marked as shared.
-+ */
-+ dw_ctf_trace("Duplicate detection: alias fixup pass.\n");
-+
-+ state.repeat_detection = 0;
-+ state.named_structs = list_filter(state.named_structs,
-+ dedup_alias_fixup,
-+ free_dups_id_file, &state);
-+ } while (state.repeat_detection);
-+ out:
-+ g_hash_table_destroy(state.vars_seen);
-+ dedup_dwarf_free(&state);
-+ dw_ctf_trace("Duplicate detection: complete.\n");
-+ dw_ctf_trace("%llu distinct type IDs known.\n",
-+ (unsigned long long) g_hash_table_size(id_to_module));
-+ dw_ctf_trace("%llu variables blacklisted for static/nonstatic conflicts.\n",
-+ (unsigned long long) g_hash_table_size(variable_blacklist));
-+ g_list_free_full(state.named_structs, free_dups_id_file);
-+}
-+
-+/*
-+ * Set up state for dedup(). A tu_init() callback.
-+ */
-+static void dedup_tu_init(const char *module_name, const char *file_name,
-+ Dwarf_Die *tu_die, void *data)
-+{
-+ struct dedup_state *state = data;
-+ struct per_module *per_mod;
-+
-+ /*
-+ * Make sure that even if this module has no types in it we still end up
-+ * generating a CTF file. (Userspace depends on this, since a CTF file
-+ * with no types in means the module is known and typeless, while no CTF
-+ * file at all means the module is not known.)
-+ */
-+
-+ per_mod = g_hash_table_lookup(per_module, module_name);
-+ if (per_mod == NULL) {
-+ init_ctf_table(module_name);
-+ dw_ctf_trace("%s: initialized CTF file.\n", module_name);
-+ }
-+
-+ state->structs_seen = g_hash_table_new(g_str_hash, g_str_equal);
-+ g_hash_table_remove_all(state->vars_seen);
-+ state->module_name = module_name;
-+}
-+
-+/*
-+ * Free state for dedup(). A tu_done() callback.
-+ */
-+static void dedup_tu_done(const char *module_name, const char *file_name,
-+ Dwarf_Die *tu_die, void *data)
-+{
-+ struct dedup_state *state = data;
-+
-+ /*
-+ * We have to annul module_name because it is freed between object files
-+ * by process_file(). Since we use that to track whether vars_seen
-+ * needs reconstructing, that means we have to destroy that as well.
-+ */
-+ g_hash_table_destroy(state->structs_seen);
-+ state->structs_seen = NULL;
-+ state->module_name = NULL;
-+}
-+
-+/*
-+ * Free DWARF state for dedup().
-+ */
-+static void dedup_dwarf_free(struct dedup_state *state)
-+{
-+ if (state->dwfl == NULL)
-+ return;
-+ simple_dwfl_free(state->dwfl);
-+ state->dwfl = NULL;
-+ state->dwarf = NULL;
-+ free(state->dwfl_file_name);
-+ state->dwfl_file_name = NULL;
-+ if (state->structs_seen)
-+ g_hash_table_destroy(state->structs_seen);
-+ state->structs_seen = NULL;
-+}
-+
-+/*
-+ * Duplicate detection.
-+ *
-+ * Scan for duplicate types. A duplicate type is defined as any type which
-+ * appears in more than one module, or, more precisely, any type for which a
-+ * type with the same ID already exists in another module.
-+ *
-+ * This pass also constructs the id_to_module table, so is essential even when
-+ * deduplication is disabled (though then it need be run only once.)
-+ */
-+
-+static void dedup(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die, void *data)
-+{
-+ struct dedup_state *state = data;
-+ int is_sou = 0;
-+ char *id = type_id(die, NULL, is_named_struct_union_enum, &is_sou);
-+
-+ state->file_name = file_name;
-+ /*
-+ * If a DWARF-4 type signature is found, abort. While we can support
-+ * DWARF-4 eventually, support in elfutils is insufficiently robust for
-+ * now (elfutils 0.152).
-+ */
-+ if (private_dwarf_hasattr(die, DW_AT_type)) {
-+ Dwarf_Attribute type_attr;
-+
-+ if ((private_dwarf_attr(die, DW_AT_type, &type_attr) != NULL) &&
-+ (dwarf_whatform(&type_attr) == DW_FORM_ref_sig8)) {
-+ pr_err("Sorry, not yet implemented: %s contains DWARF-4 debugging information.\n",
-+ module_name);
-+ exit(1);
-+ }
-+ }
-+
-+ /*
-+ * Non-anonymous, non-opaque structure/union/enum types in
-+ * non-dedup-blacklisted modules get their names and locations recorded
-+ * for subsequent passes; all type_id()-descendant types are similarly
-+ * noted.
-+ */
-+ if (is_sou && strncmp(id, "////", strlen("////")) != 0)
-+ free(type_id(die, NULL, dedup_will_rescan, state));
-+
-+ /*
-+ * Handle static variable blacklisting. (We still shuffle blacklisted
-+ * variables into the right place in id_to_module because we check for
-+ * blacklisting at the lowest level, by which point we have already
-+ * depended on id_to_module being correctly populated.)
-+ *
-+ * Avoid calling this for recursive dependent-type scans: variables
-+ * cannot be dependent types.
-+ */
-+ if (parent_die != NULL && dwarf_tag(die) == DW_TAG_variable)
-+ dedup_blacklist_var_dups(die, state);
-+
-+ dedup_mark_inner_die(module_name, die, id, NULL, data);
-+ free(id);
-+}
-+
-+/*
-+ * Do the underlying marking of a DIE as shared, iff need be. (No variable
-+ * blacklisting, non-opaque structure checks, or anything else needed only by
-+ * top-level DIEs.)
-+ *
-+ * This function may be called multiple times for overridden DIEs that are
-+ * dependent types of bitfields. (On multiple calls for normal types, the
-+ * second call will enter the NS_NO_MARKING case block and terminate recursion.)
-+ */
-+static void dedup_mark_inner_die(const char *module_name, Dwarf_Die *die,
-+ const char *id,
-+ struct die_override *overrides,
-+ void *data)
-+{
-+ /*
-+ * If we know of a single module incorporating this type, and it is not
-+ * the same as the module we are currently in, then this type is
-+ * duplicated across modules and belongs in the global type table.
-+ * (This means that duplicated types are repeatedly so marked: this
-+ * is unavoidable, because pass 3 requires re-marking structures that
-+ * have already been marked, to pick up unmarked intermediate types.)
-+ *
-+ * We never consider types in modules on the deduplication blacklist
-+ * to introduce duplicates.
-+ */
-+ switch (type_needs_sharing(module_name, id)) {
-+ case NS_NEEDS_SHARING:
-+ mark_shared(die, NULL, overrides, data);
-+ mark_seen_contained(die, "shared_ctf", overrides, data);
-+ /* Fall through */
-+ case NS_NO_MARKING:
-+ /*
-+ * A duplicated type, but in the same module, or deduplication
-+ * is disabled, so id_to_module is already correct. (When
-+ * deduplication is disabled, we will be running with only one
-+ * module at a time, and id_to_module will be a trivial
-+ * mapping.)
-+ */
-+ return;
-+ case NS_NOT_SHARED:
-+ break;
-+ }
-+
-+ /*
-+ * Record that we have seen this type, and all its dependent types, in
-+ * this module (or in the shared module if need be).
-+ */
-+
-+ dw_ctf_trace("Marking %s as seen in %s\n", id, module_name);
-+ g_hash_table_replace(id_to_module, intern(xstrdup(id)),
-+ xstrdup(module_name));
-+ mark_seen_contained(die, module_name, overrides, data);
-+ free(type_id(die, overrides, dedup_typeid, data));
-+}
-+
-+/*
-+ * Note in the dedup_id_file list that we will rescan a DIE in a later duplicate
-+ * detection pass.
-+ *
-+ * A type_id() callback.
-+ */
-+static void dedup_will_rescan(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data)
-+{
-+ struct dedup_state *state = data;
-+ struct dedup_id_file *id_file;
-+
-+ /*
-+ * We don't care about array index types, which will never be structures
-+ * in C.
-+ */
-+ if (id[0] == '[')
-+ return;
-+
-+ id_file = calloc(1, sizeof(struct dedup_id_file));
-+ if (id_file == NULL) {
-+ pr_err("Out of memory allocating id_file\n");
-+ exit(1);
-+ }
-+ id_file->file_name = intern(xstrdup(state->file_name));
-+ id_file->id = intern(xstrdup(id));
-+ id_file->dieoff = dwarf_dieoffset(die);
-+ state->named_structs = g_list_prepend(state->named_structs, id_file);
-+}
-+
-+/*
-+ * Note the variable referenced by this DIE in vars_seen: blacklist it if an
-+ * entry for this variable already exists in vars_seen and this instance is
-+ * static, or if a static entry already exists in vars_seen, whether this
-+ * instance is static or not.
-+ */
-+static void dedup_blacklist_var_dups(Dwarf_Die *die,
-+ struct dedup_state *state)
-+{
-+ void *static_var;
-+ int blacklist = 0;
-+
-+ if (g_hash_table_lookup_extended(state->vars_seen,
-+ dwarf_diename(die),
-+ NULL, &static_var)) {
-+ if (!private_dwarf_hasattr(die, DW_AT_external) &&
-+ !private_dwarf_hasattr(die, DW_AT_declaration))
-+ blacklist = 1;
-+ if (static_var != NULL)
-+ blacklist = 1;
-+ } else
-+ /*
-+ * We need a non-NULL address here, but that is all we need.
-+ * The address of a random variable will do.
-+ */
-+ g_hash_table_insert(state->vars_seen,
-+ xstrdup(dwarf_diename(die)),
-+ (!private_dwarf_hasattr(die, DW_AT_external) &&
-+ !private_dwarf_hasattr(die, DW_AT_declaration)) ?
-+ &static_var : NULL);
-+
-+ if (blacklist) {
-+ char *var = NULL;
-+ var = str_appendn(var, state->module_name, "`",
-+ dwarf_diename(die), NULL);
-+ g_hash_table_replace(variable_blacklist, var, NULL);
-+ }
-+}
-+
-+/*
-+ * Free a dedup_id_file's contents.
-+ */
-+static void free_dups_id_file(void *data)
-+{
-+ struct dedup_id_file *id_file = data;
-+ free(id_file);
-+}
-+
-+/*
-+ * Determine if a type is duplicated and needs sharing.
-+ */
-+static enum needs_sharing type_needs_sharing(const char *module_name,
-+ const char *id)
-+{
-+ const char *existing_type_module;
-+ existing_type_module = g_hash_table_lookup(id_to_module, id);
-+
-+ /*
-+ * Types not already known about do not need sharing.
-+ *
-+ * Types already in the current modules and any types in external-module
-+ * mode do not even need marking.
-+ */
-+ if (existing_type_module == NULL)
-+ return NS_NOT_SHARED;
-+
-+ if ((strcmp(existing_type_module, module_name) == 0) ||
-+ (strcmp(existing_type_module, "shared_ctf") == 0) ||
-+ !deduplicating)
-+ return NS_NO_MARKING;
-+
-+ return NS_NEEDS_SHARING;
-+}
-+
-+/*
-+ * Detect duplicates and mark seen types for a given type, via a type_id()
-+ * callback: used to detect dependent types (particularly those at child-DIE
-+ * level) as duplicates.
-+ */
-+static void dedup_typeid(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data)
-+{
-+ struct dedup_state *state = data;
-+
-+ dedup_mark_inner_die(state->module_name, die, id, overrides, data);
-+}
-+
-+/*
-+ * Mark any types contained within a particular type DIE as seen. This is
-+ * needed since even nameless types contained within other aggregates can be
-+ * used as the type of members in any of their enclosing aggregates (though they
-+ * cannot possibly be found in a module different from that of their containing
-+ * aggregate, any more than a structure member can).
-+ */
-+static void mark_seen_contained(Dwarf_Die *die, const char *module_name,
-+ struct die_override *overrides,
-+ void *data)
-+{
-+ const char *err;
-+ Dwarf_Die child;
-+
-+ if ((dwarf_tag(die) != DW_TAG_structure_type) &&
-+ (dwarf_tag(die) != DW_TAG_union_type))
-+ return;
-+
-+ switch (dwarf_child(die, &child)) {
-+ case -1:
-+ err = "fetch first child of aggregate";
-+ goto fail;
-+ case 1: /* No DIEs at all in this aggregate */
-+ return;
-+ default: /* Child DIEs exist. */
-+ break;
-+ }
-+
-+ /*
-+ * We iterate over all immediate children and recursively call ourselves
-+ * for all those of type DW_TAG_structure_type and DW_TAG_union_type.
-+ *
-+ * Further, everything with an entry in assembly_tab other than
-+ * non-bitfield members needs marking, since these may be declared at
-+ * structure scope rather than being confined to global scope.
-+ * Non-bitfield members are skipped because they cannot be used as the
-+ * type of another field. These types cannot be duplicates if their
-+ * containing type is not a duplicate, and typedefs cannot occur at this
-+ * level so they cannot be aliased; thus we can mark them directly
-+ * without going back into the top of dedup().
-+ *
-+ * (Bit-field members are not skipped: they use different CTF from their
-+ * non-bitfield equivalents, even though they refer to the same
-+ * top-level DIE. The actual different CTF is handled by type_id()
-+ * itself, but we do have to call it.)
-+ */
-+ int sib_ret;
-+
-+ do
-+ switch (dwarf_tag(&child)) {
-+ case DW_TAG_member: {
-+ /*
-+ * bit_size and bit_offset go together: we can assume
-+ * that if a member has the one, it has the other,
-+ * is a bitfield, and needs recursive marking.
-+ */
-+ if (dwarf_tag(&child) == DW_TAG_member &&
-+ !private_dwarf_hasattr(&child, DW_AT_bit_size))
-+ break;
-+
-+ free(type_id(&child, overrides, dedup_typeid, data));
-+ break;
-+ }
-+ case DW_TAG_structure_type:
-+ case DW_TAG_union_type:
-+ mark_seen_contained(&child, module_name, overrides, data);
-+ /* fall through */
-+ default:
-+ if (dwarf_tag(&child) < assembly_len &&
-+ assembly_tab[dwarf_tag(&child)] != NULL) {
-+
-+ char *id = type_id(&child, overrides, NULL, NULL);
-+
-+ dw_ctf_trace("Marking member %s as seen in "
-+ "%s\n", id, module_name);
-+ g_hash_table_replace(id_to_module, intern(id),
-+ xstrdup(module_name));
-+ }
-+ }
-+ while ((sib_ret = dwarf_siblingof(&child, &child)) == 0);
-+
-+ if (sib_ret == -1) {
-+ err = "iterate over members";
-+ goto fail;
-+ }
-+
-+ return;
-+
-+ fail:
-+ pr_err("Cannot %s while marking aggregates as seen: %s\n",
-+ err, dwfl_errmsg(dwfl_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * Mark a type as duplicated and located in the shared CTF table. Recursive,
-+ * via the type_id() callback mechanism.
-+ *
-+ * A type_id() callback (though also called directly).
-+ */
-+static void mark_shared(Dwarf_Die *die, const char *id,
-+ struct die_override *overrides, void *data)
-+{
-+ struct dedup_state *state = data;
-+ const char *existing_module;
-+
-+ /*
-+ * Non-recursive call. Trigger type_id for its recursive callback,
-+ * throwing the result away.
-+ */
-+ if (id == NULL) {
-+ free(type_id(die, overrides, mark_shared, state));
-+ return;
-+ }
-+
-+ existing_module = g_hash_table_lookup(id_to_module, id);
-+
-+ if ((existing_module == NULL) ||
-+ (strcmp(existing_module, "shared_ctf") != 0)) {
-+
-+ dw_ctf_trace("Marking %s as duplicate\n", id);
-+ g_hash_table_replace(id_to_module, intern(xstrdup(id)),
-+ xstrdup("shared_ctf"));
-+
-+ /*
-+ * Newly-marked structures/unions/enums must trigger a new
-+ * duplicate detection pass (even if they are opaque).
-+ */
-+
-+ if (((dwarf_tag(die) == DW_TAG_structure_type) ||
-+ (dwarf_tag(die) == DW_TAG_union_type) ||
-+ (dwarf_tag(die) == DW_TAG_enumeration_type)) &&
-+ (!state->repeat_detection)) {
-+ dw_ctf_trace("Requesting another duplicate detection pass.\n");
-+ state->repeat_detection = 1;
-+ }
-+ }
-+
-+ /*
-+ * If this is a structure or union, mark its members as duplicates too.
-+ *
-+ * Do this even if we've seen this structure before, as this instance of
-+ * the structure may have more members than the last we saw. However,
-+ * if we have seen this structure before *in this translation unit*,
-+ * skip it, to avoid infinite recursion in mutually referential
-+ * structures.
-+ */
-+ if ((dwarf_tag(die) == DW_TAG_structure_type) ||
-+ (dwarf_tag(die) == DW_TAG_union_type)) {
-+ Dwarf_Die child;
-+
-+ if (g_hash_table_lookup_extended(state->structs_seen, id,
-+ NULL, NULL))
-+ return;
-+ g_hash_table_replace(state->structs_seen, intern(xstrdup(id)),
-+ NULL);
-+
-+ switch (dwarf_child(die, &child)) {
-+ case -1:
-+ goto fail;
-+ case 1: /* No DIEs at all in this aggregate */
-+ return;
-+ }
-+
-+ /*
-+ * We are only interested in non-blacklisted children of type
-+ * DW_TAG_member.
-+ */
-+ int sib_ret;
-+
-+ do
-+ if ((dwarf_tag(&child) == DW_TAG_member) &&
-+ !member_blacklisted(&child, die))
-+ free(type_id(&child, overrides,
-+ mark_shared, state));
-+ while ((sib_ret = dwarf_siblingof(&child, &child)) == 0);
-+
-+ if (sib_ret == -1)
-+ goto fail;
-+ }
-+
-+ return;
-+
-+ fail:
-+ pr_err("Cannot mark aggregate %s members as duplicated: %s\n",
-+ dwarf_diename(die), dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * Determine if a type is a named struct, union, or enum.
-+ *
-+ * A type_id() callback.
-+ */
-+static void is_named_struct_union_enum(Dwarf_Die *die, const char *unused,
-+ struct die_override *overrides,
-+ void *data)
-+{
-+ int *is_sou = data;
-+
-+ if (((dwarf_tag(die) == DW_TAG_structure_type) ||
-+ (dwarf_tag(die) == DW_TAG_union_type) ||
-+ (dwarf_tag(die) == DW_TAG_enumeration_type)) &&
-+ (private_dwarf_hasattr(die, DW_AT_name)))
-+ *is_sou = 1;
-+}
-+
-+/*
-+ * Duplicate detection alias fixup pass. Once the first pass is complete, we
-+ * may have marked an opaque 'struct/union/enum foo' for sharing but not caught
-+ * the non-opaque instance, because no users of the non-opaque instance appeared
-+ * in the DWARF after the opaque copy was detected as a duplicate. This pass
-+ * detects such cases, and marks their members as duplicates too.
-+ *
-+ * (The inverse case of a non-opaque structure/union/enum detected as a
-+ * duplicate after the last usage of its opaque alias will be caught by this
-+ * trap too.)
-+ *
-+ * Warning: this routine directly computes type_id()s without access to the
-+ * corresponding type DIE, and as such is dependent on the format of type_id()s.
-+ * (This is why it must run over non-opaque structures: given a non-opaque
-+ * structure, its opaque alias is easy to compute, but the converse is not
-+ * true.)
-+ *
-+ * As a list_filter() filter function, returns nonzero if this structure will
-+ * not need to be checked again (because both its opaque and transparent
-+ * variants are shared).
-+ */
-+static int dedup_alias_fixup(void *id_file_data, void *data)
-+{
-+ struct dedup_id_file *id_file = id_file_data;
-+ struct dedup_state *state = data;
-+
-+ int transparent_shared = 0;
-+ int opaque_shared = 0;
-+ int made_shared = 0;
-+
-+ char *opaque_id;
-+ const char *line_num;
-+ const char *type_size;
-+ const char *type_name;
-+
-+ /*
-+ * Compute the opaque variant corresponding to this transparent type,
-+ * and check to see if either is marked shared, then find the DIE and
-+ * mark both as shared if either is. (Unfortunately this means a double
-+ * recursion in such cases, but this is unavoidable.)
-+ */
-+
-+ line_num = strstr(id_file->id, "//");
-+ if (!line_num) {
-+ pr_err("Internal error: type ID %s is corrupt.\n",
-+ id_file->id);
-+ exit(1);
-+ }
-+
-+ type_size = strstr(line_num + 2, "//");
-+ if (!type_size) {
-+ pr_err("Internal error: type ID %s is corrupt.\n",
-+ id_file->id);
-+ exit(1);
-+ }
-+
-+ type_name = strstr(type_size + 2, "//");
-+ if (!type_name) {
-+ /*
-+ * That's OK: the type size is optional, so what we thought was
-+ * the type size is actually the type name.
-+ */
-+ type_name = type_size;
-+ }
-+ type_name += 2;
-+
-+ opaque_id = xstrdup("////");
-+ opaque_id = str_append(opaque_id, type_name);
-+
-+ const char *transparent_module = g_hash_table_lookup(id_to_module,
-+ id_file->id);
-+ const char *opaque_module = g_hash_table_lookup(id_to_module,
-+ opaque_id);
-+
-+ transparent_shared = ((transparent_module != NULL) &&
-+ (strcmp(transparent_module, "shared_ctf") == 0));
-+
-+ opaque_shared = ((opaque_module != NULL) &&
-+ (strcmp(opaque_module, "shared_ctf") == 0));
-+
-+ /*
-+ * Transparent type needs sharing.
-+ */
-+ if (opaque_shared && !transparent_shared) {
-+ Dwarf_Die die;
-+ Dwfl_Module *mod;
-+ Dwarf_Addr dummy;
-+
-+ /*
-+ * Since we are not using process_file(), we must handle
-+ * translation unit switches by hand, including resetting
-+ * structs_seen. We also need to open the DWARF file, since
-+ * type_id() needs access to the DIE of this type and all its
-+ * dependent types as well.
-+ */
-+
-+ if (state->dwfl != NULL &&
-+ strcmp(state->dwfl_file_name, id_file->file_name) != 0)
-+ dedup_dwarf_free(state);
-+
-+ if (state->dwfl_file_name == NULL) {
-+ state->dwfl = simple_dwfl_new(id_file->file_name, &mod);
-+ state->dwarf = dwfl_module_getdwarf(mod, &dummy);
-+ state->dwfl_file_name = xstrdup(id_file->file_name);
-+ if (state->structs_seen)
-+ g_hash_table_destroy(state->structs_seen);
-+ state->structs_seen = g_hash_table_new(g_str_hash,
-+ g_str_equal);
-+ }
-+ if (!dwarf_offdie(state->dwarf, id_file->dieoff,
-+ &die)) {
-+ pr_err("Cannot look up offset %li in %s for type with ID %s\n",
-+ id_file->dieoff, id_file->file_name, id_file->id);
-+ exit(1);
-+ }
-+ mark_shared(&die, NULL, NULL, state);
-+ made_shared = 1;
-+ }
-+
-+ /*
-+ * We don't have the opaque type's DIE, so we can't use mark_shared():
-+ * this is also good since this triggers another duplicate detection
-+ * pass, and we don't want to trigger another pass merely because of a
-+ * nonshared opaque type (since they don't have members that may have
-+ * structure or union type themselves and thus force more unshared
-+ * types to become shared).
-+ *
-+ * Instead, do it by hand: this is simple, as member recursion is
-+ * guaranteed not to be required for an opaque type.
-+ */
-+ if (transparent_shared && !opaque_shared) {
-+ dw_ctf_trace("Marking %s as duplicate\n", opaque_id);
-+ g_hash_table_replace(id_to_module, intern(xstrdup(opaque_id)),
-+ xstrdup("shared_ctf"));
-+ made_shared = 1;
-+ }
-+
-+ free(opaque_id);
-+
-+ return made_shared || (opaque_shared && transparent_shared);
-+}
-+
-+/*
-+ * Mark a basic type shared by name and intern it in all relevant hashes. (Used
-+ * for marking basic types we don't have a DIE for.)
-+ */
-+static void mark_shared_by_name(ctf_file_t *ctf, ctf_id_t ctf_id,
-+ const char *name)
-+{
-+ struct ctf_full_id static_ctf_id = { ctf, ctf_id };
-+ struct ctf_full_id *full_ctf_id;
-+ char *id = NULL;
-+
-+ full_ctf_id = malloc(sizeof(struct ctf_full_id));
-+ if (full_ctf_id == NULL) {
-+ pr_err("%s: out of memory\n", __func__);
-+ exit(1);
-+ }
-+ *full_ctf_id = static_ctf_id;
-+
-+ id = str_appendn(id, "////", name, " ", NULL);
-+#ifdef DEBUG
-+ strcpy(full_ctf_id->module_name, "shared_ctf");
-+ strcpy(full_ctf_id->file_name, "<built-in type>");
-+#endif
-+ g_hash_table_replace(id_to_module, intern(xstrdup(id)), xstrdup("shared_ctf"));
-+ g_hash_table_replace(id_to_type, intern(id), full_ctf_id);
-+}
-+
-+/*
-+ * Type assembly.
-+ *
-+ * Given a DWARF DIE corresponding to a top-level type, call the appropriate
-+ * construction function, passing it the appropriate ctf_file_t, constructing it
-+ * if necessary, and stashing them in the appropriate hashes. Return the
-+ * ctf_file_t and ctf_id_t of this type.
-+ *
-+ * Indirectly recursively called for types depending on other types, and for
-+ * the types of variables (which for the sake of argument we call 'types' here
-+ * too, since we treat them exactly like types, and dealing with types is our
-+ * most important function). In such calls, the module_name may be 'shared_ctf'
-+ * if this type is in the shared CTF repository.
-+ *
-+ * Select properties of the DIE can be overridden via the overrides array, if
-+ * needed.
-+ */
-+static struct ctf_full_id *construct_ctf_id(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ struct die_override *overrides)
-+{
-+ char *id = type_id(die, overrides, NULL, NULL);
-+ char *ctf_module;
-+ ctf_file_t *ctf;
-+ ctf_snapshot_id_t snapshot;
-+
-+ dw_ctf_trace(" %p: %s: looking up %s: %s\n", &id,
-+ module_name ? module_name : "(no module)",
-+ dwarf_diename(die), id);
-+ /*
-+ * Make sure this type does not already exist. (Recursive chasing for
-+ * referenced types can lead to construct_ctf() being called on them
-+ * more than once.)
-+ */
-+ struct ctf_full_id *ctf_id;
-+
-+ ctf_id = g_hash_table_lookup(id_to_type, id);
-+ if (ctf_id != NULL) {
-+ dw_ctf_trace(" %p: %p:%i found in module %s, file %s\n", &id,
-+ ctf_id->ctf_file, (int) ctf_id->ctf_id,
-+ ctf_id->module_name, ctf_id->file_name);
-+ free(id);
-+ return ctf_id;
-+ }
-+
-+ /*
-+ * Create the CTF file for this type, if it does not exist. Verify that
-+ * the duplicate-detection pass scanned this type, and that this is
-+ * either the current module or the shared CTF module.
-+ */
-+
-+ ctf_module = g_hash_table_lookup(id_to_module, id);
-+
-+ if (ctf_module == NULL) {
-+ pr_err("Internal error: within file %s, module %s, type at DIE offset %lx\n"
-+ "with ID %s was not already noted by dedup().\n",
-+ file_name, module_name, DIEOFFSET(die), id);
-+ pr_err("dedup() is probably buggy.\n");
-+ exit(1);
-+ }
-+
-+ if ((strcmp(ctf_module, module_name) != 0) &&
-+ (strcmp(ctf_module, "shared_ctf") != 0)) {
-+ pr_err("Internal error: within file %s, module %s, type at DIE offset %lx\n"
-+ "with ID %s is in a different non-shared module, %s.\n",
-+ file_name, module_name, DIEOFFSET(die), id, ctf_module);
-+ pr_err("dedup() is probably buggy.\n");
-+ exit(1);
-+ }
-+
-+ ctf = lookup_ctf_file(ctf_module);
-+
-+ /*
-+ * Construct the CTF, then insert the top-level CTF entity into the
-+ * id->type hash so that references from other types can find it, and
-+ * update the CTF container. If conversion failed, roll back all
-+ * changes made since the last successful call to this function.
-+ *
-+ * NOTE: references within DWARF to non-top-level types will currently
-+ * fail, but I'm not sure if these can exist. (The type ID
-+ * representation implicitly assumes that they cannot.)
-+ */
-+
-+ snapshot = ctf_snapshot(ctf);
-+
-+ enum skip_type skip = SKIP_CONTINUE;
-+
-+ dw_ctf_trace("%p: into die_to_ctf() for %s\n", &id, id);
-+ ctf_id_t this_ctf_id = die_to_ctf(ctf_module, file_name, die,
-+ parent_die, ctf, -1, overrides,
-+ 1, 0, &skip, NULL, id);
-+ dw_ctf_trace("%p: out of die_to_ctf()\n", &id);
-+
-+ ctf_id = malloc(sizeof(struct ctf_full_id));
-+ if (ctf_id == NULL) {
-+ pr_err("Out of memory\n");
-+ exit(1);
-+ }
-+
-+ if (skip != SKIP_ABORT) {
-+ ctf_id->ctf_file = ctf;
-+ ctf_id->ctf_id = this_ctf_id;
-+#ifdef DEBUG
-+ strcpy(ctf_id->module_name, ctf_module);
-+ strcpy(ctf_id->file_name, file_name);
-+#endif
-+ dw_ctf_trace(" %lx: %s: new type added, CTF ID %p:%li\n",
-+ DIEOFFSET(die), id, ctf_id->ctf_file,
-+ ctf_id->ctf_id);
-+
-+ g_hash_table_replace(id_to_type, intern(id), ctf_id);
-+ } else {
-+ /*
-+ * Failure. Remove the type from the id_to_type mapping, if it
-+ * is there, and discard any added types from the CTF.
-+ *
-+ * If we have had to ctf_update() due to a new type getting
-+ * used, the rollback will fail: discard instead. It might leave
-+ * some spurious types hanging around but it will clean up as
-+ * much as we can at this point. (This cannot happen when
-+ * LIBDTRACE_CTF_OMISSIBLE_CTF_UPDATE, but it costs nothing to
-+ * leave in: failure is a rare case.)
-+ */
-+
-+ if (ctf_rollback(ctf, snapshot) < 0)
-+ if (ctf_errno(ctf) == ECTF_OVERROLLBACK)
-+ ctf_discard(ctf);
-+
-+ free(ctf_id);
-+ ctf_id = NULL;
-+
-+ g_hash_table_remove(id_to_type, id);
-+ free(id);
-+
-+ dw_ctf_trace(" %p: (failure)\n", &id);
-+ }
-+
-+ return ctf_id;
-+}
-+
-+/*
-+ * Given a DWARF DIE corresponding to a top-level type, or to an aggregate
-+ * member, and the ctf_file_t where it is to be placed, call the appropriate
-+ * construction function to place it and (for aggregates) its siblings there,
-+ * recursing to handle contained aggregates.
-+ *
-+ * The parameters to this function are:
-+ *
-+ * module_name: The kernel module.
-+ * file_name: The object file.
-+ * die: The DWARF DIE.
-+ * parent_die: Its parent, i.e. if a structure member, this is a structure: if
-+ * top-level, this is a CU DIE.
-+ * ctf: The CTF file this object should go into (possibly shared_ctf).
-+ * parent_ctf_id: The CTF ID of the parent DIE, or -1 if none.
-+ * struct die_override: Overrides for DWARF attributes (a NULL-terminated array,
-+ * or NULL).
-+ * top_level_type: 1 if this is a top-level type that can have a name and be
-+ * referred to by other types.
-+ * backwards: if 1, this is an internal call to process a series of bitfields
-+ * with descending bit_offset and identical data_member_location.
-+ * skip: The error-handling / skipping enum.
-+ * replace: if 1, this type should replace its parent type entirely.
-+ * id: the ID of this type.
-+ *
-+ * Note: id is only defined when top_level_type is 1. (We never use it
-+ * in other situations, and computing it is quite expensive.)
-+ */
-+static ctf_id_t die_to_ctf(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die,
-+ ctf_file_t *ctf, ctf_id_t parent_ctf_id,
-+ struct die_override *overrides, int top_level_type,
-+ int backwards, enum skip_type *skip, int *replace,
-+ const char *id)
-+{
-+ int sib_ret = 0;
-+ ctf_id_t this_ctf_id;
-+ int dummy;
-+
-+ do {
-+ const char *id_name;
-+ const char *decl_file_name = dwarf_decl_file(die);
-+ int decl_line_num;
-+ int emitted_backwards = 0;
-+ char locerrstr[1024];
-+ Dwarf_Die next_die;
-+
-+ /*
-+ * If the next DWARF DIE is at the same location as this one but
-+ * with a lower bit_offset, we need to process the set of DIEs
-+ * at this location in *reverse*, because DWARF has the DIEs in
-+ * declaration order, while CTF wants them in in-memory order:
-+ * so recurse to handle the next until we get to an element with
-+ * a sibling at a different data_member_location (safe because
-+ * there can't be that many of them per data_member_location),
-+ * then (at the end of die_to_ctf()) exit the recursion and skip
-+ * over the lot.
-+ *
-+ * We can ignore 'replace' and the return value of die_to_ctf
-+ * because bitfields must be structure or union members and
-+ * cannot be array dimensions.
-+ */
-+ if (die_emit_next_backwards(&next_die, die,
-+ overrides) != NULL) {
-+ ctf_id_t dummy;
-+
-+ dw_ctf_trace("Emitting %s:%s:%lx backwards\n",
-+ module_name, file_name,
-+ DIEOFFSET(&next_die));
-+
-+ dummy = die_to_ctf(module_name, file_name, &next_die,
-+ parent_die, ctf, parent_ctf_id,
-+ overrides, top_level_type, 1, skip,
-+ replace, NULL);
-+ if (*skip == SKIP_ABORT)
-+ return dummy;
-+ emitted_backwards = 1;
-+ }
-+
-+ /*
-+ * Compute a name for our current location, for error messages.
-+ * (The type representation could be used, but is likely to be
-+ * hard for users to comprehend, and should we move to a hashed
-+ * representation would be entirely useless for this purpose.)
-+ */
-+ if ((decl_file_name == NULL) ||
-+ (dwarf_decl_line(die, &decl_line_num) < 0)) {
-+ decl_file_name = "global";
-+ decl_line_num = 0;
-+ }
-+
-+ id_name = dwarf_diename(die);
-+ if (id_name == NULL)
-+ id_name = "(unnamed type)";
-+
-+ snprintf(locerrstr, sizeof(locerrstr), "%s:%i:%s",
-+ decl_file_name, decl_line_num, id_name);
-+
-+ dw_ctf_trace("Working over %s:%s:%s:%lx:%x with CTF file %p\n",
-+ module_name, file_name,
-+ dwarf_diename(die)==NULL?"NULL":dwarf_diename(die),
-+ DIEOFFSET(die), dwarf_tag(die), ctf);
-+
-+ /*
-+ * Only process a given node, or its children, if we know how to
-+ * do so.
-+ */
-+ if ((dwarf_tag(die) >= assembly_len) ||
-+ (assembly_tab[dwarf_tag(die)] == NULL)) {
-+ pr_err("%s:%i: warning: skipping identifier "
-+ "%s with unknown DWARF tag %lx.\n",
-+ decl_file_name, decl_line_num, id_name,
-+ (unsigned long) dwarf_tag(die));
-+ return -1;
-+ }
-+
-+ *skip = SKIP_CONTINUE;
-+
-+ this_ctf_id = assembly_tab[dwarf_tag(die)](module_name,
-+ file_name,
-+ die, parent_die,
-+ ctf, parent_ctf_id,
-+ locerrstr,
-+ overrides,
-+ top_level_type,
-+ skip,
-+ replace ? replace :
-+ &dummy);
-+ dw_ctf_trace("%s: out of assembly function for tag %lx with type ID %li\n",
-+ locerrstr, (unsigned long) dwarf_tag(die),
-+ this_ctf_id);
-+
-+ if (this_ctf_id < 0) {
-+ if ((this_ctf_id == CTF_NO_ERROR_REPORTED) &&
-+ (ctf_errno(ctf) != 0))
-+ pr_err("%s: CTF error in assembly of item with tag %i: %s\n",
-+ locerrstr, dwarf_tag(die),
-+ ctf_errmsg(ctf_errno(ctf)));
-+
-+ num_errors++;
-+#ifdef DEBUG
-+ exit(1);
-+#endif
-+ *skip = SKIP_ABORT;
-+ }
-+
-+ /*
-+ * Add newly-added non-skipped top-level structure or union CTF
-+ * IDs to the type table at once. This allows circular type
-+ * references via pointers in structure/union member DIEs to be
-+ * looked up correctly.
-+ */
-+ if (top_level_type && (*skip == SKIP_CONTINUE) &&
-+ ((dwarf_tag(die) == DW_TAG_structure_type) ||
-+ (dwarf_tag(die) == DW_TAG_union_type))) {
-+ struct ctf_full_id full_ctf_id = { ctf, this_ctf_id };
-+ struct ctf_full_id *ctf_id;
-+
-+#ifdef DEBUG
-+ strcpy(full_ctf_id.module_name, module_name);
-+ strcpy(full_ctf_id.file_name, file_name);
-+#endif
-+
-+ ctf_id = malloc(sizeof(struct ctf_full_id));
-+ if (ctf_id == NULL) {
-+ fprintf(stderr,
-+ "Out of memory allocating type ID\n");
-+ exit(1);
-+ }
-+
-+ dw_ctf_trace(" %s: immediate addition of %s, CTF ID "
-+ "%p:%li in module %s, file %s\n", __func__,
-+ id, full_ctf_id.ctf_file, full_ctf_id.ctf_id,
-+ module_name, file_name);
-+ *ctf_id = full_ctf_id;
-+
-+ g_hash_table_replace(id_to_type, intern(xstrdup(id)),
-+ ctf_id);
-+ }
-+
-+ /*
-+ * Recurse to handle contained DIEs.
-+ */
-+
-+ if ((dwarf_haschildren(die)) && (*skip == SKIP_CONTINUE)) {
-+ Dwarf_Die child_die;
-+ ctf_id_t new_id;
-+ int replace = 0;
-+
-+ if (dwarf_child(die, &child_die) < 0) {
-+ pr_err("%s: Cannot recurse to DWARF DIE children: %s\n",
-+ locerrstr, dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+ }
-+
-+ new_id = die_to_ctf(module_name, file_name, &child_die,
-+ die, ctf, this_ctf_id, overrides, 0,
-+ 0, skip, &replace, NULL);
-+ if (replace)
-+ this_ctf_id = new_id;
-+ }
-+
-+ /*
-+ * If we are walking backwards over a bunch of bitfields, this
-+ * is a recursive walk, not an iterative one: return.
-+ */
-+ if (backwards)
-+ return this_ctf_id;
-+
-+ /*
-+ * We are not walking backwards, but this is the final stage of
-+ * a bunch of backwards emissions: walk forwards until we hit
-+ * the last one again.
-+ */
-+ if (emitted_backwards)
-+ while (die_emit_next_backwards(&next_die, die,
-+ overrides) != NULL)
-+ *die = next_die;
-+
-+ /*
-+ * Walk siblings of non-top-level types only: the sibling walk
-+ * of top-level types is done by process_file(), so that
-+ * construct_ctf_id() gets a chance to put each such type in the
-+ * right CTF file.
-+ */
-+ } while (*skip != SKIP_ABORT && !top_level_type &&
-+ (sib_ret = dwarf_siblingof(die, die)) == 0);
-+
-+ if (sib_ret == -1) {
-+ pr_err("In module %s, failure walking the sibling list: %s\n",
-+ module_name, dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+ }
-+
-+ dw_ctf_trace("New type ID: %p:%li\n", ctf, this_ctf_id);
-+ return this_ctf_id;
-+}
-+
-+/*
-+ * Calls construct_ctf_id() and throws the ID away. Used as a process_file()
-+ * callback.
-+ */
-+static void construct_ctf(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die,
-+ void *unused __unused__)
-+{
-+ construct_ctf_id(module_name, file_name, die, parent_die, NULL);
-+}
-+
-+/*
-+ * Return the next DIE, if that DIE needs to be emitted before this one.
-+ */
-+static Dwarf_Die *die_emit_next_backwards(Dwarf_Die *next, Dwarf_Die *die,
-+ struct die_override *overrides)
-+{
-+ if (dwarf_tag(die) == DW_TAG_member &&
-+ dwarf_siblingof(die, next) == 0 &&
-+ dwarf_tag(next) == DW_TAG_member &&
-+ private_dwarf_hasattr(die, DW_AT_data_member_location) &&
-+ private_dwarf_hasattr(next, DW_AT_data_member_location) &&
-+ private_dwarf_udata(die, DW_AT_data_member_location, overrides) ==
-+ private_dwarf_udata(next, DW_AT_data_member_location, overrides) &&
-+ private_dwarf_hasattr(die, DW_AT_bit_offset) &&
-+ private_dwarf_hasattr(next, DW_AT_bit_offset) &&
-+ private_dwarf_udata(die, DW_AT_bit_offset, overrides) >
-+ private_dwarf_udata(next, DW_AT_bit_offset, overrides))
-+ return next;
-+ return NULL;
-+}
-+
-+/*
-+ * Look up a type through its reference: return its ctf_id, or recursively
-+ * construct it if need be.
-+ */
-+static ctf_id_t lookup_ctf_type(const char *module_name, const char *file_name,
-+ Dwarf_Die *die, ctf_file_t *ctf,
-+ struct die_override *overrides,
-+ const char *locerrstr)
-+{
-+ Dwarf_Die tmp;
-+ Dwarf_Die *type_die = private_dwarf_type(die, &tmp);
-+ Dwarf_Die cu_die;
-+ struct ctf_full_id *type_ref;
-+
-+ /*
-+ * Pointers to functions and void are special cases: there is only one
-+ * of each of these in CTF, so we can use global singletons.
-+ */
-+
-+ if (type_die == NULL)
-+ return ctf_void_type;
-+
-+ if (dwarf_tag(type_die) == DW_TAG_subroutine_type)
-+ return ctf_funcptr_type;
-+
-+ /*
-+ * Look up or construct CTF for this type.
-+ */
-+
-+ dwarf_diecu(type_die, &cu_die, NULL, NULL);
-+
-+ dw_ctf_trace(" %s: Looking up dependent type at offset %lx for type %s at module %s, file %s\n",
-+ locerrstr, DIEOFFSET(type_die),
-+ dwarf_diename(die) ? dwarf_diename(die) : "NULL",
-+ module_name, file_name);
-+
-+ type_ref = construct_ctf_id(module_name, file_name,
-+ type_die, &cu_die, overrides);
-+
-+ /*
-+ * Pass any error back up.
-+ */
-+ if (type_ref == NULL) {
-+ pr_err("%s: type lookup failed.\n", locerrstr);
-+ return -1;
-+ }
-+
-+ if ((type_ref->ctf_file != ctf) &&
-+ type_ref->ctf_file != lookup_ctf_file("shared_ctf")) {
-+#ifdef DEBUG
-+ pr_err("%s: Internal error: lookup of %s found in different file: "
-+ "%s/%s versus %s/%s.\n", locerrstr,
-+ dwarf_diename(die) ? dwarf_diename(die) : "(unnamed)",
-+ type_ref->module_name, type_ref->file_name,
-+ module_name, file_name);
-+#else
-+ pr_err("%s: Internal error: lookup of %s found in different file.\n",
-+ locerrstr, dwarf_diename(die) ? dwarf_diename(die) :
-+ "(unnamed)");
-+#endif
-+ pr_err("dedup() is probably buggy.\n");
-+ exit(1);
-+ }
-+
-+ return type_ref->ctf_id;
-+}
-+
-+/* Assembly functions. */
-+
-+#define CTF_DW_ENFORCE(attribute) do \
-+ if (!private_dwarf_hasattr(die, (DW_AT_##attribute))) { \
-+ pr_err("%s: %s: %lx: skipping type, %s attribute not present.\n", \
-+ locerrstr, __func__, DIEOFFSET(die), \
-+ #attribute); \
-+ *skip = SKIP_ABORT; \
-+ return CTF_ERROR_REPORTED; \
-+ } \
-+ while (0)
-+
-+#define CTF_DW_ENFORCE_NOT(attribute) do \
-+ if (private_dwarf_hasattr(die, (DW_AT_##attribute))) { \
-+ pr_err("%s: %s: %lx: skipping type, %s attribute not supported.\n", \
-+ locerrstr, __func__, DIEOFFSET(die), \
-+ #attribute); \
-+ *skip = SKIP_ABORT; \
-+ return CTF_ERROR_REPORTED; \
-+ } \
-+ while (0)
-+
-+#define ROOT_TYPE(x) (x) ? CTF_ADD_ROOT : CTF_ADD_NONROOT
-+
-+/*
-+ * A CTF assembly filter function which excludes all types not at the global
-+ * scope (i.e. whose immediate parent is not a CU DIE), and all types which
-+ * reference a type which is not at the global scope (thus ruling out local type
-+ * definitions for which the compiler is not consistently emitting all
-+ * intermediate types at the local scope).
-+ */
-+static int filter_ctf_file_scope(const char *file_name, Dwarf *dwarf,
-+ Dwarf_Die *die, Dwarf_Die *parent_die)
-+{
-+ Dwarf_Die type_die;
-+ GHashTable *parents;
-+
-+ /*
-+ * A type not dependent on another is acceptable iff it is at the global
-+ * scope.
-+ */
-+ if (private_dwarf_type(die, &type_die) == NULL)
-+ return (dwarf_tag(parent_die) == DW_TAG_compile_unit);
-+
-+ /*
-+ * No type we reference may have a subprogram DIE as any of its parents.
-+ */
-+ parents = g_hash_table_lookup(fn_to_die_to_parent,
-+ abs_file_name(file_name));
-+
-+ do {
-+ Dwarf_Die parent = type_die;
-+ Dwarf_Off parent_off = 0;
-+
-+ do {
-+ if (parent_off != 0 &&
-+ !dwarf_offdie(dwarf, parent_off, &parent))
-+ break;
-+ if (dwarf_tag(&parent) == DW_TAG_subprogram)
-+ return 0;
-+ } while ((parent_off = GPOINTER_TO_UINT(g_hash_table_lookup(parents,
-+ GUINT_TO_POINTER(dwarf_dieoffset(&parent)))))
-+ != 0);
-+ } while (private_dwarf_type(&type_die, &type_die) != NULL);
-+
-+ return 1;
-+}
-+
-+/*
-+ * A CTF assembly filter function which excludes all names not at the global
-+ * scope, and all names whose names are unlikely to be interesting. (DTrace
-+ * userspace contains a similar list, but the two lists need not be in sync.)
-+ */
-+static int filter_ctf_uninteresting(const char *file_name __unused__,
-+ Dwarf *dwarf __unused__,
-+ Dwarf_Die *die, Dwarf_Die *parent_die)
-+{
-+ const char *sym_name = dwarf_diename(die);
-+
-+ /*
-+ * 'Variables' with no name are not interesting.
-+ */
-+ if (sym_name == NULL)
-+ return 0;
-+
-+#define strstarts(var, x) (strncmp(var, x, strlen(x)) == 0)
-+ return ((dwarf_tag(parent_die) == DW_TAG_compile_unit) &&
-+ !((strcmp(sym_name, "__per_cpu_start") == 0) ||
-+ (strcmp(sym_name, "__per_cpu_end") == 0) ||
-+ (strcmp(sym_name, "_sdt_probes") == 0) ||
-+ (strstarts(sym_name, "__crc_")) ||
-+ (strstarts(sym_name, "__ksymtab_")) ||
-+ (strstarts(sym_name, "__kcrctab_")) ||
-+ (strstarts(sym_name, "__kstrtab_")) ||
-+ (strstarts(sym_name, "__param_")) ||
-+ (strstarts(sym_name, "__syscall_meta__")) ||
-+ (strstarts(sym_name, "__p_syscall_meta__")) ||
-+ (strstarts(sym_name, "__event_")) ||
-+ (strstarts(sym_name, "event_")) ||
-+ (strstarts(sym_name, "ftrace_event_")) ||
-+ (strstarts(sym_name, "types__")) ||
-+ (strstarts(sym_name, "args__")) ||
-+ (strstarts(sym_name, "__tracepoint_")) ||
-+ (strstarts(sym_name, "__tpstrtab_")) ||
-+ (strstarts(sym_name, "__tpstrtab__")) ||
-+ (strstarts(sym_name, "__initcall_")) ||
-+ (strstarts(sym_name, "__setup_")) ||
-+ (strstarts(sym_name, "__pci_fixup_")) ||
-+ (strstr(sym_name, ".") != NULL)));
-+#undef strstarts
-+}
-+
-+/*
-+ * Assemble base types.
-+ */
-+static ctf_id_t assemble_ctf_base(const char *module_name,
-+ const char *file_name, Dwarf_Die *die,
-+ Dwarf_Die *parent_die, ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id, const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type, enum skip_type *skip,
-+ int *replace)
-+{
-+ typedef ctf_id_t (*ctf_add_fun)(ctf_file_t *, uint_t,
-+ const char *, const ctf_encoding_t *);
-+
-+ const char *name = dwarf_diename(die);
-+ Dwarf_Word encoding, size;
-+ ctf_add_fun ctf_add_func;
-+ ctf_encoding_t ctf_encoding;
-+ size_t encoding_search;
-+ struct die_override *bit_size_override, *bit_offset_override;
-+
-+ struct dwarf_encoding_tab {
-+ Dwarf_Word encoding;
-+ ctf_add_fun func;
-+ uint_t encoding_fixed;
-+ struct type_encoding_tab *size_lookup;
-+ };
-+
-+ struct type_encoding_tab float_encoding[] = {
-+ {sizeof(float), CTF_FP_SINGLE },
-+ {sizeof(double), CTF_FP_DOUBLE },
-+ {sizeof(long double), CTF_FP_LDOUBLE },
-+ {0, 0}
-+ };
-+
-+ struct type_encoding_tab float_cplx_encoding[] = {
-+ {sizeof(float), CTF_FP_CPLX },
-+ {sizeof(double), CTF_FP_DCPLX },
-+ {sizeof(long double), CTF_FP_LDCPLX },
-+ {0, 0}
-+ };
-+
-+ struct type_encoding_tab float_imagry_encoding[] = {
-+ {sizeof(float), CTF_FP_IMAGRY },
-+ {sizeof(double), CTF_FP_DIMAGRY },
-+ {sizeof(long double), CTF_FP_LDIMAGRY },
-+ {0, 0}
-+ };
-+
-+ struct dwarf_encoding_tab all_encodings[] = {
-+ {DW_ATE_boolean, ctf_add_integer, CTF_INT_BOOL, NULL},
-+ {DW_ATE_signed, ctf_add_integer, CTF_INT_SIGNED, NULL},
-+ {DW_ATE_signed_char, ctf_add_integer,
-+ CTF_INT_SIGNED | CTF_INT_CHAR, NULL},
-+ {DW_ATE_unsigned, ctf_add_integer, 0, NULL},
-+ {DW_ATE_unsigned_char, ctf_add_integer, CTF_INT_CHAR, NULL},
-+ {DW_ATE_float, ctf_add_float, 0, float_encoding},
-+ {DW_ATE_complex_float, ctf_add_float, 0, float_cplx_encoding},
-+ {DW_ATE_imaginary_float, ctf_add_float, 0,
-+ float_imagry_encoding},
-+ {0, 0, 0, 0}
-+ };
-+
-+ CTF_DW_ENFORCE(name);
-+ CTF_DW_ENFORCE(encoding);
-+ CTF_DW_ENFORCE(byte_size);
-+ CTF_DW_ENFORCE_NOT(endianity);
-+
-+ encoding = private_dwarf_udata(die, DW_AT_encoding, overrides);
-+ size = private_dwarf_udata(die, DW_AT_byte_size, overrides);
-+
-+ for (encoding_search = 0; all_encodings[encoding_search].func != 0;
-+ encoding_search++) {
-+ if (all_encodings[encoding_search].encoding == encoding) {
-+ ctf_add_func = all_encodings[encoding_search].func;
-+ if (all_encodings[encoding_search].size_lookup != NULL)
-+ ctf_encoding.cte_format =
-+ find_ctf_encoding(all_encodings[encoding_search].size_lookup,
-+ size);
-+ else
-+ ctf_encoding.cte_format =
-+ all_encodings[encoding_search].encoding_fixed;
-+ break;
-+ }
-+ }
-+
-+ if (all_encodings[encoding_search].func == 0) {
-+ pr_err("%s: skipping type, base type %li not yet implemented.\n",
-+ locerrstr, (long) encoding);
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ /*
-+ * Handle bitfields. Only look at overrides, since bitfields can only
-+ * be members of structures in C, thus derived from the referencing DIE.
-+ * Bitfields are never top-level types in C, even though they are in
-+ * DWARF.
-+ */
-+ bit_size_override = private_find_override(die, DW_AT_bit_size,
-+ overrides);
-+ bit_offset_override = private_find_override(die, DW_AT_bit_offset,
-+ overrides);
-+ if (bit_size_override) {
-+ ctf_encoding.cte_bits = bit_size_override->value;
-+ top_level_type = 0;
-+ } else
-+ ctf_encoding.cte_bits = size * 8;
-+
-+ if (bit_offset_override) {
-+#if __BYTE_ORDER == __BIG_ENDIAN
-+ ctf_encoding.cte_offset = bit_offset_override->value;
-+#else
-+ /*
-+ * The figure here counts from the left to the leftmost edge of
-+ * the bitfield: we want to count from the right to the
-+ * rightmost edge.
-+ */
-+ ctf_encoding.cte_offset = (size * 8) -
-+ bit_offset_override->value - ctf_encoding.cte_bits;
-+ dw_ctf_trace("Endianizing cte_offset from %x to %x\n",
-+ (unsigned int) bit_offset_override->value,
-+ ctf_encoding.cte_offset);
-+#endif
-+ } else
-+ ctf_encoding.cte_offset = 0;
-+
-+#ifdef DEBUG
-+ if (bit_size_override || bit_offset_override)
-+ dw_ctf_trace("Bitfield overrides: bit size %i; bit offset %i\n",
-+ ctf_encoding.cte_bits, ctf_encoding.cte_offset);
-+#endif
-+
-+ return ctf_add_func(ctf, ROOT_TYPE(top_level_type), name,
-+ &ctf_encoding);
-+}
-+
-+/*
-+ * Assemble pointer types.
-+ */
-+static ctf_id_t assemble_ctf_pointer(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die, Dwarf_Die *parent_die,
-+ ctf_file_t *ctf, ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip, int *replace)
-+{
-+ ctf_id_t type_ref;
-+
-+ type_ref = lookup_ctf_type(module_name, file_name, die, ctf,
-+ overrides, locerrstr);
-+ if (type_ref < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ /*
-+ * Pointers to functions are all the same type in CTF: don't bother
-+ * adding it over again.
-+ */
-+ if (type_ref == ctf_funcptr_type)
-+ return type_ref;
-+
-+ return ctf_add_pointer(ctf, ROOT_TYPE(top_level_type), type_ref);
-+}
-+
-+/*
-+ * Assemble array types. This function looks up the array type, but does not do
-+ * any array construction: that is left to assemble_ctf_array_dimension().
-+ */
-+static ctf_id_t assemble_ctf_array(const char *module_name,
-+ const char *file_name, Dwarf_Die *die,
-+ Dwarf_Die *parent_die, ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip, int *replace)
-+{
-+ ctf_id_t type_ref;
-+
-+ CTF_DW_ENFORCE_NOT(ordering);
-+ CTF_DW_ENFORCE_NOT(bit_stride);
-+ CTF_DW_ENFORCE_NOT(byte_stride);
-+
-+ type_ref = lookup_ctf_type(module_name, file_name, die, ctf,
-+ overrides, locerrstr);
-+ if (type_ref < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+ return type_ref;
-+}
-+
-+/*
-+ * Assemble an array dimension, wrapping an array round the parent_ctf_id and
-+ * replacing it.
-+ */
-+static ctf_id_t assemble_ctf_array_dimension(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ ctf_arinfo_t arinfo;
-+
-+ CTF_DW_ENFORCE_NOT(bit_size);
-+ CTF_DW_ENFORCE_NOT(byte_size);
-+ CTF_DW_ENFORCE_NOT(bit_stride);
-+ CTF_DW_ENFORCE_NOT(byte_stride);
-+ CTF_DW_ENFORCE_NOT(lower_bound);
-+ CTF_DW_ENFORCE_NOT(threads_scaled);
-+
-+ arinfo.ctr_contents = parent_ctf_id;
-+
-+ arinfo.ctr_index = lookup_ctf_type(module_name, file_name,
-+ die, ctf, overrides, locerrstr);
-+ if (arinfo.ctr_index < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ arinfo.ctr_nelems = private_subrange_dimensions(die);
-+
-+ /*
-+ * For each array dimension, construct an appropriate array of the
-+ * type-so-far, overriding the parent type.
-+ */
-+
-+ *replace = 1;
-+ return ctf_add_array(ctf, ROOT_TYPE(top_level_type), &arinfo);
-+}
-+
-+/*
-+ * Assemble an enumeration.
-+ */
-+static ctf_id_t assemble_ctf_enumeration(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ const char *name = dwarf_diename(die);
-+
-+ return ctf_add_enum(ctf, ROOT_TYPE(top_level_type), name);
-+}
-+
-+/*
-+ * Assemble an enumeration value.
-+ */
-+static ctf_id_t assemble_ctf_enumerator(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ const char *name = dwarf_diename(die);
-+ Dwarf_Word value;
-+ int err;
-+
-+ CTF_DW_ENFORCE(name);
-+ CTF_DW_ENFORCE(const_value);
-+ CTF_DW_ENFORCE_NOT(bit_stride);
-+ CTF_DW_ENFORCE_NOT(byte_stride);
-+
-+ value = private_dwarf_udata(die, DW_AT_const_value, overrides);
-+ err = ctf_add_enumerator(ctf, parent_ctf_id, name, value);
-+
-+ if (err != 0)
-+ return err;
-+
-+ return parent_ctf_id;
-+}
-+
-+/*
-+ * Assemble a typedef.
-+ */
-+static ctf_id_t assemble_ctf_typedef(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ const char *name = dwarf_diename(die);
-+ ctf_id_t type_ref;
-+
-+ CTF_DW_ENFORCE(name);
-+
-+ type_ref = lookup_ctf_type(module_name, file_name, die, ctf,
-+ overrides, locerrstr);
-+ if (type_ref < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ return ctf_add_typedef(ctf, ROOT_TYPE(top_level_type), name, type_ref);
-+}
-+
-+/*
-+ * Assemble a const/volatile/restrict qualifier.
-+ */
-+static ctf_id_t assemble_ctf_cvr_qual(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ ctf_id_t (*ctf_cvr_fun)(ctf_file_t *fp, uint_t flag, ctf_id_t ref);
-+ ctf_id_t type_ref;
-+
-+ switch (dwarf_tag(die)) {
-+ case DW_TAG_const_type: ctf_cvr_fun = ctf_add_const; break;
-+ case DW_TAG_volatile_type: ctf_cvr_fun = ctf_add_volatile; break;
-+ case DW_TAG_restrict_type: ctf_cvr_fun = ctf_add_restrict; break;
-+ default:
-+ pr_err("%s: internal error: assemble_ctf_cvr_qual() called with\n"
-+ "non-const/volatile/restrict: %i\n", locerrstr, dwarf_tag(die));
-+ exit(1);
-+ }
-+
-+ type_ref = lookup_ctf_type(module_name, file_name, die, ctf,
-+ overrides, locerrstr);
-+ if (type_ref < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ return ctf_cvr_fun(ctf, ROOT_TYPE(top_level_type), type_ref);
-+}
-+
-+/*
-+ * Assemble a structure or union type. This assembles only the type itself, not
-+ * its constituent members: that is done by assemble_ctf_su_member().
-+ *
-+ * We assume that if a structure or union type is discovered with more members
-+ * than an earlier-discovered type, that it is compatible with that earlier type
-+ * and a superset of it.
-+ *
-+ * FIXME: in debug mode we should not assume this.
-+ */
-+static ctf_id_t assemble_ctf_struct_union(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ ctf_id_t (*ctf_add_sou)(ctf_file_t *fp, uint_t flag, const char *name,
-+ size_t size);
-+
-+ const char *name = dwarf_diename(die);
-+ int is_union = (dwarf_tag(die) == DW_TAG_union_type);
-+ struct ctf_memb_count *member_count = NULL;
-+ ctf_id_t id;
-+ long long size;
-+
-+ /*
-+ * FIXME: these both need handling for DWARF4 support.
-+ */
-+ CTF_DW_ENFORCE_NOT(specification);
-+ CTF_DW_ENFORCE_NOT(signature);
-+
-+ /*
-+ * Figure out the size of the type (if possible) and force it into the
-+ * CTF to ensure that struct/union padding is added appropriately.
-+ *
-+ * If we don't know it, force a size of zero, which is interpreted as
-+ * being equivalent to a call to the unsized struct/union addition
-+ * function, letting libdtrace-ctf figure out a likely size as best it
-+ * can.
-+ */
-+ size = private_dwarf_size(die);
-+ if (size < 0)
-+ size = 0;
-+
-+ /*
-+ * Possibly we should ignore this entire structure, if we already know
-+ * of one with the same name and at least as many members. If we
-+ * already know of one and it is shorter, we want to use its ID rather
-+ * than creating a new one.
-+ *
-+ * Note; by this point, the deduplicator has long run: thus we know for
-+ * sure what module a potentially-shared type will end up in, and
-+ * there's no need to double-check the shared CTF repository for types.
-+ * We also know that the module must exist in the per_module hash.
-+ */
-+
-+ if (name != NULL) {
-+ char *structized_name = NULL;
-+ struct per_module *ctf_pm;
-+
-+ structized_name = str_appendn(structized_name,
-+ is_union ? "u " : "s ",
-+ name, NULL);
-+
-+ ctf_pm = g_hash_table_lookup(per_module, module_name);
-+ member_count = g_hash_table_lookup(ctf_pm->member_counts,
-+ structized_name);
-+
-+ if (member_count) {
-+ free(structized_name);
-+ dw_ctf_trace("%s: already exists (with ID %li) with %zi members\n"
-+ "versus current %li members\n",
-+ locerrstr, member_count->ctf_id,
-+ member_count->count,
-+ count_dwarf_members(die));
-+
-+ if (member_count->count < count_dwarf_members(die))
-+ return member_count->ctf_id;
-+
-+ *skip = SKIP_SKIP;
-+ return member_count->ctf_id;
-+ }
-+
-+ /*
-+ * Not in existence yet. Create it.
-+ */
-+ member_count = malloc(sizeof(struct ctf_memb_count));
-+ if (member_count == NULL) {
-+ pr_err("Out of memory allocating structure/union member count\n");
-+ exit(1);
-+ }
-+ member_count->count = 0;
-+ g_hash_table_insert(ctf_pm->member_counts,
-+ structized_name, member_count);
-+ }
-+
-+ dw_ctf_trace("%s: adding structure %s\n", locerrstr, name);
-+
-+ if (is_union)
-+ ctf_add_sou = ctf_add_union_sized;
-+ else
-+ ctf_add_sou = ctf_add_struct_sized;
-+
-+ id = ctf_add_sou(ctf, ROOT_TYPE(top_level_type), name, size);
-+
-+ if (member_count != NULL)
-+ member_count->ctf_id = id;
-+
-+ return id;
-+}
-+
-+/*
-+ * Figure out the offset of this type, in bits. (This is split in two
-+ * for bitfields, where the bitfield itself gets represented elsewhere,
-+ * in the CTF type of the member itself.)
-+ *
-+ * DW_AT_data_bit_offset is the simple case. DW_AT_data_member_location
-+ * is trickier, and, alas, the DWARF2 variation is the complex one.
-+ */
-+static int ctf_su_offset(Dwarf_Die *die, const char *locerrstr,
-+ struct die_override *overrides, ulong_t *offset,
-+ ulong_t *bit_offset)
-+{
-+ struct die_override *o;
-+
-+ if (private_dwarf_hasattr(die, DW_AT_data_bit_offset))
-+ *offset = private_dwarf_udata(die, DW_AT_data_bit_offset, NULL);
-+ else if (private_dwarf_hasattr(die, DW_AT_data_member_location)) {
-+ Dwarf_Attribute location_attr;
-+
-+ private_dwarf_attr(die, DW_AT_data_member_location,
-+ &location_attr);
-+
-+ switch (dwarf_whatform(&location_attr)) {
-+ case DW_FORM_data1:
-+ case DW_FORM_data2:
-+ case DW_FORM_data4:
-+ case DW_FORM_data8:
-+ case DW_FORM_udata:
-+ case DW_FORM_sdata:
-+ {
-+ /*
-+ * Byte offset, with bit_offset of containing
-+ * structure/union added, if present.
-+ *
-+ * (No overrides supported here, yet, due to lack of
-+ * sdata overrides and the desire for consistency.
-+ * We can add them if we start passing down
-+ * DW_AT_data_member_location overrides.)
-+ */
-+ if (dwarf_whatform(&location_attr) == DW_FORM_sdata) {
-+ Dwarf_Sword location;
-+
-+ dwarf_formsdata(&location_attr, &location);
-+ *offset = location * 8;
-+ } else {
-+ Dwarf_Word location;
-+
-+ dwarf_formudata(&location_attr, &location);
-+ *offset = location * 8;
-+ }
-+ break;
-+ }
-+ case DW_FORM_block1:
-+ case DW_FORM_block2:
-+ case DW_FORM_block4:
-+ {
-+ Dwarf_Op *location;
-+ size_t nlocs;
-+
-+ /*
-+ * DWARF 2 block-based data_member_location. This can
-+ * be quite complicated in some situations (notably C++
-+ * virtual bases), but for normal structure members it
-+ * is simple. FIXME for userspace tracing of C++.
-+ *
-+ * This is thoroughly specific to the forms of DWARF2
-+ * emitted by GCC. We don't need to feel guilty about
-+ * this because elfutils does just the same thing.
-+ */
-+
-+ if (dwarf_getlocation(&location_attr, &location,
-+ &nlocs) < 0) {
-+ pr_err("%s: offset not a valid location expression: %s\n",
-+ locerrstr, dwarf_errmsg(dwarf_errno()));
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ if ((nlocs != 1) ||
-+ ((location[0].atom != DW_OP_plus_uconst) &&
-+ (location[0].atom != DW_OP_constu))) {
-+ pr_err("%s: complex location lists not supported:\n"
-+ "either C++ or non-GCC output: skipped\n", locerrstr);
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ *offset = location[0].number * 8;
-+ break;
-+ }
-+ case DW_FORM_exprloc:
-+ {
-+ /*
-+ * We need a full DWARF expression list interpreter to
-+ * handle this.
-+ */
-+ pr_err("DWARF 4 expression location lists not supported.\n");
-+ exit(1);
-+ }
-+ default:
-+ {
-+ pr_err("%s: expression location lists in form %u not supported.\n",
-+ locerrstr, dwarf_whatform(&location_attr));
-+ exit(1);
-+ }
-+ }
-+ }
-+
-+ /*
-+ * Handle the bit offset.
-+ */
-+ if (private_dwarf_hasattr(die, DW_AT_bit_offset)) {
-+ Dwarf_Attribute bit_attr;
-+ Dwarf_Word bit;
-+
-+ private_dwarf_attr(die, DW_AT_bit_offset,
-+ &bit_attr);
-+ dwarf_formudata(&bit_attr, &bit);
-+ *bit_offset = bit;
-+ }
-+
-+ /*
-+ * Handle the offset value override. It does not matter which method
-+ * has been used to get the value. At this point offset is always
-+ * the bit distance of the member from the structure/union start.
-+ *
-+ * The DW_AT_data_bit_offset override is always used to pass the offset
-+ * around, so that we don't need to add special override handling for
-+ * various forms of the DW_AT_data_member_location as a special case.
-+ * This is safe as it is not possible to have both attributes attached
-+ * to the same DIE per the DWARF4 standard, and if we have one attached
-+ * as an override to a DIE that has the other, we will only ever need to
-+ * use one (since no DIE can be both an unnamed struct/union and a
-+ * bitfield at the same time).
-+ */
-+ o = private_find_override(die, DW_AT_data_bit_offset, overrides);
-+ if (o != NULL) {
-+ if (o->op == DIE_OVERRIDE_REPLACE)
-+ *offset = o->value;
-+ else
-+ *offset += o->value;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Assemble a structure or union member.
-+ *
-+ * We only assemble a member of a given name if a member by that name does not
-+ * already exist, and if the member is not blacklisted.
-+ */
-+static ctf_id_t assemble_ctf_su_member(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ ulong_t offset = 0;
-+ ulong_t bit_offset = 0;
-+ struct ctf_full_id *new_type;
-+ Dwarf_Attribute type_attr;
-+ Dwarf_Die type_die;
-+ Dwarf_Die cu_die;
-+ int err;
-+ struct ctf_memb_count *member_count;
-+ const char *struct_name = dwarf_diename(parent_die);
-+
-+ CTF_DW_ENFORCE(type);
-+
-+ /*
-+ * Increment the member count of named structures. This is the number
-+ * of members in the DWARF, not in the CTF: blacklisted members are
-+ * counted too.
-+ */
-+ if (struct_name != NULL) {
-+ int is_union = (dwarf_tag(parent_die) == DW_TAG_union_type);
-+ char *structized_name = NULL;
-+ struct per_module *ctf_pm;
-+
-+ structized_name = str_appendn(structized_name,
-+ is_union ? "u " : "s ",
-+ struct_name, NULL);
-+
-+ ctf_pm = g_hash_table_lookup(per_module, module_name);
-+ member_count = g_hash_table_lookup(ctf_pm->member_counts,
-+ structized_name);
-+ member_count->count++;
-+ free(structized_name);
-+ }
-+
-+ /*
-+ * If this member is blacklisted, just skip it.
-+ */
-+ if (member_blacklisted(die, parent_die)) {
-+ dw_ctf_trace("%s: blacklisted, skipping.\n", locerrstr);
-+ return parent_ctf_id;
-+ }
-+
-+ /*
-+ * Find the associated type so we can either add a member with that type
-+ * (if it is named) or add its members directly (for unnamed types,
-+ * which must be unnamed structs/unions): then figure out the member's
-+ * offset.
-+ */
-+ private_dwarf_attr(die, DW_AT_type, &type_attr);
-+ if (dwarf_formref_die(&type_attr, &type_die) == NULL) {
-+ pr_err("%s: nonexistent type reference.\n"
-+ "Corrupted DWARF, cannot continue.\n", locerrstr);
-+ exit(1);
-+ }
-+ dwarf_diecu(&type_die, &cu_die, NULL, NULL);
-+
-+ err = ctf_su_offset(die, locerrstr, overrides, &offset, &bit_offset);
-+ if (err < 0) {
-+ *skip = SKIP_ABORT;
-+ return err;
-+ }
-+
-+ /*
-+ * If this is an unnamed struct/union, call directly back to
-+ * die_to_ctf() to add this struct's members to the current structure,
-+ * merging it seamlessly with its parent (excepting only the member
-+ * offsets). Use DW_AT_data_bit_offset because it does not require
-+ * the complexity of DW_AT_data_member_location to be faked.
-+ */
-+ if (!private_dwarf_hasattr(die, DW_AT_name)) {
-+ Dwarf_Die child_die;
-+ int dummy = 0;
-+
-+ if ((dwarf_tag(&type_die) != DW_TAG_structure_type) &&
-+ (dwarf_tag(&type_die) != DW_TAG_union_type)) {
-+ pr_err("%s:%lx: not supported: anonymous structure member\n"
-+ "not a structure or union.\n", locerrstr,
-+ DIEOFFSET(die));
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ /*
-+ * Anonymous structure or union with no members. Silently skip.
-+ */
-+ switch (dwarf_child(&type_die, &child_die)) {
-+ case -1:
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ case 1: /* No DIEs at all in this aggregate */
-+ return parent_ctf_id;
-+ default: /* Child DIEs exist. */
-+ break;
-+ }
-+
-+ /*
-+ * Add override that will adjust offset of the anonymous
-+ * struct/union members during inlining. The bit_offset is
-+ * ignored here as it is not expected that a nested
-+ * structure/union will start on a non-byte-aligned boundary.
-+ */
-+ struct die_override o[] = {{ dwarf_tag(&child_die),
-+ DW_AT_data_bit_offset,
-+ DIE_OVERRIDE_ADD,
-+ offset, overrides }, {0}};
-+
-+ die_to_ctf(module_name, file_name, &child_die, parent_die, ctf,
-+ parent_ctf_id, o, 0, 0, skip, &dummy, NULL);
-+
-+ return parent_ctf_id;
-+ }
-+
-+ /*
-+ * Get the CTF ID of this member's type, by recursive lookup.
-+ *
-+ * If this is a bitfield, we want to note that said type's size and
-+ * bit-offset should be adjusted.
-+ */
-+ if (private_dwarf_hasattr(die, DW_AT_bit_size)) {
-+ struct die_override o[] = {
-+ { DW_TAG_base_type,
-+ DW_AT_bit_size,
-+ DIE_OVERRIDE_REPLACE,
-+ private_dwarf_udata(die, DW_AT_bit_size,
-+ NULL),
-+ NULL },
-+ { DW_TAG_base_type,
-+ DW_AT_bit_offset,
-+ DIE_OVERRIDE_REPLACE,
-+ bit_offset,
-+ overrides },
-+ {0}
-+ };
-+
-+ new_type = construct_ctf_id(module_name, file_name, &type_die,
-+ &cu_die, o);
-+ } else {
-+ if (bit_offset != 0) {
-+ pr_err("%s:%s: error in member %s: No DW_AT_bit_size, but nonzero bit offset\n"
-+ "of %lx in overall offset of %lx\n", locerrstr,
-+ dwarf_diename(&cu_die), dwarf_diename(die),
-+ bit_offset, offset);
-+ return CTF_ERROR_REPORTED;
-+ }
-+ new_type = construct_ctf_id(module_name, file_name, &type_die,
-+ &cu_die, NULL);
-+ }
-+
-+ if (new_type == NULL) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ if ((new_type->ctf_file != ctf) &&
-+ (new_type->ctf_file != lookup_ctf_file("shared_ctf"))) {
-+ pr_err("%s:%s: internal error: referenced type lookup for member %s\n"
-+ "yields a different CTF file: %p versus %p\n",
-+ locerrstr, dwarf_diename(&cu_die), dwarf_diename(die),
-+ ctf, new_type->ctf_file);
-+ pr_err("dedup() is probably buggy.\n");
-+ exit(1);
-+ }
-+
-+ if (ctf_add_member_offset(ctf, parent_ctf_id, dwarf_diename(die),
-+ new_type->ctf_id, offset) < 0) {
-+ /*
-+ * If we have seen this member before, as part of another
-+ * definition somewhere else, that's fine. We cannot recurse
-+ * from this point, so we can just return the parent CTF ID, the
-+ * ID of the containing structure.
-+ */
-+ if (ctf_errno(ctf) == ECTF_DUPLICATE)
-+ return parent_ctf_id;
-+
-+ /*
-+ * We have special handling for cases where CTF doesn't know of
-+ * either this member's type or the enclosing structure: when
-+ * libdtrace-ctf is old enough to need it, we try a ctf_update()
-+ * in case this is recently added, but no special handling for
-+ * other errors, which the caller must report.
-+ */
-+
-+ if (ctf_errno(ctf) != ECTF_BADID &&
-+ ctf_errno(ctf) != ECTF_NOTSOU)
-+ return CTF_NO_ERROR_REPORTED;
-+
-+#ifndef LIBDTRACE_CTF_OMISSIBLE_CTF_UPDATE
-+ ctf_file_t *shared_ctf;
-+
-+ /*
-+ * Try an update of the current CTF file first, to bring the
-+ * type ID table up to date: if that doesn't work, try an update
-+ * of the shared table. (If none is needed, this is cheap.)
-+ */
-+
-+ if (ctf_update(new_type->ctf_file) < 0) {
-+ pr_err("Cannot update CTF file: %s\n",
-+ ctf_errmsg(ctf_errno(ctf)));
-+ exit(1);
-+ }
-+
-+ if (ctf_add_member_offset(ctf, parent_ctf_id,
-+ dwarf_diename(die),
-+ new_type->ctf_id,
-+ offset) == 0)
-+ return parent_ctf_id;
-+
-+ shared_ctf = lookup_ctf_file("shared_ctf");
-+ if (ctf_update(shared_ctf) < 0) {
-+ pr_err("Cannot update shared CTF: %s\n",
-+ ctf_errmsg(ctf_errno(shared_ctf)));
-+ exit(1);
-+ }
-+
-+ if (ctf_add_member_offset(ctf, parent_ctf_id,
-+ dwarf_diename(die),
-+ new_type->ctf_id,
-+ offset) == 0)
-+ return parent_ctf_id;
-+#endif
-+#ifdef DEBUG
-+ pr_err("%s: Internal error: %s %s:%s:%p:%i\n"
-+ "on member addition to ctf_file %p.\n",
-+ locerrstr, ctf_errmsg(ctf_errno(ctf)),
-+ new_type->module_name, new_type->file_name,
-+ new_type->ctf_file, (int) new_type->ctf_id, ctf);
-+#else
-+ pr_err("%s: Internal error: %s %p:%i\n"
-+ "on member addition to ctf_file %p.\n",
-+ locerrstr, ctf_errmsg(ctf_errno(ctf)),
-+ new_type->ctf_file, (int) new_type->ctf_id,
-+ ctf);
-+#endif
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ return parent_ctf_id;
-+}
-+
-+/*
-+ * Assemble a variable.
-+ */
-+static ctf_id_t assemble_ctf_variable(const char *module_name,
-+ const char *file_name,
-+ Dwarf_Die *die,
-+ Dwarf_Die *parent_die,
-+ ctf_file_t *ctf,
-+ ctf_id_t parent_ctf_id,
-+ const char *locerrstr,
-+ struct die_override *overrides,
-+ int top_level_type,
-+ enum skip_type *skip,
-+ int *replace)
-+{
-+ const char *name = dwarf_diename(die);
-+ char *blacklist_name = NULL;
-+ ctf_id_t type_ref;
-+ int err;
-+
-+ CTF_DW_ENFORCE(name);
-+
-+ /*
-+ * If blacklisted, just skip it.
-+ */
-+ blacklist_name = str_appendn(blacklist_name, module_name, "`",
-+ dwarf_diename(die), NULL);
-+ if (g_hash_table_lookup_extended(variable_blacklist, blacklist_name,
-+ NULL, NULL)) {
-+ dw_ctf_trace("%s: variable %s is blacklisted for static/non-static ambiguity.\n",
-+ file_name, blacklist_name);
-+ free(blacklist_name);
-+ return 0;
-+ }
-+ free(blacklist_name);
-+
-+ type_ref = lookup_ctf_type(module_name, file_name, die, ctf,
-+ overrides, locerrstr);
-+ if (type_ref < 0) {
-+ *skip = SKIP_ABORT;
-+ return CTF_ERROR_REPORTED;
-+ }
-+
-+ /*
-+ * This isn't a type: full DWARF child recursion and type-id addition is
-+ * not called for.
-+ */
-+ *skip = SKIP_SKIP;
-+
-+ err = ctf_add_variable(ctf, name, type_ref);
-+
-+ if (err == 0)
-+ dw_ctf_trace("%p: Added variable %s, type %i\n", ctf, name,
-+ (int)type_ref);
-+
-+ /*
-+ * Variable references to opaque versus non-opaque structures could only
-+ * get deduplicated with yet another deduplication pass. This seems
-+ * pointlessly expensive when nothing can refer to them: just skip
-+ * duplicates instead.
-+ */
-+ if ((err < 0) && (ctf_errno(ctf) == ECTF_DUPLICATE))
-+ return 0;
-+
-+ return err;
-+
-+}
-+
-+/* Writeout. */
-+
-+static void write_types(char *output, int standalone)
-+{
-+ GHashTableIter module_iter;
-+ char *module;
-+ struct per_module *per_mod;
-+ ctf_file_t **ctfs;
-+ const char **names;
-+ size_t i = 0;
-+ size_t ctf_count = g_hash_table_size(per_module);
-+
-+ /*
-+ * Work over all the modules and write their compressed CTF data out.
-+ * Standalone modules get placed in files in the output directory named
-+ * with names ending in .mod.ctf.new, and the makefile moves .ctf.new
-+ * over the top of .ctf iff it has changed; built-in modules and the
-+ * core kernel and shared type repository are placed into a CTF archive.
-+ */
-+ if (standalone) {
-+ if ((mkdir(output, 0777) < 0) && errno != EEXIST) {
-+ perror("Cannot create .ctf directory");
-+ exit(1);
-+ }
-+ } else {
-+ ctfs = calloc(ctf_count, sizeof(ctf_file_t *));
-+ names = calloc(ctf_count, sizeof(char *));
-+ if (!ctfs || !names)
-+ pr_err("Out of memory in CTF writeout\n");
-+ }
-+
-+ /*
-+ * Write the files out (in standalone mode), or construct the arrays of
-+ * module names and files to put in the archive (otherwise).
-+ */
-+ g_hash_table_iter_init(&module_iter, per_module);
-+ while (g_hash_table_iter_next(&module_iter, (void **) &module,
-+ (void **)&per_mod)) {
-+ int fd;
-+
-+ dw_ctf_trace("Writing out %s\n", module);
-+
-+ if (ctf_update(per_mod->ctf_file) < 0) {
-+ pr_err("Cannot serialize CTF file %s: %s\n",
-+ module, ctf_errmsg(ctf_errno(per_mod->ctf_file)));
-+ exit(1);
-+ }
-+
-+ if (!standalone) {
-+ names[i] = module;
-+ ctfs[i] = per_mod->ctf_file;
-+ i++;
-+ } else {
-+ char *path = NULL;
-+
-+ path = str_appendn(path, output, "/", module,
-+ ".mod.ctf.new", NULL);
-+
-+ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
-+ 0666);
-+ if (fd < 0) {
-+ pr_err("Cannot open CTF file %s for writing: %s\n",
-+ path, strerror(errno));
-+ exit(1);
-+ }
-+ if (ctf_compress_write(per_mod->ctf_file, fd) < 0) {
-+ pr_err("Cannot write to CTF file %s: "
-+ "%s\n", path,
-+ ctf_errmsg(ctf_errno(per_mod->ctf_file)));
-+ exit(1);
-+ }
-+ if (close(fd) != 0) {
-+ pr_err("Cannot close CTF file %s: %s\n",
-+ path, strerror(errno));
-+ exit(1);
-+ }
-+ free(path);
-+ }
-+ }
-+
-+ if (!standalone) {
-+ int err;
-+
-+ err = ctf_arc_write(output, ctfs, ctf_count, names, 4096);
-+ if (err != 0) {
-+ pr_err("Cannot write to CTF archive %s: %s\n",
-+ output, err < ECTF_BASE ? strerror(err) :
-+ ctf_errmsg(err));
-+ exit(1);
-+ }
-+ free(names);
-+ free(ctfs);
-+ }
-+}
-+
-+/* Utilities. */
-+
-+/*
-+ * Given a DIE that may contain a type attribute, look up the target of that
-+ * attribute and return it, or NULL if none.
-+ */
-+static Dwarf_Die *private_dwarf_type(Dwarf_Die *die, Dwarf_Die *target_die)
-+{
-+ Dwarf_Attribute type_ref_attr;
-+
-+ if (private_dwarf_attr(die, DW_AT_type, &type_ref_attr) != NULL) {
-+ if (dwarf_formref_die(&type_ref_attr, target_die) == NULL) {
-+ pr_err("Corrupt DWARF at offset %lx: ref with no target.\n",
-+ DIEOFFSET(die));
-+ exit(1);
-+ }
-+ return target_die;
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * Check for existence of an attribute in a DIE, chasing through
-+ * DW_AT_specification if need be.
-+ */
-+static inline int private_dwarf_hasattr(Dwarf_Die *die,
-+ unsigned int search_name)
-+{
-+ int hasattr = 0;
-+ Dwarf_Attribute spec_ref_attr;
-+ Dwarf_Die spec_die;
-+
-+ /*
-+ * DW_AT_declaration is not forwarded, because non-declarations can
-+ * reference declarations via DW_AT_specification, without implying that
-+ * the referencing DIE is a declaration.
-+ */
-+ hasattr = dwarf_hasattr(die, search_name);
-+ if (hasattr || (search_name == DW_AT_declaration))
-+ return hasattr;
-+
-+ if (dwarf_attr(die, DW_AT_specification, &spec_ref_attr) != NULL) {
-+ if (dwarf_formref_die(&spec_ref_attr, &spec_die) == NULL) {
-+ pr_err("Corrupt DWARF at offset %lx: ref with no target.\n",
-+ DIEOFFSET(die));
-+ exit(1);
-+ }
-+ return dwarf_hasattr(&spec_die, search_name);
-+ }
-+ return hasattr;
-+}
-+
-+/*
-+ * Return a DIE attribute, chasing through DW_AT_specification if need be.
-+ */
-+static inline Dwarf_Attribute *private_dwarf_attr(Dwarf_Die *die,
-+ unsigned int search_name,
-+ Dwarf_Attribute *result)
-+{
-+ Dwarf_Attribute spec_ref_attr;
-+ Dwarf_Die spec_die;
-+ Dwarf_Attribute *ret;
-+
-+ ret = dwarf_attr(die, search_name, result);
-+ if (ret != NULL || (search_name == DW_AT_declaration))
-+ return ret;
-+
-+ if (dwarf_attr(die, DW_AT_specification, &spec_ref_attr) != NULL) {
-+ if (dwarf_formref_die(&spec_ref_attr, &spec_die) == NULL) {
-+ pr_err("Corrupt DWARF at offset %lx: ref with no target.\n",
-+ DIEOFFSET(die));
-+ exit(1);
-+ }
-+ return dwarf_attr(&spec_die, search_name, result);
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * Given a DIE that contains a udata attribute, look up that attribute and
-+ * return its value (optionally overridden or modified by the die_overrides).
-+ */
-+static inline Dwarf_Word private_dwarf_udata(Dwarf_Die *die, int attribute,
-+ struct die_override *overrides)
-+{
-+ Dwarf_Attribute attr;
-+ Dwarf_Word value;
-+ struct die_override *override;
-+
-+ override = private_find_override(die, attribute, overrides);
-+
-+ if (override && override->op == DIE_OVERRIDE_REPLACE)
-+ return override->value;
-+
-+ private_dwarf_attr(die, attribute, &attr);
-+ dwarf_formudata(&attr, &value);
-+
-+ if (override)
-+ value += override->value;
-+
-+ return value;
-+}
-+
-+/*
-+ * Given a DIE, return its byte size, if known and interpretable, or -1
-+ * otherwise.
-+ */
-+static inline long long
-+private_dwarf_size(Dwarf_Die *die)
-+{
-+ Dwarf_Attribute size_attr;
-+
-+ if (private_dwarf_hasattr(die, DW_AT_byte_size)) {
-+ private_dwarf_attr(die, DW_AT_byte_size, &size_attr);
-+
-+ switch (dwarf_whatform(&size_attr)) {
-+ case DW_FORM_data1:
-+ case DW_FORM_data2:
-+ case DW_FORM_data4:
-+ case DW_FORM_data8:
-+ case DW_FORM_udata: {
-+ Dwarf_Word dw_size;
-+
-+ dwarf_formudata(&size_attr, &dw_size);
-+ return dw_size;
-+ }
-+ case DW_FORM_sdata: {
-+ Dwarf_Sword dw_size;
-+
-+ dwarf_formsdata(&size_attr, &dw_size);
-+ return dw_size;
-+ }
-+ }
-+ }
-+
-+ /*
-+ * exprloc or other type we don't know how to interpret yet.
-+ */
-+ return -1;
-+}
-+
-+/*
-+ * Find an override in an override list, walking up the chained overrides if
-+ * need be, until one is found.
-+ */
-+static struct die_override *
-+private_find_override(Dwarf_Die *die,
-+ int attribute,
-+ struct die_override *overrides)
-+{
-+ size_t i;
-+
-+ if (overrides == NULL)
-+ return NULL;
-+
-+ while (overrides) {
-+ struct die_override *chain = NULL;
-+ for (i = 0; overrides[i].tag != 0; i++) {
-+ chain = overrides[i].chain;
-+ if ((overrides[i].tag == dwarf_tag(die)) &&
-+ (overrides[i].attribute == attribute))
-+ return &overrides[i];
-+ }
-+ overrides = chain;
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * Determine the dimensions of an array subrange, or 0 if variable.
-+ */
-+static Dwarf_Word private_subrange_dimensions(Dwarf_Die *die)
-+{
-+ int flexible_array = 0;
-+ Dwarf_Attribute nelem_attr;
-+ Dwarf_Word nelems;
-+
-+ if (((private_dwarf_attr(die, DW_AT_upper_bound,
-+ &nelem_attr) == NULL) &&
-+ (private_dwarf_attr(die, DW_AT_count,
-+ &nelem_attr) == NULL)) ||
-+ (!private_dwarf_hasattr(die, DW_AT_type)))
-+ flexible_array = 1;
-+
-+ if (!flexible_array)
-+ switch (dwarf_whatform(&nelem_attr)) {
-+ case DW_FORM_data1:
-+ case DW_FORM_data2:
-+ case DW_FORM_data4:
-+ case DW_FORM_data8:
-+ case DW_FORM_udata:
-+ break;
-+ default:
-+ flexible_array = 1;
-+ }
-+
-+ if (flexible_array)
-+ return 0;
-+
-+ dwarf_formudata(&nelem_attr, &nelems);
-+
-+ /*
-+ * Upper bounds indicate that we have one more element than that, since
-+ * C starts counting at zero.
-+ */
-+ if (private_dwarf_hasattr(die, DW_AT_upper_bound))
-+ nelems++;
-+
-+ return nelems;
-+}
-+
-+/*
-+ * Intern an atom in the atoms table and return it, or free it and return the
-+ * existing atom if one is already interned. (Despite the type signature, this
-+ * return value is constant and should not be freed.)
-+ */
-+static void *intern(char *atom)
-+{
-+ void *foo;
-+
-+ if (!g_hash_table_lookup_extended(atoms, atom, &foo, NULL)) {
-+ g_hash_table_insert(atoms, atom, NULL);
-+ foo = atom;
-+ } else
-+ free(atom);
-+
-+ return foo;
-+}
-+
-+/*
-+ * An error checking strdup().
-+ */
-+static char *xstrdup(const char *s)
-+{
-+ char *s2 = strdup(s);
-+
-+ if (s2 == NULL) {
-+ pr_err("%s: Out of memory\n", __func__);
-+ exit(1);
-+ }
-+
-+ return s2;
-+}
-+
-+/*
-+ * A string appender working on dynamic strings.
-+ */
-+static char *str_append(char *s, const char *append)
-+{
-+ size_t s_len = 0;
-+
-+ if (append == NULL)
-+ return s;
-+
-+ if (s != NULL)
-+ s_len = strlen(s);
-+
-+ size_t append_len = strlen(append);
-+
-+ s = realloc(s, s_len + append_len + 1);
-+
-+ if (s == NULL) {
-+ pr_err("Out of memory appending a string of length %li to one of length %li\n",
-+ strlen(append), s_len);
-+ exit(1);
-+ }
-+
-+ memcpy(s + s_len, append, append_len);
-+ s[s_len+append_len] = '\0';
-+
-+ return s;
-+}
-+
-+/*
-+ * A vararg string appender.
-+ */
-+static char *str_appendn(char *s, ...)
-+{
-+ va_list ap;
-+ const char *append;
-+ size_t len, s_len = 0;
-+
-+ va_start(ap, s);
-+ if (s)
-+ s_len = strlen(s);
-+ len = s_len;
-+
-+ append = va_arg(ap, const char *);
-+ while (append != NULL) {
-+ len += strlen(append);
-+ append = va_arg(ap, char *);
-+ }
-+ va_end(ap);
-+
-+ s = realloc(s, len + 1);
-+ if (s == NULL) {
-+ pr_err("Out of memory appending a string of length %li to one of length %li\n",
-+ len - s_len, s_len);
-+ exit(1);
-+ }
-+
-+ va_start(ap, s);
-+ append = va_arg(ap, const char *);
-+ while (append != NULL) {
-+ size_t append_len = strlen(append);
-+
-+ memcpy(s + s_len, append, append_len);
-+ s_len += append_len;
-+
-+ append = va_arg(ap, char *);
-+ }
-+ s[len] = '\0';
-+ va_end(ap);
-+
-+ return s;
-+}
-+
-+/*
-+ * Filter a GList, calling a predicate on it and removing all elements for which
-+ * the predicate returns true, calling the free_func on them if set.
-+ */
-+static GList *list_filter(GList *list, filter_pred_fun fun,
-+ GDestroyNotify free_func, void *data)
-+{
-+ GList *cur = list;
-+
-+ while (cur) {
-+ GList *next = cur->next;
-+
-+ if (fun(cur->data, data)) {
-+ if (free_func)
-+ free_func(cur->data);
-+ list = g_list_delete_link(list, cur);
-+ }
-+ cur = next;
-+ }
-+
-+ return list;
-+}
-+
-+/*
-+ * Figure out the (pathless, suffixless) module name for a given module file (.o
-+ * or .ko), and return it in a new dynamically allocated string.
-+ *
-+ * Takes the object_to_module mapping into account.
-+ */
-+static char *fn_to_module(const char *file_name)
-+{
-+ char *module_name;
-+ char *chop, *dash;
-+
-+ module_name = g_hash_table_lookup(object_to_module, file_name);
-+ if (module_name != NULL)
-+ return xstrdup(module_name);
-+
-+ chop = strrchr(file_name, '/');
-+ if (chop != NULL)
-+ module_name = xstrdup(++chop);
-+ else
-+ module_name = xstrdup(file_name);
-+
-+ chop = strrchr(module_name, '.');
-+ if (chop != NULL)
-+ *chop = '\0';
-+
-+ dash = module_name;
-+ while (dash != NULL) {
-+ dash = strchr(dash, '-');
-+ if (dash != NULL)
-+ *dash = '_';
-+ }
-+
-+ return module_name;
-+}
-+
-+/*
-+ * Determine, and cache, absolute filenames. This is called in very hot
-+ * paths, notably type_id(), and must be kept fast.
-+ */
-+static const char *abs_file_name(const char *file_name)
-+{
-+ static GHashTable *abs_file_names;
-+ const char *abs_name;
-+
-+ if (abs_file_names == NULL)
-+ abs_file_names = g_hash_table_new_full(g_str_hash, g_str_equal,
-+ free, free);
-+
-+ abs_name = g_hash_table_lookup(abs_file_names, file_name);
-+
-+ if (abs_name == NULL) {
-+ char abspath[PATH_MAX] = "";
-+
-+ if (realpath(file_name, abspath) == NULL)
-+ strcpy(abspath, file_name);
-+ g_hash_table_replace(abs_file_names,
-+ xstrdup(file_name), xstrdup(abspath));
-+
-+ abs_name = g_hash_table_lookup(abs_file_names, file_name);
-+ }
-+
-+ return abs_name;
-+}
-+
-+/*
-+ * Determine absolute filenames relative to some other directory. This does not
-+ * need to be fast. The returned name is dynamically allocated, and must be
-+ * freed by the caller.
-+ */
-+static char *rel_abs_file_name(const char *file_name, const char *relative_to)
-+{
-+ int dir = -1;
-+ static int warned = 0;
-+ char *abspath;
-+ /*
-+ * If we can't get this name relatively, we might as well *try* to do it
-+ * absolutely: but print a warning.
-+ */
-+ dir = open(".", O_RDONLY | O_DIRECTORY);
-+ if (dir < 0) {
-+ if (!warned) {
-+ perror("Cannot open current directory");
-+ warned = 1;
-+ }
-+ } else {
-+ if (chdir(relative_to) < 0)
-+ if (!warned) {
-+ pr_err("Cannot change directory to "
-+ "%s: %s\n", relative_to,
-+ strerror(errno));
-+ warned = 1;
-+ }
-+ }
-+
-+ abspath = realpath(file_name, NULL);
-+ if (abspath == NULL)
-+ abspath = xstrdup(file_name);
-+
-+ if ((dir > -1) && (fchdir(dir) < 0)) {
-+ perror("Cannot return to original directory after relative realpath()");
-+ exit(1);
-+ }
-+
-+ close(dir);
-+
-+ return abspath;
-+}
-+
-+/*
-+ * Given a type encoding table, and a size, return the CTF encoding for that
-+ * type, or 0 if none.
-+ */
-+static int find_ctf_encoding(struct type_encoding_tab *type_tab, size_t size)
-+{
-+ size_t i;
-+
-+ for (i = 0; type_tab[i].size != 0; i++) {
-+ if (type_tab[i].size == size)
-+ return type_tab[i].ctf_encoding;
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * Count the number of members of a DWARF aggregate.
-+ */
-+static long count_dwarf_members(Dwarf_Die *d)
-+{
-+ const char *err;
-+ Dwarf_Die die;
-+
-+ switch (dwarf_child(d, &die)) {
-+ case -1:
-+ err = "fetch first child of aggregate";
-+ goto fail;
-+ case 1: /* No DIEs at all in this aggregate */
-+ return 0;
-+ default: /* Child DIEs exist. */
-+ break;
-+ }
-+
-+ /*
-+ * We are only interested in children of type DW_TAG_member.
-+ */
-+ int sib_ret;
-+ long count = 0;
-+
-+ do
-+ if (dwarf_tag(&die) == DW_TAG_member)
-+ count++;
-+ while ((sib_ret = dwarf_siblingof(&die, &die)) == 0);
-+
-+ if (sib_ret == -1) {
-+ err = "count members";
-+ goto fail;
-+ }
-+
-+ return count;
-+
-+ fail:
-+ pr_err("Cannot %s: %s\n", err, dwarf_errmsg(dwarf_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * Free a per_module's contents.
-+ */
-+static void private_per_module_free(void *per_module)
-+{
-+ struct per_module *per_mod = per_module;
-+
-+ ctf_close(per_mod->ctf_file);
-+ g_hash_table_destroy(per_mod->member_counts);
-+ free(per_module);
-+}
-+
-+/*
-+ * Free a fn_to_die_to_parent subhash.
-+ */
-+static void private_fn_die_parent_free(void *ptr)
-+{
-+ g_hash_table_destroy((GHashTable *) ptr);
-+}
-+
-+/*
-+ * Get a ctf_file out of the per_module hash for a given module.
-+ */
-+static ctf_file_t *lookup_ctf_file(const char *module_name)
-+{
-+ struct per_module *per_mod;
-+
-+ per_mod = g_hash_table_lookup(per_module, module_name);
-+ if (per_mod == NULL)
-+ return NULL;
-+ return per_mod->ctf_file;
-+}
-diff --git a/scripts/dwarf2ctf/eu_simple.c b/scripts/dwarf2ctf/eu_simple.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..49886e5e541105ff517694db0ed3f00a096d16ae
---- /dev/null
-+++ b/scripts/dwarf2ctf/eu_simple.c
-@@ -0,0 +1,2 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+#include "../eu_simple.c"
-diff --git a/scripts/dwarf2ctf/member.blacklist b/scripts/dwarf2ctf/member.blacklist
-new file mode 100644
-index 0000000000000000000000000000000000000000..85122def7b5f652881aa6588c407f91abf641017
---- /dev/null
-+++ b/scripts/dwarf2ctf/member.blacklist
-@@ -0,0 +1 @@
-+include/linux/netfilter/ipset/ip_set_ahash.h:ip_set_hash.next
-diff --git a/scripts/eu_simple.c b/scripts/eu_simple.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..e2736f29d00113912534c07cae6b41d97ffe8db0
---- /dev/null
-+++ b/scripts/eu_simple.c
-@@ -0,0 +1,356 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Convenience wrappers for functions in elfutils.
-+ *
-+ * (C) 2014, 2017 Oracle, Inc. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#include <errno.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+
-+#include <elfutils/libdwfl.h>
-+#include <elfutils/version.h>
-+
-+#include <eu_simple.h>
-+
-+#define __unused__ __attribute__((__unused__))
-+
-+/*
-+ * A version of dwfl_report_elf() that compensates for parameter changes in
-+ * newer elfutils.
-+ */
-+static Dwfl_Module *private_dwfl_report_elf(Dwfl *dwfl, const char *name,
-+ const char *file_name, int fd,
-+ GElf_Addr base)
-+{
-+#if _ELFUTILS_PREREQ(0,156)
-+ return dwfl_report_elf(dwfl, name, file_name, fd, base, 0);
-+#else
-+ return dwfl_report_elf(dwfl, name, file_name, fd, base);
-+#endif
-+}
-+
-+/*
-+ * Stub libdwfl callback, use only the ELF handle passed in.
-+ */
-+static int no_debuginfo(Dwfl_Module *mod __unused__,
-+ void **userdata __unused__,
-+ const char *modname __unused__,
-+ Dwarf_Addr base __unused__,
-+ const char *file_name __unused__,
-+ const char *debuglink_file __unused__,
-+ GElf_Word debuglink_crc __unused__,
-+ char **debuginfo_file_name __unused__)
-+{
-+ return -1;
-+}
-+
-+/*
-+ * Wrap up dwfl_new() complexities.
-+ */
-+Dwfl *simple_dwfl_new(const char *file_name, Dwfl_Module **module)
-+{
-+ const char *err;
-+
-+ static Dwfl_Callbacks cb = {
-+ .find_debuginfo = no_debuginfo,
-+ .section_address = dwfl_offline_section_address
-+ };
-+ Dwfl *dwfl = dwfl_begin(&cb);
-+ Dwfl_Module *mod;
-+
-+ if (dwfl == NULL) {
-+ err = "initialize libdwfl";
-+ goto fail;
-+ }
-+
-+ mod = private_dwfl_report_elf(dwfl, "", file_name, -1, 0);
-+ if (mod == NULL) {
-+ err = "open object file with libdwfl";
-+ goto fail;
-+ }
-+ if (module)
-+ *module = mod;
-+
-+ if (dwfl_report_end(dwfl, NULL, NULL) != 0) {
-+ err = "finish opening object file with libdwfl";
-+ goto fail;
-+ }
-+
-+ return dwfl;
-+ fail:
-+ fprintf(stderr, "Cannot %s for %s: %s\n", err, file_name,
-+ dwfl_errmsg(dwfl_errno()));
-+ exit(1);
-+}
-+
-+/*
-+ * A variant of simple_dwfl_new() that iterates over multiple object files.
-+ * (Used for thin archives.)
-+ *
-+ * Takes ownership of the paths, until free.
-+ */
-+struct simple_dwfl_multi *
-+simple_dwfl_new_multi(char **paths)
-+{
-+ struct simple_dwfl_multi *multi;
-+
-+ multi = malloc(sizeof(struct simple_dwfl_multi));
-+ if (multi == NULL)
-+ return NULL;
-+
-+ multi->paths = paths;
-+ multi->i = -1;
-+ multi->dwfl = NULL;
-+ multi->last_die = NULL;
-+
-+ return multi;
-+}
-+
-+/*
-+ * A variant of dwfl_nextcu() that crosses file boundaries as needed,
-+ * using the state in the simple_dwfl_multi.
-+ */
-+Dwarf_Die *
-+simple_dwfl_nextcu(struct simple_dwfl_multi *multi)
-+{
-+ Dwarf_Addr junk;
-+
-+ /*
-+ * Switch object files as needed (and always, the first time).
-+ */
-+
-+ if (multi->i >= 0)
-+ multi->last_die = dwfl_nextcu(multi->dwfl, multi->last_die,
-+ &junk);
-+
-+ while (multi->last_die == NULL) {
-+ simple_dwfl_free(multi->dwfl);
-+ if (multi->paths[++multi->i] == NULL) {
-+ multi->i = -1;
-+ multi->dwfl = NULL;
-+ multi->last_die = NULL;
-+ return NULL;
-+ }
-+
-+ multi->dwfl = simple_dwfl_new(multi->paths[multi->i], NULL);
-+ multi->last_die = dwfl_nextcu(multi->dwfl, multi->last_die,
-+ &junk);
-+ }
-+ return multi->last_die;
-+}
-+
-+/*
-+ * Free a simple_dwfl_new_multi: return its contained paths so the caller can
-+ * free them again. (They are not changed, so the caller can just hang on to
-+ * them if preferred.)
-+ */
-+char **
-+simple_dwfl_free_multi(struct simple_dwfl_multi *multi)
-+{
-+ char **paths = multi->paths;
-+ simple_dwfl_free(multi->dwfl);
-+ free(multi);
-+ return paths;
-+}
-+
-+/*
-+ * The converse of simple_dwfl_new().
-+ */
-+void simple_dwfl_free(Dwfl *dwfl)
-+{
-+ if (dwfl != NULL) {
-+ dwfl_report_end(dwfl, NULL, NULL);
-+ dwfl_end(dwfl);
-+ }
-+}
-+
-+
-+/*
-+ * Read a modules_thick.builtin file and translate it into a stream of
-+ * arguments suitable for simple_dwfl_new_multi().
-+ */
-+
-+/*
-+ * Construct a modules_thick.builtin iterator.
-+ */
-+struct modules_thick_iter *
-+modules_thick_iter_new(const char *modules_thick_file)
-+{
-+ struct modules_thick_iter *i;
-+
-+ i = calloc(1, sizeof(struct modules_thick_iter));
-+ if (i == NULL)
-+ return NULL;
-+
-+ i->f = fopen(modules_thick_file, "r");
-+
-+ if (i->f == NULL) {
-+ fprintf(stderr, "Cannot open builtin module file %s: %s\n",
-+ modules_thick_file, strerror(errno));
-+ return NULL;
-+ }
-+
-+ return i;
-+}
-+
-+/*
-+ * Iterate, returning a new null-terminated array of object file names, and a
-+ * new dynamically-allocated module name. (The module name passed in is freed.)
-+ *
-+ * The array of object file names should be freed by the caller: the strings it
-+ * points to are owned by the iterator, and should not be freed.
-+ */
-+
-+char ** __attribute__((__nonnull__))
-+modules_thick_iter_next(struct modules_thick_iter *i, char **module_name)
-+{
-+ size_t npaths = 1;
-+ char **module_paths;
-+ char *last_slash;
-+ char *last_dot;
-+ char *trailing_linefeed;
-+ char *object_name = i->line;
-+ char *dash;
-+ int composite = 0;
-+
-+ /*
-+ * Read in all module entries, computing the suffixless, pathless name
-+ * of the module and building the next arrayful of object file names for
-+ * return.
-+ *
-+ * Modules can consist of multiple files: in this case, the portion
-+ * before the colon is the path to the module (as before): the portion
-+ * after the colon is a space-separated list of files that should be *
-+ * considered part of this module. In this case, the portion before the
-+ * name is an "object file" that does not actually exist: it is merged
-+ * into built-in.a without ever being written out.
-+ *
-+ * All module names have - translated to _, to match what is done to the
-+ * names of the same things when built as modules.
-+ */
-+
-+ /*
-+ * Reinvocation of exhausted iterator. Return NULL, once.
-+ */
-+retry:
-+ if (getline(&i->line, &i->line_size, i->f) < 0) {
-+ if (ferror(i->f)) {
-+ fprintf(stderr, "Error reading from modules_thick file:"
-+ " %s\n", strerror(errno));
-+ exit(1);
-+ }
-+ rewind(i->f);
-+ return NULL;
-+ }
-+
-+ if (i->line[0] == '\0')
-+ goto retry;
-+
-+ /*
-+ * Slice the line in two at the colon, if any. If there is anything
-+ * past the ': ', this is a composite module. (We allow for no colon
-+ * for robustness, even though one should always be present.)
-+ */
-+ if (strchr(i->line, ':') != NULL) {
-+ char *name_start;
-+
-+ object_name = strchr(i->line, ':');
-+ *object_name = '\0';
-+ object_name++;
-+ name_start = object_name + strspn(object_name, " \n");
-+ if (*name_start != '\0') {
-+ composite = 1;
-+ object_name = name_start;
-+ }
-+ }
-+
-+ /*
-+ * Figure out the module name.
-+ */
-+ last_slash = strrchr(i->line, '/');
-+ last_slash = (!last_slash) ? i->line :
-+ last_slash + 1;
-+ free(*module_name);
-+ *module_name = strdup(last_slash);
-+ dash = *module_name;
-+
-+ while (dash != NULL) {
-+ dash = strchr(dash, '-');
-+ if (dash != NULL)
-+ *dash = '_';
-+ }
-+
-+ last_dot = strrchr(*module_name, '.');
-+ if (last_dot != NULL)
-+ *last_dot = '\0';
-+
-+ trailing_linefeed = strchr(object_name, '\n');
-+ if (trailing_linefeed != NULL)
-+ *trailing_linefeed = '\0';
-+
-+ /*
-+ * Multifile separator? Object file names explicitly stated:
-+ * slice them up and shuffle them in.
-+ *
-+ * The array size may be an overestimate if any object file
-+ * names start or end with spaces (very unlikely) but cannot be
-+ * an underestimate. (Check for it anyway.)
-+ */
-+ if (composite) {
-+ char *one_object;
-+
-+ for (npaths = 0, one_object = object_name;
-+ one_object != NULL;
-+ npaths++, one_object = strchr(one_object + 1, ' '));
-+ }
-+
-+ module_paths = malloc((npaths + 1) * sizeof(char *));
-+ if (!module_paths) {
-+ fprintf(stderr, "%s: out of memory on module %s\n", __func__,
-+ *module_name);
-+ exit(1);
-+ }
-+
-+ if (composite) {
-+ char *one_object;
-+ size_t i = 0;
-+
-+ while ((one_object = strsep(&object_name, " ")) != NULL) {
-+ if (i >= npaths) {
-+ fprintf(stderr, "%s: num_objs overflow on module "
-+ "%s: this is a bug.\n", __func__,
-+ *module_name);
-+ exit(1);
-+ }
-+
-+ module_paths[i++] = one_object;
-+ }
-+ } else
-+ module_paths[0] = i->line; /* untransformed module name */
-+
-+ module_paths[npaths] = NULL;
-+
-+ return module_paths;
-+}
-+
-+/*
-+ * Free an iterator. Can be called while iteration is underway, so even
-+ * state that is freed at the end of iteration must be freed here too.
-+ */
-+void
-+modules_thick_iter_free(struct modules_thick_iter *i)
-+{
-+ if (i == NULL)
-+ return;
-+ fclose(i->f);
-+ free(i->line);
-+ free(i);
-+}
-diff --git a/scripts/eu_simple.h b/scripts/eu_simple.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..8ef9f96550772495c219d24136e75bcaf26aa62c
---- /dev/null
-+++ b/scripts/eu_simple.h
-@@ -0,0 +1,91 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Simplifying wrappers for functions in elfutils, and functions to
-+ * feed them data.
-+ *
-+ * (C) 2014, 2017 Oracle, Inc. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_EU_SIMPLE_H
-+#define _LINUX_EU_SIMPLE_H
-+
-+#include <stdio.h>
-+#include <stddef.h>
-+#include <elfutils/libdwfl.h>
-+
-+/*
-+ * Iteration state for simple_dwfl_new_multi().
-+ */
-+struct simple_dwfl_multi {
-+ char **paths;
-+ ssize_t i;
-+ Dwfl *dwfl;
-+ Dwarf_Die *last_die;
-+};
-+
-+/*
-+ * Wrap up dwfl_new() complexities.
-+ */
-+Dwfl *simple_dwfl_new(const char *file_name, Dwfl_Module **module);
-+
-+/*
-+ * A variant of simple_dwfl_new() that iterates over multiple object files.
-+ * (Used for thin archives.)
-+ *
-+ * Takes ownership of the paths, until free.
-+ */
-+struct simple_dwfl_multi *simple_dwfl_new_multi(char **paths);
-+
-+/*
-+ * A variant of dwfl_nextcu() that crosses file boundaries as needed,
-+ * using the state in the simple_dwfl_multi.
-+ */
-+Dwarf_Die *simple_dwfl_nextcu(struct simple_dwfl_multi *multi);
-+
-+/*
-+ * Free a simple_dwfl_new_multi: return its contained paths so the caller
-+ * free them again. (They are not changed, so the caller can just hang on to
-+ * them if preferred.)
-+ */
-+char **simple_dwfl_free_multi(struct simple_dwfl_multi *multi);
-+
-+/*
-+ * The converse of simple_dwfl_new().
-+ */
-+void simple_dwfl_free(Dwfl *dwfl);
-+
-+/*
-+ * modules_thick.builtin iteration state.
-+ */
-+struct modules_thick_iter {
-+ FILE *f;
-+ char *line;
-+ size_t line_size;
-+};
-+
-+/*
-+ * Construct a modules_thick.builtin iterator.
-+ */
-+struct modules_thick_iter *
-+modules_thick_iter_new(const char *modules_thick_file);
-+
-+/*
-+ * Iterate, returning a new null-terminated array of object file names, and a
-+ * new dynamically-allocated module name. (The module name passed in is freed.)
-+ *
-+ * The array of object file names should be freed by the caller: the strings it
-+ * points to are owned by the iterator, and should not be freed.
-+ */
-+
-+char ** __attribute__((__nonnull__))
-+modules_thick_iter_next(struct modules_thick_iter *i, char **module_name);
-+
-+void
-+modules_thick_iter_free(struct modules_thick_iter *i);
-+
-+#endif
-diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
-index a39d93e3c6ae8d34f617b835d8ebcf5900cbad89..12445a834698db42be674f907f2e82422d8eb8e2 100644
---- a/scripts/kconfig/confdata.c
-+++ b/scripts/kconfig/confdata.c
-@@ -710,6 +710,25 @@ static struct conf_printer header_printer_cb =
- .print_comment = header_print_comment,
- };
-
-+/*
-+ * Tristate printer
-+ *
-+ * This printer is used when generating the `include/config/tristate.conf' file.
-+ */
-+static void
-+tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
-+{
-+
-+ if (sym->type == S_TRISTATE && *value != 'n')
-+ fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value));
-+}
-+
-+static struct conf_printer tristate_printer_cb =
-+{
-+ .print_symbol = tristate_print_symbol,
-+ .print_comment = kconfig_print_comment,
-+};
-+
- static void conf_write_symbol(FILE *fp, struct symbol *sym,
- struct conf_printer *printer, void *printer_arg)
- {
-@@ -1043,7 +1062,7 @@ int conf_write_autoconf(int overwrite)
- struct symbol *sym;
- const char *name;
- const char *autoconf_name = conf_get_autoconfig_name();
-- FILE *out, *out_h;
-+ FILE *out, *tristate, *out_h;
- int i;
-
- if (!overwrite && is_present(autoconf_name))
-@@ -1058,6 +1077,13 @@ int conf_write_autoconf(int overwrite)
- if (!out)
- return 1;
-
-+ tristate = fopen(".tmpconfig_tristate", "w");
-+ if (!tristate) {
-+ fclose(out);
-+ fclose(tristate);
-+ return 1;
-+ }
-+
- out_h = fopen(".tmpconfig.h", "w");
- if (!out_h) {
- fclose(out);
-@@ -1065,6 +1091,7 @@ int conf_write_autoconf(int overwrite)
- }
-
- conf_write_heading(out, &kconfig_printer_cb, NULL);
-+ conf_write_heading(tristate, &tristate_printer_cb, NULL);
- conf_write_heading(out_h, &header_printer_cb, NULL);
-
- for_all_symbols(i, sym) {
-@@ -1072,11 +1099,13 @@ int conf_write_autoconf(int overwrite)
- if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
- continue;
-
-- /* write symbols to auto.conf and autoconf.h */
-+ /* write symbols to auto.conf, tristate and header files */
- conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
-+ conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
- conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
- }
- fclose(out);
-+ fclose(tristate);
- fclose(out_h);
-
- name = getenv("KCONFIG_AUTOHEADER");
-@@ -1087,6 +1116,14 @@ int conf_write_autoconf(int overwrite)
- if (rename(".tmpconfig.h", name))
- return 1;
-
-+ name = getenv("KCONFIG_TRISTATE");
-+ if (!name)
-+ name = "include/config/tristate.conf";
-+ if (make_parent_dir(name))
-+ return 1;
-+ if (rename(".tmpconfig_tristate", name))
-+ return 1;
-+
- if (make_parent_dir(autoconf_name))
- return 1;
- /*
-diff --git a/scripts/move-if-change b/scripts/move-if-change
-new file mode 100755
-index 0000000000000000000000000000000000000000..eb745af5d972bd147b0e8bc9e3be643dde25e91e
---- /dev/null
-+++ b/scripts/move-if-change
-@@ -0,0 +1,8 @@
-+#!/bin/sh
-+# SPDX-License-Identifier: GPL-2.0+
-+
-+if test -r "$2" && cmp -s "$1" "$2"; then
-+ rm -f "$1"
-+else
-+ mv -f "$1" "$2"
-+fi
-diff --git a/scripts/package/mkspec b/scripts/package/mkspec
-index 7c477ca7dc9826a0d4bd63e332b4d5959894836a..e9ff22c6fb4c7c7082767c7c9b164e94735ea1e7 100755
---- a/scripts/package/mkspec
-+++ b/scripts/package/mkspec
-@@ -27,6 +27,13 @@ if grep -q CONFIG_DRM=y .config; then
- PROVIDES=kernel-drm
- fi
-
-+# set CTF when configured
-+if grep -q CONFIG_CTF=y .config; then
-+ C=
-+else
-+ C=DEL
-+fi
-+
- PROVIDES="$PROVIDES kernel-$KERNELRELEASE"
- __KERNELRELEASE=$(echo $KERNELRELEASE | sed -e "s/-/_/g")
- EXCLUDES="$RCS_TAR_IGNORE --exclude=*vmlinux* --exclude=*.mod \
-@@ -38,6 +45,7 @@ EXCLUDES="$RCS_TAR_IGNORE --exclude=*vmlinux* --exclude=*.mod \
- # Labels:
- # $S: this line is enabled only when building source package
- # $M: this line is enabled only when CONFIG_MODULES is enabled
-+# $C: this line is enabled only when CONFIG_CTF is enabled
- sed -e '/^DEL/d' -e 's/^\t*//' <<EOF
- Name: kernel
- Summary: The Linux Kernel
-@@ -48,6 +56,8 @@ sed -e '/^DEL/d' -e 's/^\t*//' <<EOF
- Vendor: The Linux Community
- URL: https://www.kernel.org
- $S Source: kernel-$__KERNELRELEASE.tar.gz
-+$C BuildRequires: libdtrace-ctf >= 0.5.0
-+$C BuildRequires: libdtrace-ctf-devel >= 0.5.0
- Provides: $PROVIDES
- %define __spec_install_post /usr/lib/rpm/brp-compress || :
- %define debug_package %{nil}
-@@ -74,12 +84,14 @@ $S$M AutoReqProv: no
- $S$M %description -n kernel-devel
- $S$M This package provides kernel headers and makefiles sufficient to build modules
- $S$M against the $__KERNELRELEASE kernel package.
-+$C Requires: libdtrace-ctf >= 0.5.0
- $S$M
- $S %prep
- $S %setup -q
- $S
- $S %build
- $S $MAKE %{?_smp_mflags} KBUILD_BUILD_VERSION=%{release}
-+$S$C $MAKE %{?_smp_mflags} ctf
- $S
- %install
- mkdir -p %{buildroot}/boot
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch
deleted file mode 100644
index 96fcb3a363bb..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0002-kallsyms-introduce-new-proc-kallmodsyms-including-bu.patch
+++ /dev/null
@@ -1,1050 +0,0 @@
-From 6ded42dd15783a073c9a15ad4abae87bcf234c40 Mon Sep 17 00:00:00 2001
-From: Nick Alcock <nick.alcock@oracle.com>
-Date: Wed, 14 Nov 2018 20:09:28 +0000
-Subject: [PATCH 02/19] kallsyms: introduce new /proc/kallmodsyms including
- builtin modules too
-
-/proc/kallsyms is very useful for tracers and other tools that need to
-map kernel symbols to addresses (sinful though it is to export such
-addresses to userspace). However, for some uses it does not suffice.
-We would like to be able to establish a mapping between module name and
-kernel symbol that only changes when the kernel source code is changed:
-if the kernel is recompiled so that some module becomes built in, it is
-a desirable property for portability of tracing scripts that can include
-module names if the name of this module does not change.
-
-i.e., as with the previous dwarf2ctf commit, we would like to report
-e.g. ext4 symbols as residing in [ext4] even if ext4 happens to be built
-into the kernel: it is enough that it *could* be built as a module.
-
-We use machinery shared with dwarf2ctf (in eu_simple.c) in conjunction
-with a link map to compute the mapping from the address ranges
-associated with built-in object files in vmlinux.o to module names, then
-drop a list of these modules and pointers into that list into new
-kallsyms sections (kallsyms_modules and kallsyms_symbol_modules).
-
-We also need symbol sizes to determine whether a given probe hit is
-within a symbol or outside it (possibly miles outside it in a gap
-between symbols). Adding that is much simpler, with only one new
-section, kallsyms_sizes.
-
-The resulting file looks like this:
-
-ffffffff8b013d20 409 t pt_buffer_setup_aux
-ffffffff8b014130 11f T intel_pt_interrupt
-ffffffff8b014250 2d T cpu_emergency_stop_pt
-ffffffff8b014280 13a t rapl_pmu_event_init [intel_rapl_perf]
-ffffffff8b0143c0 bb t rapl_event_update [intel_rapl_perf]
-ffffffff8b014480 10 t rapl_pmu_event_read [intel_rapl_perf]
-ffffffff8b014490 a3 t rapl_cpu_offline [intel_rapl_perf]
-ffffffff8b014540 24 t __rapl_event_show [intel_rapl_perf]
-ffffffff8b014570 f2 t rapl_pmu_event_stop [intel_rapl_perf]
-
-This is emitted even if intel_rapl_perf is built into the kernel.
-
-As with /proc/kallsyms, non-root usage produces addresses that are
-all-zero. (I am amenable to producing all-zero sizes, too, but without
-the addresses this seems like pure paranoia.)
-
-Programs that consume /proc/kallmodsyms should note that unlike
-/proc/kallsyms, kernel symbols for built-in modules may appear
-interspersed with other symbols that are part of different modules or
-part of no module at all.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- Makefile | 2 +-
- include/linux/kallsyms.h | 21 +++
- include/linux/module.h | 7 +-
- init/Kconfig | 10 ++
- kernel/kallsyms.c | 163 +++++++++++++--------
- kernel/module.c | 4 +-
- scripts/Makefile | 10 ++
- scripts/kallsyms.c | 301 +++++++++++++++++++++++++++++++++++++--
- scripts/link-vmlinux.sh | 22 ++-
- 9 files changed, 466 insertions(+), 74 deletions(-)
-
-diff --git a/Makefile b/Makefile
-index e94e5bfc9c4f5d9c64c08c83d877c2c9394bc2c7..c21d2a09c9ca1419369295c2d29535e37135e6a4 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1406,7 +1406,7 @@ modules.order: $(subdir-modorder) FORCE
-
- targets += modules.order
-
--ifneq (CONFIG_CTF@,'@')
-+ifneq (CONFIG_CTF@CONFIG_KALLMODSYMS,'@')
-
- # We need to force everything to be built, since we need the .o files below.
- KBUILD_BUILTIN := 1
-diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
-index 481273f0c72d4256979ee0ba2b02a4b9629f4497..1246b75f5c5798177cb18d100c2faa60399ef5a9 100644
---- a/include/linux/kallsyms.h
-+++ b/include/linux/kallsyms.h
-@@ -8,6 +8,7 @@
-
- #include <linux/errno.h>
- #include <linux/kernel.h>
-+#include <linux/module.h>
- #include <linux/stddef.h>
- #include <linux/mm.h>
- #include <linux/module.h>
-@@ -72,6 +73,24 @@ static inline void *dereference_symbol_descriptor(void *ptr)
- }
-
- #ifdef CONFIG_KALLSYMS
-+/* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
-+struct kallsym_iter {
-+ loff_t pos;
-+ loff_t pos_arch_end;
-+ loff_t pos_mod_end;
-+ loff_t pos_ftrace_mod_end;
-+ loff_t pos_bpf_end;
-+ unsigned long value;
-+ unsigned int nameoff; /* If iterating in core kernel symbols. */
-+ unsigned long size;
-+ char type;
-+ char name[KSYM_NAME_LEN];
-+ char module_name[MODULE_NAME_LEN];
-+ int builtin_module;
-+ int exported;
-+ int show_value;
-+};
-+
- /* Lookup the address for a symbol. Returns 0 if not found. */
- unsigned long kallsyms_lookup_name(const char *name);
-
-@@ -101,6 +120,8 @@ int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *
- /* How and when do we show kallsyms values? */
- extern bool kallsyms_show_value(const struct cred *cred);
-
-+extern void kallsyms_iter_reset(struct kallsym_iter *, loff_t);
-+extern int kallsyms_iter_update(struct kallsym_iter *, loff_t);
- #else /* !CONFIG_KALLSYMS */
-
- static inline unsigned long kallsyms_lookup_name(const char *name)
-diff --git a/include/linux/module.h b/include/linux/module.h
-index 6264617bab4d46c542f86803a860d5a0a51c6214..d44fe50d7c7fec29c95e8b07865201410216d9d3 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -599,7 +599,8 @@ struct symsearch {
- /* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
- symnum out of range. */
- int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
-- char *name, char *module_name, int *exported);
-+ char *name, char *module_name, unsigned long *size,
-+ int *exported);
-
- /* Look for this name: can be of form module:name. */
- unsigned long module_kallsyms_lookup_name(const char *name);
-@@ -780,8 +781,8 @@ static inline int lookup_module_symbol_attrs(unsigned long addr, unsigned long *
- }
-
- static inline int module_get_kallsym(unsigned int symnum, unsigned long *value,
-- char *type, char *name,
-- char *module_name, int *exported)
-+ char *type, char *name, char *module_name,
-+ unsigned long *size, int *exported)
- {
- return -ERANGE;
- }
-diff --git a/init/Kconfig b/init/Kconfig
-index 0872a5a2e7590c0ade132f624af8d6e39de61544..05d377ccc0e08c27391242886bbd8904a17b4ef4 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1472,6 +1472,16 @@ config POSIX_TIMERS
-
- If unsure say y.
-
-+config KALLMODSYMS
-+ default y
-+ bool "Enable support for /proc/kallmodsyms" if EXPERT
-+ depends on KALLSYMS
-+ help
-+ This option enables the /proc/kallmodsyms file, which maps symbols
-+ to addresses and their associated modules. This support requires
-+ a fairly recent elfutils: 0.152 -- 0.172 have been tested.
-+ elfutils before 0.142 will definitely not work.
-+
- config PRINTK
- default y
- bool "Enable support for printk" if EXPERT
-diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
-index fe9de067771c34eb89d021df40579c38d8974298..7371f8f9cf74cba744f525f78dffb0175bece48d 100644
---- a/kernel/kallsyms.c
-+++ b/kernel/kallsyms.c
-@@ -33,6 +33,7 @@
- */
- extern const unsigned long kallsyms_addresses[] __weak;
- extern const int kallsyms_offsets[] __weak;
-+extern const unsigned long kallsyms_sizes[] __weak;
- extern const u8 kallsyms_names[] __weak;
-
- /*
-@@ -47,6 +48,8 @@ __section(".rodata") __attribute__((weak));
-
- extern const char kallsyms_token_table[] __weak;
- extern const u16 kallsyms_token_index[] __weak;
-+extern const char kallsyms_modules[] __weak;
-+extern const u32 kallsyms_symbol_modules[] __weak;
-
- extern const unsigned int kallsyms_markers[] __weak;
-
-@@ -195,12 +198,24 @@ int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
- return module_kallsyms_on_each_symbol(fn, data);
- }
-
-+/*
-+ * The caller passes in an address, and we return an index to the symbol --
-+ * potentially also size and offset information.
-+ * But an address might map to multiple symbols because:
-+ * - some symbols might have zero size
-+ * - some symbols might be aliases of one another
-+ * - some symbols might span (encompass) others
-+ * The symbols should already be ordered so that, for a particular address,
-+ * we first have the zero-size ones, then the biggest, then the smallest.
-+ * So we find the index by:
-+ * - finding the last symbol with the target address
-+ * - backing the index up so long as both the address and size are unchanged
-+ */
- static unsigned long get_symbol_pos(unsigned long addr,
- unsigned long *symbolsize,
- unsigned long *offset)
- {
-- unsigned long symbol_start = 0, symbol_end = 0;
-- unsigned long i, low, high, mid;
-+ unsigned long low, high, mid;
-
- /* This kernel should never had been booted. */
- if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
-@@ -221,36 +236,17 @@ static unsigned long get_symbol_pos(unsigned long addr,
- }
-
- /*
-- * Search for the first aliased symbol. Aliased
-- * symbols are symbols with the same address.
-+ * Search for the first aliased symbol.
- */
-- while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low))
-+ while (low
-+ && kallsyms_sym_address(low-1) == kallsyms_sym_address(low)
-+ && kallsyms_sizes[low-1] == kallsyms_sizes[low])
- --low;
-
-- symbol_start = kallsyms_sym_address(low);
--
-- /* Search for next non-aliased symbol. */
-- for (i = low + 1; i < kallsyms_num_syms; i++) {
-- if (kallsyms_sym_address(i) > symbol_start) {
-- symbol_end = kallsyms_sym_address(i);
-- break;
-- }
-- }
--
-- /* If we found no next symbol, we use the end of the section. */
-- if (!symbol_end) {
-- if (is_kernel_inittext(addr))
-- symbol_end = (unsigned long)_einittext;
-- else if (IS_ENABLED(CONFIG_KALLSYMS_ALL))
-- symbol_end = (unsigned long)_end;
-- else
-- symbol_end = (unsigned long)_etext;
-- }
--
- if (symbolsize)
-- *symbolsize = symbol_end - symbol_start;
-+ *symbolsize = kallsyms_sizes[low];
- if (offset)
-- *offset = addr - symbol_start;
-+ *offset = addr - kallsyms_sym_address(low);
-
- return low;
- }
-@@ -270,6 +266,7 @@ int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
- return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) ||
- !!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
- }
-+EXPORT_SYMBOL_GPL(kallsyms_lookup_size_offset);
-
- /*
- * Lookup an address
-@@ -432,22 +429,6 @@ int sprint_backtrace(char *buffer, unsigned long address)
- return __sprint_symbol(buffer, address, -1, 1);
- }
-
--/* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
--struct kallsym_iter {
-- loff_t pos;
-- loff_t pos_arch_end;
-- loff_t pos_mod_end;
-- loff_t pos_ftrace_mod_end;
-- loff_t pos_bpf_end;
-- unsigned long value;
-- unsigned int nameoff; /* If iterating in core kernel symbols. */
-- char type;
-- char name[KSYM_NAME_LEN];
-- char module_name[MODULE_NAME_LEN];
-- int exported;
-- int show_value;
--};
--
- int __weak arch_get_kallsym(unsigned int symnum, unsigned long *value,
- char *type, char *name)
- {
-@@ -473,7 +454,9 @@ static int get_ksymbol_mod(struct kallsym_iter *iter)
- int ret = module_get_kallsym(iter->pos - iter->pos_arch_end,
- &iter->value, &iter->type,
- iter->name, iter->module_name,
-- &iter->exported);
-+ &iter->size, &iter->exported);
-+ iter->builtin_module = 0;
-+
- if (ret < 0) {
- iter->pos_mod_end = iter->pos;
- return 0;
-@@ -536,10 +519,22 @@ static int get_ksymbol_kprobe(struct kallsym_iter *iter)
- static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
- {
- unsigned off = iter->nameoff;
-+ u32 mod_index = 0;
-+
-+ if (kallsyms_symbol_modules)
-+ mod_index = kallsyms_symbol_modules[iter->pos];
-
-- iter->module_name[0] = '\0';
-+ if (mod_index == 0 || kallsyms_modules == NULL) {
-+ iter->module_name[0] = '\0';
-+ iter->builtin_module = 0;
-+ } else {
-+ strcpy(iter->module_name, &kallsyms_modules[mod_index]);
-+ iter->builtin_module = 1;
-+ }
-+ iter->exported = 0;
- iter->value = kallsyms_sym_address(iter->pos);
-
-+ iter->size = kallsyms_sizes[iter->pos];
- iter->type = kallsyms_get_symbol_type(off);
-
- off = kallsyms_expand_symbol(off, iter->name, ARRAY_SIZE(iter->name));
-@@ -547,7 +542,7 @@ static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
- return off - iter->nameoff;
- }
-
--static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
-+void kallsyms_iter_reset(struct kallsym_iter *iter, loff_t new_pos)
- {
- iter->name[0] = '\0';
- iter->nameoff = get_symbol_offset(new_pos);
-@@ -559,6 +554,7 @@ static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
- iter->pos_bpf_end = 0;
- }
- }
-+EXPORT_SYMBOL_GPL(kallsyms_iter_reset);
-
- /*
- * The end position (last + 1) of each additional kallsyms section is recorded
-@@ -589,7 +585,7 @@ static int update_iter_mod(struct kallsym_iter *iter, loff_t pos)
- }
-
- /* Returns false if pos at or past end of file. */
--static int update_iter(struct kallsym_iter *iter, loff_t pos)
-+int kallsyms_iter_update(struct kallsym_iter *iter, loff_t pos)
- {
- /* Module symbols can be accessed randomly. */
- if (pos >= kallsyms_num_syms)
-@@ -597,26 +593,27 @@ static int update_iter(struct kallsym_iter *iter, loff_t pos)
-
- /* If we're not on the desired position, reset to new position. */
- if (pos != iter->pos)
-- reset_iter(iter, pos);
-+ kallsyms_iter_reset(iter, pos);
-
- iter->nameoff += get_ksymbol_core(iter);
- iter->pos++;
-
- return 1;
- }
-+EXPORT_SYMBOL_GPL(kallsyms_iter_update);
-
- static void *s_next(struct seq_file *m, void *p, loff_t *pos)
- {
- (*pos)++;
-
-- if (!update_iter(m->private, *pos))
-+ if (!kallsyms_iter_update(m->private, *pos))
- return NULL;
- return p;
- }
-
- static void *s_start(struct seq_file *m, loff_t *pos)
- {
-- if (!update_iter(m->private, *pos))
-+ if (!kallsyms_iter_update(m->private, *pos))
- return NULL;
- return m->private;
- }
-@@ -625,7 +622,7 @@ static void s_stop(struct seq_file *m, void *p)
- {
- }
-
--static int s_show(struct seq_file *m, void *p)
-+static int s_show_internal(struct seq_file *m, void *p, int builtin_modules)
- {
- void *value;
- struct kallsym_iter *iter = m->private;
-@@ -636,7 +633,9 @@ static int s_show(struct seq_file *m, void *p)
-
- value = iter->show_value ? (void *)iter->value : NULL;
-
-- if (iter->module_name[0]) {
-+ if ((iter->builtin_module == 0 && iter->module_name[0]) ||
-+ (iter->builtin_module != 0 && iter->module_name[0] &&
-+ builtin_modules != 0)) {
- char type;
-
- /*
-@@ -645,14 +644,32 @@ static int s_show(struct seq_file *m, void *p)
- */
- type = iter->exported ? toupper(iter->type) :
- tolower(iter->type);
-- seq_printf(m, "%px %c %s\t[%s]\n", value,
-- type, iter->name, iter->module_name);
-- } else
-+ if (builtin_modules)
-+ seq_printf(m, "%px %lx %c %s\t[%s]\n", value,
-+ iter->size, type, iter->name,
-+ iter->module_name);
-+ else
-+ seq_printf(m, "%px %c %s\t[%s]\n", value,
-+ type, iter->name, iter->module_name);
-+ } else if (builtin_modules)
-+ seq_printf(m, "%px %lx %c %s\n", value, iter->size,
-+ iter->type, iter->name);
-+ else
- seq_printf(m, "%px %c %s\n", value,
- iter->type, iter->name);
- return 0;
- }
-
-+static int s_show(struct seq_file *m, void *p)
-+{
-+ return s_show_internal(m, p, 0);
-+}
-+
-+static int s_mod_show(struct seq_file *m, void *p)
-+{
-+ return s_show_internal(m, p, 1);
-+}
-+
- static const struct seq_operations kallsyms_op = {
- .start = s_start,
- .next = s_next,
-@@ -695,7 +712,15 @@ bool kallsyms_show_value(const struct cred *cred)
- }
- }
-
--static int kallsyms_open(struct inode *inode, struct file *file)
-+static const struct seq_operations kallmodsyms_op = {
-+ .start = s_start,
-+ .next = s_next,
-+ .stop = s_stop,
-+ .show = s_mod_show
-+};
-+
-+static int kallsyms_open_internal(struct inode *inode, struct file *file,
-+ const struct seq_operations *ops)
- {
- /*
- * We keep iterator in m->private, since normal case is to
-@@ -703,10 +728,10 @@ static int kallsyms_open(struct inode *inode, struct file *file)
- * using get_symbol_offset for every symbol.
- */
- struct kallsym_iter *iter;
-- iter = __seq_open_private(file, &kallsyms_op, sizeof(*iter));
-+ iter = __seq_open_private(file, ops, sizeof(*iter));
- if (!iter)
- return -ENOMEM;
-- reset_iter(iter, 0);
-+ kallsyms_iter_reset(iter, 0);
-
- /*
- * Instead of checking this on every s_show() call, cache
-@@ -716,6 +741,16 @@ static int kallsyms_open(struct inode *inode, struct file *file)
- return 0;
- }
-
-+static int kallsyms_open(struct inode *inode, struct file *file)
-+{
-+ return kallsyms_open_internal(inode, file, &kallsyms_op);
-+}
-+
-+static int kallmodsyms_open(struct inode *inode, struct file *file)
-+{
-+ return kallsyms_open_internal(inode, file, &kallmodsyms_op);
-+}
-+
- #ifdef CONFIG_KGDB_KDB
- const char *kdb_walk_kallsyms(loff_t *pos)
- {
-@@ -723,10 +758,10 @@ const char *kdb_walk_kallsyms(loff_t *pos)
- if (*pos == 0) {
- memset(&kdb_walk_kallsyms_iter, 0,
- sizeof(kdb_walk_kallsyms_iter));
-- reset_iter(&kdb_walk_kallsyms_iter, 0);
-+ kallsyms_iter_reset(&kdb_walk_kallsyms_iter, 0);
- }
- while (1) {
-- if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
-+ if (!kallsyms_iter_update(&kdb_walk_kallsyms_iter, *pos))
- return NULL;
- ++*pos;
- /* Some debugging symbols have no name. Ignore them. */
-@@ -743,9 +778,17 @@ static const struct proc_ops kallsyms_proc_ops = {
- .proc_release = seq_release_private,
- };
-
-+static const struct proc_ops kallmodsyms_proc_ops = {
-+ .proc_open = kallmodsyms_open,
-+ .proc_read = seq_read,
-+ .proc_lseek = seq_lseek,
-+ .proc_release = seq_release_private,
-+};
-+
- static int __init kallsyms_init(void)
- {
- proc_create("kallsyms", 0444, NULL, &kallsyms_proc_ops);
-+ proc_create("kallmodsyms", 0444, NULL, &kallmodsyms_proc_ops);
- return 0;
- }
- device_initcall(kallsyms_init);
-diff --git a/kernel/module.c b/kernel/module.c
-index e20499309b2af6aca7cafcf95962b94065d4fe83..9e471dbedc83a1a080612bf4f4ffabf09f3b8aa8 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -4241,7 +4241,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
- }
-
- int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
-- char *name, char *module_name, int *exported)
-+ char *name, char *module_name, unsigned long *size,
-+ int *exported)
- {
- struct module *mod;
-
-@@ -4260,6 +4261,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
- strlcpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN);
- strlcpy(module_name, mod->name, MODULE_NAME_LEN);
- *exported = is_exported(name, *value, mod);
-+ *size = kallsyms->symtab[symnum].st_size;
- preempt_enable();
- return 0;
- }
-diff --git a/scripts/Makefile b/scripts/Makefile
-index 041bcf48cc5c7613d072cf50eae142a21d31153e..efa1ff4dff951222a8c98326c29f2146d7e4c587 100644
---- a/scripts/Makefile
-+++ b/scripts/Makefile
-@@ -12,6 +12,16 @@ hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
- hostprogs-always-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
- hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
-
-+kallsyms-objs := kallsyms.o
-+
-+ifeq ($(CONFIG_KALLMODSYMS),y)
-+kallsyms-objs += eu_simple.o
-+
-+HOSTCFLAGS_eu_simple.o := -I$(srctree)/scripts
-+HOSTCFLAGS_kallsyms.o := $(shell pkg-config --cflags glib-2.0) -I$(srctree)/scripts
-+HOSTLDLIBS_kallsyms := $(shell pkg-config --libs glib-2.0) -ldw
-+endif
-+
- HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
- HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
- HOSTLDLIBS_sign-file = -lcrypto
-diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
-index 7ecd2ccba531bb4c46a01b4ecad7ea8078f29027..884ac793bdf417a34060a95f4239034680e09ea9 100644
---- a/scripts/kallsyms.c
-+++ b/scripts/kallsyms.c
-@@ -5,7 +5,10 @@
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
-- * Usage: nm -n vmlinux | scripts/kallsyms [--all-symbols] > symbols.S
-+ * Usage: nm -n -S vmlinux | scripts/kallsyms [--all-symbols]
-+ * [--symbol-prefix=<prefix char>]
-+ * [--builtin=modules_thick.builtin]
-+ * > symbols.S
- *
- * Table compression uses all the unused char codes on the symbols and
- * maps these to the most used substrings (tokens). For instance, it might
-@@ -18,12 +21,27 @@
- *
- */
-
-+#define _GNU_SOURCE 1
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <limits.h>
-+#include <errno.h>
-+#include <unistd.h>
-+
-+#include "../include/generated/autoconf.h"
-+
-+#ifdef CONFIG_KALLMODSYMS
-+#include <libelf.h>
-+#include <dwarf.h>
-+#include <elfutils/libdwfl.h>
-+#include <elfutils/libdw.h>
-+#include <glib.h>
-+
-+#include <eu_simple.h>
-+#endif
-
- #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
-
-@@ -31,9 +49,13 @@
-
- struct sym_entry {
- unsigned long long addr;
-+ unsigned long long size;
- unsigned int len;
- unsigned int start_pos;
- unsigned int percpu_absolute;
-+#ifdef CONFIG_KALLMODSYMS
-+ unsigned int module;
-+#endif
- unsigned char sym[];
- };
-
-@@ -67,11 +89,33 @@ static int token_profit[0x10000];
- static unsigned char best_table[256][2];
- static unsigned char best_table_len[256];
-
-+#ifdef CONFIG_KALLMODSYMS
-+/*
-+ * The builtin module names. The "offset" points to the name as if
-+ * all builtin module names were concatenated to a single string.
-+ */
-+static unsigned int builtin_module_size; /* number allocated */
-+static unsigned int builtin_module_len; /* number assigned */
-+static char **builtin_modules; /* array of module names */
-+static unsigned int *builtin_module_offsets; /* offset */
-+
-+/*
-+ * An ordered list of address ranges and how they map to built-in modules.
-+ */
-+struct addrmap_entry {
-+ unsigned long long addr;
-+ unsigned long long size;
-+ unsigned int module;
-+};
-+static struct addrmap_entry *addrmap;
-+static int addrmap_num, addrmap_alloced;
-+#endif
-
- static void usage(void)
- {
- fprintf(stderr, "Usage: kallsyms [--all-symbols] "
-- "[--base-relative] < in.map > out.S\n");
-+ "[--base-relative] [--builtin=modules_thick.builtin] "
-+ "< in.map > out.S\n");
- exit(1);
- }
-
-@@ -99,6 +143,8 @@ static bool is_ignored_symbol(const char *name, char type)
- "kallsyms_markers",
- "kallsyms_token_table",
- "kallsyms_token_index",
-+ "kallsyms_symbol_modules",
-+ "kallsyms_modules",
- /* Exclude linker generated symbols which vary between passes */
- "_SDA_BASE_", /* ppc */
- "_SDA2_BASE_", /* ppc */
-@@ -189,6 +235,20 @@ static void check_symbol_range(const char *sym, unsigned long long addr,
- }
- }
-
-+#ifdef CONFIG_KALLMODSYMS
-+static int addrmap_compare(const void *keyp, const void *rangep)
-+{
-+ unsigned long long addr = *((const unsigned long long *)keyp);
-+ const struct addrmap_entry *range = (const struct addrmap_entry *)rangep;
-+
-+ if (addr < range->addr)
-+ return -1;
-+ if (addr < range->addr + range->size)
-+ return 0;
-+ return 1;
-+}
-+#endif
-+
- static struct sym_entry *read_symbol(FILE *in)
- {
- char name[500], type;
-@@ -196,9 +256,14 @@ static struct sym_entry *read_symbol(FILE *in)
- unsigned int len;
- struct sym_entry *sym;
- int rc;
--
-- rc = fscanf(in, "%llx %c %499s\n", &addr, &type, name);
-- if (rc != 3) {
-+ unsigned long long size;
-+#ifdef CONFIG_KALLMODSYMS
-+ struct addrmap_entry *range;
-+ unsigned int module;
-+#endif
-+
-+ rc = fscanf(in, "%llx %llx %c %499s\n", &addr, &size, &type, name);
-+ if (rc != 4) {
- if (rc != EOF && fgets(name, 500, in) == NULL)
- fprintf(stderr, "Read error or end of file.\n");
- return NULL;
-@@ -220,6 +285,16 @@ static struct sym_entry *read_symbol(FILE *in)
- check_symbol_range(name, addr, text_ranges, ARRAY_SIZE(text_ranges));
- check_symbol_range(name, addr, &percpu_range, 1);
-
-+#ifdef CONFIG_KALLMODSYMS
-+ /* look up the builtin module this is part of (if any) */
-+ range = (struct addrmap_entry *) bsearch(&addr,
-+ addrmap, addrmap_num, sizeof(*addrmap), &addrmap_compare);
-+ if (range)
-+ module = builtin_module_offsets[range->module];
-+ else
-+ module = 0;
-+#endif
-+
- /* include the type field in the symbol name, so that it gets
- * compressed together */
-
-@@ -236,6 +311,10 @@ static struct sym_entry *read_symbol(FILE *in)
- sym->sym[0] = type;
- strcpy(sym_name(sym), name);
- sym->percpu_absolute = 0;
-+ sym->size = size;
-+#ifdef CONFIG_KALLMODSYMS
-+ sym->module = module;
-+#endif
-
- return sym;
- }
-@@ -445,6 +524,11 @@ static void write_src(void)
- printf("\n");
- }
-
-+ output_label("kallsyms_sizes");
-+ for (i = 0; i < table_cnt; i++)
-+ printf("\tPTR\t%#llx\n", table[i]->size);
-+ printf("\n");
-+
- output_label("kallsyms_num_syms");
- printf("\t.long\t%u\n", table_cnt);
- printf("\n");
-@@ -494,8 +578,22 @@ static void write_src(void)
- for (i = 0; i < 256; i++)
- printf("\t.short\t%d\n", best_idx[i]);
- printf("\n");
--}
-
-+#ifdef CONFIG_KALLMODSYMS
-+ output_label("kallsyms_modules");
-+ for (i = 0; i < builtin_module_len; i++)
-+ printf("\t.asciz\t\"%s\"\n", builtin_modules[i]);
-+ printf("\n");
-+
-+ for (i = 0; i < builtin_module_len; i++)
-+ free(builtin_modules[i]);
-+
-+ output_label("kallsyms_symbol_modules");
-+ for (i = 0; i < table_cnt; i++)
-+ printf("\t.int\t%d\n", table[i]->module);
-+ printf("\n");
-+#endif
-+}
-
- /* table lookup compression functions */
-
-@@ -697,6 +795,18 @@ static int compare_symbols(const void *a, const void *b)
- if (sa->addr < sb->addr)
- return -1;
-
-+ /* zero-size markers before nonzero-size symbols */
-+ if (sa->size > 0 && sb->size == 0)
-+ return 1;
-+ if (sa->size == 0 && sb->size > 0)
-+ return -1;
-+
-+ /* sort by size (large size preceding symbols it encompasses) */
-+ if (sa->size < sb->size)
-+ return 1;
-+ if (sa->size > sb->size)
-+ return -1;
-+
- /* sort by "weakness" type */
- wa = (sa->sym[0] == 'w') || (sa->sym[0] == 'W');
- wb = (sb->sym[0] == 'w') || (sb->sym[0] == 'W');
-@@ -756,23 +866,198 @@ static void record_relative_base(void)
- }
- }
-
-+#ifdef CONFIG_KALLMODSYMS
-+/* Built-in module list computation. */
-+
-+/*
-+ * Expand the builtin modules list.
-+ */
-+static void expand_builtin_modules(void)
-+{
-+ builtin_module_size += 50;
-+
-+ builtin_modules = realloc(builtin_modules,
-+ sizeof(*builtin_modules) *
-+ builtin_module_size);
-+ builtin_module_offsets = realloc(builtin_module_offsets,
-+ sizeof(*builtin_module_offsets) *
-+ builtin_module_size);
-+
-+ if (!builtin_modules || !builtin_module_offsets) {
-+ fprintf(stderr, "kallsyms failure: out of memory.\n");
-+ exit(EXIT_FAILURE);
-+ }
-+}
-+
-+/*
-+ * Add a single built-in module (possibly composed of many files) to the
-+ * modules list. Take the offset of the current module and return it
-+ * (purely for simplicity's sake in the caller).
-+ */
-+static size_t add_builtin_module(const char *module_name, char **module_paths,
-+ GHashTable *obj2mod, size_t offset)
-+{
-+ gpointer val = GUINT_TO_POINTER(builtin_module_len);
-+
-+ /* map the module's object paths to the module offset */
-+ while (*module_paths) {
-+ g_hash_table_insert(obj2mod, strdup(*module_paths), val);
-+ module_paths++;
-+ }
-+
-+ /* add the module name */
-+ if (builtin_module_size <= builtin_module_len)
-+ expand_builtin_modules();
-+ builtin_modules[builtin_module_len] = strdup(module_name);
-+ builtin_module_offsets[builtin_module_len] = offset;
-+ builtin_module_len++;
-+
-+ return (offset + strlen(module_name) + 1);
-+}
-+
-+/*
-+ * Read the linker map.
-+ */
-+static void read_linker_map(GHashTable *obj2mod)
-+{
-+ unsigned long long addr, size;
-+ char obj[PATH_MAX+1];
-+ FILE *f = fopen(".tmp_vmlinux.ranges", "r");
-+
-+ if (!f) {
-+ fprintf(stderr, "Cannot open '.tmp_vmlinux.ranges'.\n");
-+ exit(1);
-+ }
-+
-+ addrmap_num = 0;
-+ addrmap_alloced = 4096;
-+ addrmap = malloc(sizeof(*addrmap) * addrmap_alloced);
-+ if (!addrmap)
-+ goto oom;
-+
-+ /*
-+ * For each address range (addr,size) and object, add to addrmap
-+ * the range and the built-in module to which the object maps.
-+ */
-+ while (fscanf(f, "%llx %llx %s\n", &addr, &size, obj) == 3) {
-+ int m = GPOINTER_TO_UINT(g_hash_table_lookup(obj2mod, obj));
-+
-+ if (addr == 0 || size == 0 || m == 0)
-+ continue;
-+
-+ if (addrmap_num >= addrmap_alloced) {
-+ addrmap_alloced *= 2;
-+ addrmap = realloc(addrmap,
-+ sizeof(*addrmap) * addrmap_alloced);
-+ if (!addrmap)
-+ goto oom;
-+ }
-+
-+ addrmap[addrmap_num].addr = addr;
-+ addrmap[addrmap_num].size = size;
-+ addrmap[addrmap_num].module = m;
-+ addrmap_num++;
-+ }
-+ fclose(f);
-+ return;
-+
-+oom:
-+ fprintf(stderr, "kallsyms: out of memory\n");
-+ exit(1);
-+}
-+
-+/*
-+ * Read the list of built-in modules. Construct:
-+ * - builtin_modules: array of module names
-+ * - builtin_module_offsets: array of offsets to find module names
-+ * - obj2mod: mapping from each object-file path to a module index
-+ * (which can be used in the arrays)
-+ * Finally, read the linker map.
-+ */
-+static void read_modules(const char *modules_builtin)
-+{
-+ struct modules_thick_iter *i;
-+ size_t offset = 0;
-+ char *module_name = NULL;
-+ char **module_paths;
-+ GHashTable *obj2mod;
-+
-+ obj2mod = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
-+ if (!obj2mod) {
-+ fprintf(stderr, "kallsyms: out of memory\n");
-+ exit(1);
-+ }
-+
-+ /*
-+ * builtin_modules[0] is a null entry signifying a symbol that cannot be
-+ * modular.
-+ */
-+ builtin_module_size = 50;
-+ builtin_modules = malloc(sizeof(*builtin_modules) *
-+ builtin_module_size);
-+ builtin_module_offsets = malloc(sizeof(*builtin_module_offsets) *
-+ builtin_module_size);
-+ if (!builtin_modules || !builtin_module_offsets) {
-+ fprintf(stderr, "kallsyms: out of memory\n");
-+ exit(1);
-+ }
-+ builtin_modules[0] = strdup("");
-+ builtin_module_offsets[0] = 0;
-+ builtin_module_len = 1;
-+ offset++;
-+
-+ /*
-+ * Iterate over all modules in modules_thick.builtin and add each.
-+ */
-+ i = modules_thick_iter_new(modules_builtin);
-+ if (i == NULL) {
-+ fprintf(stderr, "Cannot iterate over builtin modules.\n");
-+ exit(1);
-+ }
-+
-+ while ((module_paths = modules_thick_iter_next(i, &module_name)) != NULL) {
-+ offset = add_builtin_module(module_name, module_paths,
-+ obj2mod, offset);
-+ free(module_paths);
-+ module_paths = NULL;
-+ }
-+
-+ free(module_name);
-+ modules_thick_iter_free(i);
-+
-+ /*
-+ * Read linker map.
-+ */
-+ read_linker_map(obj2mod);
-+
-+ g_hash_table_destroy(obj2mod);
-+}
-+#else
-+static void read_modules(const char *unused) {}
-+#endif /* CONFIG_KALLMODSYMS */
-+
- int main(int argc, char **argv)
- {
-- if (argc >= 2) {
-+ const char *modules_builtin = "modules_thick.builtin";
-+
-+ if (argc >= 1) {
- int i;
- for (i = 1; i < argc; i++) {
-- if(strcmp(argv[i], "--all-symbols") == 0)
-+ if (strcmp(argv[i], "--all-symbols") == 0)
- all_symbols = 1;
- else if (strcmp(argv[i], "--absolute-percpu") == 0)
- absolute_percpu = 1;
- else if (strcmp(argv[i], "--base-relative") == 0)
- base_relative = 1;
-+ else if (strncmp(argv[i], "--builtin=", 10) == 0)
-+ modules_builtin = &argv[i][10];
- else
- usage();
- }
- } else if (argc != 1)
- usage();
-
-+ read_modules(modules_builtin);
- read_map(stdin);
- shrink_table();
- if (absolute_percpu)
-diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
-index 6eded325c8378c8cff94c379a180060c0b154ec4..bc533252fa3c39482a870654036caf3897946123 100755
---- a/scripts/link-vmlinux.sh
-+++ b/scripts/link-vmlinux.sh
-@@ -109,6 +109,7 @@ vmlinux_link()
- --start-group \
- ${KBUILD_VMLINUX_LIBS} \
- --end-group \
-+ -Map=.tmp_vmlinux.map \
- ${@}"
-
- ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
-@@ -122,6 +123,7 @@ vmlinux_link()
- -Wl,--start-group \
- ${KBUILD_VMLINUX_LIBS} \
- -Wl,--end-group \
-+ -Wl,-Map=.tmp_vmlinux.map \
- ${@}"
-
- ${CC} ${CFLAGS_vmlinux} \
-@@ -174,6 +176,19 @@ kallsyms()
- {
- local kallsymopt;
-
-+ # read the linker map to identify ranges of addresses:
-+ # - for each *.o file, report address, size, pathname
-+ # - most such lines will have four fields
-+ # - but sometimes there is a line break after the first field
-+ # - start reading at "Linker script and memory map"
-+ # - stop reading at ".brk"
-+ ${AWK} '
-+ /\.o$/ && start==1 { print $(NF-2), $(NF-1), $NF }
-+ /^Linker script and memory map/ { start = 1 }
-+ /^\.brk/ { exit(0) }
-+ ' .tmp_vmlinux.map | sort > .tmp_vmlinux.ranges
-+
-+ # get kallsyms options
- if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
- kallsymopt="${kallsymopt} --all-symbols"
- fi
-@@ -186,8 +201,13 @@ kallsyms()
- kallsymopt="${kallsymopt} --base-relative"
- fi
-
-+ # "nm -S" does not print symbol size when size is 0
-+ # Therefore use awk to regularize the data:
-+ # - when there are only three fields, add an explicit "0"
-+ # - when there are already four fields, pass through as is
- info KSYMS ${2}
-- ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${2}
-+ ${NM} -n -S ${1} | ${AWK} 'NF==3 {print $1, 0, $2, $3}; NF==4' | \
-+ scripts/kallsyms ${kallsymopt} > ${2}
- }
-
- # Perform one step in kallsyms generation, including temporary linking of
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch
deleted file mode 100644
index 437715c7dd30..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0003-waitfd-new-syscall-implementing-waitpid-over-fds.patch
+++ /dev/null
@@ -1,809 +0,0 @@
-From 7cbd018b36da6838efe3adba191adf3acd4ef9bd Mon Sep 17 00:00:00 2001
-From: Nick Alcock <nick.alcock@oracle.com>
-Date: Wed, 14 Nov 2018 20:28:51 +0000
-Subject: [PATCH 03/19] waitfd: new syscall implementing waitpid() over fds
-
-This syscall, originally due to Casey Dahlin but significantly modified
-since, is called quite like waitid():
-
- fd = waitfd(P_PID, some_pid, WEXITED | WSTOPPED, 0);
-
-This returns a file descriptor which becomes ready whenever waitpid()
-would return, and when read() returns the return value waitpid() would
-have returned. (Alternatively, you can use it as a pure indication that
-waitpid() is callable without hanging, and then call waitpid()). See the
-example in tools/testing/selftests/waitfd/.
-
-The original reason for rejection of this patch back in 2009 was that it
-was redundant to waitpid()ing in a separate thread and transmitting
-process information to another thread that polls: but this is only the
-case for the conventional child-process use of waitpid(). Other
-waitpid() uses, such as ptrace() returns, are targetted on a single
-thread, so without waitfd or something like it, it is impossible to have
-a thread that both accepts requests for servicing from other threads
-over an fd *and* manipulates the state of a ptrace()d process in
-response to those requests without ugly CPU-chewing polling (accepting
-requests requires blocking in poll() or select(): handling the ptraced
-process requires blocking in waitpid()).
-
-There is one ugliness in this patch which I would appreciate suggestions
-to improve (due to me, not due to Casey, don't blame him). The poll()
-machinery expects to be used with files, or things enough like files
-that the wake_up key contains an indication as to whether this wakeup
-corresponds to a POLLIN / POLLOUT / POLLERR event on this fd. You can
-override this in your poll_queue_proc, but the poll() and epoll() queue
-procs both have this interpretation.
-
-Unfortunately, this is not true for waitfds, which wait on the the
-wait_chldexit waitqueue, whose key is a pointer to the task_struct of
-the task being killed. We can't do anything with this key, but we
-certainly don't want the poll machinery treating it as a bitmask and
-checking it against poll events!
-
-So we introduce a new poll_wait() analogue, poll_wait_fixed(). This is used
-for poll_wait() calls which know they must wait on waitqueues whose keys are
-not a typecast representation of poll events, and passes in an extra
-argument to the poll_queue_proc, which if nonzero is the event which a
-wakeup on this waitqueue should be considered as equivalent to. The
-poll_queue_proc can then skip adding entirely if that fixed event is not
-included in the set to be caught by this poll().
-
-We also add a new poll_table_entry.fixed_key. The poll_queue_proc can
-record the fixed key it is passed in here, and reuse it at wakeup time to
-track that a nonzero fixed key was passed in to poll_wait_fixed() and that
-the key should be ignored in preference to fixed_key.
-
-With this in place, you can say, e.g. (as waitfd does)
-
- poll_wait_fixed(file, &current->signal->wait_chldexit, wait,
- POLLIN);
-
-and the key passed to wakeups on the wait_chldexit waitqueue will be
-ignored: the fd will always be treated as having raised POLLIN, waking
-up poll()s and epoll()s that have specified that event. (Obviously, a
-poll function that calls this should return the same value from the poll
-function as was passed to poll_wait_fixed(), or, as usual, zero if this
-was a spurious wakeup.)
-
-I do not like this scheme: it's sufficiently arcane that I had to go
-back to my old commit messages to figure out what it was doing and
-why. But I don't see another way to cause poll() to return on
-appropriate activity on waitqueues that do not actually correspond to
-files. (I do wonder how signalfd works. It doesn't seem to need any of
-this and I don't understand why not. I would be overjoyed to remove the
-whole invasive poll_wait_fixed() mess, but I'm not sure what to replace
-it with.)
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/entry/syscalls/syscall_32.tbl | 3 +
- arch/x86/entry/syscalls/syscall_64.tbl | 3 +
- drivers/vfio/virqfd.c | 3 +-
- drivers/vhost/vhost.c | 2 +-
- fs/Makefile | 1 +
- fs/aio.c | 2 +-
- fs/eventpoll.c | 22 +++-
- fs/io_uring.c | 5 +-
- fs/select.c | 21 +++-
- fs/waitfd.c | 130 ++++++++++++++++++++++++
- include/linux/poll.h | 14 ++-
- include/linux/syscalls.h | 3 +
- include/uapi/asm-generic/unistd.h | 5 +-
- init/Kconfig | 16 +++
- kernel/exit.c | 13 ++-
- kernel/sys_ni.c | 1 +
- mm/memcontrol.c | 2 +-
- net/9p/trans_fd.c | 3 +-
- tools/testing/selftests/waitfd/Makefile | 28 +++++
- tools/testing/selftests/waitfd/waitfd.c | 116 +++++++++++++++++++++
- virt/kvm/eventfd.c | 2 +-
- 21 files changed, 376 insertions(+), 19 deletions(-)
- create mode 100644 fs/waitfd.c
- create mode 100644 tools/testing/selftests/waitfd/Makefile
- create mode 100644 tools/testing/selftests/waitfd/waitfd.c
-
-diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
-index 0d0667a9fbd70aeb9e297342b9f855a457d45ea4..5605708e4c31f920411aec2682d7c0d17271054f 100644
---- a/arch/x86/entry/syscalls/syscall_32.tbl
-+++ b/arch/x86/entry/syscalls/syscall_32.tbl
-@@ -445,3 +445,6 @@
- 438 i386 pidfd_getfd sys_pidfd_getfd
- 439 i386 faccessat2 sys_faccessat2
- 440 i386 process_madvise sys_process_madvise
-+# This one is a temporary number, designed for no clashes.
-+# Nothing but DTrace should use it.
-+473 i386 waitfd sys_waitfd
-diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
-index 379819244b91d275b2c98f7ff38a59049c24b42a..4f4e0585c65fc04ecf50c997d3b9e21375b7a88b 100644
---- a/arch/x86/entry/syscalls/syscall_64.tbl
-+++ b/arch/x86/entry/syscalls/syscall_64.tbl
-@@ -362,6 +362,9 @@
- 438 common pidfd_getfd sys_pidfd_getfd
- 439 common faccessat2 sys_faccessat2
- 440 common process_madvise sys_process_madvise
-+# This one is a temporary number, designed for no clashes.
-+# Nothing but DTrace should use it.
-+473 common waitfd sys_waitfd
-
- #
- # Due to a historical design error, certain syscalls are numbered differently
-diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c
-index 997cb5d0a657cb1cb795ca609704f886c7ffc276..6bfafa889af2181fc6a88aa8e63a7513393cc4ca 100644
---- a/drivers/vfio/virqfd.c
-+++ b/drivers/vfio/virqfd.c
-@@ -76,7 +76,8 @@ static int virqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void
- }
-
- static void virqfd_ptable_queue_proc(struct file *file,
-- wait_queue_head_t *wqh, poll_table *pt)
-+ wait_queue_head_t *wqh, poll_table *pt,
-+ unsigned long unused)
- {
- struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
- add_wait_queue(wqh, &virqfd->wait);
-diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
-index a262e12c6dc26f76810ac28a833ea5deb1e70d74..31128cadd1b20b24bba7b365e34e416c185d2c7c 100644
---- a/drivers/vhost/vhost.c
-+++ b/drivers/vhost/vhost.c
-@@ -152,7 +152,7 @@ static void vhost_flush_work(struct vhost_work *work)
- }
-
- static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
-- poll_table *pt)
-+ poll_table *pt, unsigned long unused)
- {
- struct vhost_poll *poll;
-
-diff --git a/fs/Makefile b/fs/Makefile
-index 999d1a23f036c9f96a06e056d333e2e3832cdc37..ad5fc1399484685eb956e934b5af56b431a4275f 100644
---- a/fs/Makefile
-+++ b/fs/Makefile
-@@ -31,6 +31,7 @@ obj-$(CONFIG_SIGNALFD) += signalfd.o
- obj-$(CONFIG_TIMERFD) += timerfd.o
- obj-$(CONFIG_EVENTFD) += eventfd.o
- obj-$(CONFIG_USERFAULTFD) += userfaultfd.o
-+obj-$(CONFIG_WAITFD) += waitfd.o
- obj-$(CONFIG_AIO) += aio.o
- obj-$(CONFIG_IO_URING) += io_uring.o
- obj-$(CONFIG_IO_WQ) += io-wq.o
-diff --git a/fs/aio.c b/fs/aio.c
-index 6a21d8919409c4aa2c0378108337724a1f73eb35..3485fe7913ef824cc7636205c13707041ee9fe95 100644
---- a/fs/aio.c
-+++ b/fs/aio.c
-@@ -1718,7 +1718,7 @@ struct aio_poll_table {
-
- static void
- aio_poll_queue_proc(struct file *file, struct wait_queue_head *head,
-- struct poll_table_struct *p)
-+ struct poll_table_struct *p, unsigned long fixed_event)
- {
- struct aio_poll_table *pt = container_of(p, struct aio_poll_table, pt);
-
-diff --git a/fs/eventpoll.c b/fs/eventpoll.c
-index 117b1c395ae4ad7d16fc3b705ec3185065159dbb..e3c9f4ea9ec6aa1b62342976af425318c7624294 100644
---- a/fs/eventpoll.c
-+++ b/fs/eventpoll.c
-@@ -157,6 +157,9 @@ struct epitem {
- /* Number of active wait queue attached to poll operations */
- int nwait;
-
-+ /* fd always raises this fixed event. */
-+ unsigned long fixed_event;
-+
- /* List containing poll wait queues */
- struct list_head pwqlist;
-
-@@ -867,7 +870,7 @@ static int ep_eventpoll_release(struct inode *inode, struct file *file)
- static __poll_t ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
- void *priv);
- static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
-- poll_table *pt);
-+ poll_table *pt, unsigned long fixed_event);
-
- /*
- * Differs from ep_eventpoll_poll() in that internal callers already have
-@@ -1283,6 +1286,13 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v
- if (!(epi->event.events & EPOLLEXCLUSIVE))
- ewake = 1;
-
-+ /*
-+ * If this fd type has a hardwired event which should override the key
-+ * (e.g. if it is waiting on a non-file waitqueue), jam it in here.
-+ */
-+ if (epi->fixed_event)
-+ key = (void *)epi->fixed_event;
-+
- if (pollflags & POLLFREE) {
- /*
- * If we race with ep_remove_wait_queue() it can miss
-@@ -1307,11 +1317,17 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v
- * target file wakeup lists.
- */
- static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
-- poll_table *pt)
-+ poll_table *pt, unsigned long fixed_event)
- {
- struct epitem *epi = ep_item_from_epqueue(pt);
- struct eppoll_entry *pwq;
-
-+ if (fixed_event & !(epi->event.events & fixed_event))
-+ return;
-+
-+ if (fixed_event)
-+ epi->fixed_event = fixed_event;
-+
- if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, GFP_KERNEL))) {
- init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
- pwq->whead = whead;
-@@ -1512,6 +1528,7 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
- ep_set_ffd(&epi->ffd, tfile, fd);
- epi->event = *event;
- epi->nwait = 0;
-+ epi->fixed_event = 0;
- epi->next = EP_UNACTIVE_PTR;
- if (epi->event.events & EPOLLWAKEUP) {
- error = ep_create_wakeup_source(epi);
-@@ -2410,7 +2427,6 @@ static int __init eventpoll_init(void)
- * We can have many thousands of epitems, so prevent this from
- * using an extra cache line on 64-bit (and smaller) CPUs
- */
-- BUILD_BUG_ON(sizeof(void *) <= 8 && sizeof(struct epitem) > 128);
-
- /* Allocates slab cache used to allocate "struct epitem" items */
- epi_cache = kmem_cache_create("eventpoll_epi", sizeof(struct epitem),
-diff --git a/fs/io_uring.c b/fs/io_uring.c
-index fd12d9327ee5b86120f2370aafa457c08f3a5de4..0d0162ab5301200c05db06dc78535bf70ab6fe6b 100644
---- a/fs/io_uring.c
-+++ b/fs/io_uring.c
-@@ -5109,7 +5109,8 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
- }
-
- static void io_async_queue_proc(struct file *file, struct wait_queue_head *head,
-- struct poll_table_struct *p)
-+ struct poll_table_struct *p,
-+ unsigned long fixed_event)
- {
- struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
- struct async_poll *apoll = pt->req->apoll;
-@@ -5405,7 +5406,7 @@ static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
- }
-
- static void io_poll_queue_proc(struct file *file, struct wait_queue_head *head,
-- struct poll_table_struct *p)
-+ struct poll_table_struct *p, unsigned long fixed_event)
- {
- struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
-
-diff --git a/fs/select.c b/fs/select.c
-index 37aaa8317f3ae1a6a9aa9153f336eefa6c2b1aa4..ec91d05beb7d58ab596c17751afd952450edb183 100644
---- a/fs/select.c
-+++ b/fs/select.c
-@@ -116,7 +116,7 @@ struct poll_table_page {
- * poll table.
- */
- static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
-- poll_table *p);
-+ poll_table *p, unsigned long fixed_event);
-
- void poll_initwait(struct poll_wqueues *pwq)
- {
-@@ -212,6 +212,14 @@ static int pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key
- struct poll_table_entry *entry;
-
- entry = container_of(wait, struct poll_table_entry, wait);
-+
-+ /*
-+ * If this fd type has a hardwired key which should override the key
-+ * (e.g. if it is waiting on a non-file waitqueue), jam it in here.
-+ */
-+ if (entry->fixed_key)
-+ key = (void *)entry->fixed_key;
-+
- if (key && !(key_to_poll(key) & entry->key))
- return 0;
- return __pollwake(wait, mode, sync, key);
-@@ -219,15 +227,22 @@ static int pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key
-
- /* Add a new entry */
- static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
-- poll_table *p)
-+ poll_table *p, unsigned long fixed_event)
- {
- struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
-- struct poll_table_entry *entry = poll_get_entry(pwq);
-+ struct poll_table_entry *entry;
-+
-+ if (fixed_event && !(p->_key & fixed_event))
-+ return;
-+
-+ entry = poll_get_entry(pwq);
- if (!entry)
- return;
-+
- entry->filp = get_file(filp);
- entry->wait_address = wait_address;
- entry->key = p->_key;
-+ entry->fixed_key = fixed_event;
- init_waitqueue_func_entry(&entry->wait, pollwake);
- entry->wait.private = pwq;
- add_wait_queue(wait_address, &entry->wait);
-diff --git a/fs/waitfd.c b/fs/waitfd.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..311f84d7b85fdf71c2caf908050953bc8aef8430
---- /dev/null
-+++ b/fs/waitfd.c
-@@ -0,0 +1,130 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * fs/waitfd.c
-+ *
-+ * Copyright (C) 2008 Red Hat, Casey Dahlin <cdahlin@redhat.com>
-+ *
-+ * Largely derived from fs/signalfd.c
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/poll.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/kernel.h>
-+#include <linux/signal.h>
-+#include <linux/list.h>
-+#include <linux/anon_inodes.h>
-+#include <linux/syscalls.h>
-+
-+long kernel_wait4(pid_t upid, int __user *stat_addr,
-+ int options, struct rusage __user *ru);
-+
-+struct waitfd_ctx {
-+ int options;
-+ pid_t upid;
-+};
-+
-+static int waitfd_release(struct inode *inode, struct file *file)
-+{
-+ kfree(file->private_data);
-+ return 0;
-+}
-+
-+static unsigned int waitfd_poll(struct file *file, poll_table *wait)
-+{
-+ struct waitfd_ctx *ctx = file->private_data;
-+ long value;
-+
-+ poll_wait_fixed(file, &current->signal->wait_chldexit, wait,
-+ POLLIN);
-+
-+ value = kernel_wait4(ctx->upid, NULL, ctx->options | WNOHANG | WNOWAIT,
-+ NULL);
-+ if (value > 0 || value == -ECHILD)
-+ return POLLIN | POLLRDNORM;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Returns a multiple of the size of a stat_addr, or a negative error code. The
-+ * "count" parameter must be at least sizeof(int).
-+ */
-+static ssize_t waitfd_read(struct file *file, char __user *buf, size_t count,
-+ loff_t *ppos)
-+{
-+ struct waitfd_ctx *ctx = file->private_data;
-+ int __user *stat_addr = (int *)buf;
-+ int flags = ctx->options;
-+ ssize_t ret, total = 0;
-+
-+ count /= sizeof(int);
-+ if (!count)
-+ return -EINVAL;
-+
-+ if (file->f_flags & O_NONBLOCK)
-+ flags |= WNOHANG;
-+
-+ do {
-+ ret = kernel_wait4(ctx->upid, stat_addr, flags, NULL);
-+ if (ret == 0)
-+ ret = -EAGAIN;
-+ if (ret == -ECHILD)
-+ ret = 0;
-+ if (ret <= 0)
-+ break;
-+
-+ stat_addr++;
-+ total += sizeof(int);
-+ } while (--count);
-+
-+ return total ? total : ret;
-+}
-+
-+static const struct file_operations waitfd_fops = {
-+ .release = waitfd_release,
-+ .poll = waitfd_poll,
-+ .read = waitfd_read,
-+ .llseek = noop_llseek,
-+};
-+
-+SYSCALL_DEFINE4(waitfd, int __maybe_unused, which, pid_t, upid, int, options,
-+ int __maybe_unused, flags)
-+{
-+ int ufd;
-+ struct waitfd_ctx *ctx;
-+
-+ /*
-+ * Options validation from kernel_wait4(), minus WNOWAIT, which is
-+ * only used by our polling implementation. If WEXITED or WSTOPPED
-+ * are provided, silently remove them (for backward compatibility with
-+ * older callers).
-+ */
-+ options &= ~(WEXITED | WSTOPPED);
-+ if (options & ~(WNOHANG|WUNTRACED|WCONTINUED|
-+ __WNOTHREAD|__WCLONE|__WALL))
-+ return -EINVAL;
-+
-+ ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
-+ if (!ctx)
-+ return -ENOMEM;
-+
-+ ctx->options = options;
-+ ctx->upid = upid;
-+
-+ ufd = anon_inode_getfd("[waitfd]", &waitfd_fops, ctx,
-+ O_RDWR | flags | ((options & WNOHANG) ?
-+ O_NONBLOCK | 0 : 0));
-+ /*
-+ * Use the fd's nonblocking state from now on, since that can change.
-+ */
-+ ctx->options &= ~WNOHANG;
-+
-+ if (ufd < 0)
-+ kfree(ctx);
-+
-+ return ufd;
-+}
-diff --git a/include/linux/poll.h b/include/linux/poll.h
-index 1cdc32b1f1b0836e6dccf2ecf446b9aeab0a950b..1c06718f39bc8562c12dd22ae61967f2c8b332b5 100644
---- a/include/linux/poll.h
-+++ b/include/linux/poll.h
-@@ -34,7 +34,8 @@ struct poll_table_struct;
- /*
- * structures and helpers for f_op->poll implementations
- */
--typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
-+typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *,
-+ struct poll_table_struct *, unsigned long fixed_event);
-
- /*
- * Do not touch the structure directly, use the access functions
-@@ -48,7 +49,15 @@ typedef struct poll_table_struct {
- static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
- {
- if (p && p->_qproc && wait_address)
-- p->_qproc(filp, wait_address, p);
-+ p->_qproc(filp, wait_address, p, 0);
-+}
-+
-+static inline void poll_wait_fixed(struct file *filp,
-+ wait_queue_head_t *wait_address, poll_table *p,
-+ unsigned long fixed_event)
-+{
-+ if (p && p->_qproc && wait_address)
-+ p->_qproc(filp, wait_address, p, fixed_event);
- }
-
- /*
-@@ -93,6 +102,7 @@ static inline __poll_t vfs_poll(struct file *file, struct poll_table_struct *pt)
- struct poll_table_entry {
- struct file *filp;
- __poll_t key;
-+ unsigned long fixed_key;
- wait_queue_entry_t wait;
- wait_queue_head_t *wait_address;
- };
-diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
-index aea0ce9f3b745ad8f8bfeed1b74ad9c1307f1c28..0db3a09986d7b856267c6e6d801e04cbbd294ef7 100644
---- a/include/linux/syscalls.h
-+++ b/include/linux/syscalls.h
-@@ -1366,6 +1366,9 @@ long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
- long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
- unsigned int nsops,
- const struct old_timespec32 __user *timeout);
-+#ifdef CONFIG_DTRACE
-+asmlinkage long sys_waitfd(int which, pid_t upid, int options, int flags);
-+#endif
-
- int __sys_getsockopt(int fd, int level, int optname, char __user *optval,
- int __user *optlen);
-diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
-index 2056318988f774931c4e0a3104144bf4a75ff52f..58238d6fbbcba9e52cf799d5b283851c3e593b82 100644
---- a/include/uapi/asm-generic/unistd.h
-+++ b/include/uapi/asm-generic/unistd.h
-@@ -860,8 +860,11 @@ __SYSCALL(__NR_faccessat2, sys_faccessat2)
- #define __NR_process_madvise 440
- __SYSCALL(__NR_process_madvise, sys_process_madvise)
-
-+#define __NR_waitfd 473
-+__SYSCALL(__NR_waitfd, sys_waitfd)
-+
- #undef __NR_syscalls
--#define __NR_syscalls 441
-+#define __NR_syscalls 474
-
- /*
- * 32 bit systems traditionally used different
-diff --git a/init/Kconfig b/init/Kconfig
-index 05d377ccc0e08c27391242886bbd8904a17b4ef4..5a86bbbf43e052f9092da824536c8e223c4a4329 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1562,6 +1562,22 @@ config EPOLL
- Disabling this option will cause the kernel to be built without
- support for epoll family of system calls.
-
-+config WAITFD
-+ bool "Enable waitfd() system call" if EXPERT
-+ select ANON_INODES
-+ default n
-+ help
-+ Enable the waitfd() system call that allows receiving child state
-+ changes from a file descriptor. This permits use of poll() to
-+ monitor waitpid() output simultaneously with other fd state changes,
-+ even if the waitpid() output is coming from thread-targetted sources
-+ such as ptrace().
-+
-+ Note: this system call is not upstream: its syscall number is not
-+ finalized, so the call itself should only be used with caution.
-+
-+ If unsure, say N.
-+
- config SIGNALFD
- bool "Enable signalfd() system call" if EXPERT
- default y
-diff --git a/kernel/exit.c b/kernel/exit.c
-index d13d67fc5f4e2085f93c46b77440ca1eeb908833..5c5859a9ba75afff23fcdffcb01eef159724c6df 100644
---- a/kernel/exit.c
-+++ b/kernel/exit.c
-@@ -1586,7 +1586,10 @@ long kernel_wait4(pid_t upid, int __user *stat_addr, int options,
- enum pid_type type;
- long ret;
-
-- if (options & ~(WNOHANG|WUNTRACED|WCONTINUED|
-+ /*
-+ * As for wait4(), except that waitfd() additionally needs WNOWAIT.
-+ */
-+ if (options & ~(WNOHANG|WNOWAIT|WUNTRACED|WCONTINUED|
- __WNOTHREAD|__WCLONE|__WALL))
- return -EINVAL;
-
-@@ -1641,7 +1644,13 @@ SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
- int, options, struct rusage __user *, ru)
- {
- struct rusage r;
-- long err = kernel_wait4(upid, stat_addr, options, ru ? &r : NULL);
-+ long err;
-+
-+ if (options & ~(WNOHANG|WUNTRACED|WCONTINUED|
-+ __WNOTHREAD|__WCLONE|__WALL))
-+ return -EINVAL;
-+
-+ err = kernel_wait4(upid, stat_addr, options, ru ? &r : NULL);
-
- if (err > 0) {
- if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
-diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
-index f27ac94d5fa7270ba9f272be1bcba6a903149206..53900d50a8af730dbc419cf35e9bafe2f29024e5 100644
---- a/kernel/sys_ni.c
-+++ b/kernel/sys_ni.c
-@@ -391,6 +391,7 @@ COND_SYSCALL(subpage_prot);
- * include/uapi/asm-generic/unistd.h and wanted by >= 1 arch
- */
-
-+COND_SYSCALL(waitfd);
- /* __ARCH_WANT_SYSCALL_NO_FLAGS */
- COND_SYSCALL(epoll_create);
- COND_SYSCALL(inotify_init);
-diff --git a/mm/memcontrol.c b/mm/memcontrol.c
-index 8fc23d53f55009064c3160a0f6fab047bff6acf8..a5d4a1d4f8683a8138c836021c85c16978c53e68 100644
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -4839,7 +4839,7 @@ static int memcg_event_wake(wait_queue_entry_t *wait, unsigned mode,
- }
-
- static void memcg_event_ptable_queue_proc(struct file *file,
-- wait_queue_head_t *wqh, poll_table *pt)
-+ wait_queue_head_t *wqh, poll_table *pt, unsigned long unused)
- {
- struct mem_cgroup_event *event =
- container_of(pt, struct mem_cgroup_event, pt);
-diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
-index 8f528e783a6c533f604371228b7e31c28ea87577..d4890a86c0ce717009e31562f03ff0bcb3cffc3f 100644
---- a/net/9p/trans_fd.c
-+++ b/net/9p/trans_fd.c
-@@ -545,7 +545,8 @@ static int p9_pollwake(wait_queue_entry_t *wait, unsigned int mode, int sync, vo
- */
-
- static void
--p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
-+p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p,
-+ unsigned long unused)
- {
- struct p9_conn *m = container_of(p, struct p9_conn, pt);
- struct p9_poll_wait *pwait = NULL;
-diff --git a/tools/testing/selftests/waitfd/Makefile b/tools/testing/selftests/waitfd/Makefile
-new file mode 100644
-index 0000000000000000000000000000000000000000..f85c80b54f05ed71c4ad8cadc1ba6fc766a303d6
---- /dev/null
-+++ b/tools/testing/selftests/waitfd/Makefile
-@@ -0,0 +1,28 @@
-+uname_M := $(shell uname -m 2>/dev/null || echo not)
-+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
-+ifeq ($(ARCH),i386)
-+ ARCH := X86
-+ CFLAGS := -DCONFIG_X86_32 -D__i386__
-+endif
-+ifeq ($(ARCH),x86_64)
-+ ARCH := X86
-+ CFLAGS := -DCONFIG_X86_64 -D__x86_64__
-+endif
-+
-+CFLAGS += -I../../../../arch/x86/include/generated/
-+CFLAGS += -I../../../../include/
-+CFLAGS += -I../../../../usr/include/
-+CFLAGS += -I../../../../arch/x86/include/
-+
-+all:
-+ifeq ($(ARCH),X86)
-+ gcc $(CFLAGS) waitfd.c -o waitfd
-+else
-+ echo "Not an x86 target, can't build waitfd selftest"
-+endif
-+
-+run_tests: all
-+ @./waitfd || echo "waitfd: [FAIL]"
-+
-+clean:
-+ rm -fr ./waitfd
-diff --git a/tools/testing/selftests/waitfd/waitfd.c b/tools/testing/selftests/waitfd/waitfd.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..2df60bbdbb3569384dccca820ca77593abc67988
---- /dev/null
-+++ b/tools/testing/selftests/waitfd/waitfd.c
-@@ -0,0 +1,116 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/* waitfd testcase. */
-+
-+#define _GNU_SOURCE 1
-+#include <linux/unistd.h>
-+#include <sys/syscall.h>
-+#include <sys/ptrace.h>
-+#include <sys/types.h>
-+#include <sys/wait.h>
-+#include <errno.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <string.h>
-+#include <poll.h>
-+
-+int waitfd(int which, pid_t upid, int options, int flags)
-+{
-+ return syscall(__NR_waitfd, which, upid, options, flags);
-+}
-+
-+void sleeper(void)
-+{
-+ sleep(10);
-+ exit(0);
-+}
-+
-+int main (void)
-+{
-+ pid_t die_pid, ptrace_pid;
-+ int die_fd, ptrace_fd;
-+ int status;
-+ struct pollfd pfd[2];
-+ int procs_left = 2;
-+
-+ memset(pfd, 0, sizeof(pfd));
-+
-+ /*
-+ * Fork off two children, one of which waits for a ptrace().
-+ * Both just sleep after that. Make sure we can use __WNOTHREAD,
-+ * __WALL, and WUNTRACED without getting an -EINVAL.
-+ */
-+
-+ die_pid = fork();
-+
-+ if (die_pid == 0)
-+ sleeper();
-+
-+ ptrace_pid = fork();
-+ if (ptrace_pid == 0) {
-+ ptrace(PTRACE_TRACEME, 0, 0, 0);
-+ sleeper();
-+ }
-+
-+ die_fd = waitfd(P_PID, die_pid, 0, 0);
-+ ptrace_fd = waitfd(P_PID, ptrace_pid, __WNOTHREAD | __WALL | WUNTRACED, 0);
-+
-+ if (die_fd < 0 || ptrace_fd < 0) {
-+ perror("Cannot waitfd()");
-+ exit(1);
-+ }
-+
-+ pfd[0].fd = die_fd;
-+ pfd[0].events = POLLIN;
-+ pfd[1].fd = ptrace_fd;
-+ pfd[1].events = POLLIN;
-+
-+ /*
-+ * Hit the ptrace PID with a signal
-+ */
-+ kill(ptrace_pid, SIGABRT);
-+
-+ while (procs_left > 0) {
-+ ssize_t bytes;
-+
-+ if (poll(pfd, 2, -1) < 0)
-+ perror ("poll() failed");
-+
-+ if (pfd[0].revents != 0) {
-+ bytes = read(die_fd, &status, sizeof(int));
-+ if (bytes < sizeof(int)) {
-+ fprintf(stderr, "Only read %zi bytes\n", bytes);
-+ exit(1);
-+ }
-+
-+ printf("die_fd returned %i via waitfd read: revents are %x\n",
-+ status, pfd[0].revents);
-+ pfd[0].fd *= -1;
-+ procs_left--;
-+ }
-+
-+ if (pfd[1].revents != 0) {
-+ pid_t check_pid;
-+ status = 0;
-+ check_pid = waitpid(ptrace_pid, &status, __WNOTHREAD |
-+ __WALL | WUNTRACED | WNOHANG);
-+ if (check_pid < 0) {
-+ fprintf(stderr, "waitpid() failed: %s\n",
-+ strerror(errno));
-+ exit(1);
-+ }
-+ if (check_pid != ptrace_pid) {
-+ fprintf(stderr, "waitfd() said PID %i was ready, but waitpid() says it isn't: %i\n",
-+ ptrace_pid, check_pid);
-+ exit(1);
-+ }
-+ printf("ptrace_fd returned status %i via waitpid; revents are %x\n",
-+ status, pfd[1].revents);
-+ pfd[1].fd *= -1;
-+ procs_left--;
-+ }
-+ }
-+
-+ return 0;
-+}
-diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
-index c2323c27a28b52dd14c6405dcbc8d54b1356efe0..8da91bb7015c1a354e6e0e3b973a8a828a19d7a5 100644
---- a/virt/kvm/eventfd.c
-+++ b/virt/kvm/eventfd.c
-@@ -232,7 +232,7 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
-
- static void
- irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh,
-- poll_table *pt)
-+ poll_table *pt, unsigned long unused)
- {
- struct kvm_kernel_irqfd *irqfd =
- container_of(pt, struct kvm_kernel_irqfd, pt);
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0004-dtrace-core-and-x86.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0004-dtrace-core-and-x86.patch
deleted file mode 100644
index 7731639119d8..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0004-dtrace-core-and-x86.patch
+++ /dev/null
@@ -1,8053 +0,0 @@
-From 6b71ecc990f6b40c944f31ec14a75032e4e09235 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 22:21:36 +0000
-Subject: [PATCH 04/19] dtrace: core and x86
-
-This implements DTrace's core kernel (linked-in) components,
-including platform-dependent portions for x86. (Most of this
-machinery is not used until the next commit.)
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- Makefile | 7 +-
- arch/x86/Kconfig | 3 +
- arch/x86/include/asm/dtrace_arch.h | 28 +
- arch/x86/include/asm/dtrace_cpuinfo.h | 14 +
- arch/x86/include/asm/dtrace_util.h | 16 +
- arch/x86/kernel/dtrace_util.c | 244 ++++
- arch/x86/mm/fault.c | 28 +-
- fs/exec.c | 5 +
- include/asm-generic/qrwlock.h | 24 +
- include/dtrace/dtrace_impl.h | 1236 +++++++++++++++++
- include/dtrace/dtrace_impl_defines.h | 173 +++
- include/dtrace/provider.h | 971 +++++++++++++
- include/dtrace/provider_defines.h | 41 +
- include/dtrace/types.h | 131 ++
- include/linux/cpuhotplug.h | 1 +
- include/linux/cyclic.h | 49 +
- include/linux/dtrace/cpu_defines.h | 61 +
- include/linux/dtrace_cpu.h | 53 +
- include/linux/dtrace_cpu_defines.h | 2 +
- include/linux/dtrace_os.h | 120 ++
- include/linux/dtrace_psinfo.h | 59 +
- include/linux/dtrace_task.h | 38 +
- include/linux/dtrace_task_impl.h | 28 +
- include/linux/dtrace_types.h | 13 +
- include/linux/ktime.h | 8 +
- include/linux/module.h | 3 +
- include/linux/mutex.h | 16 +
- include/linux/rwlock.h | 7 +
- include/linux/sched.h | 4 +
- include/linux/spinlock_up.h | 5 +
- include/uapi/linux/dtrace/Kbuild | 35 +
- include/uapi/linux/dtrace/actions.h | 14 +
- include/uapi/linux/dtrace/actions_defines.h | 181 +++
- include/uapi/linux/dtrace/arg.h | 42 +
- include/uapi/linux/dtrace/arg_defines.h | 21 +
- include/uapi/linux/dtrace/buffer.h | 43 +
- include/uapi/linux/dtrace/buffer_defines.h | 21 +
- include/uapi/linux/dtrace/conf.h | 35 +
- include/uapi/linux/dtrace/conf_defines.h | 21 +
- include/uapi/linux/dtrace/cpu_defines.h | 17 +
- include/uapi/linux/dtrace/dif.h | 60 +
- include/uapi/linux/dtrace/dif_defines.h | 288 ++++
- include/uapi/linux/dtrace/difo.h | 57 +
- include/uapi/linux/dtrace/difo_defines.h | 21 +
- include/uapi/linux/dtrace/dof.h | 196 +++
- include/uapi/linux/dtrace/dof_defines.h | 192 +++
- include/uapi/linux/dtrace/dtrace.h | 33 +
- include/uapi/linux/dtrace/enabling.h | 76 +
- include/uapi/linux/dtrace/enabling_defines.h | 25 +
- include/uapi/linux/dtrace/fasttrap.h | 56 +
- include/uapi/linux/dtrace/fasttrap_defines.h | 25 +
- include/uapi/linux/dtrace/fasttrap_ioctl.h | 19 +
- include/uapi/linux/dtrace/faults.h | 20 +
- include/uapi/linux/dtrace/faults_defines.h | 39 +
- include/uapi/linux/dtrace/helpers.h | 101 ++
- include/uapi/linux/dtrace/helpers_defines.h | 21 +
- include/uapi/linux/dtrace/ioctl.h | 47 +
- include/uapi/linux/dtrace/metadesc.h | 81 ++
- include/uapi/linux/dtrace/metadesc_defines.h | 24 +
- include/uapi/linux/dtrace/options.h | 20 +
- include/uapi/linux/dtrace/options_defines.h | 72 +
- include/uapi/linux/dtrace/stability.h | 52 +
- include/uapi/linux/dtrace/stability_defines.h | 53 +
- include/uapi/linux/dtrace/status.h | 50 +
- include/uapi/linux/dtrace/universal.h | 47 +
- init/Kconfig | 2 +
- init/main.c | 10 +
- kernel/Makefile | 1 +
- kernel/dtrace/Kconfig | 54 +
- kernel/dtrace/Makefile | 12 +
- kernel/dtrace/cyclic.c | 526 +++++++
- kernel/dtrace/dtrace_cpu.c | 61 +
- kernel/dtrace/dtrace_os.c | 332 +++++
- kernel/dtrace/dtrace_psinfo.c | 212 +++
- kernel/dtrace/dtrace_task.c | 237 ++++
- kernel/exit.c | 4 +
- kernel/fork.c | 23 +
- kernel/module.c | 14 +
- kernel/sched/core.c | 10 +
- kernel/sched/sched.h | 4 +
- kernel/time/timekeeping.c | 2 +
- scripts/coccinelle/dtrace/enum-elision.cocci | 29 +
- .../coccinelle/dtrace/typedef-elision.cocci | 83 ++
- scripts/package/mkspec | 1 +
- 84 files changed, 7106 insertions(+), 4 deletions(-)
- create mode 100644 arch/x86/include/asm/dtrace_arch.h
- create mode 100644 arch/x86/include/asm/dtrace_cpuinfo.h
- create mode 100644 arch/x86/include/asm/dtrace_util.h
- create mode 100644 arch/x86/kernel/dtrace_util.c
- create mode 100644 include/dtrace/dtrace_impl.h
- create mode 100644 include/dtrace/dtrace_impl_defines.h
- create mode 100644 include/dtrace/provider.h
- create mode 100644 include/dtrace/provider_defines.h
- create mode 100644 include/dtrace/types.h
- create mode 100644 include/linux/cyclic.h
- create mode 100644 include/linux/dtrace/cpu_defines.h
- create mode 100644 include/linux/dtrace_cpu.h
- create mode 100644 include/linux/dtrace_cpu_defines.h
- create mode 100644 include/linux/dtrace_os.h
- create mode 100644 include/linux/dtrace_psinfo.h
- create mode 100644 include/linux/dtrace_task.h
- create mode 100644 include/linux/dtrace_task_impl.h
- create mode 100644 include/linux/dtrace_types.h
- create mode 100644 include/uapi/linux/dtrace/Kbuild
- create mode 100644 include/uapi/linux/dtrace/actions.h
- create mode 100644 include/uapi/linux/dtrace/actions_defines.h
- create mode 100644 include/uapi/linux/dtrace/arg.h
- create mode 100644 include/uapi/linux/dtrace/arg_defines.h
- create mode 100644 include/uapi/linux/dtrace/buffer.h
- create mode 100644 include/uapi/linux/dtrace/buffer_defines.h
- create mode 100644 include/uapi/linux/dtrace/conf.h
- create mode 100644 include/uapi/linux/dtrace/conf_defines.h
- create mode 100644 include/uapi/linux/dtrace/cpu_defines.h
- create mode 100644 include/uapi/linux/dtrace/dif.h
- create mode 100644 include/uapi/linux/dtrace/dif_defines.h
- create mode 100644 include/uapi/linux/dtrace/difo.h
- create mode 100644 include/uapi/linux/dtrace/difo_defines.h
- create mode 100644 include/uapi/linux/dtrace/dof.h
- create mode 100644 include/uapi/linux/dtrace/dof_defines.h
- create mode 100644 include/uapi/linux/dtrace/dtrace.h
- create mode 100644 include/uapi/linux/dtrace/enabling.h
- create mode 100644 include/uapi/linux/dtrace/enabling_defines.h
- create mode 100644 include/uapi/linux/dtrace/fasttrap.h
- create mode 100644 include/uapi/linux/dtrace/fasttrap_defines.h
- create mode 100644 include/uapi/linux/dtrace/fasttrap_ioctl.h
- create mode 100644 include/uapi/linux/dtrace/faults.h
- create mode 100644 include/uapi/linux/dtrace/faults_defines.h
- create mode 100644 include/uapi/linux/dtrace/helpers.h
- create mode 100644 include/uapi/linux/dtrace/helpers_defines.h
- create mode 100644 include/uapi/linux/dtrace/ioctl.h
- create mode 100644 include/uapi/linux/dtrace/metadesc.h
- create mode 100644 include/uapi/linux/dtrace/metadesc_defines.h
- create mode 100644 include/uapi/linux/dtrace/options.h
- create mode 100644 include/uapi/linux/dtrace/options_defines.h
- create mode 100644 include/uapi/linux/dtrace/stability.h
- create mode 100644 include/uapi/linux/dtrace/stability_defines.h
- create mode 100644 include/uapi/linux/dtrace/status.h
- create mode 100644 include/uapi/linux/dtrace/universal.h
- create mode 100644 kernel/dtrace/Kconfig
- create mode 100644 kernel/dtrace/Makefile
- create mode 100644 kernel/dtrace/cyclic.c
- create mode 100644 kernel/dtrace/dtrace_cpu.c
- create mode 100644 kernel/dtrace/dtrace_os.c
- create mode 100644 kernel/dtrace/dtrace_psinfo.c
- create mode 100644 kernel/dtrace/dtrace_task.c
- create mode 100644 scripts/coccinelle/dtrace/enum-elision.cocci
- create mode 100644 scripts/coccinelle/dtrace/typedef-elision.cocci
-
-diff --git a/Makefile b/Makefile
-index c21d2a09c9ca1419369295c2d29535e37135e6a4..fb9393fa10f082c29ab717aefcc812e34f8caf9d 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1106,15 +1106,15 @@ core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
-
- vmlinux-dirs := $(patsubst %/,%,$(filter %/, \
- $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
-- $(libs-y) $(libs-m)))
-+ $(libs-y) $(libs-m) $(dtrace-y) $(dtrace-m)))
-
- vmlinux-alldirs := $(sort $(vmlinux-dirs) Documentation \
- $(patsubst %/,%,$(filter %/, $(core-) \
-- $(drivers-) $(libs-))))
-+ $(drivers-) $(libs-) $(dtrace-))))
-
- subdir-modorder := $(addsuffix modules.order,$(filter %/, \
- $(core-y) $(core-m) $(libs-y) $(libs-m) \
-- $(drivers-y) $(drivers-m)))
-+ $(drivers-y) $(drivers-m) $(dtrace-y) $(dtrace-m)))
-
- build-dirs := $(vmlinux-dirs)
- clean-dirs := $(vmlinux-alldirs)
-@@ -1129,6 +1129,7 @@ else
- KBUILD_VMLINUX_LIBS := $(patsubst %/,%/lib.a, $(libs-y))
- endif
- KBUILD_VMLINUX_OBJS += $(patsubst %/,%/built-in.a, $(drivers-y))
-+KBUILD_VMLINUX_OBJS += $(patsubst %/,%/built-in.a, $(dtrace-y))
-
- export KBUILD_VMLINUX_OBJS KBUILD_VMLINUX_LIBS
- export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 3a5ecb1039bfb8e9033f56d404ba9db20a2beddd..372e81191f8e42e6deba09586db9d81cd03b80fe 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -371,6 +371,9 @@ config PGTABLE_LEVELS
- default 3 if X86_PAE
- default 2
-
-+config ARCH_SUPPORTS_DTRACE
-+ def_bool y if X86_64
-+
- config CC_HAS_SANE_STACKPROTECTOR
- bool
- default $(success,$(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC)) if 64BIT
-diff --git a/arch/x86/include/asm/dtrace_arch.h b/arch/x86/include/asm/dtrace_arch.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..74e27f08a873c9cd3ed329d911e8e18505ae5b62
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_arch.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/*
-+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _X86_DTRACE_ARCH_H
-+#define _X86_DTRACE_ARCH_H
-+
-+/* Number of arguments stored inside the mstate. */
-+#define DTRACE_MSTATE_ARGS_MAX 6
-+
-+typedef uint8_t asm_instr_t;
-+
-+typedef int (*prov_exit_f)(void);
-+
-+/*
-+ * Structure to hold DTrace specific information about modules (including the
-+ * core kernel module). Note that each module (and the main kernel) already
-+ * has one field that relates to probing:
-+ * - pdata: pointer to a dtrace_module struct (for DTrace)
-+ */
-+struct dtrace_module {
-+ int enabled_cnt;
-+ prov_exit_f prov_exit; /* Called with module_mutex held */
-+};
-+
-+#endif /* _X86_DTRACE_ARCH_H */
-diff --git a/arch/x86/include/asm/dtrace_cpuinfo.h b/arch/x86/include/asm/dtrace_cpuinfo.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..47024e169ec4f93eeea38a6c03922e3385d9e282
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_cpuinfo.h
-@@ -0,0 +1,14 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/* Copyright (C) 2013-2014 Oracle, Inc. */
-+
-+#ifndef _ASM_X86_DTRACE_CPUINFO_H_
-+#define _ASM_X86_DTRACE_CPUINFO_H_
-+
-+#include <asm/processor.h>
-+
-+typedef struct cpuinfo_x86 cpuinfo_arch_t;
-+
-+#define dtrace_cpuinfo_chip(ci) ((ci)->phys_proc_id)
-+
-+#endif /* _ASM_X86_DTRACE_CPUINFO_H_ */
-diff --git a/arch/x86/include/asm/dtrace_util.h b/arch/x86/include/asm/dtrace_util.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..4d9843bbc95b92dcc3c20d4aa1d2b762b7376d91
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_util.h
-@@ -0,0 +1,16 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _X86_DTRACE_UTIL_H
-+#define _X86_DTRACE_UTIL_H
-+
-+#ifndef __ASSEMBLY__
-+
-+#include <asm/dtrace_arch.h>
-+#include <asm/ptrace.h>
-+
-+#endif
-+
-+#endif /* _X86_DTRACE_UTIL_H */
-diff --git a/arch/x86/kernel/dtrace_util.c b/arch/x86/kernel/dtrace_util.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..d3d552c062f7ea425567cdb867b31f65d0242cac
---- /dev/null
-+++ b/arch/x86/kernel/dtrace_util.c
-@@ -0,0 +1,244 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_util.c
-+ * DESCRIPTION: Dynamic Tracing: Architecture utility functions
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/kdebug.h>
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/memory.h>
-+#include <linux/notifier.h>
-+#include <linux/ptrace.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+#include <linux/sched/task_stack.h>
-+#include <asm/insn.h>
-+#include <asm/pgtable.h>
-+#include <asm/ptrace.h>
-+#include <asm/text-patching.h>
-+#include <asm/dtrace_arch.h>
-+#include <asm/dtrace_util.h>
-+
-+int dtrace_instr_size(const asm_instr_t *addr)
-+{
-+ struct insn insn;
-+
-+ kernel_insn_init(&insn, addr, MAX_INSN_SIZE);
-+ insn_get_length(&insn);
-+
-+ return insn_complete(&insn) ? insn.length : -1;
-+}
-+EXPORT_SYMBOL(dtrace_instr_size);
-+
-+/*
-+ * Move the instruction pointer forward to the next instruction, effectiely
-+ * skipping the current one.
-+ */
-+static void dtrace_skip_instruction(struct pt_regs *regs)
-+{
-+ int delta;
-+
-+ delta = dtrace_instr_size((asm_instr_t *)regs->ip);
-+ BUG_ON(delta <= 0);
-+
-+ regs->ip += delta;
-+}
-+
-+void dtrace_handle_badaddr(struct pt_regs *regs)
-+{
-+ unsigned long addr = read_cr2();
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = addr;
-+
-+ dtrace_skip_instruction(regs);
-+}
-+
-+/*
-+ * Trap notification handler.
-+ */
-+int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
-+ void *args)
-+{
-+ struct die_args *dargs = args;
-+
-+ switch (val) {
-+ case DIE_PAGE_FAULT: {
-+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
-+ return NOTIFY_DONE;
-+
-+ dtrace_handle_badaddr(dargs->regs);
-+
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ }
-+ case DIE_GPF: {
-+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
-+ return NOTIFY_DONE;
-+
-+ dtrace_handle_badaddr(dargs->regs);
-+
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ }
-+ /* fallthrough */
-+ default:
-+ return NOTIFY_DONE;
-+ }
-+}
-+
-+static inline int dtrace_bad_address(void *addr)
-+{
-+ unsigned long dummy;
-+
-+ return get_kernel_nofault(dummy, (unsigned long *)addr);
-+}
-+
-+static int dtrace_user_addr_is_exec(uintptr_t addr)
-+{
-+ struct mm_struct *mm = current->mm;
-+ pgd_t *pgd;
-+
-+#if CONFIG_PGTABLE_LEVELS > 3
-+ p4d_t *p4d;
-+#endif
-+
-+ pud_t *pud;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+ unsigned long flags;
-+ int ret = 0;
-+
-+ if (mm == NULL)
-+ return 0;
-+
-+ addr &= PAGE_MASK;
-+
-+ local_irq_save(flags);
-+
-+ pgd = pgd_offset(mm, addr);
-+ if (dtrace_bad_address(pgd))
-+ goto out;
-+ if (pgd_none(*pgd) || !pgd_present(*pgd))
-+ goto out;
-+
-+#if CONFIG_PGTABLE_LEVELS > 3
-+ p4d = p4d_offset(pgd, addr);
-+ if (dtrace_bad_address(p4d))
-+ goto out;
-+ if (p4d_none(*p4d) || !p4d_present(*p4d))
-+ goto out;
-+
-+ pud = pud_offset(p4d, addr);
-+#else
-+ pud = pud_offset(pgd, addr);
-+#endif
-+
-+ if (dtrace_bad_address(pud))
-+ goto out;
-+ if (pud_none(*pud) || !pud_present(*pud))
-+ goto out;
-+ if (unlikely(pud_large(*pud))) {
-+ pte = (pte_t *)pud;
-+ if (dtrace_bad_address(pte))
-+ goto out;
-+
-+ ret = pte_exec(*pte);
-+ goto out;
-+ }
-+
-+ pmd = pmd_offset(pud, addr);
-+ if (dtrace_bad_address(pmd))
-+ goto out;
-+ if (pmd_none(*pmd))
-+ goto out;
-+ if (unlikely(pmd_large(*pmd) || !pmd_present(*pmd))) {
-+ pte = (pte_t *)pmd;
-+ if (dtrace_bad_address(pte))
-+ goto out;
-+
-+ ret = pte_exec(*pte);
-+ goto out;
-+ }
-+
-+ pte = pte_offset_map(pmd, addr);
-+ if (dtrace_bad_address(pte))
-+ goto out;
-+ if (pte_protnone(*pte))
-+ goto out;
-+ if ((pte_flags(*pte) & (_PAGE_PRESENT|_PAGE_USER|_PAGE_SPECIAL)) !=
-+ (_PAGE_PRESENT|_PAGE_USER))
-+ goto out;
-+
-+ ret = pte_exec(*pte);
-+
-+out:
-+ local_irq_restore(flags);
-+
-+ return ret;
-+}
-+
-+void dtrace_user_stacktrace(struct stacktrace_state *st)
-+{
-+ struct pt_regs *regs = current_pt_regs();
-+ uint64_t *pcs = st->pcs;
-+ int limit = st->limit;
-+ unsigned long *bos;
-+ unsigned long *sp = (unsigned long *)user_stack_pointer(regs);
-+ int ret;
-+
-+ if (!user_mode(regs))
-+ goto out;
-+
-+ if (current->dt_task == NULL)
-+ goto out;
-+
-+ bos = current->dt_task->dt_ustack;
-+
-+ st->depth = 1;
-+ if (pcs)
-+ *pcs++ = (uint64_t)instruction_pointer(regs);
-+ limit--;
-+
-+ if (!limit)
-+ goto out;
-+
-+ while (sp <= bos && limit) {
-+ unsigned long pc;
-+
-+ pagefault_disable();
-+ ret = __copy_from_user_inatomic(&pc, sp, sizeof(pc));
-+ pagefault_enable();
-+
-+ if (ret)
-+ break;
-+
-+ if (dtrace_user_addr_is_exec(pc)) {
-+ if (pcs)
-+ *pcs++ = pc;
-+ limit--;
-+ st->depth++;
-+ }
-+
-+ sp++;
-+ }
-+
-+out:
-+ if (pcs) {
-+ while (limit--)
-+ *pcs++ = 0;
-+ }
-+}
-+
-+void dtrace_mod_pdata_init(struct dtrace_module *pdata)
-+{
-+}
-+
-+void dtrace_mod_pdata_cleanup(struct dtrace_module *pdata)
-+{
-+}
-diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
-index 82bf37a5c9eccadcc3a9b0ba875d6bdb2d5df1eb..5b16183100d07fb85d26163b11694097b774a751 100644
---- a/arch/x86/mm/fault.c
-+++ b/arch/x86/mm/fault.c
-@@ -18,6 +18,7 @@
- #include <linux/uaccess.h> /* faulthandler_disabled() */
- #include <linux/efi.h> /* efi_recover_from_page_fault()*/
- #include <linux/mm_types.h>
-+#include <linux/dtrace_os.h> /* dtrace_no_pf */
-
- #include <asm/cpufeature.h> /* boot_cpu_has, ... */
- #include <asm/traps.h> /* dotraplinkage, ... */
-@@ -680,6 +681,16 @@ no_context(struct pt_regs *regs, unsigned long error_code,
- (((unsigned long)tsk->stack - 1 - address < PAGE_SIZE) ||
- address - ((unsigned long)tsk->stack + THREAD_SIZE) < PAGE_SIZE)) {
- unsigned long stack = __this_cpu_ist_top_va(DF) - sizeof(void *);
-+
-+ /*
-+ * Allow for the possibility that we know what we are doing and
-+ * ignore this fault. E.g. the address may come from a source
-+ * we cannot trust and it is OK if we cannot access it.
-+ */
-+ if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code,
-+ 14, SIGKILL) == NOTIFY_STOP)
-+ return;
-+
- /*
- * We're likely to be running with very little stack space
- * left. It's plausible that we'd hit this condition but
-@@ -728,8 +739,13 @@ no_context(struct pt_regs *regs, unsigned long error_code,
- oops:
- /*
- * Oops. The kernel tried to access some bad page. We'll have to
-- * terminate things with extreme prejudice:
-+ * terminate things with extreme prejudice, unless a notifier decides
-+ * to let this one slide.
- */
-+ if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-+ SIGKILL) == NOTIFY_STOP)
-+ return;
-+
- flags = oops_begin();
-
- show_fault_oops(regs, error_code, address);
-@@ -1223,10 +1239,20 @@ void do_user_addr_fault(struct pt_regs *regs,
- tsk = current;
- mm = tsk->mm;
-
-+ /*
-+ * From here on, we know this must be a fault in userspace.
-+ */
-+
- /* kprobes don't want to hook the spurious faults: */
- if (unlikely(kprobe_page_fault(regs, X86_TRAP_PF)))
- return;
-
-+ /*
-+ * DTrace doesn't want to either.
-+ */
-+ if (unlikely(dtrace_no_pf(regs)))
-+ return;
-+
- /*
- * Reserved bits are never expected to be set on
- * entries in the user portion of the page tables.
-diff --git a/fs/exec.c b/fs/exec.c
-index ca89e0e3ef10f19ee0ba7243c52fa7ff130900cf..4340b28030047552a40dfa962e08d994d3f33278 100644
---- a/fs/exec.c
-+++ b/fs/exec.c
-@@ -64,6 +64,7 @@
- #include <linux/compat.h>
- #include <linux/vmalloc.h>
- #include <linux/io_uring.h>
- #include <linux/random.h>
-+#include <linux/dtrace_os.h>
-
- #include <linux/uaccess.h>
- #include <asm/mmu_context.h>
-@@ -1822,6 +1823,10 @@ static int bprm_execve(struct linux_binprm *bprm,
- goto out;
-
- /* execve succeeded */
-+
-+ /* Update DTrace per-task data. */
-+ dtrace_task_exec(current);
-+
- current->fs->in_exec = 0;
- current->in_execve = 0;
- rseq_execve(current);
-diff --git a/include/asm-generic/qrwlock.h b/include/asm-generic/qrwlock.h
-index 3aefde23dceab8b87d54f8c7e4493dc1a2b54eeb..addbb3c7d953ead4e88a98c609cebc4c6a245bc2 100644
---- a/include/asm-generic/qrwlock.h
-+++ b/include/asm-generic/qrwlock.h
-@@ -30,6 +30,26 @@
- extern void queued_read_lock_slowpath(struct qrwlock *lock);
- extern void queued_write_lock_slowpath(struct qrwlock *lock);
-
-+#ifdef CONFIG_DTRACE
-+/**
-+ * queued_peek_read_can_lock -- would read_trylock() be likely to succeed?
-+ * @lock: Pointer to queue rwlock structure
-+ */
-+static inline int queued_peek_read_can_lock(struct qrwlock *lock)
-+{
-+ return !(atomic_read(&lock->cnts) & _QW_WMASK);
-+}
-+
-+/**
-+ * queued_peek_write_can_lock -- would write_trylock() be likely to succeed?
-+ * @lock: Pointer to queue rwlock structure
-+ */
-+static inline int queued_peek_write_can_lock(struct qrwlock *lock)
-+{
-+ return !atomic_read(&lock->cnts);
-+}
-+#endif /* CONFIG_DTRACE */
-+
- /**
- * queued_read_trylock - try to acquire read lock of a queue rwlock
- * @lock : Pointer to queue rwlock structure
-@@ -120,6 +140,10 @@ static inline void queued_write_unlock(struct qrwlock *lock)
- * Remapping rwlock architecture specific functions to the corresponding
- * queue rwlock functions.
- */
-+#ifdef CONFIG_DTRACE
-+#define arch_peek_read_can_lock(l) queued_peek_read_can_lock(l)
-+#define arch_peek_write_can_lock(l) queued_peek_write_can_lock(l)
-+#endif /* CONFIG_DTRACE */
- #define arch_read_lock(l) queued_read_lock(l)
- #define arch_write_lock(l) queued_write_lock(l)
- #define arch_read_trylock(l) queued_read_trylock(l)
-diff --git a/include/dtrace/dtrace_impl.h b/include/dtrace/dtrace_impl.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..2420103c765cefec965a7dac2b03e50ac8b37f02
---- /dev/null
-+++ b/include/dtrace/dtrace_impl.h
-@@ -0,0 +1,1236 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Implementation
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_IMPL_H
-+#define _LINUX_DTRACE_IMPL_H
-+
-+#include <linux/cyclic.h>
-+#include <linux/idr.h>
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/dif.h>
-+#include <linux/dtrace/difo_defines.h>
-+#include <linux/dtrace/metadesc.h>
-+#include <linux/dtrace/stability.h>
-+#include <linux/dtrace/helpers.h>
-+#include <dtrace/types.h>
-+#include <dtrace/provider.h>
-+#include <dtrace/dtrace_impl_defines.h>
-+
-+struct dtrace_provider {
-+ struct dtrace_pattr dtpv_attr;
-+ struct dtrace_ppriv dtpv_priv;
-+ struct dtrace_pops dtpv_pops;
-+ char *dtpv_name;
-+ void *dtpv_arg;
-+ uint_t dtpv_defunct;
-+ struct dtrace_provider *dtpv_next;
-+};
-+
-+struct dtrace_predicate {
-+ struct dtrace_difo *dtp_difo;
-+ dtrace_cacheid_t dtp_cacheid;
-+ int dtp_refcnt;
-+};
-+
-+struct dtrace_statvar {
-+ uint64_t dtsv_data;
-+ size_t dtsv_size;
-+ int dtsv_refcnt;
-+ struct dtrace_difv dtsv_var;
-+};
-+
-+struct dtrace_action {
-+ dtrace_actkind_t dta_kind;
-+ uint16_t dta_intuple;
-+ uint32_t dta_refcnt;
-+ struct dtrace_difo *dta_difo;
-+ struct dtrace_recdesc dta_rec;
-+ struct dtrace_action *dta_prev;
-+ struct dtrace_action *dta_next;
-+};
-+
-+struct dtrace_ecb;
-+
-+struct dtrace_probe {
-+ dtrace_id_t dtpr_id;
-+ struct dtrace_ecb *dtpr_ecb;
-+ struct dtrace_ecb *dtpr_ecb_last;
-+ void *dtpr_arg;
-+ dtrace_cacheid_t dtpr_predcache;
-+ int dtpr_aframes;
-+ struct dtrace_provider *dtpr_provider;
-+ char *dtpr_mod;
-+ char *dtpr_func;
-+ char *dtpr_name;
-+ struct dtrace_probe *dtpr_nextmod;
-+ struct dtrace_probe *dtpr_prevmod;
-+ struct dtrace_probe *dtpr_nextfunc;
-+ struct dtrace_probe *dtpr_prevfunc;
-+ struct dtrace_probe *dtpr_nextname;
-+ struct dtrace_probe *dtpr_prevname;
-+ dtrace_genid_t dtpr_gen;
-+};
-+
-+struct dtrace_state;
-+
-+struct dtrace_ecb {
-+ dtrace_epid_t dte_epid;
-+ uint32_t dte_alignment;
-+ size_t dte_needed;
-+ size_t dte_size;
-+ struct dtrace_predicate *dte_predicate;
-+ struct dtrace_action *dte_action;
-+ struct dtrace_ecb *dte_next;
-+ struct dtrace_state *dte_state;
-+ uint32_t dte_cond;
-+ struct dtrace_probe *dte_probe;
-+ struct dtrace_action *dte_action_last;
-+ uint64_t dte_uarg;
-+};
-+
-+struct dtrace_key {
-+ uint64_t dttk_value;
-+ uint64_t dttk_size;
-+};
-+
-+struct dtrace_tuple {
-+ uint32_t dtt_nkeys;
-+ uint32_t dtt_pad;
-+ struct dtrace_key dtt_key[1];
-+};
-+
-+struct dtrace_dynvar {
-+ uint64_t dtdv_hashval;
-+ struct dtrace_dynvar *dtdv_next;
-+ void *dtdv_data;
-+ struct dtrace_tuple dtdv_tuple;
-+};
-+
-+struct dtrace_dstate_percpu {
-+ struct dtrace_dynvar *dtdsc_free;
-+ struct dtrace_dynvar *dtdsc_dirty;
-+ struct dtrace_dynvar *dtdsc_rinsing;
-+ struct dtrace_dynvar *dtdsc_clean;
-+ uint64_t dtdsc_drops;
-+ uint64_t dtdsc_dirty_drops;
-+ uint64_t dtdsc_rinsing_drops;
-+#ifdef CONFIG_64BIT
-+ uint64_t dtdsc_pad;
-+#else
-+ uint64_t dtdsc_pad[2];
-+#endif
-+};
-+
-+struct dtrace_dynhash {
-+ struct dtrace_dynvar *dtdh_chain;
-+ uintptr_t dtdh_lock;
-+#ifdef CONFIG_64BIT
-+ uintptr_t dtdh_pad[6];
-+#else
-+ uintptr_t dtdh_pad[14];
-+#endif
-+};
-+
-+struct dtrace_dstate {
-+ void *dtds_base;
-+ size_t dtds_size;
-+ size_t dtds_hashsize;
-+ size_t dtds_chunksize;
-+ struct dtrace_dynhash *dtds_hash;
-+ enum dtrace_dstate_state dtds_state;
-+ struct dtrace_dstate_percpu *dtds_percpu;
-+};
-+
-+struct dtrace_vstate {
-+ struct dtrace_state *dtvs_state;
-+ struct dtrace_statvar **dtvs_globals;
-+ int dtvs_nglobals;
-+ struct dtrace_difv *dtvs_tlocals;
-+ int dtvs_ntlocals;
-+ struct dtrace_statvar **dtvs_locals;
-+ int dtvs_nlocals;
-+ struct dtrace_dstate dtvs_dynvars;
-+};
-+
-+/*
-+ * DTrace Machine State
-+ *
-+ * In the process of processing a fired probe, DTrace needs to track and/or
-+ * cache some per-CPU state associated with that particular firing. This is
-+ * state that is always discarded after the probe firing has completed, and
-+ * much of it is not specific to any DTrace consumer, remaining valid across
-+ * all ECBs. This state is tracked in the dtrace_mstate structure.
-+ */
-+
-+struct dtrace_mstate {
-+ uintptr_t dtms_scratch_base;
-+ uintptr_t dtms_scratch_ptr;
-+ size_t dtms_scratch_size;
-+ uint32_t dtms_present;
-+ uint64_t dtms_arg[7];
-+ dtrace_epid_t dtms_epid;
-+ ktime_t dtms_timestamp;
-+ int dtms_stackdepth;
-+ int dtms_ustackdepth;
-+ struct dtrace_probe *dtms_probe;
-+ uintptr_t dtms_caller;
-+ uint64_t dtms_ucaller;
-+ int dtms_ipl;
-+ int dtms_fltoffs;
-+ uintptr_t dtms_strtok;
-+ uint32_t dtms_access;
-+ struct dtrace_difo *dtms_difo;
-+};
-+
-+struct dtrace_buffer {
-+ uint64_t dtb_offset;
-+ uint64_t dtb_size;
-+ uint32_t dtb_flags;
-+ uint32_t dtb_drops;
-+ caddr_t dtb_tomax;
-+ caddr_t dtb_xamot;
-+ uint32_t dtb_xamot_flags;
-+ uint32_t dtb_xamot_drops;
-+ uint64_t dtb_xamot_offset;
-+ uint32_t dtb_errors;
-+ uint32_t dtb_xamot_errors;
-+#ifndef CONFIG_64BIT
-+ uint64_t dtb_pad1;
-+#endif
-+};
-+
-+struct dtrace_speculation {
-+ enum dtrace_speculation_state dtsp_state;
-+ int dtsp_cleaning;
-+ struct dtrace_buffer *dtsp_buffer;
-+};
-+
-+struct dtrace_aggregation {
-+ struct dtrace_action dtag_action;
-+ dtrace_aggid_t dtag_id;
-+ struct dtrace_ecb *dtag_ecb;
-+ struct dtrace_action *dtag_first;
-+ uint32_t dtag_base;
-+ uint8_t dtag_hasarg;
-+ uint64_t dtag_initial;
-+ void (*dtag_aggregate)(uint64_t *, uint64_t, uint64_t);
-+};
-+
-+struct dtrace_cred {
-+ const struct cred *dcr_cred;
-+ uint8_t dcr_destructive;
-+ uint8_t dcr_visible;
-+ uint16_t dcr_action;
-+};
-+
-+struct dtrace_state {
-+ dev_t dts_dev;
-+ int dts_necbs;
-+ struct dtrace_ecb **dts_ecbs;
-+ dtrace_epid_t dts_epid;
-+ size_t dts_needed;
-+ struct dtrace_state *dts_anon;
-+ enum dtrace_activity dts_activity;
-+ struct dtrace_vstate dts_vstate;
-+ struct dtrace_buffer *dts_buffer;
-+ struct dtrace_buffer *dts_aggbuffer;
-+ struct dtrace_speculation *dts_speculations;
-+ int dts_nspeculations;
-+ struct idr dts_agg_idr;
-+ int dts_naggs;
-+ uint64_t dts_errors;
-+ uint32_t dts_speculations_busy;
-+ uint32_t dts_speculations_unavail;
-+ uint32_t dts_stkstroverflows;
-+ uint32_t dts_dblerrors;
-+ uint32_t dts_reserve;
-+ cyclic_id_t dts_cleaner;
-+ cyclic_id_t dts_deadman;
-+ ktime_t dts_laststatus;
-+ ktime_t dts_alive;
-+ char dts_speculates;
-+ char dts_destructive;
-+ int dts_nformats;
-+ char **dts_formats;
-+ dtrace_optval_t dts_options[DTRACEOPT_MAX];
-+ struct dtrace_cred dts_cred;
-+ size_t dts_nretained;
-+};
-+
-+struct dtrace_enabling {
-+ struct dtrace_ecbdesc **dten_desc;
-+ int dten_ndesc;
-+ int dten_maxdesc;
-+ struct dtrace_vstate *dten_vstate;
-+ dtrace_genid_t dten_probegen;
-+ struct dtrace_ecbdesc *dten_current;
-+ int dten_error;
-+ int dten_primed;
-+ struct dtrace_enabling *dten_prev;
-+ struct dtrace_enabling *dten_next;
-+};
-+
-+typedef int dtrace_probekey_f(const char *, const char *, int);
-+
-+struct dtrace_probekey {
-+ const char *dtpk_prov;
-+ dtrace_probekey_f *dtpk_pmatch;
-+ const char *dtpk_mod;
-+ dtrace_probekey_f *dtpk_mmatch;
-+ const char *dtpk_func;
-+ dtrace_probekey_f *dtpk_fmatch;
-+ const char *dtpk_name;
-+ dtrace_probekey_f *dtpk_nmatch;
-+ dtrace_id_t dtpk_id;
-+};
-+
-+struct dtrace_hashbucket {
-+ struct dtrace_hashbucket *dthb_next;
-+ struct dtrace_probe *dthb_chain;
-+ int dthb_len;
-+};
-+
-+struct dtrace_hash {
-+ struct dtrace_hashbucket **dth_tab;
-+ int dth_size;
-+ int dth_mask;
-+ int dth_nbuckets;
-+ uintptr_t dth_nextoffs;
-+ uintptr_t dth_prevoffs;
-+ uintptr_t dth_stroffs;
-+};
-+
-+/*
-+ * DTrace supports safe loads from probe context; if the address turns out to
-+ * be invalid, a bit will be set by the kernel indicating that DTrace
-+ * encountered a memory error, and DTrace will propagate the error to the user
-+ * accordingly. However, there may exist some regions of memory in which an
-+ * arbitrary load can change system state, and from which it is impossible to
-+ * recover from such a load after it has been attempted. Examples of this may
-+ * include memory in which programmable I/O registers are mapped (for which a
-+ * read may have some implications for the device) or (in the specific case of
-+ * UltraSPARC-I and -II) the virtual address hole. The platform is required
-+ * to make DTrace aware of these toxic ranges; DTrace will then check that
-+ * target addresses are not in a toxic range before attempting to issue a
-+ * safe load.
-+ */
-+struct dtrace_toxrange {
-+ uintptr_t dtt_base;
-+ uintptr_t dtt_limit;
-+};
-+
-+/*
-+ * DTrace Helper Implementation
-+ *
-+ * A description of the helper architecture may be found in <linux/dtrace.h>.
-+ * Each process contains a pointer to its helpers in its dtrace_helpers
-+ * member. This is a pointer to a dtrace_helpers structure, which contains an
-+ * array of pointers to dtrace_helper structures, helper variable state (shared
-+ * among a process's helpers) and a generation count. (The generation count is
-+ * used to provide an identifier when a helper is added so that it may be
-+ * subsequently removed.) The dtrace_helper structure is self-explanatory,
-+ * containing pointers to the objects needed to execute the helper. Note that
-+ * helpers are _duplicated_ across fork(2), and destroyed on exec(2). No more
-+ * than dtrace_helpers_max are allowed per-process.
-+ */
-+struct dtrace_helper_action {
-+ int dtha_generation; /* helper action generation */
-+ int dtha_nactions; /* number of actions */
-+ struct dtrace_difo *dtha_predicate; /* helper action predicate */
-+ struct dtrace_difo **dtha_actions; /* array of actions */
-+ struct dtrace_helper_action *dtha_next; /* next helper action */
-+};
-+
-+struct dtrace_helper_provider {
-+ int dthp_generation; /* helper provider generation */
-+ uint32_t dthp_ref; /* reference count */
-+ struct dof_helper dthp_prov; /* DOF w/ provider and probes */
-+};
-+
-+struct dtrace_helpers {
-+ struct dtrace_helper_action **dthps_actions; /* helper actions array */
-+ struct dtrace_vstate dthps_vstate; /* helper action var. state */
-+ struct dtrace_helper_provider **dthps_provs; /* providers array */
-+ uint_t dthps_nprovs; /* count of providers */
-+ uint_t dthps_maxprovs; /* provider array size */
-+ int dthps_generation; /* current generation */
-+ pid_t dthps_pid; /* pid of associated proc */
-+ int dthps_deferred; /* helper in deferred list */
-+ struct dtrace_helpers *dthps_next; /* next pointer */
-+ struct dtrace_helpers *dthps_prev; /* prev pointer */
-+};
-+
-+/*
-+ * DTrace Helper Action Tracing
-+ *
-+ * Debugging helper actions can be arduous. To ease the development and
-+ * debugging of helpers, DTrace contains a tracing-framework-within-a-tracing-
-+ * framework: helper tracing. If dtrace_helptrace_enabled is non-zero (which
-+ * it is by default on DEBUG kernels), all helper activity will be traced to a
-+ * global, in-kernel ring buffer. Each entry includes a pointer to the specific
-+ * helper, the location within the helper, and a trace of all local variables.
-+ * The ring buffer may be displayed in a human-readable format with the
-+ * ::dtrace_helptrace mdb(1) dcmd.
-+ */
-+struct dtrace_helptrace {
-+ struct dtrace_helper_action *dtht_helper; /* helper action */
-+ int dtht_where; /* where in helper action */
-+ int dtht_nlocals; /* number of locals */
-+ int dtht_fault; /* type of fault (if any) */
-+ int dtht_fltoffs; /* DIF offset */
-+ uint64_t dtht_illval; /* faulting value */
-+ uint64_t dtht_locals[1]; /* local variables */
-+};
-+
-+extern struct mutex dtrace_lock;
-+extern struct mutex dtrace_provider_lock;
-+extern struct mutex dtrace_meta_lock;
-+
-+extern dtrace_genid_t dtrace_probegen;
-+extern struct kmem_cache *dtrace_probe_cachep;
-+
-+extern struct dtrace_pops dtrace_provider_ops;
-+
-+extern int dtrace_opens;
-+extern int dtrace_err_verbose;
-+
-+extern struct dtrace_toxrange *dtrace_toxrange;
-+extern int dtrace_toxranges;
-+
-+extern void dtrace_nullop(void);
-+extern int dtrace_enable_nullop(void);
-+extern int dtrace_istoxic(uintptr_t, size_t);
-+
-+/*
-+ * DTrace Probe Context Functions
-+ */
-+
-+extern void dtrace_panic(const char *, ...);
-+extern int dtrace_assfail(const char *, const char *, int);
-+extern void dtrace_aggregate_min(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_max(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_quantize(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_lquantize(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_llquantize(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_avg(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_stddev(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_count(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate_sum(uint64_t *, uint64_t, uint64_t);
-+extern void dtrace_aggregate(struct dtrace_aggregation *,
-+ struct dtrace_buffer *,
-+ intptr_t, struct dtrace_buffer *, uint64_t,
-+ uint64_t);
-+
-+/*
-+ * DTrace Probe Hashing Functions
-+ */
-+
-+extern struct dtrace_hash *dtrace_hash_create(uintptr_t, uintptr_t, uintptr_t);
-+extern void dtrace_hash_destroy(struct dtrace_hash *);
-+extern int dtrace_hash_add(struct dtrace_hash *, struct dtrace_probe *);
-+extern struct dtrace_probe *dtrace_hash_lookup(struct dtrace_hash *,
-+ struct dtrace_probe *);
-+extern int dtrace_hash_collisions(struct dtrace_hash *, struct dtrace_probe *);
-+extern void dtrace_hash_remove(struct dtrace_hash *, struct dtrace_probe *);
-+
-+/*
-+ * DTrace Speculation Functions
-+ */
-+extern int dtrace_speculation(struct dtrace_state *);
-+extern void dtrace_speculation_commit(struct dtrace_state *, processorid_t,
-+ dtrace_specid_t);
-+extern void dtrace_speculation_discard(struct dtrace_state *, processorid_t,
-+ dtrace_specid_t);
-+extern void dtrace_speculation_clean(struct dtrace_state *);
-+extern struct dtrace_buffer *dtrace_speculation_buffer(struct dtrace_state *,
-+ processorid_t,
-+ dtrace_specid_t);
-+
-+/*
-+ * DTrace Non-Probe Context Utility Functions
-+ */
-+
-+/*
-+ * DTrace Matching Functions
-+ */
-+extern struct dtrace_hash *dtrace_bymod;
-+extern struct dtrace_hash *dtrace_byfunc;
-+extern struct dtrace_hash *dtrace_byname;
-+
-+extern int dtrace_match_priv(const struct dtrace_probe *, uint32_t, kuid_t);
-+extern int dtrace_match_probe(const struct dtrace_probe *,
-+ const struct dtrace_probekey *, uint32_t,
-+ kuid_t);
-+extern int dtrace_match_glob(const char *, const char *, int);
-+extern int dtrace_match_string(const char *, const char *, int);
-+extern int dtrace_match_nul(const char *, const char *, int);
-+extern int dtrace_match_nonzero(const char *, const char *, int);
-+extern int dtrace_match(const struct dtrace_probekey *, uint32_t, kuid_t,
-+ int (*matched)(struct dtrace_probe *, void *), void *);
-+extern void dtrace_probekey(const struct dtrace_probedesc *,
-+ struct dtrace_probekey *);
-+
-+/*
-+ * DTrace Provider-to-Framework API Functions
-+ */
-+
-+extern struct dtrace_provider *dtrace_provider;
-+extern struct dtrace_meta *dtrace_meta_pid;
-+extern struct dtrace_helpers *dtrace_deferred_pid;
-+
-+/*
-+ * DTrace Privilege Check Functions
-+ */
-+extern int dtrace_priv_proc_destructive(struct dtrace_state *);
-+extern int dtrace_priv_proc_control(struct dtrace_state *);
-+extern int dtrace_priv_proc(struct dtrace_state *);
-+extern int dtrace_priv_kernel(struct dtrace_state *);
-+
-+/*
-+ * DTrace Probe Management Functions
-+ */
-+
-+extern int dtrace_probe_enable(const struct dtrace_probedesc *,
-+ struct dtrace_enabling *);
-+extern void dtrace_probe_description(const struct dtrace_probe *,
-+ struct dtrace_probedesc *);
-+extern void dtrace_probe_provide(struct dtrace_probedesc *,
-+ struct dtrace_provider *);
-+extern int dtrace_probe_init(void);
-+extern void dtrace_probe_exit(void);
-+extern void dtrace_probe_remove_id(dtrace_id_t);
-+extern struct dtrace_probe *dtrace_probe_lookup_id(dtrace_id_t);
-+extern struct dtrace_probe *dtrace_probe_get_next(dtrace_id_t *);
-+extern int dtrace_probe_for_each(int (*)(int, void *, void *), void *);
-+
-+/*
-+ * DTrace Kernel Hooks
-+ */
-+extern void (*dtrace_modload)(struct module *);
-+extern void (*dtrace_modunload)(struct module *);
-+
-+extern uint8_t dtrace_load8(uintptr_t);
-+extern uint16_t dtrace_load16(uintptr_t);
-+extern uint32_t dtrace_load32(uintptr_t);
-+extern uint64_t dtrace_load64(uintptr_t);
-+#ifdef CONFIG_64BIT
-+#define dtrace_loadptr dtrace_load64
-+#else
-+#define dtrace_loadptr dtrace_load32
-+#endif
-+
-+
-+extern void dtrace_bzero(void *, size_t);
-+
-+extern int dtrace_vcanload(void *, struct dtrace_diftype *,
-+ struct dtrace_mstate *,
-+ struct dtrace_vstate *);
-+extern int dtrace_canload(uintptr_t, size_t, struct dtrace_mstate *,
-+ struct dtrace_vstate *);
-+
-+extern int dtrace_difo_validate(struct dtrace_difo *, struct dtrace_vstate *,
-+ uint_t, const struct cred *);
-+extern int dtrace_difo_validate_helper(struct dtrace_difo *);
-+extern int dtrace_difo_cacheable(struct dtrace_difo *);
-+extern void dtrace_difo_hold(struct dtrace_difo *);
-+extern void dtrace_difo_init(struct dtrace_difo *, struct dtrace_vstate *);
-+extern struct dtrace_difo *dtrace_difo_duplicate(struct dtrace_difo *,
-+ struct dtrace_vstate *);
-+extern void dtrace_difo_release(struct dtrace_difo *, struct dtrace_vstate *);
-+
-+extern uint64_t dtrace_vtime_references;
-+
-+extern uint64_t dtrace_dif_emulate(struct dtrace_difo *,
-+ struct dtrace_mstate *,
-+ struct dtrace_vstate *,
-+ struct dtrace_state *);
-+
-+/*
-+ * DTrace Format Functions
-+ */
-+extern uint16_t dtrace_format_add(struct dtrace_state *, char *);
-+extern void dtrace_format_remove(struct dtrace_state *, uint16_t);
-+extern void dtrace_format_destroy(struct dtrace_state *);
-+
-+/*
-+ * DTrace Predicate Functions
-+ */
-+extern struct dtrace_predicate *dtrace_predicate_create(struct dtrace_difo *);
-+extern void dtrace_predicate_hold(struct dtrace_predicate *);
-+extern void dtrace_predicate_release(struct dtrace_predicate *,
-+ struct dtrace_vstate *);
-+
-+/*
-+ * DTrace Action Description Functions
-+ */
-+extern struct dtrace_actdesc *dtrace_actdesc_create(dtrace_actkind_t, uint32_t,
-+ uint64_t, uint64_t);
-+extern void dtrace_actdesc_hold(struct dtrace_actdesc *);
-+extern void dtrace_actdesc_release(struct dtrace_actdesc *,
-+ struct dtrace_vstate *);
-+
-+/*
-+ * DTrace Helper Functions
-+ */
-+extern void dtrace_helpers_destroy(struct task_struct *);
-+extern void dtrace_helpers_duplicate(struct task_struct *,
-+ struct task_struct *);
-+extern uint64_t dtrace_helper(int, struct dtrace_mstate *,
-+ struct dtrace_state *,
-+ uint64_t, uint64_t);
-+
-+/*
-+ * DTrace ECB Functions
-+ */
-+extern struct dtrace_ecb *dtrace_ecb_create_cache;
-+
-+extern int dtrace_ecb_create_enable(struct dtrace_probe *, void *);
-+extern void dtrace_ecb_disable(struct dtrace_ecb *);
-+extern void dtrace_ecb_destroy(struct dtrace_ecb *);
-+extern void dtrace_ecb_resize(struct dtrace_ecb *);
-+extern int dtrace_ecb_enable(struct dtrace_ecb *);
-+extern struct dtrace_ecb *dtrace_epid2ecb(struct dtrace_state *,
-+ dtrace_epid_t);
-+extern struct dtrace_aggregation *dtrace_aggid2agg(struct dtrace_state *,
-+ dtrace_aggid_t);
-+
-+/*
-+ * DTrace Buffer Functions
-+ *
-+ * DTrace Buffers
-+ *
-+ * Principal buffers, aggregation buffers, and speculative buffers are all
-+ * managed with the dtrace_buffer structure. By default, this structure
-+ * includes twin data buffers -- dtb_tomax and dtb_xamot -- that serve as the
-+ * active and passive buffers, respectively. For speculative buffers,
-+ * dtb_xamot will be NULL; for "ring" and "fill" buffers, dtb_xamot will point
-+ * to a scratch buffer. For all buffer types, the dtrace_buffer structure is
-+ * always allocated on a per-CPU basis; a single dtrace_buffer structure is
-+ * never shared among CPUs. (That is, there is never true sharing of the
-+ * dtrace_buffer structure; to prevent false sharing of the structure, it must
-+ * always be aligned to the coherence granularity -- generally 64 bytes.)
-+ *
-+ * One of the critical design decisions of DTrace is that a given ECB always
-+ * stores the same quantity and type of data. This is done to assure that the
-+ * only metadata required for an ECB's traced data is the EPID. That is, from
-+ * the EPID, the consumer can determine the data layout. (The data buffer
-+ * layout is shown schematically below.) By assuring that one can determine
-+ * data layout from the EPID, the metadata stream can be separated from the
-+ * data stream -- simplifying the data stream enormously.
-+ *
-+ * base of data buffer ---> +------+--------------------+------+
-+ * | EPID | data | EPID |
-+ * +------+--------+------+----+------+
-+ * | data | EPID | data |
-+ * +---------------+------+-----------+
-+ * | data, cont. |
-+ * +------+--------------------+------+
-+ * | EPID | data | |
-+ * +------+--------------------+ |
-+ * | || |
-+ * | || |
-+ * | \/ |
-+ * : :
-+ * . .
-+ * . .
-+ * . .
-+ * : :
-+ * | |
-+ * limit of data buffer ---> +----------------------------------+
-+ *
-+ * When evaluating an ECB, dtrace_probe() determines if the ECB's needs of the
-+ * principal buffer (both scratch and payload) exceed the available space. If
-+ * the ECB's needs exceed available space (and if the principal buffer policy
-+ * is the default "switch" policy), the ECB is dropped, the buffer's drop count
-+ * is incremented, and processing advances to the next ECB. If the ECB's needs
-+ * can be met with the available space, the ECB is processed, but the offset in
-+ * the principal buffer is only advanced if the ECB completes processing
-+ * without error.
-+ *
-+ * When a buffer is to be switched (either because the buffer is the principal
-+ * buffer with a "switch" policy or because it is an aggregation buffer), a
-+ * cross call is issued to the CPU associated with the buffer. In the cross
-+ * call context, interrupts are disabled, and the active and the inactive
-+ * buffers are atomically switched. This involves switching the data pointers,
-+ * copying the various state fields (offset, drops, errors, etc.) into their
-+ * inactive equivalents, and clearing the state fields. Because interrupts are
-+ * disabled during this procedure, the switch is guaranteed to appear atomic to
-+ * dtrace_probe().
-+ *
-+ * DTrace Ring Buffering
-+ *
-+ * To process a ring buffer correctly, one must know the oldest valid record.
-+ * Processing starts at the oldest record in the buffer and continues until
-+ * the end of the buffer is reached. Processing then resumes starting with
-+ * the record stored at offset 0 in the buffer, and continues until the
-+ * youngest record is processed. If trace records are of a fixed-length,
-+ * determining the oldest record is trivial:
-+ *
-+ * - If the ring buffer has not wrapped, the oldest record is the record
-+ * stored at offset 0.
-+ *
-+ * - If the ring buffer has wrapped, the oldest record is the record stored
-+ * at the current offset.
-+ *
-+ * With variable length records, however, just knowing the current offset
-+ * doesn't suffice for determining the oldest valid record: assuming that one
-+ * allows for arbitrary data, one has no way of searching forward from the
-+ * current offset to find the oldest valid record. (That is, one has no way
-+ * of separating data from metadata.) It would be possible to simply refuse to
-+ * process any data in the ring buffer between the current offset and the
-+ * limit, but this leaves (potentially) an enormous amount of otherwise valid
-+ * data unprocessed.
-+ *
-+ * To effect ring buffering, we track two offsets in the buffer: the current
-+ * offset and the _wrapped_ offset. If a request is made to reserve some
-+ * amount of data, and the buffer has wrapped, the wrapped offset is
-+ * incremented until the wrapped offset minus the current offset is greater
-+ * than or equal to the reserve request. This is done by repeatedly looking
-+ * up the ECB corresponding to the EPID at the current wrapped offset, and
-+ * incrementing the wrapped offset by the size of the data payload
-+ * corresponding to that ECB. If this offset is greater than or equal to the
-+ * limit of the data buffer, the wrapped offset is set to 0. Thus, the
-+ * current offset effectively "chases" the wrapped offset around the buffer.
-+ * Schematically:
-+ *
-+ * base of data buffer ---> +------+--------------------+------+
-+ * | EPID | data | EPID |
-+ * +------+--------+------+----+------+
-+ * | data | EPID | data |
-+ * +---------------+------+-----------+
-+ * | data, cont. |
-+ * +------+---------------------------+
-+ * | EPID | data |
-+ * current offset ---> +------+---------------------------+
-+ * | invalid data |
-+ * wrapped offset ---> +------+--------------------+------+
-+ * | EPID | data | EPID |
-+ * +------+--------+------+----+------+
-+ * | data | EPID | data |
-+ * +---------------+------+-----------+
-+ * : :
-+ * . .
-+ * . ... valid data ... .
-+ * . .
-+ * : :
-+ * +------+-------------+------+------+
-+ * | EPID | data | EPID | data |
-+ * +------+------------++------+------+
-+ * | data, cont. | leftover |
-+ * limit of data buffer ---> +-------------------+--------------+
-+ *
-+ * If the amount of requested buffer space exceeds the amount of space
-+ * available between the current offset and the end of the buffer:
-+ *
-+ * (1) all words in the data buffer between the current offset and the limit
-+ * of the data buffer (marked "leftover", above) are set to
-+ * DTRACE_EPIDNONE
-+ *
-+ * (2) the wrapped offset is set to zero
-+ *
-+ * (3) the iteration process described above occurs until the wrapped offset
-+ * is greater than the amount of desired space.
-+ *
-+ * The wrapped offset is implemented by (re-)using the inactive offset.
-+ * In a "switch" buffer policy, the inactive offset stores the offset in
-+ * the inactive buffer; in a "ring" buffer policy, it stores the wrapped
-+ * offset.
-+ *
-+ * DTrace Scratch Buffering
-+ *
-+ * Some ECBs may wish to allocate dynamically-sized temporary scratch memory.
-+ * To accommodate such requests easily, scratch memory may be allocated in
-+ * the buffer beyond the current offset plus the needed memory of the current
-+ * ECB. If there isn't sufficient room in the buffer for the requested amount
-+ * of scratch space, the allocation fails and an error is generated. Scratch
-+ * memory is tracked in the dtrace_mstate_t and is automatically freed when
-+ * the ECB ceases processing. Note that ring buffers cannot allocate their
-+ * scratch from the principal buffer -- lest they needlessly overwrite older,
-+ * valid data. Ring buffers therefore have their own dedicated scratch buffer
-+ * from which scratch is allocated.
-+ */
-+
-+extern void dtrace_buffer_switch(struct dtrace_buffer *);
-+extern void dtrace_buffer_activate(struct dtrace_state *);
-+extern int dtrace_buffer_alloc(struct dtrace_buffer *, size_t, int,
-+ processorid_t);
-+extern void dtrace_buffer_drop(struct dtrace_buffer *);
-+extern intptr_t dtrace_buffer_reserve(struct dtrace_buffer *, size_t, size_t,
-+ struct dtrace_state *,
-+ struct dtrace_mstate *);
-+extern void dtrace_buffer_polish(struct dtrace_buffer *);
-+extern void dtrace_buffer_free(struct dtrace_buffer *);
-+
-+/*
-+ * DTrace framework/probe data synchronization
-+ * -------------------------------------------
-+ *
-+ * The dtrace_sync() facility is used to synchronize global DTrace framework
-+ * data with DTrace probe context. The framework updates data and then calls
-+ * dtrace_sync(). dtrace_sync() loops until it observes all CPUs have been out
-+ * of probe context at least once. This ensures all consumers are using the
-+ * updated data.
-+ *
-+ * DTrace probes have several requirements. First DTrace probe context cannot
-+ * block. DTrace probes execute with interrupts disabled. Locks cannot be
-+ * acquired in DTrace probe context. A second requirement is that DTrace
-+ * probes need to be as high performance as possible to minimize the effect of
-+ * enabled probes.
-+ *
-+ * DTrace framework data changes have their own requirements. DTrace data
-+ * changes/syncs are extremely infrequent compared to DTrace probe firings.
-+ * Probes can be in commonly executed code. A good trade-off is to favor
-+ * DTrace probe context performance over DTrace sync performance.
-+ *
-+ * To meet the above requirements, the DTrace data synchronization algorithm
-+ * is lock-less. The DTrace probe path is wait-free. The DTrace probe path
-+ * is memory-barrier-free in the common case to minimize probe effect.
-+ * dtrace_probe has been made membar free in the common case by adding a read
-+ * in dtrace_probe and adding an additional write and membar to dtrace_sync().
-+ *
-+ * A simple algorithm is to have dtrace_probe set a flag for its CPU when
-+ * entering DTrace probe context and clear the flag when it exits DTrace probe
-+ * context. A producer of DTrace framework data checks the flag to detect and
-+ * synchronize with probe context. Unfortunately memory ordering issues
-+ * complicate the implementation. Memory barriers are required in probe
-+ * context for this simple approach to work.
-+ *
-+ * A simple implementation to sync with one CPU that works with any memory
-+ * ordering model is:
-+ *
-+ * DTrace probe:
-+ * 1. CPU->in_probe_context = B_TRUE;
-+ * 2. dtrace_membar_enter()// membar #StoreLoad|#StoreStore
-+ * 3. access framework shared data// critical section
-+ * 4. dtrace_membar_exit()// membar #LoadStore|#StoreStore
-+ * 5. CPU->in_probe_context = B_FALSE;
-+ *
-+ * DTrace framework dtrace_sync:
-+ * 0. update framework shared data
-+ * 1. dtrace_membar_enter()// membar #StoreLoad|#StoreStore
-+ * 2. while (CPU->in_probe_context == B_TRUE)
-+ * 3. spin
-+ * 4. dtrace_membar_exit()// membar #LoadStore|#StoreStore
-+ * 5. produce shared dtrace data
-+ *
-+ * A note on memory ordering
-+ * -------------------------
-+ *
-+ * dtrace_membar_enter() guarantees later loads cannot complete before earlier
-+ * stores, and it guarantees later stores cannot complete before earlier stores.
-+ * dtrace_membar_enter() is, in SPARC parlance, a membar #StoreLoad|#StoreStore.
-+ *
-+ * dtrace_membar_exit() guarantees later stores cannot complete before earlier
-+ * loads, and it guarantees later stores cannot complete before earlier stores.
-+ * dtrace_membar_exit() is, in SPARC parlance, a membar #LoadStore|#StoreStore.
-+ *
-+ * Please see the SPARC and Intel processor guides on memory ordering.
-+ * All sun4v and Fujitsu processors are TSO (Total Store Order). Modern
-+ * supported Intel and AMD processors have similar load and store ordering
-+ * to SPARC. All processors currently supported by Solaris have these memory
-+ * ordering properties:
-+ * 1) Loads are ordered with respect to earlier loads.
-+ * 2) Stores are ordered with respect to earlier stores.
-+ * 3a) SPARC Atomic load-store behaves as if it were followed by a
-+ * MEMBAR #LoadLoad, #LoadStore, and #StoreStore.
-+ * 3b) X86 Atomic operations serialize load and store.
-+ * 4) Stores cannot bypass earlier loads.
-+ *
-+ * The above implementation details allow the membars to be simplified thus:
-+ * A) dtrace_membar_enter() can be reduced to "membar #StoreLoad" on sparc.
-+ * See property number 4 above.
-+ * Since dtrace_membar_enter() is an atomic operation on x86, it cannot be
-+ * reduced further.
-+ * B) dtrace_membar_exit() becomes a NOP on both SPARC and x86.
-+ * See properties 2 and 4.
-+ *
-+ *
-+ * Elimination of membar #StoreLoad from dtrace probe context
-+ * ----------------------------------------------------------
-+ *
-+ * Furthermore it is possible to eliminate all memory barriers from the common
-+ * dtrace_probe() entry case. The only membar needed in dtrace_probe is there
-+ * to prevent Loads of global DTrace framework data from passing the Store to
-+ * the "in_probe_context" flag (i.e. the dtrace_membar_enter()).
-+ * A Load at the beginning of the algorithm is also ordered with these later
-+ * Loads and Stores: the membar #StoreLoad can be replaced with a early Load of
-+ * a "sync_request" flag and a conditional branch on the flag value.
-+ *
-+ * dtrace_sync() first Stores to the "sync_request" flag, and dtrace_probe()
-+ * starts by Loading the flag. This Load in dtrace_probe() of "sync_request"
-+ * is ordered with its later Store to the "in_probe_context" flag and
-+ * dtrace_probe's later Loads of DTrace framework data. dtrace_probe() only
-+ * needs a membar #StoreLoad iff the "sync_request" flag is set.
-+ *
-+ * Optimized Synchronization Algorithm
-+ * -----------------------------------
-+ *
-+ * DTrace probe:
-+ * + 1a. request_flag = CPU->sync_request // Load
-+ * 1b. CPU->in_probe_context = B_TRUE // Store
-+ * + 2. if request_flag > 0
-+ * dtrace_membar_enter() // membar #StoreLoad
-+ * 3. access framework shared data // critical section
-+ * -
-+ * 5. CPU->in_probe_context = B_FALSE // Store
-+ *
-+ * DTrace framework dtrace_sync:
-+ * + 1a. atomically add 1 to CPU->sync_request // Store and
-+ * 1b. dtrace_membar_enter() // membar #StoreLoad
-+ * 2. while (CPU->in_probe_context == B_TRUE) // Load
-+ * 3. spin
-+ * + 4a. atomically subtract 1 from CPU->sync_request // Load + Store
-+ * -
-+ * 5. produce shared dtrace data
-+ *
-+ * This algorithm has been proven correct by analysis of all interleaving
-+ * scenarios of the above operations with the hardware memory ordering
-+ * described above.
-+ *
-+ * The Load and store of the flag pair is very inexpensive. The cacheline with
-+ * the flag pair is never accessed by a different CPU except by dtrace_sync.
-+ * dtrace_sync is very uncommon compared to typical probe firings. The removal
-+ * of membars from DTrace probe context at the expense of a Load and Store and
-+ * a conditional branch is a good performance win.
-+ *
-+ * As implemented there is one pair of flags per CPU. The flags are in one
-+ * cacheline; they could be split into two cachelines if dtrace_sync was more
-+ * common. dtrace_sync loops over all NCPU sets of flags. dtrace_sync lazily
-+ * only does one dtrace_membar_enter() (step 1b) after setting all NCPU
-+ * sync_request flags.
-+ *
-+ * Sample aliasing could cause dtrace_sync() to always sample a CPU's
-+ * in_probe_context flag when the CPU is in probe context even if the CPU
-+ * left and returned to probe context one or more times since the last sample.
-+ * cpuc_in_probe_ctxt is implemented as an even/odd counter instead of a
-+ * boolean flag. cpuc_in_probe_ctxt is odd when in probe context and even
-+ * when not in probe context. Probe context increments cpuc_in_probe_ctxt when
-+ * entering and exiting. dtrace_probe() handles re-entry by not increment the
-+ * counter for re-enterant entry and exit.
-+ */
-+
-+/*
-+ * dtrace_membar_exit() is a NOP on current SPARC and X86 hardware.
-+ * It is defined as an inline asm statement to prevent the C optimizer from
-+ * moving C statements around the membar.
-+ */
-+#define dtrace_membar_exit() \
-+ __asm__ __volatile__("" ::: "memory")
-+
-+/*
-+ * dtrace_membar_enter() does not need an explicit membar #StoreStore because
-+ * modern SPARC hardware is TSO: stores are ordered with other stores.
-+ */
-+#define dtrace_membar_enter() \
-+ mb()
-+
-+#define dtrace_safe_smt_pause() \
-+ cpu_relax()
-+
-+/*
-+ * Used by dtrace_probe() to flag entry to the the critical section.
-+ * dtrace_probe() context may be consuming DTrace framework data.
-+ *
-+ * cpuc_in_probe_ctxt is odd when in probe context and even when not in
-+ * probe context. The flag must not be incremented when re-entering from
-+ * probe context.
-+ */
-+#define DTRACE_SYNC_ENTER_CRITICAL(cookie, re_entry) \
-+{ \
-+ uint64_t requests; \
-+ uint64_t count; \
-+ \
-+ preempt_disable(); \
-+ local_irq_save(cookie); \
-+ \
-+ requests = atomic64_read(&this_cpu_core->cpuc_sync_requests); \
-+ \
-+ /* Increment flag iff it is even */ \
-+ count = atomic64_read(&this_cpu_core->cpuc_in_probe_ctx); \
-+ re_entry = count & 0x1; \
-+ atomic64_set(&this_cpu_core->cpuc_in_probe_ctx, count | 0x1); \
-+ ASSERT(DTRACE_SYNC_IN_CRITICAL(smp_processor_id())); \
-+ \
-+ /* \
-+ * Later Loads are ordered with respect to the Load of \
-+ * cpuc_sync_requests. The Load is also guaranteed to complete \
-+ * before the store to cpuc_in_probe_ctxt. Thus a member_enter \
-+ * is only needed when requests is not 0. This is very \
-+ * uncommon. \
-+ */ \
-+ if (requests > 0) { \
-+ dtrace_membar_enter(); \
-+ } \
-+}
-+
-+/*
-+ * Used by dtrace_probe() to flag exit from the critical section.
-+ * dtrace_probe context is no longer using DTrace framework data.
-+ */
-+#define DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry) \
-+{ \
-+ dtrace_membar_exit(); \
-+ ASSERT((re_entry | 0x1) == 0x1); \
-+ \
-+ /* \
-+ * flag must not be incremented when returning to probe context.\
-+ */ \
-+ atomic64_add(~re_entry & 0x1, &this_cpu_core->cpuc_in_probe_ctx); \
-+ ASSERT(re_entry == \
-+ (atomic64_read(&this_cpu_core->cpuc_in_probe_ctx) & 0x1)); \
-+ local_irq_restore(cookie); \
-+ preempt_enable(); \
-+}
-+
-+/*
-+ * Used by dtrace_sync to inform dtrace_probe it needs to synchronize with
-+ * dtrace_sync. dtrace_probe consumes the cpuc_sync_requests flag to determine
-+ * if it needs a membar_enter. Not called from probe context.
-+ *
-+ * cpuc_sync_requests must be updated atomically by dtrace_sync because there
-+ * may be multiple dtrace_sync operations executing at the same time.
-+ * cpuc_sync_requests is a simple count of the number of concurrent
-+ * dtrace_sync requests.
-+ */
-+#define DTRACE_SYNC_START(cpuid) \
-+{ \
-+ atomic64_add(1, &(per_cpu_core(cpuid))->cpuc_sync_requests); \
-+ ASSERT(atomic64_read(&per_cpu_core(cpuid)->cpuc_sync_requests) > 0); \
-+}
-+
-+/*
-+ * Used by dtrace_sync to flag dtrace_probe that it no longer needs to
-+ * synchronize with dtrace_sync. Not called from probe context.
-+ */
-+#define DTRACE_SYNC_END(cpuid) \
-+{ \
-+ atomic64_add(-1, &(per_cpu_core(cpuid))->cpuc_sync_requests); \
-+ ASSERT(atomic64_read(&per_cpu_core(cpuid)->cpuc_sync_requests) >= 0); \
-+}
-+
-+/*
-+ * The next two macros are used by dtrace_sync to check if the target CPU is in
-+ * DTrace probe context. cpuc_in_probe_ctxt is a monotonically increasing
-+ * count which dtrace_probe() increments when entering and exiting probe
-+ * context. The flag is odd when in probe context, and even when not in probe
-+ * context.
-+ */
-+#define DTRACE_SYNC_IN_CRITICAL(cpuid) \
-+ (atomic64_read(&per_cpu_core(cpuid)->cpuc_in_probe_ctx) & 0x1)
-+
-+/*
-+ * Used to check if the target CPU left and then entered probe context again.
-+ */
-+#define DTRACE_SYNC_CRITICAL_COUNT(cpuid) \
-+ (atomic64_read(&per_cpu_core(cpuid)->cpuc_in_probe_ctx))
-+
-+/*
-+ * The next three macros are bitmap operations used by dtrace_sync to keep track
-+ * of which CPUs it still needs to synchronize with.
-+ */
-+#define DTRACE_SYNC_OUTSTANDING(cpuid, bitmap) \
-+ (cpumask_test_cpu(cpuid, bitmap) == 1)
-+
-+#define DTRACE_SYNC_NEEDED(cpuid, bitmap) \
-+ cpumask_set_cpu(cpuid, bitmap)
-+
-+#define DTRACE_SYNC_DONE(cpuid, bitmap) \
-+ cpumask_clear_cpu(cpuid, bitmap)
-+
-+extern uint64_t dtrace_sync_sample_count;
-+extern void dtrace_sync(void);
-+
-+/*
-+ * DTrace Enabling Functions
-+ */
-+extern struct dtrace_enabling *dtrace_retained;
-+extern dtrace_genid_t dtrace_retained_gen;
-+
-+extern struct dtrace_enabling *dtrace_enabling_create(struct dtrace_vstate *);
-+extern void dtrace_enabling_add(struct dtrace_enabling *,
-+ struct dtrace_ecbdesc *);
-+extern void dtrace_enabling_dump(struct dtrace_enabling *);
-+extern void dtrace_enabling_destroy(struct dtrace_enabling *);
-+extern int dtrace_enabling_retain(struct dtrace_enabling *);
-+extern int dtrace_enabling_replicate(struct dtrace_state *,
-+ struct dtrace_probedesc *,
-+ struct dtrace_probedesc *);
-+extern void dtrace_enabling_retract(struct dtrace_state *);
-+extern int dtrace_enabling_match(struct dtrace_enabling *, int *);
-+extern void dtrace_enabling_matchall(void);
-+extern void dtrace_enabling_prime(struct dtrace_state *);
-+extern void dtrace_enabling_provide(struct dtrace_provider *);
-+
-+/*
-+ * DOF functions
-+ */
-+extern void dtrace_dof_error(struct dof_hdr *, const char *);
-+extern struct dof_hdr *dtrace_dof_create(struct dtrace_state *);
-+extern struct dof_hdr *dtrace_dof_copyin(void __user *, int *);
-+extern struct dof_hdr *dtrace_dof_property(const char *);
-+extern void dtrace_dof_destroy(struct dof_hdr *);
-+extern int dtrace_dof_slurp(struct dof_hdr *, struct dtrace_vstate *,
-+ const struct cred *, struct dtrace_enabling **,
-+ uint64_t, int);
-+extern int dtrace_dof_options(struct dof_hdr *, struct dtrace_state *);
-+extern void dtrace_helper_provide(struct dof_helper *dhp, pid_t pid);
-+extern int dtrace_helper_slurp(struct dof_hdr *, struct dof_helper *);
-+extern int dtrace_helper_destroygen(int);
-+
-+/*
-+ * DTrace Anonymous Enabling Functions
-+ */
-+struct dtrace_anon {
-+ struct dtrace_state *dta_state;
-+ struct dtrace_enabling *dta_enabling;
-+ processorid_t dta_beganon;
-+};
-+
-+extern struct dtrace_anon dtrace_anon;
-+
-+extern struct dtrace_state *dtrace_anon_grab(void);
-+extern void dtrace_anon_property(void);
-+
-+/*
-+ * DTrace Consumer State Functions
-+ */
-+extern struct kmem_cache *dtrace_state_cachep;
-+extern size_t dtrace_strsize_default;
-+
-+extern ktime_t dtrace_deadman_timeout;
-+extern int dtrace_destructive_disallow;
-+
-+extern dtrace_id_t dtrace_probeid_begin;
-+extern dtrace_id_t dtrace_probeid_end;
-+extern dtrace_id_t dtrace_probeid_error;
-+
-+extern struct dtrace_dynvar dtrace_dynhash_sink;
-+
-+extern struct user_namespace *init_user_namespace;
-+
-+extern int dtrace_dstate_init(struct dtrace_dstate *, size_t);
-+extern void dtrace_dstate_fini(struct dtrace_dstate *);
-+extern void dtrace_vstate_fini(struct dtrace_vstate *);
-+extern struct dtrace_state *dtrace_state_create(struct file *);
-+extern int dtrace_state_go(struct dtrace_state *, processorid_t *);
-+extern int dtrace_state_stop(struct dtrace_state *, processorid_t *);
-+extern int dtrace_state_option(struct dtrace_state *, dtrace_optid_t,
-+ dtrace_optval_t);
-+extern void dtrace_state_destroy(struct dtrace_state *);
-+
-+/*
-+ * DTrace Utility Functions
-+ */
-+extern int dtrace_isglob(const char *);
-+extern int dtrace_gmatch(const char *, const char *);
-+extern void *dtrace_vzalloc(unsigned long);
-+extern void *dtrace_vzalloc_try(unsigned long);
-+extern char *dtrace_strdup(const char *);
-+extern int dtrace_strncmp(char *, char *, size_t);
-+extern size_t dtrace_strlen(const char *, size_t);
-+extern int dtrace_badattr(const struct dtrace_attribute *);
-+extern int dtrace_badname(const char *);
-+extern void dtrace_cred2priv(const struct cred *, uint32_t *, kuid_t *);
-+
-+extern void ctf_forceload(void);
-+
-+#define dtrace_membar_producer() smp_wmb()
-+#define dtrace_membar_consumer() smp_rmb()
-+
-+typedef unsigned long dtrace_icookie_t;
-+
-+extern struct mutex cpu_lock;
-+
-+extern void dtrace_toxic_ranges(void (*)(uintptr_t, uintptr_t));
-+extern void dtrace_vpanic(const char *, va_list);
-+extern int dtrace_getipl(void);
-+
-+extern dtrace_icookie_t dtrace_interrupt_disable(void);
-+extern void dtrace_interrupt_enable(dtrace_icookie_t);
-+
-+typedef void (*dtrace_xcall_t)(void *);
-+
-+extern void dtrace_xcall(processorid_t, dtrace_xcall_t, void *);
-+
-+extern uintptr_t dtrace_fulword(void *);
-+extern uint8_t dtrace_fuword8(void *);
-+extern uint16_t dtrace_fuword16(void *);
-+extern uint32_t dtrace_fuword32(void *);
-+extern uint64_t dtrace_fuword64(void *);
-+
-+extern void dtrace_probe_error(struct dtrace_state *, dtrace_epid_t, int, int,
-+ int, uintptr_t);
-+
-+extern void dtrace_getpcstack(uint64_t *, int, int, uint32_t *);
-+extern void dtrace_getupcstack(uint64_t *, int);
-+extern unsigned long dtrace_getufpstack(uint64_t *, uint64_t *, int);
-+extern uintptr_t dtrace_getfp(void);
-+extern uint64_t dtrace_getarg(int, int);
-+extern int dtrace_getstackdepth(struct dtrace_mstate *, int);
-+extern int dtrace_getustackdepth(void);
-+extern ulong_t dtrace_getreg(struct task_struct *, uint_t);
-+extern void dtrace_copyin(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+extern void dtrace_copyout(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+extern void dtrace_copyinstr(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+extern void dtrace_copyoutstr(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+
-+/*
-+ * Plaforms that support a fast path to obtain the caller implement the
-+ * dtrace_caller() function.
-+ *
-+ * The first argument is the number of frames that should be skipped when
-+ * looking for a caller address. The 2nd argument is a dummy argument that
-+ * is necessary for SPARC.
-+ *
-+ * On x86 this is effectively a NOP.
-+ *
-+ * On SPARC it is possible to retrieve the caller address from the register
-+ * windows without flushing them to the stack. This involves performing
-+ * explicit rotation of the register windows. Modification of the windowing
-+ * mechanism state alters all %i, %o, and %l registers so we are can only use
-+ * %g registers to store temporary data.
-+ *
-+ * On Linux a lot of %g registers are already allocated for specific purposes.
-+ * Saving temporaries to the stack would be a violation of the fast path code
-+ * logic. Therefore, the function prototype declares a 2nd argument that serves
-+ * as a temporary value. A compiler will not expect that the value in %o1
-+ * will survive the call and therefore dtrace_caller() can use %o1 as a
-+ * temporary register.
-+ */
-+extern uintptr_t dtrace_caller(int, int);
-+
-+extern void dtrace_copyin_arch(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+extern void dtrace_copyinstr_arch(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+
-+extern void pdata_init(struct dtrace_module *, struct module *);
-+extern void pdata_cleanup(struct dtrace_module *, struct module *);
-+
-+extern void debug_enter(char *);
-+
-+#endif /* _LINUX_DTRACE_IMPL_H */
-diff --git a/include/dtrace/dtrace_impl_defines.h b/include/dtrace/dtrace_impl_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..19b57f6188a0515cb63765bae20d9cf376dc4a21
---- /dev/null
-+++ b/include/dtrace/dtrace_impl_defines.h
-@@ -0,0 +1,173 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Implementation Defines
-+ *
-+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_IMPL_DEFINES_H
-+#define _LINUX_DTRACE_IMPL_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/preempt.h>
-+#include <asm/ptrace.h>
-+
-+typedef typeof(instruction_pointer((struct pt_regs *)0)) pc_t;
-+
-+enum dtrace_activity {
-+ DTRACE_ACTIVITY_INACTIVE = 0,
-+ DTRACE_ACTIVITY_WARMUP,
-+ DTRACE_ACTIVITY_ACTIVE,
-+ DTRACE_ACTIVITY_DRAINING,
-+ DTRACE_ACTIVITY_COOLDOWN,
-+ DTRACE_ACTIVITY_STOPPED,
-+ DTRACE_ACTIVITY_KILLED
-+};
-+
-+enum dtrace_dstate_state {
-+ DTRACE_DSTATE_CLEAN = 0,
-+ DTRACE_DSTATE_EMPTY,
-+ DTRACE_DSTATE_DIRTY,
-+ DTRACE_DSTATE_RINSING
-+};
-+
-+enum dtrace_dynvar_op {
-+ DTRACE_DYNVAR_ALLOC,
-+ DTRACE_DYNVAR_NOALLOC,
-+ DTRACE_DYNVAR_DEALLOC
-+};
-+
-+#define DTRACE_MSTATE_ARGS 0x00000001
-+#define DTRACE_MSTATE_PROBE 0x00000002
-+#define DTRACE_MSTATE_EPID 0x00000004
-+#define DTRACE_MSTATE_TIMESTAMP 0x00000008
-+#define DTRACE_MSTATE_STACKDEPTH 0x00000010
-+#define DTRACE_MSTATE_CALLER 0x00000020
-+#define DTRACE_MSTATE_IPL 0x00000040
-+#define DTRACE_MSTATE_FLTOFFS 0x00000080
-+#define DTRACE_MSTATE_USTACKDEPTH 0x00000100
-+#define DTRACE_MSTATE_UCALLER 0x00000200
-+
-+#define DTRACE_PROBEKEY_MAXDEPTH 8
-+
-+enum dtrace_speculation_state {
-+ DTRACESPEC_INACTIVE = 0,
-+ DTRACESPEC_ACTIVE,
-+ DTRACESPEC_ACTIVEONE,
-+ DTRACESPEC_ACTIVEMANY,
-+ DTRACESPEC_COMMITTING,
-+ DTRACESPEC_COMMITTINGMANY,
-+ DTRACESPEC_DISCARDING
-+};
-+
-+#define DTRACE_HELPER_ACTION_USTACK 0
-+#define DTRACE_NHELPER_ACTIONS 1
-+
-+#define DTRACE_HELPTRACE_NEXT (-1)
-+#define DTRACE_HELPTRACE_DONE (-2)
-+#define DTRACE_HELPTRACE_ERR (-3)
-+
-+#undef ASSERT
-+#ifdef CONFIG_DT_DEBUG
-+# define ASSERT(x) ((void)((x) || dtrace_assfail(#x, __FILE__, __LINE__)))
-+#else
-+# define ASSERT(x) ((void)0)
-+#endif
-+
-+/*
-+ * DTrace Probe Hashing
-+ */
-+
-+#define DTRACE_HASHNEXT(hash, probe) \
-+ (struct dtrace_probe **)((uintptr_t)(probe) + (hash)->dth_nextoffs)
-+#define DTRACE_HASHPREV(hash, probe) \
-+ (struct dtrace_probe **)((uintptr_t)(probe) + (hash)->dth_prevoffs)
-+
-+/*
-+ * DTrace Probe Management
-+ */
-+#define DTRACE_ANCHORED(probe) ((probe)->dtpr_func[0] != '\0')
-+#define DTRACE_FLAGS2FLT(flags) \
-+ (((flags) & CPU_DTRACE_BADADDR) ? DTRACEFLT_BADADDR : \
-+ ((flags) & CPU_DTRACE_ILLOP) ? DTRACEFLT_ILLOP : \
-+ ((flags) & CPU_DTRACE_DIVZERO) ? DTRACEFLT_DIVZERO : \
-+ ((flags) & CPU_DTRACE_KPRIV) ? DTRACEFLT_KPRIV : \
-+ ((flags) & CPU_DTRACE_UPRIV) ? DTRACEFLT_UPRIV : \
-+ ((flags) & CPU_DTRACE_TUPOFLOW) ? DTRACEFLT_TUPOFLOW : \
-+ ((flags) & CPU_DTRACE_BADALIGN) ? DTRACEFLT_BADALIGN : \
-+ ((flags) & CPU_DTRACE_NOSCRATCH) ? DTRACEFLT_NOSCRATCH : \
-+ ((flags) & CPU_DTRACE_BADSTACK) ? DTRACEFLT_BADSTACK : \
-+ DTRACEFLT_UNKNOWN)
-+
-+/*
-+ * Test whether alloc_sz bytes will fit in the scratch region. We isolate
-+ * alloc_sz on the righthand side of the comparison in order to avoid overflow
-+ * or underflow in the comparison with it. This is simpler than the INRANGE
-+ * check above, because we know that the dtms_scratch_ptr is valid in the
-+ * range. Allocations of size zero are allowed.
-+ */
-+#define DTRACE_INSCRATCH(mstate, alloc_sz) \
-+ ((mstate)->dtms_scratch_base + (mstate)->dtms_scratch_size - \
-+ (mstate)->dtms_scratch_ptr >= (alloc_sz))
-+
-+/*
-+ * Buffering.
-+ */
-+
-+#define DTRACEBUF_RING 0x0001 /* bufpolicy set to "ring" */
-+#define DTRACEBUF_FILL 0x0002 /* bufpolicy set to "fill" */
-+#define DTRACEBUF_NOSWITCH 0x0004 /* do not switch buffer */
-+#define DTRACEBUF_WRAPPED 0x0008 /* ring buffer has wrapped */
-+#define DTRACEBUF_DROPPED 0x0010 /* drops occurred */
-+#define DTRACEBUF_ERROR 0x0020 /* errors occurred */
-+#define DTRACEBUF_FULL 0x0040 /* "fill" buffer is full */
-+#define DTRACEBUF_CONSUMED 0x0080 /* buffer has been consumed */
-+#define DTRACEBUF_INACTIVE 0x0100 /* buffer is not yet active */
-+
-+#define DTRACE_STORE(type, tomax, offset, what) \
-+ do { \
-+ *((type *)((uintptr_t)(tomax) + (uintptr_t)(offset))) = (type)(what); \
-+ } while (0)
-+
-+#define KERNELBASE (uintptr_t)_text
-+
-+#ifdef CONFIG_DT_DEBUG_MUTEX
-+# define real_mutex_lock(x) mutex_lock(x)
-+# define real_mutex_unlock(x) mutex_unlock(x)
-+
-+# define mutex_lock(x) do { \
-+ pr_debug("mutex_lock(%s) at %s::%d for %p (PID %d)\n", \
-+ __stringify(x), \
-+ __FILE__, __LINE__, current, \
-+ current ? current->pid : -1); \
-+ real_mutex_lock(x); \
-+ } while (0)
-+# define mutex_unlock(x) do { \
-+ pr_debug("mutex_unlock(%s) at %s::%d for %p (PID %d)\n", \
-+ __stringify(x), \
-+ __FILE__, __LINE__, current, \
-+ current ? current->pid : -1); \
-+ real_mutex_unlock(x); \
-+ } while (0)
-+#endif
-+
-+#define MUTEX_HELD(lock) mutex_owned(lock)
-+
-+#define PDATA(mp) ((struct dtrace_module *)mp->pdata)
-+
-+#endif /* _LINUX_DTRACE_IMPL_DEFINES_H */
-diff --git a/include/dtrace/provider.h b/include/dtrace/provider.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..9eeb147f03639207768d212cd1ef8e8b00325105
---- /dev/null
-+++ b/include/dtrace/provider.h
-@@ -0,0 +1,971 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Provider API
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _DTRACE_PROVIDER_H
-+#define _DTRACE_PROVIDER_H
-+
-+/*
-+ * The following functions are implemented by the DTrace framework and are
-+ * used to implement separate in-kernel DTrace providers.
-+ *
-+ * The provider API has two halves: the API that the providers consume from
-+ * DTrace, and the API that providers make available to DTrace.
-+ *
-+ * 1 Framework-to-Provider API
-+ *
-+ * 1.1 Overview
-+ *
-+ * The Framework-to-Provider API is represented by the dtrace_pops structure
-+ * that the provider passes to the framework when registering itself. This
-+ * structure consists of the following members:
-+ *
-+ * dtps_provide() <-- Provide all probes, all modules
-+ * dtps_provide_module() <-- Provide all probes in specified module
-+ * dtps_enable() <-- Enable specified probe
-+ * dtps_disable() <-- Disable specified probe
-+ * dtps_suspend() <-- Suspend specified probe
-+ * dtps_resume() <-- Resume specified probe
-+ * dtps_getargdesc() <-- Get the argument description for args[X]
-+ * dtps_getargval() <-- Get the value for an argX or args[X] variable
-+ * dtps_usermode() <-- Find out if the probe was fired in user mode
-+ * dtps_destroy() <-- Destroy all state associated with this probe
-+ * dtps_destroy_module() <-- Destroy per-module data
-+ *
-+ * 1.2 void dtps_provide(void *arg, const struct dtrace_probedesc *spec)
-+ *
-+ * 1.2.1 Overview
-+ *
-+ * Called to indicate that the provider should provide all probes. If the
-+ * specified description is non-NULL, dtps_provide() is being called because
-+ * no probe matched a specified probe -- if the provider has the ability to
-+ * create custom probes, it may wish to create a probe that matches the
-+ * specified description.
-+ *
-+ * 1.2.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is a pointer to a probe description that the provider may
-+ * wish to consider when creating custom probes. The provider is expected to
-+ * call back into the DTrace framework via dtrace_probe_create() to create
-+ * any necessary probes. dtps_provide() may be called even if the provider
-+ * has made available all probes; the provider should check the return value
-+ * of dtrace_probe_create() to handle this case. Note that the provider need
-+ * not implement both dtps_provide() and dtps_provide_module(); see
-+ * "Arguments and Notes" for dtrace_register(), below.
-+ *
-+ * 1.2.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.2.4 Caller's context
-+ *
-+ * dtps_provide() is typically called from open() or ioctl() context, but may
-+ * be called from other contexts as well. The DTrace framework is locked in
-+ * such a way that providers may not register or unregister. This means that
-+ * the provider may not call any DTrace API that affects its registration with
-+ * the framework, including dtrace_register(), dtrace_unregister(),
-+ * dtrace_invalidate(), and dtrace_condense(). However, the context is such
-+ * that the provider may (and indeed, is expected to) call probe-related
-+ * DTrace routines, including dtrace_probe_create(), dtrace_probe_lookup(),
-+ * and dtrace_probe_arg().
-+ *
-+ * 1.3 void dtps_provide_module(void *arg, struct modctl *mp)
-+ *
-+ * 1.3.1 Overview
-+ *
-+ * Called to indicate that the provider should provide all probes in the
-+ * specified module.
-+ *
-+ * 1.3.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is a pointer to a modctl structure that indicates the
-+ * module for which probes should be created.
-+ *
-+ * 1.3.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.3.4 Caller's context
-+ *
-+ * dtps_provide_module() may be called from open() or ioctl() context, but
-+ * may also be called from a module loading context. mod_lock is held, and
-+ * the DTrace framework is locked in such a way that providers may not
-+ * register or unregister. This means that the provider may not call any
-+ * DTrace API that affects its registration with the framework, including
-+ * dtrace_register(), dtrace_unregister(), dtrace_invalidate(), and
-+ * dtrace_condense(). However, the context is such that the provider may (and
-+ * indeed, is expected to) call probe-related DTrace routines, including
-+ * dtrace_probe_create(), dtrace_probe_lookup(), and dtrace_probe_arg(). Note
-+ * that the provider need not implement both dtps_provide() and
-+ * dtps_provide_module(); see "Arguments and Notes" for dtrace_register(),
-+ * below.
-+ *
-+ * 1.4 int dtps_enable(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.4.1 Overview
-+ *
-+ * Called to enable the specified probe.
-+ *
-+ * 1.4.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the probe to be enabled. The third
-+ * argument is the probe argument as passed to dtrace_probe_create().
-+ * dtps_enable() will be called when a probe transitions from not being
-+ * enabled at all to having one or more ECB. The number of ECBs associated
-+ * with the probe may change without subsequent calls into the provider.
-+ * When the number of ECBs drops to zero, the provider will be explicitly
-+ * told to disable the probe via dtps_disable(). dtrace_probe() should never
-+ * be called for a probe identifier that hasn't been explicitly enabled via
-+ * dtps_enable().
-+ *
-+ * 1.4.3 Return value
-+ *
-+ * On success, dtps_enable() should return 0. On failure, -1 should be
-+ * returned.
-+ *
-+ * 1.4.4 Caller's context
-+ *
-+ * The DTrace framework is locked in such a way that it may not be called
-+ * back into at all. cpu_lock is held. mod_lock is not held and may not
-+ * be acquired.
-+ *
-+ * 1.5 void dtps_disable(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.5.1 Overview
-+ *
-+ * Called to disable the specified probe.
-+ *
-+ * 1.5.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the probe to be disabled. The third
-+ * argument is the probe argument as passed to dtrace_probe_create().
-+ * dtps_disable() will be called when a probe transitions from being enabled
-+ * to having zero ECBs. dtrace_probe() should never be called for a probe
-+ * identifier that has been explicitly enabled via dtps_disable().
-+ *
-+ * 1.5.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.5.4 Caller's context
-+ *
-+ * The DTrace framework is locked in such a way that it may not be called
-+ * back into at all. cpu_lock is held. mod_lock is not held and may not
-+ * be acquired.
-+ *
-+ * 1.6 void dtps_suspend(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.6.1 Overview
-+ *
-+ * Called to suspend the specified enabled probe. This entry point is for
-+ * providers that may need to suspend some or all of their probes when CPUs
-+ * are being powered on or when the boot monitor is being entered for a
-+ * prolonged period of time.
-+ *
-+ * 1.6.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the probe to be suspended. The
-+ * third argument is the probe argument as passed to dtrace_probe_create().
-+ * dtps_suspend will only be called on an enabled probe. Providers that
-+ * provide a dtps_suspend entry point will want to take roughly the action
-+ * that it takes for dtps_disable.
-+ *
-+ * 1.6.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.6.4 Caller's context
-+ *
-+ * Interrupts are disabled. The DTrace framework is in a state such that the
-+ * specified probe cannot be disabled or destroyed for the duration of
-+ * dtps_suspend(). As interrupts are disabled, the provider is afforded
-+ * little latitude; the provider is expected to do no more than a store to
-+ * memory.
-+ *
-+ * 1.7 void dtps_resume(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.7.1 Overview
-+ *
-+ * Called to resume the specified enabled probe. This entry point is for
-+ * providers that may need to resume some or all of their probes after the
-+ * completion of an event that induced a call to dtps_suspend().
-+ *
-+ * 1.7.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the probe to be resumed. The
-+ * third argument is the probe argument as passed to dtrace_probe_create().
-+ * dtps_resume will only be called on an enabled probe. Providers that
-+ * provide a dtps_resume entry point will want to take roughly the action
-+ * that it takes for dtps_enable.
-+ *
-+ * 1.7.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.7.4 Caller's context
-+ *
-+ * Interrupts are disabled. The DTrace framework is in a state such that the
-+ * specified probe cannot be disabled or destroyed for the duration of
-+ * dtps_resume(). As interrupts are disabled, the provider is afforded
-+ * little latitude; the provider is expected to do no more than a store to
-+ * memory.
-+ *
-+ * 1.8 void dtps_getargdesc(void *arg, dtrace_id_t id, void *parg,
-+ * struct dtrace_argdesc *desc)
-+ *
-+ * 1.8.1 Overview
-+ *
-+ * Called to retrieve the argument description for an args[X] variable.
-+ *
-+ * 1.8.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the current probe. The third
-+ * argument is the probe argument as passed to dtrace_probe_create(). The
-+ * fourth argument is a pointer to the argument description. This
-+ * description is both an input and output parameter: it contains the
-+ * index of the desired argument in the dtargd_ndx field, and expects
-+ * the other fields to be filled in upon return. If there is no argument
-+ * corresponding to the specified index, the dtargd_ndx field should be set
-+ * to DTRACE_ARGNONE.
-+ *
-+ * 1.8.3 Return value
-+ *
-+ * None. The dtargd_ndx, dtargd_native, dtargd_xlate and dtargd_mapping
-+ * members of the dtrace_argdesc structure are all output values.
-+ *
-+ * 1.8.4 Caller's context
-+ *
-+ * dtps_getargdesc() is called from ioctl() context. mod_lock is held, and
-+ * the DTrace framework is locked in such a way that providers may not
-+ * register or unregister. This means that the provider may not call any
-+ * DTrace API that affects its registration with the framework, including
-+ * dtrace_register(), dtrace_unregister(), dtrace_invalidate(), and
-+ * dtrace_condense().
-+ *
-+ * 1.9 uint64_t dtps_getargval(void *arg, dtrace_id_t id, void *parg,
-+ * int argno, int aframes)
-+ *
-+ * 1.9.1 Overview
-+ *
-+ * Called to retrieve a value for an argX or args[X] variable.
-+ *
-+ * 1.9.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the current probe. The third
-+ * argument is the probe argument as passed to dtrace_probe_create(). The
-+ * fourth argument is the number of the argument (the X in the example in
-+ * 1.9.1). The fifth argument is the number of stack frames that were used
-+ * to get from the actual place in the code that fired the probe to
-+ * dtrace_probe() itself, the so-called artificial frames. This argument may
-+ * be used to descend an appropriate number of frames to find the correct
-+ * values. If this entry point is left NULL, the dtrace_getarg() built-in
-+ * function is used.
-+ *
-+ * 1.9.3 Return value
-+ *
-+ * The value of the argument.
-+ *
-+ * 1.9.4 Caller's context
-+ *
-+ * This is called from within dtrace_probe() meaning that interrupts
-+ * are disabled. No locks should be taken within this entry point.
-+ *
-+ * 1.10 int dtps_usermode(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.10.1 Overview
-+ *
-+ * Called to determine if the probe was fired in a user context.
-+ *
-+ * 1.10.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the current probe. The third
-+ * argument is the probe argument as passed to dtrace_probe_create(). This
-+ * entry point must not be left NULL for providers whose probes allow for
-+ * mixed mode tracing, that is to say those probes that can fire during
-+ * kernel- _or_ user-mode execution
-+ *
-+ * 1.10.3 Return value
-+ *
-+ * A boolean value.
-+ *
-+ * 1.10.4 Caller's context
-+ *
-+ * This is called from within dtrace_probe() meaning that interrupts
-+ * are disabled. No locks should be taken within this entry point.
-+ *
-+ * 1.11 void dtps_destroy(void *arg, dtrace_id_t id, void *parg)
-+ *
-+ * 1.11.1 Overview
-+ *
-+ * Called to destroy the specified probe.
-+ *
-+ * 1.11.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is the identifier of the probe to be destroyed. The third
-+ * argument is the probe argument as passed to dtrace_probe_create(). The
-+ * provider should free all state associated with the probe. The framework
-+ * guarantees that dtps_destroy() is only called for probes that have either
-+ * been disabled via dtps_disable() or were never enabled via dtps_enable().
-+ * Once dtps_disable() has been called for a probe, no further call will be
-+ * made specifying the probe.
-+ *
-+ * 1.11.3 Return value
-+ *
-+ * None.
-+ *
-+ * 1.11.4 Caller's context
-+ *
-+ * The DTrace framework is locked in such a way that it may not be called
-+ * back into at all. mod_lock is held. cpu_lock is not held, and may not be
-+ * acquired.
-+ *
-+ * 1.12 void dtps_destroy_module(void *arg, struct modctl *mp)
-+ *
-+ * 1.12.1 Overview
-+ *
-+ * Called to notify provider that it can remove any per-module data.
-+ *
-+ * 1.12.2 Arguments and notes
-+ *
-+ * The first argument is the cookie as passed to dtrace_register(). The
-+ * second argument is a pointer to a struct module structure that points to
-+ * the module for which data may be cleared.
-+ *
-+ * 1.12.3 Return value
-+ *
-+ * None.
-+ *
-+ *
-+ * 2 Provider-to-Framework API
-+ *
-+ * 2.1 Overview
-+ *
-+ * The Provider-to-Framework API provides the mechanism for the provider to
-+ * register itself with the DTrace framework, to create probes, to lookup
-+ * probes and (most importantly) to fire probes. The Provider-to-Framework
-+ * consists of:
-+ *
-+ * dtrace_register() <-- Register a provider with the DTrace framework
-+ * dtrace_unregister() <-- Remove a provider's DTrace registration
-+ * dtrace_meta_register() <-- Register a metaprovider with the DTrace framework
-+ * dtrace_meta_unregister()<-- Remove a metaprovider's DTrace registration
-+ * dtrace_invalidate() <-- Invalidate the specified provider
-+ * dtrace_condense() <-- Remove a provider's unenabled probes
-+ * dtrace_attached() <-- Indicates whether or not DTrace has attached
-+ * dtrace_probe_create() <-- Create a DTrace probe
-+ * dtrace_probe_lookup() <-- Lookup a DTrace probe based on its name
-+ * dtrace_probe_arg() <-- Return the probe argument for a specific probe
-+ * dtrace_probe() <-- Fire the specified probe
-+ *
-+ * 2.2 int dtrace_register(const char *name, const struct dtrace_pattr *pap,
-+ * uint32_t priv, struct cred *cr, const struct dtrace_pops *pops,
-+ * void *arg, dtrace_provider_id_t *idp)
-+ *
-+ * 2.2.1 Overview
-+ *
-+ * dtrace_register() registers the calling provider with the DTrace
-+ * framework. It should generally be called by DTrace providers in their
-+ * attach(9E) entry point.
-+ *
-+ * 2.2.2 Arguments and Notes
-+ *
-+ * The first argument is the name of the provider. The second argument is a
-+ * pointer to the stability attributes for the provider. The third argument
-+ * is the privilege flags for the provider, and must be some combination of:
-+ *
-+ * DTRACE_PRIV_NONE <= All users may enable probes from this provider
-+ *
-+ * DTRACE_PRIV_PROC <= Any user with privilege of PRIV_DTRACE_PROC may
-+ * enable probes from this provider
-+ *
-+ * DTRACE_PRIV_USER <= Any user with privilege of PRIV_DTRACE_USER may
-+ * enable probes from this provider
-+ *
-+ * DTRACE_PRIV_KERNEL <= Any user with privilege of PRIV_DTRACE_KERNEL
-+ * may enable probes from this provider
-+ *
-+ * DTRACE_PRIV_OWNER <= This flag places an additional constraint on
-+ * the privilege requirements above. These probes
-+ * require either (a) a user ID matching the user
-+ * ID of the cred passed in the fourth argument
-+ * or (b) the PRIV_PROC_OWNER privilege.
-+ *
-+ * Note that these flags designate the _visibility_ of the probes, not
-+ * the conditions under which they may or may not fire.
-+ *
-+ * The fourth argument is the credential that is associated with the provider.
-+ * This argument should be NULL if the privilege flags don't include
-+ * DTRACE_PRIV_OWNER. If non-NULL, the framework stashes the uid represented
-+ * by this credential for use at probe-time, in implicit predicates. These
-+ * limit visibility of the probes to users which have sufficient privilege to
-+ * access them.
-+ *
-+ * The fifth argument is a DTrace provider operations vector, which provides
-+ * the implementation for the Framework-to-Provider API. (See Section 1,
-+ * above.) This must be non-NULL, and each member must be non-NULL. The
-+ * exceptions to this are (1) the dtps_provide() and dtps_provide_module()
-+ * members (if the provider so desires, _one_ of these members may be left
-+ * NULL -- denoting that the provider only implements the other) and (2)
-+ * the dtps_suspend() and dtps_resume() members, which must either both be
-+ * NULL or both be non-NULL.
-+ *
-+ * The sixth argument is a cookie to be specified as the first argument for
-+ * each function in the Framework-to-Provider API. This argument may have
-+ * any value.
-+ *
-+ * The final argument is a pointer to dtrace_provider_id_t. If
-+ * dtrace_register() successfully completes, the provider identifier will be
-+ * stored in the memory pointed to be this argument. This argument must be
-+ * non-NULL.
-+ *
-+ * 2.2.3 Return value
-+ *
-+ * On success, dtrace_register() returns 0 and stores the new provider's
-+ * identifier into the memory pointed to by the idp argument. On failure,
-+ * dtrace_register() returns an errno:
-+ *
-+ * EINVAL The arguments passed to dtrace_register() were somehow invalid.
-+ * This may because a parameter that must be non-NULL was NULL,
-+ * because the name was invalid (either empty or an illegal
-+ * provider name) or because the attributes were invalid.
-+ *
-+ * No other failure code is returned.
-+ *
-+ * 2.2.4 Caller's context
-+ *
-+ * dtrace_register() may induce calls to dtrace_provide(); the provider must
-+ * hold no locks across dtrace_register() that may also be acquired by
-+ * dtrace_provide(). cpu_lock and mod_lock must not be held.
-+ *
-+ * 2.3 int dtrace_unregister(dtrace_provider_id_t id)
-+ *
-+ * 2.3.1 Overview
-+ *
-+ * Unregisters the specified provider from the DTrace framework. It should
-+ * generally be called by DTrace providers in their detach(9E) entry point.
-+ *
-+ * 2.3.2 Arguments and Notes
-+ *
-+ * The only argument is the provider identifier, as returned from a
-+ * successful call to dtrace_register(). As a result of calling
-+ * dtrace_unregister(), the DTrace framework will call back into the provider
-+ * via the dtps_destroy() entry point. Once dtrace_unregister() successfully
-+ * completes, however, the DTrace framework will no longer make calls through
-+ * the Framework-to-Provider API.
-+ *
-+ * 2.3.3 Return value
-+ *
-+ * On success, dtrace_unregister returns 0. On failure, dtrace_unregister()
-+ * returns an errno:
-+ *
-+ * EBUSY There are currently processes that have the DTrace pseudodevice
-+ * open, or there exists an anonymous enabling that hasn't yet
-+ * been claimed.
-+ *
-+ * No other failure code is returned.
-+ *
-+ * 2.3.4 Caller's context
-+ *
-+ * Because a call to dtrace_unregister() may induce calls through the
-+ * Framework-to-Provider API, the caller may not hold any lock across
-+ * dtrace_register() that is also acquired in any of the Framework-to-
-+ * Provider API functions. Additionally, mod_lock may not be held.
-+ *
-+ * 2.4 void dtrace_invalidate(dtrace_provider_id_t id)
-+ *
-+ * 2.4.1 Overview
-+ *
-+ * Invalidates the specified provider. All subsequent probe lookups for the
-+ * specified provider will fail, but its probes will not be removed.
-+ *
-+ * 2.4.2 Arguments and note
-+ *
-+ * The only argument is the provider identifier, as returned from a
-+ * successful call to dtrace_register(). In general, a provider's probes
-+ * always remain valid; dtrace_invalidate() is a mechanism for invalidating
-+ * an entire provider, regardless of whether or not probes are enabled or
-+ * not. Note that dtrace_invalidate() will _not_ prevent already enabled
-+ * probes from firing -- it will merely prevent any new enablings of the
-+ * provider's probes.
-+ *
-+ * 2.5 int dtrace_condense(dtrace_provider_id_t id)
-+ *
-+ * 2.5.1 Overview
-+ *
-+ * Removes all the unenabled probes for the given provider. This function is
-+ * not unlike dtrace_unregister(), except that it doesn't remove the
-+ * provider just as many of its associated probes as it can.
-+ *
-+ * 2.5.2 Arguments and Notes
-+ *
-+ * As with dtrace_unregister(), the sole argument is the provider identifier
-+ * as returned from a successful call to dtrace_register(). As a result of
-+ * calling dtrace_condense(), the DTrace framework will call back into the
-+ * given provider's dtps_destroy() entry point for each of the provider's
-+ * unenabled probes.
-+ *
-+ * 2.5.3 Return value
-+ *
-+ * Currently, dtrace_condense() always returns 0. However, consumers of this
-+ * function should check the return value as appropriate; its behavior may
-+ * change in the future.
-+ *
-+ * 2.5.4 Caller's context
-+ *
-+ * As with dtrace_unregister(), the caller may not hold any lock across
-+ * dtrace_condense() that is also acquired in the provider's entry points.
-+ * Also, mod_lock may not be held.
-+ *
-+ * 2.6 int dtrace_attached()
-+ *
-+ * 2.6.1 Overview
-+ *
-+ * Indicates whether or not DTrace has attached.
-+ *
-+ * 2.6.2 Arguments and Notes
-+ *
-+ * For most providers, DTrace makes initial contact beyond registration.
-+ * That is, once a provider has registered with DTrace, it waits to hear
-+ * from DTrace to create probes. However, some providers may wish to
-+ * proactively create probes without first being told by DTrace to do so.
-+ * If providers wish to do this, they must first call dtrace_attached() to
-+ * determine if DTrace itself has attached. If dtrace_attached() returns 0,
-+ * the provider must not make any other Provider-to-Framework API call.
-+ *
-+ * 2.6.3 Return value
-+ *
-+ * dtrace_attached() returns 1 if DTrace has attached, 0 otherwise.
-+ *
-+ * 2.7 int dtrace_probe_create(dtrace_provider_id_t id, const char *mod,
-+ * const char *func, const char *name, int aframes, void *arg)
-+ *
-+ * 2.7.1 Overview
-+ *
-+ * Creates a probe with specified module name, function name, and name.
-+ *
-+ * 2.7.2 Arguments and Notes
-+ *
-+ * The first argument is the provider identifier, as returned from a
-+ * successful call to dtrace_register(). The second, third, and fourth
-+ * arguments are the module name, function name, and probe name,
-+ * respectively. Of these, module name and function name may both be NULL
-+ * (in which case the probe is considered to be unanchored), or they may both
-+ * be non-NULL. The name must be non-NULL, and must point to a non-empty
-+ * string.
-+ *
-+ * The fifth argument is the number of artificial stack frames that will be
-+ * found on the stack when dtrace_probe() is called for the new probe. These
-+ * artificial frames will be automatically be pruned should the stack() or
-+ * stackdepth() functions be called as part of one of the probe's ECBs. If
-+ * the parameter doesn't add an artificial frame, this parameter should be
-+ * zero.
-+ *
-+ * The final argument is a probe argument that will be passed back to the
-+ * provider when a probe-specific operation is called. (e.g., via
-+ * dtps_enable(), dtps_disable(), etc.)
-+ *
-+ * Note that it is up to the provider to be sure that the probe that it
-+ * creates does not already exist -- if the provider is unsure of the probe's
-+ * existence, it should assure its absence with dtrace_probe_lookup() before
-+ * calling dtrace_probe_create().
-+ *
-+ * 2.7.3 Return value
-+ *
-+ * dtrace_probe_create() always succeeds, and always returns the identifier
-+ * of the newly-created probe.
-+ *
-+ * 2.7.4 Caller's context
-+ *
-+ * While dtrace_probe_create() is generally expected to be called from
-+ * dtps_provide() and/or dtps_provide_module(), it may be called from other
-+ * non-DTrace contexts. Neither cpu_lock nor mod_lock may be held.
-+ *
-+ * 2.8 dtrace_id_t dtrace_probe_lookup(dtrace_provider_id_t id,
-+ * const char *mod, const char *func, const char *name)
-+ *
-+ * 2.8.1 Overview
-+ *
-+ * Looks up a probe based on provdider and one or more of module name,
-+ * function name and probe name.
-+ *
-+ * 2.8.2 Arguments and Notes
-+ *
-+ * The first argument is the provider identifier, as returned from a
-+ * successful call to dtrace_register(). The second, third, and fourth
-+ * arguments are the module name, function name, and probe name,
-+ * respectively. Any of these may be NULL; dtrace_probe_lookup() will return
-+ * the identifier of the first probe that is provided by the specified
-+ * provider and matches all of the non-NULL matching criteria.
-+ * dtrace_probe_lookup() is generally used by a provider to be check the
-+ * existence of a probe before creating it with dtrace_probe_create().
-+ *
-+ * 2.8.3 Return value
-+ *
-+ * If the probe exists, returns its identifier. If the probe does not exist,
-+ * return DTRACE_IDNONE.
-+ *
-+ * 2.8.4 Caller's context
-+ *
-+ * While dtrace_probe_lookup() is generally expected to be called from
-+ * dtps_provide() and/or dtps_provide_module(), it may also be called from
-+ * other non-DTrace contexts. Neither cpu_lock nor mod_lock may be held.
-+ *
-+ * 2.9 void *dtrace_probe_arg(dtrace_provider_id_t id, dtrace_id_t probe)
-+ *
-+ * 2.9.1 Overview
-+ *
-+ * Returns the probe argument associated with the specified probe.
-+ *
-+ * 2.9.2 Arguments and Notes
-+ *
-+ * The first argument is the provider identifier, as returned from a
-+ * successful call to dtrace_register(). The second argument is a probe
-+ * identifier, as returned from dtrace_probe_lookup() or
-+ * dtrace_probe_create(). This is useful if a probe has multiple
-+ * provider-specific components to it: the provider can create the probe
-+ * once with provider-specific state, and then add to the state by looking
-+ * up the probe based on probe identifier.
-+ *
-+ * 2.9.3 Return value
-+ *
-+ * Returns the argument associated with the specified probe. If the
-+ * specified probe does not exist, or if the specified probe is not provided
-+ * by the specified provider, NULL is returned.
-+ *
-+ * 2.9.4 Caller's context
-+ *
-+ * While dtrace_probe_arg() is generally expected to be called from
-+ * dtps_provide() and/or dtps_provide_module(), it may also be called from
-+ * other non-DTrace contexts. Neither cpu_lock nor mod_lock may be held.
-+ *
-+ * 2.10 void dtrace_probe(dtrace_id_t probe, uintptr_t arg0, uintptr_t arg1,
-+ * uintptr_t arg2, uintptr_t arg3, uintptr_t arg4)
-+ *
-+ * 2.10.1 Overview
-+ *
-+ * The epicenter of DTrace: fires the specified probes with the specified
-+ * arguments.
-+ *
-+ * 2.10.2 Arguments and Notes
-+ *
-+ * The first argument is a probe identifier as returned by
-+ * dtrace_probe_create() or dtrace_probe_lookup(). The second through sixth
-+ * arguments are the values to which the D variables "arg0" through "arg4"
-+ * will be mapped.
-+ *
-+ * dtrace_probe() should be called whenever the specified probe has fired --
-+ * however the provider defines it.
-+ *
-+ * 2.10.3 Return value
-+ *
-+ * None.
-+ *
-+ * 2.10.4 Caller's context
-+ *
-+ * dtrace_probe() may be called in virtually any context: kernel, user,
-+ * interrupt, high-level interrupt, with arbitrary adaptive locks held, with
-+ * dispatcher locks held, with interrupts disabled, etc. The only latitude
-+ * that must be afforded to DTrace is the ability to make calls within
-+ * itself (and to its in-kernel subroutines) and the ability to access
-+ * arbitrary (but mapped) memory. On some platforms, this constrains
-+ * context. For example, on UltraSPARC, dtrace_probe() cannot be called
-+ * from any context in which TL is greater than zero. dtrace_probe() may
-+ * also not be called from any routine which may be called by dtrace_probe()
-+ * -- which includes functions in the DTrace framework and some in-kernel
-+ * DTrace subroutines. All such functions "dtrace_"; providers that
-+ * instrument the kernel arbitrarily should be sure to not instrument these
-+ * routines.
-+ */
-+
-+#include <dtrace/types.h>
-+#include <linux/cred.h>
-+#include <linux/module.h>
-+#include <linux/dtrace/enabling_defines.h>
-+#include <linux/dtrace/arg_defines.h>
-+#include <dtrace/provider_defines.h>
-+#include <linux/dtrace/stability.h>
-+
-+struct dtrace_pops {
-+ void (*dtps_provide)(void *, const struct dtrace_probedesc *);
-+ void (*dtps_provide_module)(void *, struct module *);
-+ int (*dtps_enable)(void *, dtrace_id_t, void *);
-+ void (*dtps_disable)(void *, dtrace_id_t, void *);
-+ void (*dtps_suspend)(void *, dtrace_id_t, void *);
-+ void (*dtps_resume)(void *, dtrace_id_t, void *);
-+ void (*dtps_getargdesc)(void *, dtrace_id_t, void *,
-+ struct dtrace_argdesc *);
-+ uint64_t (*dtps_getargval)(void *, dtrace_id_t, void *, int, int);
-+ int (*dtps_usermode)(void *, dtrace_id_t, void *);
-+ void (*dtps_destroy)(void *, dtrace_id_t, void *);
-+ void (*dtps_destroy_module)(void *, struct module *);
-+};
-+
-+struct dtrace_helper_probedesc {
-+ char *dthpb_mod;
-+ char *dthpb_func;
-+ char *dthpb_name;
-+ uint64_t dthpb_base;
-+ uint32_t *dthpb_offs;
-+ uint32_t *dthpb_enoffs;
-+ uint32_t dthpb_noffs;
-+ uint32_t dthpb_nenoffs;
-+ uint8_t *dthpb_args;
-+ uint8_t dthpb_xargc;
-+ uint8_t dthpb_nargc;
-+ char *dthpb_xtypes;
-+ char *dthpb_ntypes;
-+};
-+
-+struct dtrace_helper_provdesc {
-+ char *dthpv_provname;
-+ struct dtrace_pattr dthpv_pattr;
-+};
-+
-+struct dtrace_mops {
-+ void (*dtms_create_probe)(void *, void *,
-+ struct dtrace_helper_probedesc *);
-+ void *(*dtms_provide_pid)(void *, struct dtrace_helper_provdesc *,
-+ pid_t);
-+ void (*dtms_remove_pid)(void *, struct dtrace_helper_provdesc *,
-+ pid_t);
-+};
-+
-+/*
-+ * DTrace Provider-to-Framework API Functions
-+ */
-+
-+struct dtrace_meta {
-+ struct dtrace_mops dtm_mops;
-+ char *dtm_name;
-+ void *dtm_arg;
-+ uint64_t dtm_count;
-+};
-+
-+struct dtrace_mprovider {
-+ char *dtmp_name;
-+ char *dtmp_pref;
-+ struct dtrace_pattr *dtmp_attr;
-+ uint32_t dtmp_priv;
-+ struct dtrace_pops *dtmp_pops;
-+ dtrace_provider_id_t dtmp_id;
-+};
-+
-+struct dtrace_pmod {
-+ struct module *mod;
-+ struct list_head list;
-+};
-+
-+extern int dtrace_register(const char *, const struct dtrace_pattr *,
-+ uint32_t, const struct cred *,
-+ const struct dtrace_pops *, void *,
-+ dtrace_provider_id_t *);
-+extern int dtrace_unregister(dtrace_provider_id_t);
-+extern void dtrace_invalidate(dtrace_provider_id_t);
-+extern int dtrace_condense(dtrace_provider_id_t);
-+extern int dtrace_attached(void);
-+
-+extern int dtrace_meta_register(const char *, const struct dtrace_mops *,
-+ void *, dtrace_meta_provider_id_t *);
-+extern int dtrace_meta_unregister(dtrace_meta_provider_id_t);
-+
-+extern dtrace_id_t dtrace_probe_create(dtrace_provider_id_t, const char *,
-+ const char *, const char *, int,
-+ void *);
-+extern void *dtrace_probe_arg(dtrace_provider_id_t, dtrace_id_t);
-+extern dtrace_id_t dtrace_probe_lookup(dtrace_provider_id_t, const char *,
-+ const char *, const char *);
-+extern void dtrace_probe(dtrace_id_t, uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t, uintptr_t);
-+
-+/*
-+ * Provider creation.
-+ */
-+#ifdef DTRACE_HAVE_PROV_EXIT
-+# define DT_PROV_EXIT(name) \
-+ extern int name##_prov_exit(void);
-+#else
-+# define DT_PROV_EXIT(name) \
-+ static int name##_prov_exit(void) \
-+ { \
-+ return (dtrace_unregister(name##_id) == 0); \
-+ }
-+#endif
-+
-+#define DT_PROVIDER_MODULE(name, priv) \
-+ dtrace_provider_id_t name##_id = DTRACE_PROVNONE; \
-+ \
-+ DT_PROV_EXIT(name) \
-+ \
-+ static int __init name##_init(void) \
-+ { \
-+ int ret = -ENOMEM; \
-+ struct dtrace_module *pdata = THIS_MODULE->pdata; \
-+ \
-+ if (pdata == NULL) \
-+ goto failed; \
-+ \
-+ ret = name##_dev_init(); \
-+ if (ret) \
-+ goto failed; \
-+ \
-+ ret = dtrace_register(__stringify(name), &name##_attr, priv, \
-+ NULL, &name##_pops, NULL, &name##_id); \
-+ if (ret) \
-+ goto failed; \
-+ \
-+ pdata->prov_exit = name##_prov_exit; \
-+ \
-+ return 0; \
-+ \
-+ failed: \
-+ return ret; \
-+ } \
-+ \
-+ static void __exit name##_exit(void) \
-+ { \
-+ name##_dev_exit(); \
-+ } \
-+ \
-+ module_init(name##_init); \
-+ module_exit(name##_exit);
-+
-+#ifdef DTRACE_HAVE_PROV_EXIT
-+# define DT_META_PROV_EXIT(name) \
-+ extern int name##_prov_exit(void);
-+#else
-+# define DT_META_PROV_EXIT(name) \
-+ static int name##_prov_exit(void) \
-+ { \
-+ return (dtrace_meta_unregister(name##_id) == 0); \
-+ }
-+#endif
-+
-+#define DT_META_PROVIDER_MODULE(name) \
-+ dtrace_meta_provider_id_t name##_id = DTRACE_METAPROVNONE; \
-+ \
-+ DT_META_PROV_EXIT(name) \
-+ \
-+ static int __init name##_init(void) \
-+ { \
-+ int ret = -ENOMEM; \
-+ struct dtrace_module *pdata = THIS_MODULE->pdata; \
-+ \
-+ if (pdata == NULL) \
-+ goto failed; \
-+ \
-+ ret = name##_dev_init(); \
-+ if (ret) \
-+ goto failed; \
-+ \
-+ ret = dtrace_meta_register(__stringify(name), &name##_mops, \
-+ NULL, &name##_id); \
-+ if (ret) \
-+ goto failed; \
-+ \
-+ pdata->prov_exit = name##_prov_exit; \
-+ \
-+ return 0; \
-+ \
-+ failed: \
-+ return ret; \
-+ } \
-+ \
-+ static void __exit name##_exit(void) \
-+ { \
-+ name##_dev_exit(); \
-+ } \
-+ \
-+ module_init(name##_init); \
-+ module_exit(name##_exit);
-+
-+#define DT_MULTI_PROVIDER_MODULE(name, plist) \
-+ static int name##_prov_exit(void) \
-+ { \
-+ int ret = 0; \
-+ struct dtrace_mprovider *prov; \
-+ \
-+ for (prov = plist; prov->dtmp_name != NULL; prov++) { \
-+ if (prov->dtmp_id != DTRACE_PROVNONE) { \
-+ ret = dtrace_unregister(prov->dtmp_id); \
-+ if (ret != 0) { \
-+ pr_warn("Failed to unregister " \
-+ "provider %s: %d", \
-+ prov->dtmp_name, ret); \
-+ break; \
-+ } \
-+ \
-+ prov->dtmp_id = DTRACE_PROVNONE; \
-+ } \
-+ } \
-+ \
-+ return (ret == 0); \
-+ } \
-+ \
-+ static int __init name##_init(void) \
-+ { \
-+ int ret = -ENOMEM; \
-+ struct dtrace_mprovider *prov; \
-+ struct dtrace_module *pdata = THIS_MODULE->pdata; \
-+ \
-+ if (pdata == NULL) \
-+ goto failed; \
-+ \
-+ ret = name##_dev_init(); \
-+ if (ret) \
-+ goto failed; \
-+ \
-+ for (prov = plist; prov->dtmp_name != NULL; prov++) { \
-+ if (dtrace_register(prov->dtmp_name, prov->dtmp_attr, \
-+ prov->dtmp_priv, NULL, \
-+ prov->dtmp_pops, prov, \
-+ &prov->dtmp_id) != 0) \
-+ pr_warn("Failed to register provider %s", \
-+ prov->dtmp_name); \
-+ } \
-+ \
-+ pdata->prov_exit = name##_prov_exit; \
-+ \
-+ return 0; \
-+ \
-+ failed: \
-+ return ret; \
-+ } \
-+ \
-+ static void __exit name##_exit(void) \
-+ { \
-+ name##_dev_exit(); \
-+ } \
-+ \
-+ module_init(name##_init); \
-+ module_exit(name##_exit);
-+
-+
-+#endif /* _DTRACE_PROVIDER_H */
-diff --git a/include/dtrace/provider_defines.h b/include/dtrace/provider_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..104514e1261be3e7803e84f6276b01d42186b67f
---- /dev/null
-+++ b/include/dtrace/provider_defines.h
-@@ -0,0 +1,41 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Provider defines
-+ *
-+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _DTRACE_PROVIDER_DEFINES_H
-+#define _DTRACE_PROVIDER_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/in6.h>
-+
-+typedef uintptr_t dtrace_provider_id_t;
-+typedef uintptr_t dtrace_meta_provider_id_t;
-+typedef __be32 ipaddr_t;
-+typedef ipaddr_t *ipaddr_t_p;
-+typedef struct in6_addr in6_addr_t;
-+
-+struct dtrace_pops;
-+struct dtrace_helper_probedesc;
-+struct dtrace_helper_provdesc;
-+struct dtrace_mops;
-+struct dtrace_meta;
-+
-+#endif /* _DTRACE_PROVIDER_DEFINES_H */
-diff --git a/include/dtrace/types.h b/include/dtrace/types.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..7f8d0d7efcc7b9552d75935233572c4de8fe0532
---- /dev/null
-+++ b/include/dtrace/types.h
-@@ -0,0 +1,131 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Kernel Types
-+ *
-+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _DTRACE_TYPES_H
-+#define _DTRACE_TYPES_H
-+
-+/*
-+ * This file contains types needed to parse the DTrace shared userspace/ kernel
-+ * headers, and a few others (it has not been gardened to remove constants used
-+ * only by the DTrace core). Userspace has its own version of these types
-+ * (mostly from <unistd.h>).
-+ *
-+ * This file is compiled both in a normal kernel environment and in a peculiar
-+ * halfway-house environment used for headers_checking of <ioctl.h>, in which
-+ * among other things, no config.h symbols are available. As a result, you
-+ * should be careful about #including kernel headers here: many will break
-+ * headers_check if added. So far, it has always been sufficient to add them to
-+ * dtrace/dtrace.h instead; if this turns out to be insufficient later (perhaps
-+ * because DTrace core files cease to #include all of <dtrace.h>), the
-+ * HEADERS_CHECK #define may prove useful to disable kernel-only portions of
-+ * this file.
-+ */
-+
-+#include <asm/bitsperlong.h>
-+#include <linux/dtrace_os.h>
-+
-+typedef unsigned char uchar_t;
-+typedef unsigned int uint_t;
-+typedef unsigned long ulong_t;
-+
-+typedef long intptr_t;
-+
-+#define UINT8_MAX (0xff)
-+#define UINT8_MIN 0
-+#define UINT16_MAX (0xffff)
-+#define UINT16_MIN 0
-+#define UINT32_MAX (0xffffffff)
-+#define UINT32_MIN 0
-+#define UINT64_MAX (~0ULL)
-+#define UINT64_MIN (0)
-+#define INT64_MAX ((long long)(~0ULL>>1))
-+#define INT64_MIN (-INT64_MAX - 1LL)
-+
-+#define NBBY (__BITS_PER_LONG / sizeof(long))
-+
-+/*
-+ * This is a bit unusual, but OpenSolaris seems to like it. Basically, the
-+ * values below are the number of time units (sec, milli, micro, nano) that
-+ * comprise 1 second. As such, it is the value of the respective multiplier.
-+ */
-+#define SEC 1
-+#define MILLISEC 1000
-+#define MICROSEC 1000000
-+#define NANOSEC 1000000000
-+
-+typedef enum {
-+ TRUE = -1,
-+ FALSE = 0
-+} boolean_t;
-+
-+
-+#define DTRACE_ACCESS_KERNEL 0x1
-+
-+#define DTRACE_CRA_PROC 0x0001
-+#define DTRACE_CRA_PROC_CONTROL 0x0002
-+#define DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER 0x0004
-+#define DTRACE_CRA_PROC_DESTRUCTIVE_CREDCHG 0x0010
-+#define DTRACE_CRA_KERNEL 0x0020
-+#define DTRACE_CRA_KERNEL_DESTRUCTIVE 0x0040
-+
-+#define DTRACE_CRA_ALL (DTRACE_CRA_PROC | \
-+ DTRACE_CRA_PROC_CONTROL | \
-+ DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER | \
-+ DTRACE_CRA_PROC_DESTRUCTIVE_CREDCHG | \
-+ DTRACE_CRA_KERNEL | \
-+ DTRACE_CRA_KERNEL_DESTRUCTIVE)
-+
-+#define DTRACE_CRV_ALLPROC 0x01
-+#define DTRACE_CRV_KERNEL 0x02
-+#define DTRACE_CRV_ALL (DTRACE_CRV_ALLPROC | DTRACE_CRV_KERNEL)
-+
-+#define DTRACE_MATCH_FAIL -1
-+#define DTRACE_MATCH_NEXT 0
-+#define DTRACE_MATCH_DONE 1
-+
-+#define DTRACE_COND_OWNER 0x01
-+#define DTRACE_COND_USERMODE 0x02
-+
-+#define P2ROUNDUP(x, a) (-(-(x) & -(a)))
-+
-+#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)
-+#define KTIME_INIT(s, ns) ((s64)(s) * NSEC_PER_SEC + (s64)(ns))
-+#else
-+# define KTIME_INIT(n, ns) { .sec = (s), .nsec = (ns) }
-+#endif
-+#define ktime_lt(t0, t1) (t0 < t1)
-+#define ktime_le(t0, t1) (t0 <= t1)
-+#define ktime_ge(t0, t1) (t0 >= t1)
-+#define ktime_gt(t0, t1) (t0 > t1)
-+#define ktime_cp(t0, t1) (t0 = t1)
-+
-+/*
-+ * Translate between kernel config options and userspace-compatible definitions.
-+ */
-+#ifdef CONFIG_64BIT
-+#define _LP64 1
-+#endif
-+#ifdef __LITTLE_ENDIAN
-+#define _LITTLE_ENDIAN 1
-+#endif
-+
-+#endif /* _DTRACE_TYPES_H */
-diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
-index bc56287a1ed1395059df7236e6bacdcb2af5d72c..25e7b8778b714ab95962bbe2b5e8b76ecae6bcbc 100644
---- a/include/linux/cpuhotplug.h
-+++ b/include/linux/cpuhotplug.h
-@@ -107,6 +107,7 @@ enum cpuhp_state {
- CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
- CPUHP_AP_ARM_MVEBU_COHERENCY,
- CPUHP_AP_MICROCODE_LOADER,
-+ CPUHP_AP_CYCLIC_STARTING,
- CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
- CPUHP_AP_PERF_X86_STARTING,
- CPUHP_AP_PERF_X86_AMD_IBS_STARTING,
-diff --git a/include/linux/cyclic.h b/include/linux/cyclic.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..12ab85dc185b556ba71f0993937bcb00413dcbfe
---- /dev/null
-+++ b/include/linux/cyclic.h
-@@ -0,0 +1,49 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _CYCLIC_H_
-+#define _CYCLIC_H_
-+
-+#include <linux/ktime.h>
-+#include <linux/types.h>
-+
-+#define CY_LOW_LEVEL 0
-+#define CY_LOCK_LEVEL 1
-+#define CY_HIGH_LEVEL 2
-+#define CY_SOFT_LEVELS 2
-+#define CY_LEVELS 3
-+
-+typedef uintptr_t cyclic_id_t;
-+typedef uint16_t cyc_level_t;
-+typedef void (*cyc_func_t)(uintptr_t);
-+
-+#define CYCLIC_NONE ((cyclic_id_t)0)
-+
-+struct cyc_handler {
-+ cyc_func_t cyh_func;
-+ uintptr_t cyh_arg;
-+ cyc_level_t cyh_level;
-+};
-+
-+#define CY_INTERVAL_INF (-1)
-+
-+struct cyc_time {
-+ ktime_t cyt_when;
-+ ktime_t cyt_interval;
-+};
-+
-+struct cyc_omni_handler {
-+ void (*cyo_online)(void *, uint32_t, struct cyc_handler *,
-+ struct cyc_time *);
-+ void (*cyo_offline)(void *, uint32_t, void *);
-+ void *cyo_arg;
-+};
-+
-+extern cyclic_id_t cyclic_add(struct cyc_handler *, struct cyc_time *);
-+extern cyclic_id_t cyclic_add_omni(struct cyc_omni_handler *);
-+extern void cyclic_remove(cyclic_id_t);
-+extern void cyclic_reprogram(cyclic_id_t, ktime_t);
-+
-+#endif /* _CYCLIC_H_ */
-diff --git a/include/linux/dtrace/cpu_defines.h b/include/linux/dtrace/cpu_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..c8719378da80dd9293e92abe4713ab395b3b6db1
---- /dev/null
-+++ b/include/linux/dtrace/cpu_defines.h
-@@ -0,0 +1,61 @@
-+/* Copyright (C) 2011-2014 Oracle, Inc. */
-+
-+#ifndef _LINUX_DTRACE_CPU_DEFINES_H_
-+#define _LINUX_DTRACE_CPU_DEFINES_H_
-+
-+#include <linux/percpu.h>
-+
-+#define CPUC_SIZE (sizeof (uint16_t) + sizeof(uint8_t) + \
-+ sizeof(uintptr_t) + sizeof(struct mutex))
-+#define CPUC_PADSIZE (192 - CPUC_SIZE)
-+
-+#define per_cpu_core(cpu) (&per_cpu(dtrace_cpu_core, (cpu)))
-+#if 0
-+# define this_cpu_core (this_cpu_ptr(&dtrace_cpu_core))
-+#else
-+# define this_cpu_core (per_cpu_core(smp_processor_id()))
-+#endif
-+
-+#define DTRACE_CPUFLAG_ISSET(flag) \
-+ (this_cpu_core->cpuc_dtrace_flags & (flag))
-+
-+#define DTRACE_CPUFLAG_SET(flag) \
-+ (this_cpu_core->cpuc_dtrace_flags |= (flag))
-+
-+#define DTRACE_CPUFLAG_CLEAR(flag) \
-+ (this_cpu_core->cpuc_dtrace_flags &= ~(flag))
-+
-+#define CPU_DTRACE_NOFAULT 0x0001
-+#define CPU_DTRACE_DROP 0x0002
-+#define CPU_DTRACE_BADADDR 0x0004
-+#define CPU_DTRACE_BADALIGN 0x0008
-+#define CPU_DTRACE_DIVZERO 0x0010
-+#define CPU_DTRACE_ILLOP 0x0020
-+#define CPU_DTRACE_NOSCRATCH 0x0040
-+#define CPU_DTRACE_KPRIV 0x0080
-+#define CPU_DTRACE_UPRIV 0x0100
-+#define CPU_DTRACE_TUPOFLOW 0x0200
-+#define CPU_DTRACE_ENTRY 0x0800
-+#define CPU_DTRACE_BADSTACK 0x1000
-+#define CPU_DTRACE_NOPF 0x2000
-+#define CPU_DTRACE_PF_TRAPPED 0x4000
-+
-+#define CPU_DTRACE_FAULT (CPU_DTRACE_BADADDR | CPU_DTRACE_BADALIGN | \
-+ CPU_DTRACE_DIVZERO | CPU_DTRACE_ILLOP | \
-+ CPU_DTRACE_NOSCRATCH | CPU_DTRACE_KPRIV | \
-+ CPU_DTRACE_UPRIV | CPU_DTRACE_TUPOFLOW | \
-+ CPU_DTRACE_BADSTACK | CPU_DTRACE_PF_TRAPPED)
-+#define CPU_DTRACE_ERROR (CPU_DTRACE_FAULT | CPU_DTRACE_DROP)
-+
-+typedef uint32_t processorid_t;
-+typedef uint32_t psetid_t;
-+typedef uint32_t chipid_t;
-+typedef uint32_t lgrp_id_t;
-+
-+struct cpu_core;
-+struct cpuinfo;
-+
-+#define per_cpu_info(cpu) (&per_cpu(dtrace_cpu_info, (cpu)))
-+#define this_cpu_info (this_cpu_ptr(&dtrace_cpu_info))
-+
-+#endif /* _LINUX_DTRACE_CPU_DEFINES_H_ */
-diff --git a/include/linux/dtrace_cpu.h b/include/linux/dtrace_cpu.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..6b3dc7219f49d3bbadcb16a6939c1a98d520ecf2
---- /dev/null
-+++ b/include/linux/dtrace_cpu.h
-@@ -0,0 +1,53 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_CPU_H_
-+#define _LINUX_DTRACE_CPU_H_
-+
-+#ifdef CONFIG_DTRACE
-+
-+#include <linux/ktime.h>
-+#include <linux/mutex.h>
-+#include <linux/spinlock.h>
-+#include <linux/dtrace_types.h>
-+#include <linux/dtrace_cpu_defines.h>
-+#include <asm/dtrace_cpuinfo.h>
-+
-+struct cpu_core {
-+ uint16_t cpuc_dtrace_flags;
-+ uint8_t cpuc_dcpc_intr_state;
-+ uint8_t cpuc_pad[CPUC_PADSIZE];
-+ uintptr_t cpuc_dtrace_illval;
-+ struct mutex cpuc_pid_lock;
-+
-+ uintptr_t cpu_dtrace_caller;
-+ struct pt_regs *cpu_dtrace_regs;
-+ ktime_t cpu_dtrace_chillmark;
-+ ktime_t cpu_dtrace_chilled;
-+ rwlock_t cpu_ft_lock;
-+ atomic64_t cpuc_sync_requests;
-+ atomic64_t cpuc_in_probe_ctx;
-+ dtrace_id_t cpuc_current_probe;
-+};
-+
-+DECLARE_PER_CPU_SHARED_ALIGNED(struct cpu_core, dtrace_cpu_core);
-+
-+struct cpuinfo {
-+ processorid_t cpu_id;
-+ psetid_t cpu_pset;
-+ chipid_t cpu_chip;
-+ lgrp_id_t cpu_lgrp;
-+ cpuinfo_arch_t *cpu_info;
-+};
-+
-+DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo, dtrace_cpu_info);
-+
-+/* ABI requirement: type names compiled into DTrace userspace. */
-+typedef struct cpuinfo cpuinfo_t;
-+
-+extern void dtrace_cpu_init(void);
-+
-+#endif /* CONFIG_DTRACE */
-+#endif /* _LINUX_DTRACE_CPU_H_ */
-diff --git a/include/linux/dtrace_cpu_defines.h b/include/linux/dtrace_cpu_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..f5866a6e95b8e4a0e39efb926aa4357842112b0e
---- /dev/null
-+++ b/include/linux/dtrace_cpu_defines.h
-@@ -0,0 +1,2 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+#include <linux/dtrace/cpu_defines.h>
-diff --git a/include/linux/dtrace_os.h b/include/linux/dtrace_os.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..5bcd77e08a14e8502cbadb53004dbbeb711dc953
---- /dev/null
-+++ b/include/linux/dtrace_os.h
-@@ -0,0 +1,120 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_OS_H_
-+#define _LINUX_DTRACE_OS_H_
-+
-+#ifndef HEADERS_CHECK
-+
-+#ifdef CONFIG_DTRACE
-+
-+#include <linux/ktime.h>
-+#include <linux/mm.h>
-+#include <linux/notifier.h>
-+#include <linux/timekeeper_internal.h>
-+#include <asm/unistd.h>
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_task.h>
-+#include <linux/dtrace_psinfo.h>
-+
-+extern struct module *dtrace_kmod;
-+
-+extern void __init dtrace_os_init(void);
-+extern void __init dtrace_psinfo_os_init(void);
-+extern void __init dtrace_task_os_init(void);
-+
-+extern void dtrace_mod_pdata_alloc(struct module *);
-+extern void dtrace_mod_pdata_free(struct module *);
-+extern int dtrace_destroy_prov(struct module *);
-+
-+extern int dtrace_enable(void);
-+extern void dtrace_disable(void);
-+
-+extern ktime_t dtrace_gethrtime(void);
-+extern ktime_t dtrace_getwalltime(void);
-+
-+enum dtrace_vtime_state {
-+ DTRACE_VTIME_INACTIVE = 0,
-+ DTRACE_VTIME_ACTIVE
-+};
-+
-+extern enum dtrace_vtime_state dtrace_vtime_active;
-+
-+typedef void for_each_module_fn(void *, struct module *);
-+extern void dtrace_for_each_module(for_each_module_fn *fn, void *arg);
-+
-+extern void dtrace_update_time(struct timekeeper *);
-+extern ktime_t dtrace_get_walltime(void);
-+
-+extern void dtrace_vtime_enable(void);
-+extern void dtrace_vtime_disable(void);
-+extern void dtrace_vtime_switch(struct task_struct *, struct task_struct *);
-+
-+#include <asm/dtrace_util.h>
-+
-+extern int dtrace_instr_size(const asm_instr_t *);
-+
-+extern int dtrace_die_notifier(struct notifier_block *, unsigned long, void *);
-+
-+#define STACKTRACE_KERNEL 0x01
-+#define STACKTRACE_USER 0x02
-+#define STACKTRACE_TYPE 0x0f
-+
-+struct stacktrace_state {
-+ uint64_t *pcs;
-+ uint64_t *fps;
-+ int limit;
-+ int depth;
-+ int flags;
-+};
-+
-+extern void dtrace_stacktrace(struct stacktrace_state *);
-+extern void dtrace_user_stacktrace(struct stacktrace_state *);
-+extern void dtrace_handle_badaddr(struct pt_regs *);
-+extern void dtrace_mod_pdata_init(struct dtrace_module *pdata);
-+extern void dtrace_mod_pdata_cleanup(struct dtrace_module *pdata);
-+
-+/*
-+ * This is only safe to call if we know this is a userspace fault
-+ * or that the call happens after early boot.
-+ */
-+static inline int dtrace_no_pf(struct pt_regs *regs)
-+{
-+ if (unlikely(DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))) {
-+ dtrace_handle_badaddr(regs);
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+extern void (*dtrace_helpers_cleanup)(struct task_struct *);
-+extern void (*dtrace_helpers_fork)(struct task_struct *, struct task_struct *);
-+
-+#else
-+
-+/*
-+ * See arch/x86/mm/fault.c.
-+ */
-+
-+#define dtrace_no_pf(ignore) 0
-+
-+/*
-+ * See kernel/timekeeper.c
-+ */
-+#define dtrace_update_time(ignore)
-+
-+/*
-+ * See kernel/dtrace/dtrace_os.c
-+ */
-+#define dtrace_mod_pdata_alloc(ignore)
-+#define dtrace_mod_pdata_free(ignore)
-+#define dtrace_destroy_prov(ignore) 1
-+
-+#endif /* CONFIG_DTRACE */
-+
-+#endif /* !HEADERS_CHECK */
-+
-+#endif /* _LINUX_DTRACE_OS_H_ */
-diff --git a/include/linux/dtrace_psinfo.h b/include/linux/dtrace_psinfo.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..53a9c317a8a34f84927868b339904047cdf98ef1
---- /dev/null
-+++ b/include/linux/dtrace_psinfo.h
-@@ -0,0 +1,59 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_PSINFO_H_
-+#define _LINUX_DTRACE_PSINFO_H_
-+
-+#ifdef CONFIG_DTRACE
-+
-+#define PR_PSARGS_SZ 80
-+#define PR_ARGV_SZ 512
-+#define PR_ENVP_SZ 512
-+
-+/*
-+ * DTrace's per-process info (per-tgid).
-+ *
-+ * All threads in a process share the same structure instance.
-+ */
-+struct dtrace_psinfo {
-+ atomic_t dtps_usage;
-+ unsigned long dtps_argc;
-+ char **dtps_argv;
-+ unsigned long dtps_envc;
-+ char **dtps_envp;
-+ char dtps_psargs[PR_PSARGS_SZ];
-+};
-+
-+/*
-+ * DTrace psinfo API. Requires struct dtrace_task as its argument.
-+ */
-+
-+extern void dtrace_psinfo_alloc(struct task_struct *);
-+extern void dtrace_psinfo_free(struct dtrace_psinfo *);
-+
-+static inline void dtrace_psinfo_get(struct dtrace_psinfo *psinfo)
-+{
-+ if (likely(psinfo))
-+ atomic_inc(&(psinfo)->dtps_usage);
-+}
-+
-+static inline void dtrace_psinfo_put(struct dtrace_psinfo *psinfo)
-+{
-+ if (likely((psinfo))) {
-+ if (atomic_dec_and_test(&(psinfo)->dtps_usage))
-+ dtrace_psinfo_free(psinfo);
-+ }
-+}
-+
-+#else /* CONFIG_DTRACE */
-+
-+#define dtrace_psinfo_alloc(ignore)
-+#define dtrace_psinfo_free(ignore)
-+#define dtrace_psinfo_get(ignore)
-+#define dtrace_psinfo_put(ignore)
-+
-+#endif /* CONFIG_DTRACE */
-+
-+#endif /* _LINUX_DTRACE_PSINFO_H_ */
-diff --git a/include/linux/dtrace_task.h b/include/linux/dtrace_task.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..ce7111223788a8b7d0c43e96a8da6ef042263b61
---- /dev/null
-+++ b/include/linux/dtrace_task.h
-@@ -0,0 +1,38 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_TASK_H_
-+#define _LINUX_DTRACE_TASK_H_
-+
-+#ifdef CONFIG_DTRACE
-+
-+#include <linux/sched.h>
-+
-+/*
-+ * Opaque handle for per-task data.
-+ */
-+struct dtrace_task;
-+
-+/*
-+ * DTrace's kernel API for per-task data manipulation.
-+ */
-+
-+extern void dtrace_task_init(struct task_struct *);
-+extern void dtrace_task_exec(struct task_struct *);
-+extern void dtrace_task_copy(struct task_struct *, struct task_struct *);
-+extern void dtrace_task_free(struct task_struct *);
-+extern void dtrace_task_dup(struct task_struct *, struct task_struct *);
-+
-+#else /* CONFIG_DTRACE */
-+
-+#define dtrace_task_init(ignore)
-+#define dtrace_task_exec(ignore)
-+#define dtrace_task_copy(ignore1, ignore2)
-+#define dtrace_task_free(ignore)
-+#define dtrace_task_dup(ignore1, ignore2)
-+
-+#endif /* CONFIG_DTRACE */
-+
-+#endif /* _LINUX_DTRACE_TASK_H_ */
-diff --git a/include/linux/dtrace_task_impl.h b/include/linux/dtrace_task_impl.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..2f76b475c2f88822c5e5e69bab1f17364ae81a3e
---- /dev/null
-+++ b/include/linux/dtrace_task_impl.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+#ifndef _LINUX_DTRACE_TASK_IMPL_H_
-+#define _LINUX_DTRACE_TASK_IMPL_H_
-+
-+#ifdef CONFIG_DTRACE
-+
-+#include <linux/dtrace_task.h>
-+#include <linux/dtrace_psinfo.h>
-+
-+struct dtrace_task {
-+ uint32_t dt_predcache;
-+ ktime_t dt_vtime;
-+ ktime_t dt_start;
-+ uint8_t dt_stop;
-+ uint8_t dt_sig;
-+ struct dtrace_psinfo *dt_psinfo;
-+ void *dt_helpers;
-+ uint32_t dt_probes;
-+ uint64_t dt_tp_count;
-+ void *dt_ustack;
-+};
-+
-+#endif /* CONFIG_DTRACE */
-+#endif /* _LINUX_DTRACE_TASK_IMPL_H_ */
-+
-diff --git a/include/linux/dtrace_types.h b/include/linux/dtrace_types.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..4484dc58e188c0c5ffe0495b8dc351405b3f945f
---- /dev/null
-+++ b/include/linux/dtrace_types.h
-@@ -0,0 +1,13 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _DTRACE_TYPES_H_
-+#define _DTRACE_TYPES_H_
-+
-+typedef uint32_t dtrace_id_t;
-+
-+#define DTRACE_IDNONE 0
-+
-+#endif /* _DTRACE_TYPES_H_ */
-diff --git a/include/linux/ktime.h b/include/linux/ktime.h
-index a12b5523cc18e699fea0f36ca49b65dbfdfeb015..ba226005fd2ad641b70163e2d5f49753b64760d0 100644
---- a/include/linux/ktime.h
-+++ b/include/linux/ktime.h
-@@ -156,6 +156,14 @@ static inline s64 ktime_divns(const ktime_t kt, s64 div)
- }
- #endif
-
-+/*
-+ * ktime_nz - Check whether a ktime_v variable is non-zero
-+ */
-+static inline int ktime_nz(const ktime_t kt)
-+{
-+ return kt != 0LL;
-+}
-+
- static inline s64 ktime_to_us(const ktime_t kt)
- {
- return ktime_divns(kt, NSEC_PER_USEC);
-diff --git a/include/linux/module.h b/include/linux/module.h
-index d44fe50d7c7fec29c95e8b07865201410216d9d3..44915ed85337f8ef9931afaee5b78f9961ac112e 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -512,6 +512,9 @@ struct module {
- struct klp_modinfo *klp_info;
- #endif
-
-+#ifdef CONFIG_DTRACE
-+ void *pdata;
-+#endif
- #ifdef CONFIG_MODULE_UNLOAD
- /* What modules depend on me? */
- struct list_head source_list;
-diff --git a/include/linux/mutex.h b/include/linux/mutex.h
-index dcd185cbfe793b6f9d325dfabd6db87297d32383..bb18028db361585e6ed56b1b90853c006282e727 100644
---- a/include/linux/mutex.h
-+++ b/include/linux/mutex.h
-@@ -20,6 +20,10 @@
- #include <linux/osq_lock.h>
- #include <linux/debug_locks.h>
-
-+#ifdef CONFIG_SMP
-+# include <asm/current.h>
-+#endif
-+
- struct ww_acquire_ctx;
-
- /*
-@@ -224,4 +228,16 @@ enum mutex_trylock_recursive_enum {
- extern /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
- mutex_trylock_recursive(struct mutex *lock);
-
-+#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
-+static inline int mutex_owned(struct mutex *lock)
-+{
-+ return mutex_is_locked(lock) && __mutex_owner(lock) == current;
-+}
-+#else
-+static inline int mutex_owned(struct mutex *lock)
-+{
-+ return mutex_is_locked(lock);
-+}
-+#endif
-+
- #endif /* __LINUX_MUTEX_H */
-diff --git a/include/linux/rwlock.h b/include/linux/rwlock.h
-index 3dcd617e65ae902316399b0717f0dc0e834b355c..a7e72774f17eb9040d7ba0ac26c8efcf10f69087 100644
---- a/include/linux/rwlock.h
-+++ b/include/linux/rwlock.h
-@@ -59,6 +59,13 @@ do { \
- # define do_raw_write_unlock(rwlock) do {arch_write_unlock(&(rwlock)->raw_lock); __release(lock); } while (0)
- #endif
-
-+#ifdef CONFIG_DTRACE
-+#define peek_read_can_lock(rwlock) \
-+ arch_peek_read_can_lock(&(rwlock)->raw_lock)
-+#define peek_write_can_lock(rwlock) \
-+ arch_peek_write_can_lock(&(rwlock)->raw_lock)
-+#endif /* CONFIG_DTRACE */
-+
- /*
- * Define the various rw_lock methods. Note we define these
- * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
-diff --git a/include/linux/sched.h b/include/linux/sched.h
-index 76cd21fa55016e5e8ab7a09cec3d1516a18f5998..0be45d97998922eea294cb95dc269a761fda79fb 100644
---- a/include/linux/sched.h
-+++ b/include/linux/sched.h
-@@ -34,6 +34,7 @@
- #include <linux/rseq.h>
- #include <linux/seqlock.h>
- #include <linux/kcsan.h>
-+#include <linux/dtrace_task.h>
-
- /* task_struct member predeclarations (sorted alphabetically): */
- struct audit_context;
-@@ -1304,6 +1305,9 @@ struct task_struct {
- struct request_queue *throttle_queue;
- #endif
-
-+#ifdef CONFIG_DTRACE
-+ struct dtrace_task *dt_task;
-+#endif
- #ifdef CONFIG_UPROBES
- struct uprobe_task *utask;
- #endif
-diff --git a/include/linux/spinlock_up.h b/include/linux/spinlock_up.h
-index 0ac9112c1bbe3287658057098c37a67bc818c559..cfd00c13f2aa1bc08f6b7c8b79449edbdf0681b2 100644
---- a/include/linux/spinlock_up.h
-+++ b/include/linux/spinlock_up.h
-@@ -69,4 +69,9 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
-
- #define arch_spin_is_contended(lock) (((void)(lock), 0))
-
-+#ifdef CONFIG_DTRACE
-+#define arch_peek_read_can_lock(lock) (((void)(lock), 1))
-+#define arch_peek_write_can_lock(lock) (((void)(lock), 1))
-+#endif /* CONFIG_DTRACE */
-+
- #endif /* __LINUX_SPINLOCK_UP_H */
-diff --git a/include/uapi/linux/dtrace/Kbuild b/include/uapi/linux/dtrace/Kbuild
-new file mode 100644
-index 0000000000000000000000000000000000000000..0cb5b941b72b292cd03a0df30844aa9e35c5d768
---- /dev/null
-+++ b/include/uapi/linux/dtrace/Kbuild
-@@ -0,0 +1,35 @@
-+# UAPI Header export list
-+header-y += actions_defines.h
-+header-y += actions.h
-+header-y += arg_defines.h
-+header-y += arg.h
-+header-y += buffer_defines.h
-+header-y += buffer.h
-+header-y += conf_defines.h
-+header-y += conf.h
-+header-y += cpu_defines.h
-+header-y += dif_defines.h
-+header-y += dif.h
-+header-y += difo_defines.h
-+header-y += difo.h
-+header-y += dof_defines.h
-+header-y += dof.h
-+header-y += dtrace.h
-+header-y += enabling_defines.h
-+header-y += enabling.h
-+header-y += fasttrap_defines.h
-+header-y += fasttrap.h
-+header-y += fasttrap_ioctl.h
-+header-y += faults_defines.h
-+header-y += faults.h
-+header-y += helpers_defines.h
-+header-y += helpers.h
-+header-y += ioctl.h
-+header-y += metadesc_defines.h
-+header-y += metadesc.h
-+header-y += options_defines.h
-+header-y += options.h
-+header-y += stability_defines.h
-+header-y += stability.h
-+header-y += status.h
-+header-y += universal.h
-diff --git a/include/uapi/linux/dtrace/actions.h b/include/uapi/linux/dtrace/actions.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..9b47343271babcf501645d2b3c86b130987f13a1
---- /dev/null
-+++ b/include/uapi/linux/dtrace/actions.h
-@@ -0,0 +1,14 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ACTIONS_H
-+#define _LINUX_DTRACE_ACTIONS_H
-+
-+#include <linux/dtrace/actions_defines.h>
-+
-+#endif /* _LINUX_DTRACE_ACTIONS_H */
-diff --git a/include/uapi/linux/dtrace/actions_defines.h b/include/uapi/linux/dtrace/actions_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..4512c291f58a75d05fc97567137ead42092c8454
---- /dev/null
-+++ b/include/uapi/linux/dtrace/actions_defines.h
-@@ -0,0 +1,181 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ACTIONS_DEFINES_H
-+#define _LINUX_DTRACE_ACTIONS_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * The upper byte determines the class of the action; the low bytes determines
-+ * the specific action within that class. The classes of actions are as
-+ * follows:
-+ *
-+ * [ no class ] <= May record process- or kernel-related data
-+ * DTRACEACT_PROC <= Only records process-related data
-+ * DTRACEACT_PROC_DESTRUCTIVE <= Potentially destructive to processes
-+ * DTRACEACT_KERNEL <= Only records kernel-related data
-+ * DTRACEACT_KERNEL_DESTRUCTIVE <= Potentially destructive to the kernel
-+ * DTRACEACT_SPECULATIVE <= Speculation-related action
-+ * DTRACEACT_AGGREGATION <= Aggregating action
-+ */
-+#define DTRACEACT_NONE 0 /* no action */
-+#define DTRACEACT_DIFEXPR 1 /* action is DIF expression */
-+#define DTRACEACT_EXIT 2 /* exit() action */
-+#define DTRACEACT_PRINTF 3 /* printf() action */
-+#define DTRACEACT_PRINTA 4 /* printa() action */
-+#define DTRACEACT_LIBACT 5 /* library-controlled action */
-+#define DTRACEACT_TRACEMEM 6 /* tracemem() action */
-+#define DTRACEACT_PCAP 7 /* pcap() action */
-+
-+#define DTRACEACT_PROC 0x0100
-+#define DTRACEACT_USTACK (DTRACEACT_PROC + 1)
-+#define DTRACEACT_JSTACK (DTRACEACT_PROC + 2)
-+#define DTRACEACT_USYM (DTRACEACT_PROC + 3)
-+#define DTRACEACT_UMOD (DTRACEACT_PROC + 4)
-+#define DTRACEACT_UADDR (DTRACEACT_PROC + 5)
-+
-+#define DTRACEACT_PROC_DESTRUCTIVE 0x0200
-+#define DTRACEACT_STOP (DTRACEACT_PROC_DESTRUCTIVE + 1)
-+#define DTRACEACT_RAISE (DTRACEACT_PROC_DESTRUCTIVE + 2)
-+#define DTRACEACT_SYSTEM (DTRACEACT_PROC_DESTRUCTIVE + 3)
-+#define DTRACEACT_FREOPEN (DTRACEACT_PROC_DESTRUCTIVE + 4)
-+
-+#define DTRACEACT_PROC_CONTROL 0x0300
-+
-+#define DTRACEACT_KERNEL 0x0400
-+#define DTRACEACT_STACK (DTRACEACT_KERNEL + 1)
-+#define DTRACEACT_SYM (DTRACEACT_KERNEL + 2)
-+#define DTRACEACT_MOD (DTRACEACT_KERNEL + 3)
-+
-+#define DTRACEACT_KERNEL_DESTRUCTIVE 0x0500
-+#define DTRACEACT_BREAKPOINT (DTRACEACT_KERNEL_DESTRUCTIVE + 1)
-+#define DTRACEACT_PANIC (DTRACEACT_KERNEL_DESTRUCTIVE + 2)
-+#define DTRACEACT_CHILL (DTRACEACT_KERNEL_DESTRUCTIVE + 3)
-+
-+#define DTRACEACT_SPECULATIVE 0x0600
-+#define DTRACEACT_SPECULATE (DTRACEACT_SPECULATIVE + 1)
-+#define DTRACEACT_COMMIT (DTRACEACT_SPECULATIVE + 2)
-+#define DTRACEACT_DISCARD (DTRACEACT_SPECULATIVE + 3)
-+
-+#define DTRACEACT_CLASS(x) ((x) & 0xff00)
-+
-+#define DTRACEACT_ISAGG(x) \
-+ (DTRACEACT_CLASS(x) == DTRACEACT_AGGREGATION)
-+
-+#define DTRACEACT_ISDESTRUCTIVE(x) \
-+ (DTRACEACT_CLASS(x) == DTRACEACT_PROC_DESTRUCTIVE || \
-+ DTRACEACT_CLASS(x) == DTRACEACT_KERNEL_DESTRUCTIVE)
-+
-+#define DTRACEACT_ISSPECULATIVE(x) \
-+ (DTRACEACT_CLASS(x) == DTRACEACT_SPECULATIVE)
-+
-+#define DTRACEACT_ISPRINTFLIKE(x) \
-+ ((x) == DTRACEACT_PRINTF || (x) == DTRACEACT_PRINTA || \
-+ (x) == DTRACEACT_SYSTEM || (x) == DTRACEACT_FREOPEN)
-+
-+/*
-+ * DTrace Aggregating Actions
-+ *
-+ * These are functions f(x) for which the following is true:
-+ *
-+ * f(f(x_0) U f(x_1) U ... U f(x_n)) = f(x_0 U x_1 U ... U x_n)
-+ *
-+ * where x_n is a set of arbitrary data. Aggregating actions are in their own
-+ * DTrace action class, DTTRACEACT_AGGREGATION. The macros provided here allow
-+ * for easier processing of the aggregation argument and data payload for a few
-+ * aggregating actions (notably: quantize(), lquantize(), and ustack()).
-+ */
-+
-+#define DTRACEACT_AGGREGATION 0x0700
-+#define DTRACEAGG_COUNT (DTRACEACT_AGGREGATION + 1)
-+#define DTRACEAGG_MIN (DTRACEACT_AGGREGATION + 2)
-+#define DTRACEAGG_MAX (DTRACEACT_AGGREGATION + 3)
-+#define DTRACEAGG_AVG (DTRACEACT_AGGREGATION + 4)
-+#define DTRACEAGG_SUM (DTRACEACT_AGGREGATION + 5)
-+#define DTRACEAGG_STDDEV (DTRACEACT_AGGREGATION + 6)
-+#define DTRACEAGG_QUANTIZE (DTRACEACT_AGGREGATION + 7)
-+#define DTRACEAGG_LQUANTIZE (DTRACEACT_AGGREGATION + 8)
-+#define DTRACEAGG_LLQUANTIZE (DTRACEACT_AGGREGATION + 9)
-+
-+#define DTRACE_QUANTIZE_NBUCKETS \
-+ (((sizeof(uint64_t) * NBBY) - 1) * 2 + 1)
-+
-+#define DTRACE_QUANTIZE_ZEROBUCKET ((sizeof(uint64_t) * NBBY) - 1)
-+
-+#define DTRACE_QUANTIZE_BUCKETVAL(buck) \
-+ (int64_t)((buck) < DTRACE_QUANTIZE_ZEROBUCKET ? \
-+ -(1LL << (DTRACE_QUANTIZE_ZEROBUCKET - 1 - (buck))) : \
-+ (buck) == DTRACE_QUANTIZE_ZEROBUCKET ? 0 : \
-+ 1LL << ((buck) - DTRACE_QUANTIZE_ZEROBUCKET - 1))
-+
-+#define DTRACE_LQUANTIZE_STEPSHIFT 48
-+#define DTRACE_LQUANTIZE_STEPMASK ((uint64_t)UINT16_MAX << 48)
-+#define DTRACE_LQUANTIZE_LEVELSHIFT 32
-+#define DTRACE_LQUANTIZE_LEVELMASK ((uint64_t)UINT16_MAX << 32)
-+#define DTRACE_LQUANTIZE_BASESHIFT 0
-+#define DTRACE_LQUANTIZE_BASEMASK UINT32_MAX
-+
-+#define DTRACE_LQUANTIZE_STEP(x) \
-+ (uint16_t)(((x) & DTRACE_LQUANTIZE_STEPMASK) >> \
-+ DTRACE_LQUANTIZE_STEPSHIFT)
-+
-+#define DTRACE_LQUANTIZE_LEVELS(x) \
-+ (uint16_t)(((x) & DTRACE_LQUANTIZE_LEVELMASK) >> \
-+ DTRACE_LQUANTIZE_LEVELSHIFT)
-+
-+#define DTRACE_LQUANTIZE_BASE(x) \
-+ (int32_t)(((x) & DTRACE_LQUANTIZE_BASEMASK) >> \
-+ DTRACE_LQUANTIZE_BASESHIFT)
-+
-+#define DTRACE_LLQUANTIZE_STEPSSHIFT 48
-+#define DTRACE_LLQUANTIZE_STEPSMASK ((uint64_t)UINT16_MAX << 48)
-+#define DTRACE_LLQUANTIZE_HMAGSHIFT 32
-+#define DTRACE_LLQUANTIZE_HMAGMASK ((uint64_t)UINT16_MAX << 32)
-+#define DTRACE_LLQUANTIZE_LMAGSHIFT 16
-+#define DTRACE_LLQUANTIZE_LMAGMASK ((uint64_t)UINT16_MAX << 16)
-+#define DTRACE_LLQUANTIZE_FACTORSHIFT 0
-+#define DTRACE_LLQUANTIZE_FACTORMASK UINT16_MAX
-+
-+#define DTRACE_LLQUANTIZE_STEPS(x) \
-+ (uint16_t)(((x) & DTRACE_LLQUANTIZE_STEPSMASK) >> \
-+ DTRACE_LLQUANTIZE_STEPSSHIFT)
-+
-+#define DTRACE_LLQUANTIZE_HMAG(x) \
-+ (uint16_t)(((x) & DTRACE_LLQUANTIZE_HMAGMASK) >> \
-+ DTRACE_LLQUANTIZE_HMAGSHIFT)
-+
-+#define DTRACE_LLQUANTIZE_LMAG(x) \
-+ (uint16_t)(((x) & DTRACE_LLQUANTIZE_LMAGMASK) >> \
-+ DTRACE_LLQUANTIZE_LMAGSHIFT)
-+
-+#define DTRACE_LLQUANTIZE_FACTOR(x) \
-+ (uint16_t)(((x) & DTRACE_LLQUANTIZE_FACTORMASK) >> \
-+ DTRACE_LLQUANTIZE_FACTORSHIFT)
-+
-+#define DTRACE_USTACK_NFRAMES(x) (uint32_t)((x) & UINT32_MAX)
-+#define DTRACE_USTACK_STRSIZE(x) (uint32_t)((x) >> 32)
-+#define DTRACE_USTACK_ARG(x, y) \
-+ ((((uint64_t)(y)) << 32) | ((x) & UINT32_MAX))
-+
-+#ifndef _LP64
-+# ifndef _LITTLE_ENDIAN
-+# define DTRACE_PTR(type, name) uint32_t name##pad; type *name
-+# else
-+# define DTRACE_PTR(type, name) type *name; uint32_t name##pad
-+# endif
-+#else
-+# define DTRACE_PTR(type, name) type *name
-+#endif
-+
-+#endif /* _LINUX_DTRACE_ACTIONS_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/arg.h b/include/uapi/linux/dtrace/arg.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..4a9099a816e6d3576cd93eb5bccb4f2de98907c2
---- /dev/null
-+++ b/include/uapi/linux/dtrace/arg.h
-@@ -0,0 +1,42 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ARG_H
-+#define _LINUX_DTRACE_ARG_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/arg_defines.h>
-+
-+/*
-+ * Because it would waste both space and time, argument types do not reside
-+ * with the probe. In order to determine argument types for args[X]
-+ * variables, the D compiler queries for argument types on a probe-by-probe
-+ * basis. (This optimizes for the common case that arguments are either not
-+ * used or used in an untyped fashion.) Typed arguments are specified with a
-+ * string of the type name in the dtragd_native member of the argument
-+ * description structure. Typed arguments may be further translated to types
-+ * of greater stability; the provider indicates such a translated argument by
-+ * filling in the dtargd_xlate member with the string of the translated type.
-+ * Finally, the provider may indicate which argument value a given argument
-+ * maps to by setting the dtargd_mapping member -- allowing a single argument
-+ * to map to multiple args[X] variables.
-+ */
-+typedef struct dtrace_argdesc {
-+ dtrace_id_t dtargd_id;
-+ int dtargd_ndx;
-+ int dtargd_mapping;
-+ char dtargd_native[DTRACE_ARGTYPELEN];
-+ char dtargd_xlate[DTRACE_ARGTYPELEN];
-+} dtrace_argdesc_t;
-+
-+#endif /* _LINUX_DTRACE_ARG_H */
-diff --git a/include/uapi/linux/dtrace/arg_defines.h b/include/uapi/linux/dtrace/arg_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..72862cd1b8e6dccee6803955deb15f8d897187e4
---- /dev/null
-+++ b/include/uapi/linux/dtrace/arg_defines.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ARG_DEFINES_H
-+#define _LINUX_DTRACE_ARG_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_argdesc;
-+
-+#endif /* _LINUX_DTRACE_ARG_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/buffer.h b/include/uapi/linux/dtrace/buffer.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..9bbbc4f1f14bb3835e2fefbe432fd32e8f527090
---- /dev/null
-+++ b/include/uapi/linux/dtrace/buffer.h
-@@ -0,0 +1,43 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_BUFFER_H
-+#define _LINUX_DTRACE_BUFFER_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/actions_defines.h>
-+#include <linux/dtrace/buffer_defines.h>
-+
-+/*
-+ * In order to get a snapshot of the principal or aggregation buffer,
-+ * user-level passes a buffer description to the kernel with the dtrace_bufdesc
-+ * structure. This describes which CPU user-level is interested in, and
-+ * where user-level wishes the kernel to snapshot the buffer to (the
-+ * dtbd_data field). The kernel uses the same structure to pass back some
-+ * information regarding the buffer: the size of data actually copied out, the
-+ * number of drops, the number of errors, and the offset of the oldest record.
-+ * If the buffer policy is a "switch" policy, taking a snapshot of the
-+ * principal buffer has the additional effect of switching the active and
-+ * inactive buffers. Taking a snapshot of the aggregation buffer _always_ has
-+ * the additional effect of switching the active and inactive buffers.
-+ */
-+typedef struct dtrace_bufdesc {
-+ uint64_t dtbd_size; /* size of buffer */
-+ uint32_t dtbd_cpu; /* CPU or DTRACE_CPUALL */
-+ uint32_t dtbd_errors; /* number of errors */
-+ uint64_t dtbd_drops; /* number of drops */
-+ DTRACE_PTR(char, dtbd_data); /* data */
-+ uint64_t dtbd_oldest; /* offset of oldest record */
-+} dtrace_bufdesc_t;
-+
-+#endif /* _LINUX_DTRACE_BUFFER_H */
-diff --git a/include/uapi/linux/dtrace/buffer_defines.h b/include/uapi/linux/dtrace/buffer_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..16c3c193618ac9fd1bed0439244f2645761df388
---- /dev/null
-+++ b/include/uapi/linux/dtrace/buffer_defines.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_BUFFER_DEFINES_H
-+#define _LINUX_DTRACE_BUFFER_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_bufdesc;
-+
-+#endif /* _LINUX_DTRACE_BUFFER_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/conf.h b/include/uapi/linux/dtrace/conf.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..95b201958f4c046fa3c03bc5a1a3776a366588d1
---- /dev/null
-+++ b/include/uapi/linux/dtrace/conf.h
-@@ -0,0 +1,35 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_CONF_H
-+#define _LINUX_DTRACE_CONF_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/conf_defines.h>
-+
-+/*
-+ * User-level may need to understand some elements of the kernel DTrace
-+ * configuration in order to generate correct DIF. This information is
-+ * conveyed via the dtrace_conf structure.
-+ */
-+typedef struct dtrace_conf {
-+ uint_t dtc_difversion; /* supported DIF version */
-+ uint_t dtc_difintregs; /* # of DIF integer registers */
-+ uint_t dtc_diftupregs; /* # of DIF tuple registers */
-+ uint_t dtc_ctfmodel; /* CTF data model */
-+ /* Deviation from Solaris... Used to just be 8 padding entries. */
-+ uint_t dtc_maxbufs; /* max # of buffers */
-+ uint_t dtc_pad[7]; /* reserved for future use */
-+} dtrace_conf_t;
-+
-+#endif /* _LINUX_DTRACE_CONF_H */
-diff --git a/include/uapi/linux/dtrace/conf_defines.h b/include/uapi/linux/dtrace/conf_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..5c4a1cb5d37c944574b25f4f5f8a8eb5068d9bd5
---- /dev/null
-+++ b/include/uapi/linux/dtrace/conf_defines.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_CONF_DEFINES_H
-+#define _LINUX_DTRACE_CONF_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_conf;
-+
-+#endif /* _LINUX_DTRACE_CONF_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/cpu_defines.h b/include/uapi/linux/dtrace/cpu_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..a1cd3e410ccc24befea3becaf3049be8180b66b8
---- /dev/null
-+++ b/include/uapi/linux/dtrace/cpu_defines.h
-@@ -0,0 +1,17 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_CPU_DEFINES_H_
-+#define _LINUX_DTRACE_CPU_DEFINES_H_
-+
-+typedef uint32_t processorid_t;
-+typedef uint32_t psetid_t;
-+typedef uint32_t chipid_t;
-+typedef uint32_t lgrp_id_t;
-+
-+#endif /* _LINUX_DTRACE_CPU_DEFINES_H_ */
-diff --git a/include/uapi/linux/dtrace/dif.h b/include/uapi/linux/dtrace/dif.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..92daea17a1f149551b0495b31ee07a8525d50fb8
---- /dev/null
-+++ b/include/uapi/linux/dtrace/dif.h
-@@ -0,0 +1,60 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DIF_H
-+#define _LINUX_DTRACE_DIF_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/dif_defines.h>
-+
-+/*
-+ * The following definitions describe the DTrace Intermediate Format (DIF), a a
-+ * RISC-like instruction set and program encoding used to represent predicates
-+ * and actions that can be bound to DTrace probes. The constants below defining
-+ * the number of available registers are suggested minimums; the compiler should
-+ * use DTRACEIOC_CONF to dynamically obtain the number of registers provided by
-+ * the current DTrace implementation.
-+ */
-+
-+/*
-+ * A DTrace Intermediate Format Type (DIF Type) is used to represent the types
-+ * of variables, function and associative array arguments, and the return type
-+ * for each DIF object (shown below). It contains a description of the type,
-+ * its size in bytes, and a module identifier.
-+ */
-+
-+typedef struct dtrace_diftype {
-+ uint8_t dtdt_kind;
-+ uint8_t dtdt_ckind;
-+ uint8_t dtdt_flags;
-+ uint8_t dtdt_pad;
-+ uint32_t dtdt_size;
-+} dtrace_diftype_t;
-+
-+/*
-+ * A DTrace Intermediate Format variable record is used to describe each of the
-+ * variables referenced by a given DIF object. It contains an integer variable
-+ * identifier along with variable scope and properties, as shown below. The
-+ * size of this structure must be sizeof (int) aligned.
-+ */
-+
-+typedef struct dtrace_difv {
-+ uint32_t dtdv_name;
-+ uint32_t dtdv_id;
-+ uint8_t dtdv_kind;
-+ uint8_t dtdv_scope;
-+ uint16_t dtdv_flags;
-+ struct dtrace_diftype dtdv_type;
-+} dtrace_difv_t;
-+
-+#endif /* _LINUX_DTRACE_DIF_H */
-diff --git a/include/uapi/linux/dtrace/dif_defines.h b/include/uapi/linux/dtrace/dif_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..80b913f097a22ed174acd574a727ebee68be4fd4
---- /dev/null
-+++ b/include/uapi/linux/dtrace/dif_defines.h
-@@ -0,0 +1,288 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DIF_DEFINES_H
-+#define _LINUX_DTRACE_DIF_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * The following definitions describe the DTrace Intermediate Format (DIF), a a
-+ * RISC-like instruction set and program encoding used to represent predicates
-+ * and actions that can be bound to DTrace probes. The constants below defining
-+ * the number of available registers are suggested minimums; the compiler should
-+ * use DTRACEIOC_CONF to dynamically obtain the number of registers provided by
-+ * the current DTrace implementation.
-+ */
-+
-+#define DIF_VERSION_1 1
-+#define DIF_VERSION_2 2
-+#define DIF_VERSION DIF_VERSION_2
-+#define DIF_DIR_NREGS 8 /* number of DIF integer registers */
-+#define DIF_DTR_NREGS 8 /* number of DIF tuple registers */
-+
-+#define DIF_OP_OR 1 /* or r1, r2, rd */
-+#define DIF_OP_XOR 2 /* xor r1, r2, rd */
-+#define DIF_OP_AND 3 /* and r1, r2, rd */
-+#define DIF_OP_SLL 4 /* sll r1, r2, rd */
-+#define DIF_OP_SRL 5 /* srl r1, r2, rd */
-+#define DIF_OP_SUB 6 /* sub r1, r2, rd */
-+#define DIF_OP_ADD 7 /* add r1, r2, rd */
-+#define DIF_OP_MUL 8 /* mul r1, r2, rd */
-+#define DIF_OP_SDIV 9 /* sdiv r1, r2, rd */
-+#define DIF_OP_UDIV 10 /* udiv r1, r2, rd */
-+#define DIF_OP_SREM 11 /* srem r1, r2, rd */
-+#define DIF_OP_UREM 12 /* urem r1, r2, rd */
-+#define DIF_OP_NOT 13 /* not r1, rd */
-+#define DIF_OP_MOV 14 /* mov r1, rd */
-+#define DIF_OP_CMP 15 /* cmp r1, r2 */
-+#define DIF_OP_TST 16 /* tst r1 */
-+#define DIF_OP_BA 17 /* ba label */
-+#define DIF_OP_BE 18 /* be label */
-+#define DIF_OP_BNE 19 /* bne label */
-+#define DIF_OP_BG 20 /* bg label */
-+#define DIF_OP_BGU 21 /* bgu label */
-+#define DIF_OP_BGE 22 /* bge label */
-+#define DIF_OP_BGEU 23 /* bgeu label */
-+#define DIF_OP_BL 24 /* bl label */
-+#define DIF_OP_BLU 25 /* blu label */
-+#define DIF_OP_BLE 26 /* ble label */
-+#define DIF_OP_BLEU 27 /* bleu label */
-+#define DIF_OP_LDSB 28 /* ldsb [r1], rd */
-+#define DIF_OP_LDSH 29 /* ldsh [r1], rd */
-+#define DIF_OP_LDSW 30 /* ldsw [r1], rd */
-+#define DIF_OP_LDUB 31 /* ldub [r1], rd */
-+#define DIF_OP_LDUH 32 /* lduh [r1], rd */
-+#define DIF_OP_LDUW 33 /* lduw [r1], rd */
-+#define DIF_OP_LDX 34 /* ldx [r1], rd */
-+#define DIF_OP_RET 35 /* ret rd */
-+#define DIF_OP_NOP 36 /* nop */
-+#define DIF_OP_SETX 37 /* setx intindex, rd */
-+#define DIF_OP_SETS 38 /* sets strindex, rd */
-+#define DIF_OP_SCMP 39 /* scmp r1, r2 */
-+#define DIF_OP_LDGA 40 /* ldga var, ri, rd */
-+#define DIF_OP_LDGS 41 /* ldgs var, rd */
-+#define DIF_OP_STGS 42 /* stgs var, rs */
-+#define DIF_OP_LDTA 43 /* ldta var, ri, rd */
-+#define DIF_OP_LDTS 44 /* ldts var, rd */
-+#define DIF_OP_STTS 45 /* stts var, rs */
-+#define DIF_OP_SRA 46 /* sra r1, r2, rd */
-+#define DIF_OP_CALL 47 /* call subr, rd */
-+#define DIF_OP_PUSHTR 48 /* pushtr type, rs, rr */
-+#define DIF_OP_PUSHTV 49 /* pushtv type, rs, rv */
-+#define DIF_OP_POPTS 50 /* popts */
-+#define DIF_OP_FLUSHTS 51 /* flushts */
-+#define DIF_OP_LDGAA 52 /* ldgaa var, rd */
-+#define DIF_OP_LDTAA 53 /* ldtaa var, rd */
-+#define DIF_OP_STGAA 54 /* stgaa var, rs */
-+#define DIF_OP_STTAA 55 /* sttaa var, rs */
-+#define DIF_OP_LDLS 56 /* ldls var, rd */
-+#define DIF_OP_STLS 57 /* stls var, rs */
-+#define DIF_OP_ALLOCS 58 /* allocs r1, rd */
-+#define DIF_OP_COPYS 59 /* copys r1, r2, rd */
-+#define DIF_OP_STB 60 /* stb r1, [rd] */
-+#define DIF_OP_STH 61 /* sth r1, [rd] */
-+#define DIF_OP_STW 62 /* stw r1, [rd] */
-+#define DIF_OP_STX 63 /* stx r1, [rd] */
-+#define DIF_OP_ULDSB 64 /* uldsb [r1], rd */
-+#define DIF_OP_ULDSH 65 /* uldsh [r1], rd */
-+#define DIF_OP_ULDSW 66 /* uldsw [r1], rd */
-+#define DIF_OP_ULDUB 67 /* uldub [r1], rd */
-+#define DIF_OP_ULDUH 68 /* ulduh [r1], rd */
-+#define DIF_OP_ULDUW 69 /* ulduw [r1], rd */
-+#define DIF_OP_ULDX 70 /* uldx [r1], rd */
-+#define DIF_OP_RLDSB 71 /* rldsb [r1], rd */
-+#define DIF_OP_RLDSH 72 /* rldsh [r1], rd */
-+#define DIF_OP_RLDSW 73 /* rldsw [r1], rd */
-+#define DIF_OP_RLDUB 74 /* rldub [r1], rd */
-+#define DIF_OP_RLDUH 75 /* rlduh [r1], rd */
-+#define DIF_OP_RLDUW 76 /* rlduw [r1], rd */
-+#define DIF_OP_RLDX 77 /* rldx [r1], rd */
-+#define DIF_OP_XLATE 78 /* xlate xlrindex, rd */
-+#define DIF_OP_XLARG 79 /* xlarg xlrindex, rd */
-+
-+#define DIF_INTOFF_MAX 0xffff /* highest integer table offset */
-+#define DIF_STROFF_MAX 0xffff /* highest string table offset */
-+#define DIF_REGISTER_MAX 0xff /* highest register number */
-+#define DIF_VARIABLE_MAX 0xffff /* highest variable identifier */
-+#define DIF_SUBROUTINE_MAX 0xffff /* highest subroutine code */
-+
-+#define DIF_VAR_ARRAY_MIN 0x0000 /* lowest numbered array variable */
-+#define DIF_VAR_ARRAY_UBASE 0x0080 /* lowest user-defined array */
-+#define DIF_VAR_ARRAY_MAX 0x00ff /* highest numbered array variable */
-+
-+#define DIF_VAR_OTHER_MIN 0x0100 /* lowest numbered scalar or assc */
-+#define DIF_VAR_OTHER_UBASE 0x0500 /* lowest user-defined scalar or assc */
-+#define DIF_VAR_OTHER_MAX 0xffff /* highest numbered scalar or assc */
-+
-+#define DIF_VAR_ARGS 0x0000
-+#define DIF_VAR_REGS 0x0001
-+#define DIF_VAR_UREGS 0x0002
-+#define DIF_VAR_CURTHREAD 0x0100
-+#define DIF_VAR_TIMESTAMP 0x0101
-+#define DIF_VAR_VTIMESTAMP 0x0102
-+#define DIF_VAR_IPL 0x0103
-+#define DIF_VAR_EPID 0x0104
-+#define DIF_VAR_ID 0x0105
-+#define DIF_VAR_ARG0 0x0106
-+#define DIF_VAR_ARG1 0x0107
-+#define DIF_VAR_ARG2 0x0108
-+#define DIF_VAR_ARG3 0x0109
-+#define DIF_VAR_ARG4 0x010a
-+#define DIF_VAR_ARG5 0x010b
-+#define DIF_VAR_ARG6 0x010c
-+#define DIF_VAR_ARG7 0x010d
-+#define DIF_VAR_ARG8 0x010e
-+#define DIF_VAR_ARG9 0x010f
-+#define DIF_VAR_STACKDEPTH 0x0110
-+#define DIF_VAR_CALLER 0x0111
-+#define DIF_VAR_PROBEPROV 0x0112
-+#define DIF_VAR_PROBEMOD 0x0113
-+#define DIF_VAR_PROBEFUNC 0x0114
-+#define DIF_VAR_PROBENAME 0x0115
-+#define DIF_VAR_PID 0x0116
-+#define DIF_VAR_TID 0x0117
-+#define DIF_VAR_EXECNAME 0x0118
-+#define DIF_VAR_ZONENAME 0x0119
-+#define DIF_VAR_WALLTIMESTAMP 0x011a
-+#define DIF_VAR_USTACKDEPTH 0x011b
-+#define DIF_VAR_UCALLER 0x011c
-+#define DIF_VAR_PPID 0x011d
-+#define DIF_VAR_UID 0x011e
-+#define DIF_VAR_GID 0x011f
-+#define DIF_VAR_ERRNO 0x0120
-+#define DIF_VAR_CURCPU 0x0121
-+
-+#define DIF_SUBR_RAND 0
-+#define DIF_SUBR_MUTEX_OWNED 1
-+#define DIF_SUBR_MUTEX_OWNER 2
-+#define DIF_SUBR_MUTEX_TYPE_ADAPTIVE 3
-+#define DIF_SUBR_MUTEX_TYPE_SPIN 4
-+#define DIF_SUBR_RW_READ_HELD 5
-+#define DIF_SUBR_RW_WRITE_HELD 6
-+#define DIF_SUBR_RW_ISWRITER 7
-+#define DIF_SUBR_COPYIN 8
-+#define DIF_SUBR_COPYINSTR 9
-+#define DIF_SUBR_SPECULATION 10
-+#define DIF_SUBR_PROGENYOF 11
-+#define DIF_SUBR_STRLEN 12
-+#define DIF_SUBR_COPYOUT 13
-+#define DIF_SUBR_COPYOUTSTR 14
-+#define DIF_SUBR_ALLOCA 15
-+#define DIF_SUBR_BCOPY 16
-+#define DIF_SUBR_COPYINTO 17
-+#define DIF_SUBR_MSGDSIZE 18
-+#define DIF_SUBR_MSGSIZE 19
-+#define DIF_SUBR_GETMAJOR 20
-+#define DIF_SUBR_GETMINOR 21
-+#define DIF_SUBR_DDI_PATHNAME 22
-+#define DIF_SUBR_STRJOIN 23
-+#define DIF_SUBR_LLTOSTR 24
-+#define DIF_SUBR_BASENAME 25
-+#define DIF_SUBR_DIRNAME 26
-+#define DIF_SUBR_CLEANPATH 27
-+#define DIF_SUBR_STRCHR 28
-+#define DIF_SUBR_STRRCHR 29
-+#define DIF_SUBR_STRSTR 30
-+#define DIF_SUBR_STRTOK 31
-+#define DIF_SUBR_SUBSTR 32
-+#define DIF_SUBR_INDEX 33
-+#define DIF_SUBR_RINDEX 34
-+#define DIF_SUBR_HTONS 35
-+#define DIF_SUBR_HTONL 36
-+#define DIF_SUBR_HTONLL 37
-+#define DIF_SUBR_NTOHS 38
-+#define DIF_SUBR_NTOHL 39
-+#define DIF_SUBR_NTOHLL 40
-+#define DIF_SUBR_INET_NTOP 41
-+#define DIF_SUBR_INET_NTOA 42
-+#define DIF_SUBR_INET_NTOA6 43
-+#define DIF_SUBR_D_PATH 44
-+#define DIF_SUBR_LINK_NTOP 45
-+
-+#define DIF_SUBR_MAX 45
-+
-+typedef uint32_t dif_instr_t;
-+
-+#define DIF_INSTR_OP(i) (((i) >> 24) & 0xff)
-+#define DIF_INSTR_R1(i) (((i) >> 16) & 0xff)
-+#define DIF_INSTR_R2(i) (((i) >> 8) & 0xff)
-+#define DIF_INSTR_RD(i) ((i) & 0xff)
-+#define DIF_INSTR_RS(i) ((i) & 0xff)
-+#define DIF_INSTR_LABEL(i) ((i) & 0xffffff)
-+#define DIF_INSTR_VAR(i) (((i) >> 8) & 0xffff)
-+#define DIF_INSTR_INTEGER(i) (((i) >> 8) & 0xffff)
-+#define DIF_INSTR_STRING(i) (((i) >> 8) & 0xffff)
-+#define DIF_INSTR_SUBR(i) (((i) >> 8) & 0xffff)
-+#define DIF_INSTR_TYPE(i) (((i) >> 16) & 0xff)
-+#define DIF_INSTR_XLREF(i) (((i) >> 8) & 0xffff)
-+#define DIF_INSTR_FMT(op, r1, r2, d) \
-+ (((op) << 24) | ((r1) << 16) | ((r2) << 8) | (d))
-+
-+#define DIF_INSTR_NOT(r1, d) (DIF_INSTR_FMT(DIF_OP_NOT, r1, 0, d))
-+#define DIF_INSTR_MOV(r1, d) (DIF_INSTR_FMT(DIF_OP_MOV, r1, 0, d))
-+#define DIF_INSTR_CMP(op, r1, r2) (DIF_INSTR_FMT(op, r1, r2, 0))
-+#define DIF_INSTR_TST(r1) (DIF_INSTR_FMT(DIF_OP_TST, r1, 0, 0))
-+#define DIF_INSTR_BRANCH(op, label) (((op) << 24) | (label))
-+#define DIF_INSTR_LOAD(op, r1, d) (DIF_INSTR_FMT(op, r1, 0, d))
-+#define DIF_INSTR_STORE(op, r1, d) (DIF_INSTR_FMT(op, r1, 0, d))
-+#define DIF_INSTR_SETX(i, d) ((DIF_OP_SETX << 24) | ((i) << 8) | (d))
-+#define DIF_INSTR_SETS(s, d) ((DIF_OP_SETS << 24) | ((s) << 8) | (d))
-+#define DIF_INSTR_RET(d) (DIF_INSTR_FMT(DIF_OP_RET, 0, 0, d))
-+#define DIF_INSTR_NOP (DIF_OP_NOP << 24)
-+#define DIF_INSTR_LDA(op, v, r, d) (DIF_INSTR_FMT(op, v, r, d))
-+#define DIF_INSTR_LDV(op, v, d) (((op) << 24) | ((v) << 8) | (d))
-+#define DIF_INSTR_STV(op, v, rs) (((op) << 24) | ((v) << 8) | (rs))
-+#define DIF_INSTR_CALL(s, d) ((DIF_OP_CALL << 24) | ((s) << 8) | (d))
-+#define DIF_INSTR_PUSHTS(op, t, r2, rs) (DIF_INSTR_FMT(op, t, r2, rs))
-+#define DIF_INSTR_POPTS (DIF_OP_POPTS << 24)
-+#define DIF_INSTR_FLUSHTS (DIF_OP_FLUSHTS << 24)
-+#define DIF_INSTR_ALLOCS(r1, d) (DIF_INSTR_FMT(DIF_OP_ALLOCS, r1, 0, d))
-+#define DIF_INSTR_COPYS(r1, r2, d) (DIF_INSTR_FMT(DIF_OP_COPYS, r1, r2, d))
-+#define DIF_INSTR_XLATE(op, r, d) (((op) << 24) | ((r) << 8) | (d))
-+
-+#define DIF_REG_R0 0
-+
-+/*
-+ * A DTrace Intermediate Format Type (DIF Type) is used to represent the types
-+ * of variables, function and associative array arguments, and the return type
-+ * for each DIF object (shown below). It contains a description of the type,
-+ * its size in bytes, and a module identifier.
-+ */
-+
-+#define DIF_TYPE_CTF 0
-+#define DIF_TYPE_STRING 1
-+
-+#define DIF_TF_BYREF 0x1
-+
-+/*
-+ * A DTrace Intermediate Format variable record is used to describe each of the
-+ * variables referenced by a given DIF object. It contains an integer variable
-+ * identifier along with variable scope and properties, as shown below. The
-+ * size of this structure must be sizeof (int) aligned.
-+ */
-+
-+#define DIFV_KIND_ARRAY 0
-+#define DIFV_KIND_SCALAR 1
-+
-+#define DIFV_SCOPE_GLOBAL 0
-+#define DIFV_SCOPE_THREAD 1
-+#define DIFV_SCOPE_LOCAL 2
-+
-+#define DIFV_F_REF 0x1
-+#define DIFV_F_MOD 0x2
-+
-+struct dtrace_diftype;
-+struct dtrace_difv;
-+
-+#endif /* _LINUX_DTRACE_DIF_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/difo.h b/include/uapi/linux/dtrace/difo.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..6e9efd7f0a43047a7f5e1804c7192f888d9adef8
---- /dev/null
-+++ b/include/uapi/linux/dtrace/difo.h
-@@ -0,0 +1,57 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DIFO_H
-+#define _LINUX_DTRACE_DIFO_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/dif.h>
-+#include <linux/dtrace/dof_defines.h>
-+
-+/*
-+ * A DIFO is used to store the compiled DIF for a D expression, its return
-+ * type, and its string and variable tables. The string table is a single
-+ * buffer of character data into which sets instructions and variable
-+ * references can reference strings using a byte offset. The variable table
-+ * is an array of dtrace_difv_t structures that describe the name and type of
-+ * each variable and the id used in the DIF code. This structure is described
-+ * above in the DIF section of this header file. The DIFO is used at both
-+ * user-level (in the library) and in the kernel, but the structure is never
-+ * passed between the two: the DOF structures form the only interface. As a
-+ * result, the definition can change depending on the presence of _KERNEL.
-+ */
-+
-+typedef struct dtrace_difo {
-+ dif_instr_t *dtdo_buf; /* instruction buffer */
-+ uint64_t *dtdo_inttab; /* integer table (optional) */
-+ char *dtdo_strtab; /* string table (optional) */
-+ struct dtrace_difv *dtdo_vartab; /* variable table (optional) */
-+ uint_t dtdo_len; /* length of instruction buffer */
-+ uint_t dtdo_intlen; /* length of integer table */
-+ uint_t dtdo_strlen; /* length of string table */
-+ uint_t dtdo_varlen; /* length of variable table */
-+ struct dtrace_diftype dtdo_rtype; /* return type */
-+ uint_t dtdo_refcnt; /* owner reference count */
-+ uint_t dtdo_destructive; /* invokes destructive subroutines */
-+#ifndef _KERNEL
-+ struct dtrace_diftype orig_dtdo_rtype; /* original return type */
-+ struct dof_relodesc *dtdo_kreltab; /* kernel relocations */
-+ struct dof_relodesc *dtdo_ureltab; /* user relocations */
-+ struct dt_node **dtdo_xlmtab; /* translator references */
-+ uint_t dtdo_krelen; /* length of krelo table */
-+ uint_t dtdo_urelen; /* length of urelo table */
-+ uint_t dtdo_xlmlen; /* length of translator table */
-+#endif
-+} dtrace_difo_t;
-+
-+#endif /* _LINUX_DTRACE_DIFO_H */
-diff --git a/include/uapi/linux/dtrace/difo_defines.h b/include/uapi/linux/dtrace/difo_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..fdd25f2b76913c41a3306a19d600a7bdd9513099
---- /dev/null
-+++ b/include/uapi/linux/dtrace/difo_defines.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DIFO_DEFINES_H
-+#define _LINUX_DTRACE_DIFO_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_difo;
-+
-+#endif /* _LINUX_DTRACE_DIFO_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/dof.h b/include/uapi/linux/dtrace/dof.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..54c6ca71044368b77d0352c04f5dbe7b0aa4c8dd
---- /dev/null
-+++ b/include/uapi/linux/dtrace/dof.h
-@@ -0,0 +1,196 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DOF_H
-+#define _LINUX_DTRACE_DOF_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/dif.h>
-+#include <linux/dtrace/dof_defines.h>
-+
-+/*
-+ * DTrace programs can be persistently encoded in the DOF format so that they
-+ * may be embedded in other programs (for example, in an ELF file) or in the
-+ * dtrace driver configuration file for use in anonymous tracing. The DOF
-+ * format is versioned and extensible so that it can be revised and so that
-+ * internal data structures can be modified or extended compatibly. All DOF
-+ * structures use fixed-size types, so the 32-bit and 64-bit representations
-+ * are identical and consumers can use either data model transparently.
-+ *
-+ * The file layout is structured as follows:
-+ *
-+ * +---------------+-------------------+----- ... ----+---- ... ------+
-+ * | dof_hdr_t | dof_sec_t[ ... ] | loadable | non-loadable |
-+ * | (file header) | (section headers) | section data | section data |
-+ * +---------------+-------------------+----- ... ----+---- ... ------+
-+ * |<------------ dof_hdr.dofh_loadsz --------------->| |
-+ * |<------------ dof_hdr.dofh_filesz ------------------------------->|
-+ *
-+ * The file header stores meta-data including a magic number, data model for
-+ * the instrumentation, data encoding, and properties of the DIF code within.
-+ * The header describes its own size and the size of the section headers. By
-+ * convention, an array of section headers follows the file header, and then
-+ * the data for all loadable sections and unloadable sections. This permits
-+ * consumer code to easily download the headers and all loadable data into the
-+ * DTrace driver in one contiguous chunk, omitting other extraneous sections.
-+ *
-+ * The section headers describe the size, offset, alignment, and section type
-+ * for each section. Sections are described using a set of #defines that tell
-+ * the consumer what kind of data is expected. Sections can contain links to
-+ * other sections by storing a dof_secidx_t, an index into the section header
-+ * array, inside of the section data structures. The section header includes
-+ * an entry size so that sections with data arrays can grow their structures.
-+ *
-+ * The DOF data itself can contain many snippets of DIF (i.e. >1 DIFOs), which
-+ * are represented themselves as a collection of related DOF sections. This
-+ * permits us to change the set of sections associated with a DIFO over time,
-+ * and also permits us to encode DIFOs that contain different sets of sections.
-+ * When a DOF section wants to refer to a DIFO, it stores the dof_secidx_t of a
-+ * section of type DOF_SECT_DIFOHDR. This section's data is then an array of
-+ * dof_secidx_t's which in turn denote the sections associated with this DIFO.
-+ *
-+ * This loose coupling of the file structure (header and sections) to the
-+ * structure of the DTrace program itself (ECB descriptions, action
-+ * descriptions, and DIFOs) permits activities such as relocation processing
-+ * to occur in a single pass without having to understand D program structure.
-+ *
-+ * Finally, strings are always stored in ELF-style string tables along with a
-+ * string table section index and string table offset. Therefore strings in
-+ * DOF are always arbitrary-length and not bound to the current implementation.
-+ */
-+
-+typedef struct dof_hdr {
-+ uint8_t dofh_ident[DOF_ID_SIZE];/* ident bytes (see defines) */
-+ uint32_t dofh_flags; /* file attribute flags (if any) */
-+ uint32_t dofh_hdrsize; /* size of file header in bytes */
-+ uint32_t dofh_secsize; /* size of section header in bytes */
-+ uint32_t dofh_secnum; /* number of section headers */
-+ uint64_t dofh_secoff; /* file offset of section headers */
-+ uint64_t dofh_loadsz; /* file size of loadable portion */
-+ uint64_t dofh_filesz; /* file size of entire DOF file */
-+ uint64_t dofh_pad; /* reserved for future use */
-+} dof_hdr_t;
-+
-+typedef struct dof_sec {
-+ uint32_t dofs_type; /* section type (see defines) */
-+ uint32_t dofs_align; /* section data memory alignment */
-+ uint32_t dofs_flags; /* section flags (if any) */
-+ uint32_t dofs_entsize; /* size of section entry (if table) */
-+ uint64_t dofs_offset; /* offset of section data within file */
-+ uint64_t dofs_size; /* size of section data in bytes */
-+} dof_sec_t;
-+
-+
-+typedef struct dof_ecbdesc {
-+ dof_secidx_t dofe_probes; /* link to DOF_SECT_PROBEDESC */
-+ dof_secidx_t dofe_pred; /* link to DOF_SECT_DIFOHDR */
-+ dof_secidx_t dofe_actions; /* link to DOF_SECT_ACTDESC */
-+ uint32_t dofe_pad; /* reserved for future use */
-+ uint64_t dofe_uarg; /* user-supplied library argument */
-+} dof_ecbdesc_t;
-+
-+typedef struct dof_probedesc {
-+ dof_secidx_t dofp_strtab; /* link to DOF_SECT_STRTAB section */
-+ dof_stridx_t dofp_provider; /* provider string */
-+ dof_stridx_t dofp_mod; /* module string */
-+ dof_stridx_t dofp_func; /* function string */
-+ dof_stridx_t dofp_name; /* name string */
-+ uint32_t dofp_id; /* probe identifier (or zero) */
-+} dof_probedesc_t;
-+
-+typedef struct dof_actdesc {
-+ dof_secidx_t dofa_difo; /* link to DOF_SECT_DIFOHDR */
-+ dof_secidx_t dofa_strtab; /* link to DOF_SECT_STRTAB section */
-+ uint32_t dofa_kind; /* action kind (DTRACEACT_* constant) */
-+ uint32_t dofa_ntuple; /* number of subsequent tuple actions */
-+ uint64_t dofa_arg; /* kind-specific argument */
-+ uint64_t dofa_uarg; /* user-supplied argument */
-+} dof_actdesc_t;
-+
-+typedef struct dof_difohdr {
-+ struct dtrace_diftype dofd_rtype; /* return type for this fragment */
-+ dof_secidx_t dofd_links[1]; /* variable length array of indices */
-+} dof_difohdr_t;
-+
-+typedef struct dof_relohdr {
-+ dof_secidx_t dofr_strtab; /* link to DOF_SECT_STRTAB for names */
-+ dof_secidx_t dofr_relsec; /* link to DOF_SECT_RELTAB for relos */
-+ dof_secidx_t dofr_tgtsec; /* link to section we are relocating */
-+} dof_relohdr_t;
-+
-+typedef struct dof_relodesc {
-+ dof_stridx_t dofr_name; /* string name of relocation symbol */
-+ uint32_t dofr_type; /* relo type (DOF_RELO_* constant) */
-+ uint64_t dofr_offset; /* byte offset for relocation */
-+ uint64_t dofr_data; /* additional type-specific data */
-+} dof_relodesc_t;
-+
-+typedef struct dof_optdesc {
-+ uint32_t dofo_option; /* option identifier */
-+ dof_secidx_t dofo_strtab; /* string table, if string option */
-+ uint64_t dofo_value; /* option value or string index */
-+} dof_optdesc_t;
-+
-+typedef struct dof_provider {
-+ dof_secidx_t dofpv_strtab; /* link to DOF_SECT_STRTAB section */
-+ dof_secidx_t dofpv_probes; /* link to DOF_SECT_PROBES section */
-+ dof_secidx_t dofpv_prargs; /* link to DOF_SECT_PRARGS section */
-+ dof_secidx_t dofpv_proffs; /* link to DOF_SECT_PROFFS section */
-+ dof_stridx_t dofpv_name; /* provider name string */
-+ dof_attr_t dofpv_provattr; /* provider attributes */
-+ dof_attr_t dofpv_modattr; /* module attributes */
-+ dof_attr_t dofpv_funcattr; /* function attributes */
-+ dof_attr_t dofpv_nameattr; /* name attributes */
-+ dof_attr_t dofpv_argsattr; /* args attributes */
-+ dof_secidx_t dofpv_prenoffs; /* link to DOF_SECT_PRENOFFS section */
-+} dof_provider_t;
-+
-+typedef struct dof_probe {
-+ uint64_t dofpr_addr; /* probe base address or offset */
-+ dof_stridx_t dofpr_func; /* probe function string */
-+ dof_stridx_t dofpr_name; /* probe name string */
-+ dof_stridx_t dofpr_nargv; /* native argument type strings */
-+ dof_stridx_t dofpr_xargv; /* translated argument type strings */
-+ uint32_t dofpr_argidx; /* index of first argument mapping */
-+ uint32_t dofpr_offidx; /* index of first offset entry */
-+ uint8_t dofpr_nargc; /* native argument count */
-+ uint8_t dofpr_xargc; /* translated argument count */
-+ uint16_t dofpr_noffs; /* number of offset entries for probe */
-+ uint32_t dofpr_enoffidx; /* index of first is-enabled offset */
-+ uint16_t dofpr_nenoffs; /* number of is-enabled offsets */
-+ uint16_t dofpr_pad1; /* reserved for future use */
-+ uint32_t dofpr_pad2; /* reserved for future use */
-+} dof_probe_t;
-+
-+typedef struct dof_xlator {
-+ dof_secidx_t dofxl_members; /* link to DOF_SECT_XLMEMBERS section */
-+ dof_secidx_t dofxl_strtab; /* link to DOF_SECT_STRTAB section */
-+ dof_stridx_t dofxl_argv; /* input parameter type strings */
-+ uint32_t dofxl_argc; /* input parameter list length */
-+ dof_stridx_t dofxl_type; /* output type string name */
-+ dof_attr_t dofxl_attr; /* output stability attributes */
-+} dof_xlator_t;
-+
-+typedef struct dof_xlmember {
-+ dof_secidx_t dofxm_difo; /* member link to DOF_SECT_DIFOHDR */
-+ dof_stridx_t dofxm_name; /* member name */
-+ struct dtrace_diftype dofxm_type; /* member type */
-+} dof_xlmember_t;
-+
-+typedef struct dof_xlref {
-+ dof_secidx_t dofxr_xlator; /* link to DOF_SECT_XLATORS section */
-+ uint32_t dofxr_member; /* index of referenced dof_xlmember */
-+ uint32_t dofxr_argn; /* index of argument for DIF_OP_XLARG */
-+} dof_xlref_t;
-+
-+#endif /* _LINUX_DTRACE_DOF_H */
-diff --git a/include/uapi/linux/dtrace/dof_defines.h b/include/uapi/linux/dtrace/dof_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..5357d5e099cc21a88ca60ccd7616f6e0a4764cc2
---- /dev/null
-+++ b/include/uapi/linux/dtrace/dof_defines.h
-@@ -0,0 +1,192 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_DOF_DEFINES_H
-+#define _LINUX_DTRACE_DOF_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * DTrace programs can be persistently encoded in the DOF format so that they
-+ * may be embedded in other programs (for example, in an ELF file) or in the
-+ * dtrace driver configuration file for use in anonymous tracing. The DOF
-+ * format is versioned and extensible so that it can be revised and so that
-+ * internal data structures can be modified or extended compatibly. All DOF
-+ * structures use fixed-size types, so the 32-bit and 64-bit representations
-+ * are identical and consumers can use either data model transparently.
-+ *
-+ * The file layout is structured as follows:
-+ *
-+ * +---------------+-------------------+----- ... ----+---- ... ------+
-+ * | dof_hdr_t | dof_sec_t[ ... ] | loadable | non-loadable |
-+ * | (file header) | (section headers) | section data | section data |
-+ * +---------------+-------------------+----- ... ----+---- ... ------+
-+ * |<------------ dof_hdr.dofh_loadsz --------------->| |
-+ * |<------------ dof_hdr.dofh_filesz ------------------------------->|
-+ *
-+ * The file header stores meta-data including a magic number, data model for
-+ * the instrumentation, data encoding, and properties of the DIF code within.
-+ * The header describes its own size and the size of the section headers. By
-+ * convention, an array of section headers follows the file header, and then
-+ * the data for all loadable sections and unloadable sections. This permits
-+ * consumer code to easily download the headers and all loadable data into the
-+ * DTrace driver in one contiguous chunk, omitting other extraneous sections.
-+ *
-+ * The section headers describe the size, offset, alignment, and section type
-+ * for each section. Sections are described using a set of #defines that tell
-+ * the consumer what kind of data is expected. Sections can contain links to
-+ * other sections by storing a dof_secidx_t, an index into the section header
-+ * array, inside of the section data structures. The section header includes
-+ * an entry size so that sections with data arrays can grow their structures.
-+ *
-+ * The DOF data itself can contain many snippets of DIF (i.e. >1 DIFOs), which
-+ * are represented themselves as a collection of related DOF sections. This
-+ * permits us to change the set of sections associated with a DIFO over time,
-+ * and also permits us to encode DIFOs that contain different sets of sections.
-+ * When a DOF section wants to refer to a DIFO, it stores the dof_secidx_t of a
-+ * section of type DOF_SECT_DIFOHDR. This section's data is then an array of
-+ * dof_secidx_t's which in turn denote the sections associated with this DIFO.
-+ *
-+ * This loose coupling of the file structure (header and sections) to the
-+ * structure of the DTrace program itself (ECB descriptions, action
-+ * descriptions, and DIFOs) permits activities such as relocation processing
-+ * to occur in a single pass without having to understand D program structure.
-+ *
-+ * Finally, strings are always stored in ELF-style string tables along with a
-+ * string table section index and string table offset. Therefore strings in
-+ * DOF are always arbitrary-length and not bound to the current implementation.
-+ */
-+
-+#define DOF_ID_SIZE 16 /* total size of dofh_ident[] in bytes */
-+
-+#define DOF_ID_MAG0 0
-+#define DOF_ID_MAG1 1
-+#define DOF_ID_MAG2 2
-+#define DOF_ID_MAG3 3
-+#define DOF_ID_MODEL 4
-+#define DOF_ID_ENCODING 5
-+#define DOF_ID_VERSION 6
-+#define DOF_ID_DIFVERS 7
-+#define DOF_ID_DIFIREG 8 /* DIF integer registers used by compiler */
-+#define DOF_ID_DIFTREG 9 /* DIF tuple registers used by compiler */
-+#define DOF_ID_PAD 10 /* start of padding bytes (all zeroes) */
-+
-+#define DOF_MAG_MAG0 0x7F /* DOF_ID_MAG[0-3] */
-+#define DOF_MAG_MAG1 'D'
-+#define DOF_MAG_MAG2 'O'
-+#define DOF_MAG_MAG3 'F'
-+
-+#define DOF_MAG_STRING "\177DOF"
-+#define DOF_MAG_STRLEN 4
-+
-+#define DOF_MODEL_NONE 0 /* DOF_ID_MODEL */
-+#define DOF_MODEL_ILP32 1
-+#define DOF_MODEL_LP64 2
-+
-+#ifdef _LP64
-+#define DOF_MODEL_NATIVE DOF_MODEL_LP64
-+#else
-+#define DOF_MODEL_NATIVE DOF_MODEL_ILP32
-+#endif
-+
-+#define DOF_ENCODE_NONE 0 /* DOF_ID_ENCODING */
-+#define DOF_ENCODE_LSB 1
-+#define DOF_ENCODE_MSB 2
-+
-+#ifndef _LITTLE_ENDIAN
-+#define DOF_ENCODE_NATIVE DOF_ENCODE_MSB
-+#else
-+#define DOF_ENCODE_NATIVE DOF_ENCODE_LSB
-+#endif
-+
-+#define DOF_VERSION_1 1
-+#define DOF_VERSION_2 2
-+#define DOF_VERSION DOF_VERSION_2
-+
-+#define DOF_FL_VALID 0 /* mask of all valid dofh_flags bits */
-+
-+typedef uint32_t dof_secidx_t; /* section header table index type */
-+typedef uint32_t dof_stridx_t; /* string table index type */
-+
-+#define DOF_SECIDX_NONE -1U /* null value for section indices */
-+#define DOF_STRIDX_NONE -1U /* null value for string indices */
-+
-+#define DOF_SECT_NONE 0 /* null section */
-+#define DOF_SECT_COMMENTS 1 /* compiler comments */
-+#define DOF_SECT_SOURCE 2 /* D program source code */
-+#define DOF_SECT_ECBDESC 3 /* dof_ecbdesc_t */
-+#define DOF_SECT_PROBEDESC 4 /* dof_probedesc_t */
-+#define DOF_SECT_ACTDESC 5 /* dof_actdesc_t array */
-+#define DOF_SECT_DIFOHDR 6 /* dof_difohdr_t (variable length) */
-+#define DOF_SECT_DIF 7 /* uint32_t array of byte code */
-+#define DOF_SECT_STRTAB 8 /* string table */
-+#define DOF_SECT_VARTAB 9 /* dtrace_difv_t array */
-+#define DOF_SECT_RELTAB 10 /* dof_relodesc_t array */
-+#define DOF_SECT_TYPTAB 11 /* dtrace_diftype_t array */
-+#define DOF_SECT_URELHDR 12 /* dof_relohdr_t (user relocations) */
-+#define DOF_SECT_KRELHDR 13 /* dof_relohdr_t (kernel relocations) */
-+#define DOF_SECT_OPTDESC 14 /* dof_optdesc_t array */
-+#define DOF_SECT_PROVIDER 15 /* dof_provider_t */
-+#define DOF_SECT_PROBES 16 /* dof_probe_t array */
-+#define DOF_SECT_PRARGS 17 /* uint8_t array (probe arg mappings) */
-+#define DOF_SECT_PROFFS 18 /* uint32_t array (probe arg offsets) */
-+#define DOF_SECT_INTTAB 19 /* uint64_t array */
-+#define DOF_SECT_UTSNAME 20 /* struct utsname */
-+#define DOF_SECT_XLTAB 21 /* dof_xlref_t array */
-+#define DOF_SECT_XLMEMBERS 22 /* dof_xlmember_t array */
-+#define DOF_SECT_XLIMPORT 23 /* dof_xlator_t */
-+#define DOF_SECT_XLEXPORT 24 /* dof_xlator_t */
-+#define DOF_SECT_PREXPORT 25 /* dof_secidx_t array (exported objs) */
-+#define DOF_SECT_PRENOFFS 26 /* uint32_t array (enabled offsets) */
-+
-+#define DOF_SECF_LOAD 1 /* section should be loaded */
-+
-+#define DOF_SEC_ISLOADABLE(x) \
-+ (((x) == DOF_SECT_ECBDESC) || ((x) == DOF_SECT_PROBEDESC) || \
-+ ((x) == DOF_SECT_ACTDESC) || ((x) == DOF_SECT_DIFOHDR) || \
-+ ((x) == DOF_SECT_DIF) || ((x) == DOF_SECT_STRTAB) || \
-+ ((x) == DOF_SECT_VARTAB) || ((x) == DOF_SECT_RELTAB) || \
-+ ((x) == DOF_SECT_TYPTAB) || ((x) == DOF_SECT_URELHDR) || \
-+ ((x) == DOF_SECT_KRELHDR) || ((x) == DOF_SECT_OPTDESC) || \
-+ ((x) == DOF_SECT_PROVIDER) || ((x) == DOF_SECT_PROBES) || \
-+ ((x) == DOF_SECT_PRARGS) || ((x) == DOF_SECT_PROFFS) || \
-+ ((x) == DOF_SECT_INTTAB) || ((x) == DOF_SECT_XLTAB) || \
-+ ((x) == DOF_SECT_XLMEMBERS) || ((x) == DOF_SECT_XLIMPORT) || \
-+ ((x) == DOF_SECT_XLIMPORT) || ((x) == DOF_SECT_XLEXPORT) || \
-+ ((x) == DOF_SECT_PREXPORT) || ((x) == DOF_SECT_PRENOFFS))
-+
-+#define DOF_RELO_NONE 0 /* empty relocation entry */
-+#define DOF_RELO_SETX 1 /* relocate setx value */
-+
-+typedef uint32_t dof_attr_t; /* encoded stability attributes */
-+
-+#define DOF_ATTR(n, d, c) (((n) << 24) | ((d) << 16) | ((c) << 8))
-+#define DOF_ATTR_NAME(a) (((a) >> 24) & 0xff)
-+#define DOF_ATTR_DATA(a) (((a) >> 16) & 0xff)
-+#define DOF_ATTR_CLASS(a) (((a) >> 8) & 0xff)
-+
-+struct dof_hdr;
-+struct dof_sec;
-+struct dof_ecbdesc;
-+struct dof_probedesc;
-+struct dof_actdesc;
-+struct dof_difohdr;
-+struct dof_relohdr;
-+struct dof_relodesc;
-+struct dof_optdesc;
-+struct dof_provider;
-+struct dof_xlator;
-+struct dof_xlmember;
-+struct dof_xlref;
-+
-+#endif /* _LINUX_DTRACE_DOF_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/dtrace.h b/include/uapi/linux/dtrace/dtrace.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..0ee9d35876ef5db0c5231c780735681434917e40
---- /dev/null
-+++ b/include/uapi/linux/dtrace/dtrace.h
-@@ -0,0 +1,33 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_H_
-+#define _LINUX_DTRACE_H_
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/dif.h>
-+#include <linux/dtrace/actions.h>
-+#include <linux/dtrace/dof.h>
-+#include <linux/dtrace/difo.h>
-+#include <linux/dtrace/enabling.h>
-+#include <linux/dtrace/metadesc.h>
-+#include <linux/dtrace/options.h>
-+#include <linux/dtrace/buffer.h>
-+#include <linux/dtrace/status.h>
-+#include <linux/dtrace/conf.h>
-+#include <linux/dtrace/faults.h>
-+#include <linux/dtrace/arg.h>
-+#include <linux/dtrace/stability.h>
-+#include <linux/dtrace/helpers.h>
-+
-+#endif /* _LINUX_DTRACE_H_ */
-diff --git a/include/uapi/linux/dtrace/enabling.h b/include/uapi/linux/dtrace/enabling.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..8aac2ab9ea8daa3ddeae345584eb85b21b6418df
---- /dev/null
-+++ b/include/uapi/linux/dtrace/enabling.h
-@@ -0,0 +1,76 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ENABLING_H
-+#define _LINUX_DTRACE_ENABLING_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/difo_defines.h>
-+#include <linux/dtrace/enabling_defines.h>
-+
-+/*
-+ * When DTrace is tracking the description of a DTrace enabling entity (probe,
-+ * predicate, action, ECB, record, etc.), it does so in a description
-+ * structure. These structures all end in "desc", and are used at both
-+ * user-level and in the kernel -- but (with the exception of
-+ * dtrace_probedesc_t) they are never passed between them. Typically,
-+ * user-level will use the description structures when assembling an enabling.
-+ * It will then distill those description structures into a DOF object (see
-+ * above), and send it into the kernel. The kernel will again use the
-+ * description structures to create a description of the enabling as it reads
-+ * the DOF. When the description is complete, the enabling will be actually
-+ * created -- turning it into the structures that represent the enabling
-+ * instead of merely describing it. Not surprisingly, the description
-+ * structures bear a strong resemblance to the DOF structures that act as their
-+ * conduit.
-+ */
-+
-+struct dtrace_predicate;
-+
-+typedef struct dtrace_probedesc {
-+ dtrace_id_t dtpd_id; /* probe identifier */
-+ char dtpd_provider[DTRACE_PROVNAMELEN]; /* probe provider name */
-+ char dtpd_mod[DTRACE_MODNAMELEN]; /* probe module name */
-+ char dtpd_func[DTRACE_FUNCNAMELEN]; /* probe function name */
-+ char dtpd_name[DTRACE_NAMELEN]; /* probe name */
-+} dtrace_probedesc_t;
-+
-+typedef struct dtrace_repldesc {
-+ struct dtrace_probedesc dtrpd_match; /* probe descr. to match */
-+ struct dtrace_probedesc dtrpd_create; /* probe descr. to create */
-+} dtrace_repldesc_t;
-+
-+typedef struct dtrace_preddesc {
-+ struct dtrace_difo *dtpdd_difo; /* pointer to DIF object */
-+ struct dtrace_predicate *dtpdd_predicate; /* pointer to predicate */
-+} dtrace_preddesc_t;
-+
-+typedef struct dtrace_actdesc {
-+ struct dtrace_difo *dtad_difo; /* pointer to DIF object */
-+ struct dtrace_actdesc *dtad_next; /* next action */
-+ dtrace_actkind_t dtad_kind; /* kind of action */
-+ uint32_t dtad_ntuple; /* number in tuple */
-+ uint64_t dtad_arg; /* action argument */
-+ uint64_t dtad_uarg; /* user argument */
-+ int dtad_refcnt; /* reference count */
-+} dtrace_actdesc_t;
-+
-+typedef struct dtrace_ecbdesc {
-+ struct dtrace_actdesc *dted_action; /* action description(s) */
-+ struct dtrace_preddesc dted_pred; /* predicate description */
-+ struct dtrace_probedesc dted_probe; /* probe description */
-+ uint64_t dted_uarg; /* library argument */
-+ int dted_refcnt; /* reference count */
-+} dtrace_ecbdesc_t;
-+
-+#endif /* _LINUX_DTRACE_ENABLING_H */
-diff --git a/include/uapi/linux/dtrace/enabling_defines.h b/include/uapi/linux/dtrace/enabling_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..221c3efca015cb0737648eaa345d4910e57bb485
---- /dev/null
-+++ b/include/uapi/linux/dtrace/enabling_defines.h
-@@ -0,0 +1,25 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_ENABLING_DEFINES_H
-+#define _LINUX_DTRACE_ENABLING_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_probedesc;
-+struct dtrace_repldesc;
-+struct dtrace_preddesc;
-+struct dtrace_actdesc;
-+struct dtrace_ecbdesc;
-+
-+#endif /* _LINUX_DTRACE_ENABLING_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/fasttrap.h b/include/uapi/linux/dtrace/fasttrap.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..4dbf1a2a35cd6f9a6b3f1ad86eaa2c67bb516ea6
---- /dev/null
-+++ b/include/uapi/linux/dtrace/fasttrap.h
-@@ -0,0 +1,56 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FASTTRAP_H
-+#define _LINUX_DTRACE_FASTTRAP_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/fasttrap_defines.h>
-+
-+typedef enum fasttrap_probe_type {
-+ DTFTP_NONE = 0,
-+ DTFTP_ENTRY,
-+ DTFTP_RETURN,
-+ DTFTP_OFFSETS,
-+ DTFTP_POST_OFFSETS,
-+ DTFTP_IS_ENABLED
-+} fasttrap_probe_type_t;
-+
-+typedef struct fasttrap_probe_spec {
-+ pid_t ftps_pid; /* task PID */
-+ enum fasttrap_probe_type ftps_type; /* probe type */
-+ char ftps_func[DTRACE_FUNCNAMELEN]; /* probe function */
-+ char ftps_mod[DTRACE_MODNAMELEN]; /* probe module */
-+ uint64_t ftps_pc; /* probe address */
-+ uint64_t ftps_size; /* function size (in bytes) */
-+ uint8_t ftps_glen; /* glob pattern length */
-+ char ftps_gstr[1]; /* glob pattern string */
-+} fasttrap_probe_spec_t;
-+
-+typedef uint8_t fasttrap_instr_t;
-+
-+typedef struct fasttrap_instr_query {
-+ uint64_t ftiq_pc;
-+ pid_t ftiq_pid;
-+ fasttrap_instr_t ftiq_instr;
-+} fasttrap_instr_query_t;
-+
-+/*
-+ * Include after the definitions, to get ioctl()s when fasttrap.h is included.
-+ * fasttrap_ioctl.h also #includes this header, to get structures when it is
-+ * included itself, as is done by headers_check.
-+ */
-+
-+#include <linux/dtrace/fasttrap_ioctl.h>
-+
-+#endif /* _LINUX_DTRACE_FASTTRAP_H */
-diff --git a/include/uapi/linux/dtrace/fasttrap_defines.h b/include/uapi/linux/dtrace/fasttrap_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..4bb07564e1c454f617fc8afb786decf84910612b
---- /dev/null
-+++ b/include/uapi/linux/dtrace/fasttrap_defines.h
-@@ -0,0 +1,25 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FASTTRAP_DEFINES_H
-+#define _LINUX_DTRACE_FASTTRAP_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+#ifndef __cplusplus
-+enum fasttrap_probe_type;
-+#endif
-+struct fasttrap_probe_spec;
-+struct fasttrap_instr_query;
-+
-+#endif /* _LINUX_DTRACE_FASTTRAP_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/fasttrap_ioctl.h b/include/uapi/linux/dtrace/fasttrap_ioctl.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..b5a8b0731fb67cf2155c83dada7a5b09547d937b
---- /dev/null
-+++ b/include/uapi/linux/dtrace/fasttrap_ioctl.h
-@@ -0,0 +1,19 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FASTRRAP_IOCTL_H_
-+#define _LINUX_DTRACE_FASTTRAP_IOCTL_H_
-+
-+#include <linux/ioctl.h>
-+#include <linux/dtrace/fasttrap.h>
-+
-+#define FASTTRAPIOC 0xf4
-+#define FASTTRAPIOC_MAKEPROBE _IOW(FASTTRAPIOC, 1, struct fasttrap_probe_spec)
-+#define FASTTRAPIOC_GETINSTR _IOR(FASTTRAPIOC, 2, struct fasttrap_instr_query)
-+
-+#endif /* _LINUX_DTRACE_FASTTRAP_IOCTL_H_ */
-diff --git a/include/uapi/linux/dtrace/faults.h b/include/uapi/linux/dtrace/faults.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..afa2ae548fa6952b30fb4c6fc19e4d1436392908
---- /dev/null
-+++ b/include/uapi/linux/dtrace/faults.h
-@@ -0,0 +1,20 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FAULTS_H
-+#define _LINUX_DTRACE_FAULTS_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/faults_defines.h>
-+
-+#endif /* _LINUX_DTRACE_FAULTS_H */
-diff --git a/include/uapi/linux/dtrace/faults_defines.h b/include/uapi/linux/dtrace/faults_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..d225f2e847e4f9359c11ceaf736cbd6ae3de3474
---- /dev/null
-+++ b/include/uapi/linux/dtrace/faults_defines.h
-@@ -0,0 +1,39 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FAULTS_DEFINES_H
-+#define _LINUX_DTRACE_FAULTS_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * The constants below DTRACEFLT_LIBRARY indicate probe processing faults;
-+ * constants at or above DTRACEFLT_LIBRARY indicate faults in probe
-+ * postprocessing at user-level. Probe processing faults induce an ERROR
-+ * probe and are replicated in unistd.d to allow users' ERROR probes to decode
-+ * the error condition using thse symbolic labels.
-+ */
-+#define DTRACEFLT_UNKNOWN 0 /* Unknown fault */
-+#define DTRACEFLT_BADADDR 1 /* Bad address */
-+#define DTRACEFLT_BADALIGN 2 /* Bad alignment */
-+#define DTRACEFLT_ILLOP 3 /* Illegal operation */
-+#define DTRACEFLT_DIVZERO 4 /* Divide-by-zero */
-+#define DTRACEFLT_NOSCRATCH 5 /* Out of scratch space */
-+#define DTRACEFLT_KPRIV 6 /* Illegal kernel access */
-+#define DTRACEFLT_UPRIV 7 /* Illegal user access */
-+#define DTRACEFLT_TUPOFLOW 8 /* Tuple stack overflow */
-+#define DTRACEFLT_BADSTACK 9 /* Bad stack */
-+
-+#define DTRACEFLT_LIBRARY 1000 /* Library-level fault */
-+
-+#endif /* _LINUX_DTRACE_FAULTS_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/helpers.h b/include/uapi/linux/dtrace/helpers.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..553f2399488120b20e37bbeee269ad2276977c6f
---- /dev/null
-+++ b/include/uapi/linux/dtrace/helpers.h
-@@ -0,0 +1,101 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_HELPERS_H
-+#define _LINUX_DTRACE_HELPERS_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/helpers_defines.h>
-+
-+/*
-+ * DTrace Helpers
-+ *
-+ * In general, DTrace establishes probes in processes and takes actions on
-+ * processes without knowing their specific user-level structures. Instead of
-+ * existing in the framework, process-specific knowledge is contained by the
-+ * enabling D program -- which can apply process-specific knowledge by making
-+ * appropriate use of DTrace primitives like copyin() and copyinstr() to
-+ * operate on user-level data. However, there may exist some specific probes
-+ * of particular semantic relevance that the application developer may wish to
-+ * explicitly export. For example, an application may wish to export a probe
-+ * at the point that it begins and ends certain well-defined transactions. In
-+ * addition to providing probes, programs may wish to offer assistance for
-+ * certain actions. For example, in highly dynamic environments (e.g., Java),
-+ * it may be difficult to obtain a stack trace in terms of meaningful symbol
-+ * names (the translation from instruction addresses to corresponding symbol
-+ * names may only be possible in situ); these environments may wish to define
-+ * a series of actions to be applied in situ to obtain a meaningful stack
-+ * trace.
-+ *
-+ * These two mechanisms -- user-level statically defined tracing and assisting
-+ * DTrace actions -- are provided via DTrace _helpers_. Helpers are specified
-+ * via DOF, but unlike enabling DOF, helper DOF may contain definitions of
-+ * providers, probes and their arguments. If a helper wishes to provide
-+ * action assistance, probe descriptions and corresponding DIF actions may be
-+ * specified in the helper DOF. For such helper actions, however, the probe
-+ * description describes the specific helper: all DTrace helpers have the
-+ * provider name "dtrace" and the module name "helper", and the name of the
-+ * helper is contained in the function name (for example, the ustack() helper
-+ * is named "ustack"). Any helper-specific name may be contained in the name
-+ * (for example, if a helper were to have a constructor, it might be named
-+ * "dtrace:helper:<helper>:init"). Helper actions are only called when the
-+ * action that they are helping is taken. Helper actions may only return DIF
-+ * expressions, and may only call the following subroutines:
-+ *
-+ * alloca() <= Allocates memory out of the consumer's scratch space
-+ * bcopy() <= Copies memory to scratch space
-+ * copyin() <= Copies memory from user-level into consumer's scratch
-+ * copyinto() <= Copies memory into a specific location in scratch
-+ * copyinstr() <= Copies a string into a specific location in scratch
-+ *
-+ * Helper actions may only access the following built-in variables:
-+ *
-+ * curthread <= Current kthread_t pointer
-+ * tid <= Current thread identifier
-+ * pid <= Current process identifier
-+ * ppid <= Parent process identifier
-+ * uid <= Current user ID
-+ * gid <= Current group ID
-+ * execname <= Current executable name
-+ * zonename <= Current zone name
-+ *
-+ * Helper actions may not manipulate or allocate dynamic variables, but they
-+ * may have clause-local and statically-allocated global variables. The
-+ * helper action variable state is specific to the helper action -- variables
-+ * used by the helper action may not be accessed outside of the helper
-+ * action, and the helper action may not access variables that like outside
-+ * of it. Helper actions may not load from kernel memory at-large; they are
-+ * restricting to loading current user state (via copyin() and variants) and
-+ * scratch space. As with probe enablings, helper actions are executed in
-+ * program order. The result of the helper action is the result of the last
-+ * executing helper expression.
-+ *
-+ * Helpers -- composed of either providers/probes or probes/actions (or both)
-+ * -- are added by opening the "helper" minor node, and issuing an ioctl(2)
-+ * (DTRACEHIOC_ADDDOF) that specifies the dof_helper_t structure. This
-+ * encapsulates the name and base address of the user-level library or
-+ * executable publishing the helpers and probes as well as the DOF that
-+ * contains the definitions of those helpers and probes.
-+ *
-+ * The DTRACEHIOC_ADD and DTRACEHIOC_REMOVE are left in place for legacy
-+ * helpers and should no longer be used. No other ioctls are valid on the
-+ * helper minor node.
-+ */
-+
-+typedef struct dof_helper {
-+ char dofhp_mod[DTRACE_MODNAMELEN]; /* executable or library name */
-+ uint64_t dofhp_addr; /* base address of object */
-+ uint64_t dofhp_dof; /* address of helper DOF */
-+} dof_helper_t;
-+
-+#endif /* _LINUX_DTRACE_HELPERS_H */
-diff --git a/include/uapi/linux/dtrace/helpers_defines.h b/include/uapi/linux/dtrace/helpers_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..8bf52f05800199eac66a99187b007f9d48785484
---- /dev/null
-+++ b/include/uapi/linux/dtrace/helpers_defines.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_HELPERS_DEFINES_H
-+#define _LINUX_DTRACE_HELPERS_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dof_helper;
-+
-+#endif /* _LINUX_DTRACE_HELPERS_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/ioctl.h b/include/uapi/linux/dtrace/ioctl.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..ef2476af2629166d7b0acd66c5d87d039c49f636
---- /dev/null
-+++ b/include/uapi/linux/dtrace/ioctl.h
-@@ -0,0 +1,47 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_IOCTL_H_
-+#define _LINUX_DTRACE_IOCTL_H_
-+
-+#include <linux/ioctl.h>
-+#include <linux/dtrace/arg.h>
-+#include <linux/dtrace/buffer.h>
-+#include <linux/dtrace/conf.h>
-+#include <linux/dtrace/dof.h>
-+#include <linux/dtrace/enabling.h>
-+#include <linux/dtrace/helpers.h>
-+#include <linux/dtrace/metadesc.h>
-+#include <linux/dtrace/stability.h>
-+#include <linux/dtrace/status.h>
-+#include <linux/dtrace/cpu_defines.h>
-+
-+#define DTRACEIOC 0xd4
-+#define DTRACEIOC_PROVIDER _IOR(DTRACEIOC, 1, struct dtrace_providerdesc)
-+#define DTRACEIOC_PROBES _IOR(DTRACEIOC, 2, struct dtrace_probedesc)
-+#define DTRACEIOC_BUFSNAP _IOR(DTRACEIOC, 4, struct dtrace_bufdesc)
-+#define DTRACEIOC_PROBEMATCH _IOR(DTRACEIOC, 5, struct dtrace_probedesc)
-+#define DTRACEIOC_ENABLE _IOW(DTRACEIOC, 6, void *)
-+#define DTRACEIOC_AGGSNAP _IOR(DTRACEIOC, 7, struct dtrace_bufdesc)
-+#define DTRACEIOC_EPROBE _IOW(DTRACEIOC, 8, struct dtrace_eprobedesc)
-+#define DTRACEIOC_PROBEARG _IOR(DTRACEIOC, 9, struct dtrace_argdesc)
-+#define DTRACEIOC_CONF _IOR(DTRACEIOC, 10, struct dtrace_conf)
-+#define DTRACEIOC_STATUS _IOR(DTRACEIOC, 11, struct dtrace_status)
-+#define DTRACEIOC_GO _IOW(DTRACEIOC, 12, processorid_t)
-+#define DTRACEIOC_STOP _IOW(DTRACEIOC, 13, processorid_t)
-+#define DTRACEIOC_AGGDESC _IOR(DTRACEIOC, 15, struct dtrace_aggdesc)
-+#define DTRACEIOC_FORMAT _IOR(DTRACEIOC, 16, struct dtrace_fmtdesc)
-+#define DTRACEIOC_DOFGET _IOR(DTRACEIOC, 17, struct dof_hdr)
-+#define DTRACEIOC_REPLICATE _IOR(DTRACEIOC, 18, void *)
-+
-+#define DTRACEHIOC 0xd8
-+#define DTRACEHIOC_ADD _IOW(DTRACEHIOC, 1, struct dof_hdr)
-+#define DTRACEHIOC_REMOVE _IOW(DTRACEHIOC, 2, int)
-+#define DTRACEHIOC_ADDDOF _IOW(DTRACEHIOC, 3, struct dof_helper)
-+
-+#endif /* _LINUX_DTRACE_IOCTL_H */
-diff --git a/include/uapi/linux/dtrace/metadesc.h b/include/uapi/linux/dtrace/metadesc.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..a6b3d82b2c97b4cb1da600362ac1b6d09f8963fd
---- /dev/null
-+++ b/include/uapi/linux/dtrace/metadesc.h
-@@ -0,0 +1,81 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_METADESC_H
-+#define _LINUX_DTRACE_METADESC_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/actions_defines.h>
-+#include <linux/dtrace/metadesc_defines.h>
-+
-+/*
-+ * DTrace separates the trace data stream from the metadata stream. The only
-+ * metadata tokens placed in the data stream are enabled probe identifiers
-+ * (EPIDs) or (in the case of aggregations) aggregation identifiers. In order
-+ * to determine the structure of the data, DTrace consumers pass the token to
-+ * the kernel, and receive in return a corresponding description of the enabled
-+ * probe (via the dtrace_eprobedesc structure) or the aggregation (via the
-+ * dtrace_aggdesc structure). Both of these structures are expressed in terms
-+ * of record descriptions (via the dtrace_recdesc structure) that describe the
-+ * exact structure of the data. Some record descriptions may also contain a
-+ * format identifier; this additional bit of metadata can be retrieved from the
-+ * kernel, for which a format description is returned via the dtrace_fmtdesc
-+ * structure. Note that all four of these structures must be bitness-neutral
-+ * to allow for a 32-bit DTrace consumer on a 64-bit kernel.
-+ */
-+typedef struct dtrace_recdesc {
-+ dtrace_actkind_t dtrd_action; /* kind of action */
-+ uint32_t dtrd_size; /* size of record */
-+ uint32_t dtrd_offset; /* offset in ECB's data */
-+ uint16_t dtrd_alignment; /* required alignment */
-+ uint16_t dtrd_format; /* format, if any */
-+ uint64_t dtrd_arg; /* action argument */
-+ uint64_t dtrd_uarg; /* user argument */
-+} dtrace_recdesc_t;
-+
-+typedef struct dtrace_eprobedesc {
-+ dtrace_epid_t dtepd_epid; /* enabled probe ID */
-+ dtrace_id_t dtepd_probeid; /* probe ID */
-+ uint64_t dtepd_uarg; /* library argument */
-+ uint32_t dtepd_size; /* total size */
-+ int dtepd_nrecs; /* number of records */
-+ struct dtrace_recdesc dtepd_rec[1]; /* records themselves */
-+} dtrace_eprobedesc_t;
-+
-+typedef struct dtrace_aggdesc {
-+ DTRACE_PTR(char, dtagd_name); /* not filled in by kernel */
-+ dtrace_aggvarid_t dtagd_varid; /* not filled in by kernel */
-+ int dtagd_flags; /* not filled in by kernel */
-+ dtrace_aggid_t dtagd_id; /* aggregation ID */
-+ dtrace_epid_t dtagd_epid; /* enabled probe ID */
-+ uint32_t dtagd_size; /* size in bytes */
-+ int dtagd_nrecs; /* number of records */
-+ uint32_t dtagd_pad; /* explicit padding */
-+ struct dtrace_recdesc dtagd_rec[1]; /* record descriptions */
-+} dtrace_aggdesc_t;
-+
-+typedef struct dtrace_fmtdesc {
-+ DTRACE_PTR(char, dtfd_string); /* format string */
-+ int dtfd_length; /* length of format string */
-+ uint16_t dtfd_format; /* format identifier */
-+} dtrace_fmtdesc_t;
-+
-+#define DTRACE_SIZEOF_EPROBEDESC(desc) \
-+ (sizeof(struct dtrace_eprobedesc) + ((desc)->dtepd_nrecs ? \
-+ (((desc)->dtepd_nrecs - 1) * sizeof(struct dtrace_recdesc)) : 0))
-+
-+#define DTRACE_SIZEOF_AGGDESC(desc) \
-+ (sizeof(struct dtrace_aggdesc) + ((desc)->dtagd_nrecs ? \
-+ (((desc)->dtagd_nrecs - 1) * sizeof(struct dtrace_recdesc)) : 0))
-+
-+#endif /* _LINUX_DTRACE_METADESC_H */
-diff --git a/include/uapi/linux/dtrace/metadesc_defines.h b/include/uapi/linux/dtrace/metadesc_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..b27cc28822c87fc50c8419633cf8b57c6bea98c1
---- /dev/null
-+++ b/include/uapi/linux/dtrace/metadesc_defines.h
-@@ -0,0 +1,24 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_METADESC_DEFINES_H
-+#define _LINUX_DTRACE_METADESC_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+struct dtrace_recdesc;
-+struct dtrace_eprobedesc;
-+struct dtrace_aggdesc;
-+struct dtrace_fmtdesc;
-+
-+#endif /* _LINUX_DTRACE_METADESC_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/options.h b/include/uapi/linux/dtrace/options.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..0a652ca2a1485689b06fbc250d0521c08027d52a
---- /dev/null
-+++ b/include/uapi/linux/dtrace/options.h
-@@ -0,0 +1,20 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_OPTIONS_H
-+#define _LINUX_DTRACE_OPTIONS_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/options_defines.h>
-+
-+#endif /* _LINUX_DTRACE_OPTIONS_H */
-diff --git a/include/uapi/linux/dtrace/options_defines.h b/include/uapi/linux/dtrace/options_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..26009c84437e7ba3459b0e35f38ccc2a99862f7d
---- /dev/null
-+++ b/include/uapi/linux/dtrace/options_defines.h
-@@ -0,0 +1,72 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_OPTIONS_DEFINES_H
-+#define _LINUX_DTRACE_OPTIONS_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * Run-time DTrace options are set and retrieved via DOF_SECT_OPTDESC sections
-+ * in a DOF image. The dof_optdesc structure contains an option identifier and
-+ * an option value. The valid option identifiers are found below; the mapping
-+ * between option identifiers and option identifying strings is maintained at
-+ * user-level. Note that the value of DTRACEOPT_UNSET is such that all of the
-+ * following are potentially valid option values: all positive integers, zero
-+ * and negative one. Some options (notably "bufpolicy" and "bufresize") take
-+ * predefined tokens as their values; these are defined with
-+ * DTRACEOPT_{option}_{token}.
-+ */
-+
-+#define DTRACEOPT_BUFSIZE 0 /* buffer size */
-+#define DTRACEOPT_BUFPOLICY 1 /* buffer policy */
-+#define DTRACEOPT_DYNVARSIZE 2 /* dynamic variable size */
-+#define DTRACEOPT_AGGSIZE 3 /* aggregation size */
-+#define DTRACEOPT_SPECSIZE 4 /* speculation size */
-+#define DTRACEOPT_NSPEC 5 /* number of speculations */
-+#define DTRACEOPT_STRSIZE 6 /* string size */
-+#define DTRACEOPT_CLEANRATE 7 /* dynvar cleaning rate */
-+#define DTRACEOPT_CPU 8 /* CPU to trace */
-+#define DTRACEOPT_BUFRESIZE 9 /* buffer resizing policy */
-+#define DTRACEOPT_GRABANON 10 /* grab anonymous state, if any */
-+#define DTRACEOPT_FLOWINDENT 11 /* indent function entry/return */
-+#define DTRACEOPT_QUIET 12 /* only output explicitly traced data */
-+#define DTRACEOPT_STACKFRAMES 13 /* number of stack frames */
-+#define DTRACEOPT_USTACKFRAMES 14 /* number of user stack frames */
-+#define DTRACEOPT_AGGRATE 15 /* aggregation snapshot rate */
-+#define DTRACEOPT_SWITCHRATE 16 /* buffer switching rate */
-+#define DTRACEOPT_STATUSRATE 17 /* status rate */
-+#define DTRACEOPT_DESTRUCTIVE 18 /* destructive actions allowed */
-+#define DTRACEOPT_STACKINDENT 19 /* output indent for stack traces */
-+#define DTRACEOPT_RAWBYTES 20 /* always print bytes in raw form */
-+#define DTRACEOPT_JSTACKFRAMES 21 /* number of jstack() frames */
-+#define DTRACEOPT_JSTACKSTRSIZE 22 /* size of jstack() string table */
-+#define DTRACEOPT_AGGSORTKEY 23 /* sort aggregations by key */
-+#define DTRACEOPT_AGGSORTREV 24 /* reverse-sort aggregations */
-+#define DTRACEOPT_AGGSORTPOS 25 /* agg. position to sort on */
-+#define DTRACEOPT_AGGSORTKEYPOS 26 /* agg. key position to sort on */
-+#define DTRACEOPT_QUIETRESIZE 27 /* quieten buffer-resize messages */
-+#define DTRACEOPT_NORESOLVE 28 /* prevent resolution of symbols */
-+#define DTRACEOPT_PCAPSIZE 29 /* number of bytes to be captured */
-+#define DTRACEOPT_MAX 30 /* number of options */
-+
-+#define DTRACEOPT_UNSET (dtrace_optval_t)-2 /* unset option */
-+
-+#define DTRACEOPT_BUFPOLICY_RING 0 /* ring buffer */
-+#define DTRACEOPT_BUFPOLICY_FILL 1 /* fill buffer, then stop */
-+#define DTRACEOPT_BUFPOLICY_SWITCH 2 /* switch buffers */
-+
-+#define DTRACEOPT_BUFRESIZE_AUTO 0 /* automatic resizing */
-+#define DTRACEOPT_BUFRESIZE_MANUAL 1 /* manual resizing */
-+
-+#endif /* _LINUX_DTRACE_OPTIONS_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/stability.h b/include/uapi/linux/dtrace/stability.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..380effdab2916dd2ab0bff8c9b73d1f624476cd0
---- /dev/null
-+++ b/include/uapi/linux/dtrace/stability.h
-@@ -0,0 +1,52 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_STABILITY_H
-+#define _LINUX_DTRACE_STABILITY_H
-+
-+#include <linux/dtrace/universal.h>
-+#include <linux/dtrace/stability_defines.h>
-+
-+/*
-+ * Each DTrace provider advertises the name and data stability of each of its
-+ * probe description components, as well as its architectural dependencies. The
-+ * D compiler can query the provider attributes (dtrace_pattr_t) in order to
-+ * compute the properties of an input program and report them.
-+ */
-+
-+typedef struct dtrace_ppriv {
-+ uint32_t dtpp_flags; /* privilege flags */
-+ uid_t dtpp_uid; /* user ID */
-+} dtrace_ppriv_t;
-+
-+typedef struct dtrace_attribute {
-+ dtrace_stability_t dtat_name; /* entity name stability */
-+ dtrace_stability_t dtat_data; /* entity data stability */
-+ dtrace_class_t dtat_class; /* entity data dependency */
-+} dtrace_attribute_t;
-+
-+typedef struct dtrace_pattr {
-+ struct dtrace_attribute dtpa_provider; /* provider attributes */
-+ struct dtrace_attribute dtpa_mod; /* module attributes */
-+ struct dtrace_attribute dtpa_func; /* function attributes */
-+ struct dtrace_attribute dtpa_name; /* name attributes */
-+ struct dtrace_attribute dtpa_args; /* args[] attributes */
-+} dtrace_pattr_t;
-+
-+typedef struct dtrace_providerdesc {
-+ char dtvd_name[DTRACE_PROVNAMELEN]; /* provider name */
-+ struct dtrace_pattr dtvd_attr; /* stability attributes */
-+ struct dtrace_ppriv dtvd_priv; /* privileges required */
-+} dtrace_providerdesc_t;
-+
-+#endif /* _LINUX_DTRACE_STABILITY_H */
-diff --git a/include/uapi/linux/dtrace/stability_defines.h b/include/uapi/linux/dtrace/stability_defines.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..ca58c5c03c2b5456fd9bf89d713b063df0de1f37
---- /dev/null
-+++ b/include/uapi/linux/dtrace/stability_defines.h
-@@ -0,0 +1,53 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_STABILITY_DEFINES_H
-+#define _LINUX_DTRACE_STABILITY_DEFINES_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+typedef uint8_t dtrace_stability_t; /* stability code */
-+typedef uint8_t dtrace_class_t; /* architectural dependency class */
-+
-+#define DTRACE_STABILITY_INTERNAL 0 /* private to DTrace itself */
-+#define DTRACE_STABILITY_PRIVATE 1 /* private to Sun (see docs) */
-+#define DTRACE_STABILITY_OBSOLETE 2 /* scheduled for removal */
-+#define DTRACE_STABILITY_EXTERNAL 3 /* not controlled by Sun */
-+#define DTRACE_STABILITY_UNSTABLE 4 /* new or rapidly changing */
-+#define DTRACE_STABILITY_EVOLVING 5 /* less rapidly changing */
-+#define DTRACE_STABILITY_STABLE 6 /* mature interface from Sun */
-+#define DTRACE_STABILITY_STANDARD 7 /* industry standard */
-+#define DTRACE_STABILITY_MAX 7 /* maximum valid stability */
-+
-+#define DTRACE_CLASS_UNKNOWN 0 /* unknown architectural dependency */
-+#define DTRACE_CLASS_CPU 1 /* CPU-module-specific */
-+#define DTRACE_CLASS_PLATFORM 2 /* platform-specific (uname -i) */
-+#define DTRACE_CLASS_GROUP 3 /* hardware-group-specific (uname -m) */
-+#define DTRACE_CLASS_ISA 4 /* ISA-specific (uname -p) */
-+#define DTRACE_CLASS_COMMON 5 /* common to all systems */
-+#define DTRACE_CLASS_MAX 5 /* maximum valid class */
-+
-+#define DTRACE_PRIV_NONE 0x0000
-+#define DTRACE_PRIV_KERNEL 0x0001
-+#define DTRACE_PRIV_USER 0x0002
-+#define DTRACE_PRIV_PROC 0x0004
-+#define DTRACE_PRIV_OWNER 0x0008
-+#define DTRACE_PRIV_ALL (DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER | \
-+ DTRACE_PRIV_PROC | DTRACE_PRIV_OWNER)
-+
-+struct dtrace_ppriv;
-+struct dtrace_attribute;
-+struct dtrace_pattr;
-+struct dtrace_providerdesc;
-+
-+#endif /* _LINUX_DTRACE_STABILITY_DEFINES_H */
-diff --git a/include/uapi/linux/dtrace/status.h b/include/uapi/linux/dtrace/status.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..dc324199f170381f3ff661228143751a200669ca
---- /dev/null
-+++ b/include/uapi/linux/dtrace/status.h
-@@ -0,0 +1,50 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_STATUS_H
-+#define _LINUX_DTRACE_STATUS_H
-+
-+#include <linux/dtrace/universal.h>
-+
-+/*
-+ * The status of DTrace is relayed via the dtrace_status structure. This
-+ * structure contains members to count drops other than the capacity drops
-+ * available via the buffer interface (see above). This consists of dynamic
-+ * drops (including capacity dynamic drops, rinsing drops and dirty drops), and
-+ * speculative drops (including capacity speculative drops, drops due to busy
-+ * speculative buffers and drops due to unavailable speculative buffers).
-+ * Additionally, the status structure contains a field to indicate the number
-+ * of "fill"-policy buffers have been filled and a boolean field to indicate
-+ * that exit() has been called. If the dtst_exiting field is non-zero, no
-+ * further data will be generated until tracing is stopped (at which time any
-+ * enablings of the END action will be processed); if user-level sees that
-+ * this field is non-zero, tracing should be stopped as soon as possible.
-+ */
-+
-+typedef struct dtrace_status {
-+ uint64_t dtst_dyndrops; /* dynamic drops */
-+ uint64_t dtst_dyndrops_rinsing; /* dyn drops due to rinsing */
-+ uint64_t dtst_dyndrops_dirty; /* dyn drops due to dirty */
-+ uint64_t dtst_specdrops; /* speculative drops */
-+ uint64_t dtst_specdrops_busy; /* spec drops due to busy */
-+ uint64_t dtst_specdrops_unavail; /* spec drops due to unavail */
-+ uint64_t dtst_errors; /* total errors */
-+ uint64_t dtst_filled; /* number of filled bufs */
-+ uint64_t dtst_stkstroverflows; /* stack string tab overflows */
-+ uint64_t dtst_dblerrors; /* errors in ERROR probes */
-+ char dtst_killed; /* non-zero if killed */
-+ char dtst_exiting; /* non-zero if exit() called */
-+ char dtst_pad[6]; /* pad out to 64-bit align */
-+} dtrace_status_t;
-+
-+#endif /* _LINUX_DTRACE_STATUS_H */
-diff --git a/include/uapi/linux/dtrace/universal.h b/include/uapi/linux/dtrace/universal.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..5c2f3f838fef435bf44cd0d4581900f1446fef12
---- /dev/null
-+++ b/include/uapi/linux/dtrace/universal.h
-@@ -0,0 +1,47 @@
-+/* SPDX-License-Identifier: UPL-1.0 */
-+/*
-+ * Licensed under the Universal Permissive License v 1.0 as shown at
-+ * http://oss.oracle.com/licenses/upl.
-+ *
-+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _LINUX_DTRACE_UNIVERSAL_H_
-+#define _LINUX_DTRACE_UNIVERSAL_H_
-+
-+#define DTRACE_CPUALL -1 /* all CPUs */
-+#define DTRACE_IDNONE 0 /* invalid probe identifier */
-+#define DTRACE_EPIDNONE 0 /* invalid enabled probe identifier */
-+#define DTRACE_AGGIDNONE 0 /* invalid aggregation identifier */
-+#define DTRACE_AGGVARIDNONE 0 /* invalid aggregation variable ID */
-+#define DTRACE_CACHEIDNONE 0 /* invalid predicate cache */
-+#define DTRACE_PROVNONE 0 /* invalid provider identifier */
-+#define DTRACE_METAPROVNONE 0 /* invalid meta-provider identifier */
-+#define DTRACE_ARGNONE -1 /* invalid argument index */
-+
-+#define DTRACE_PROVNAMELEN 64
-+#define DTRACE_MODNAMELEN 64
-+#define DTRACE_FUNCNAMELEN 128
-+#define DTRACE_NAMELEN 64
-+#define DTRACE_FULLNAMELEN (DTRACE_PROVNAMELEN + DTRACE_MODNAMELEN + \
-+ DTRACE_FUNCNAMELEN + DTRACE_NAMELEN + 4)
-+#define DTRACE_ARGTYPELEN 128
-+
-+typedef uint16_t dtrace_actkind_t; /* action kind */
-+
-+typedef uint32_t dtrace_aggid_t; /* aggregation identifier */
-+typedef uint32_t dtrace_cacheid_t; /* predicate cache identifier */
-+typedef uint32_t dtrace_epid_t; /* enabled probe identifier */
-+typedef uint32_t dtrace_optid_t; /* option identifier */
-+typedef uint32_t dtrace_specid_t; /* speculation identifier */
-+
-+typedef uint64_t dtrace_aggvarid_t; /* aggregation variable id */
-+typedef uint64_t dtrace_genid_t; /* generation identifier */
-+typedef uint64_t dtrace_optval_t; /* option value */
-+
-+#endif /* _LINUX_DTRACE_UNIVERSAL_H_ */
-diff --git a/init/Kconfig b/init/Kconfig
-index 5a86bbbf43e052f9092da824536c8e223c4a4329..0f1b919272daaa02ac0b40632641e5e0079721de 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -2052,6 +2052,8 @@ config PROFILING
- Say Y here to enable the extended profiling support mechanisms used
- by profilers such as OProfile.
-
-+source "kernel/dtrace/Kconfig"
-+
- #
- # Place an empty function call at each tracepoint site. Can be
- # dynamically changed for a probe function.
-diff --git a/init/main.c b/init/main.c
-index 9d964511fe0c2d9e8e0d3e8178fd237690415ce9..f510b7af38c20bca171a3d146781f99d37e8936a 100644
---- a/init/main.c
-+++ b/init/main.c
-@@ -98,6 +98,8 @@
- #include <linux/mem_encrypt.h>
- #include <linux/kcsan.h>
- #include <linux/init_syscalls.h>
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-
- #include <asm/io.h>
- #include <asm/bugs.h>
-@@ -1057,6 +1059,10 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
- sfi_init_late();
- kcsan_init();
-
-+#ifdef CONFIG_DTRACE
-+ dtrace_os_init();
-+#endif
-+
- /* Do the rest non-__init'ed, we're now alive */
- arch_call_rest_init();
-
-@@ -1512,6 +1518,10 @@ static noinline void __init kernel_init_freeable(void)
-
- init_mm_internals();
-
-+#ifdef CONFIG_DTRACE
-+ dtrace_cpu_init();
-+#endif
-+
- rcu_init_tasks_generic();
- do_pre_smp_initcalls();
- lockup_detector_init();
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 6c9f19911be03e526e29389811fda6247656a253..498cb12d89c6f57f44dd7e48f025f0176dfcbe44 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -121,6 +121,7 @@ obj-$(CONFIG_TORTURE_TEST) += torture.o
- obj-$(CONFIG_HAS_IOMEM) += iomem.o
- obj-$(CONFIG_RSEQ) += rseq.o
- obj-$(CONFIG_WATCH_QUEUE) += watch_queue.o
-+obj-$(CONFIG_DTRACE) += dtrace/
-
- obj-$(CONFIG_SYSCTL_KUNIT_TEST) += sysctl-test.o
-
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-new file mode 100644
-index 0000000000000000000000000000000000000000..854e4411343f9f7c773bf7fd54349fa46e6de5cb
---- /dev/null
-+++ b/kernel/dtrace/Kconfig
-@@ -0,0 +1,54 @@
-+#
-+# Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+#
-+
-+menuconfig DTRACE
-+ bool "DTrace (Dynamic Tracing) Support"
-+ default y
-+ depends on ARCH_SUPPORTS_DTRACE
-+ select KALLSYMS
-+ select KALLMODSYMS
-+ select WAITFD
-+ select CTF
-+ help
-+ The DTrace dynamic tracing framework.
-+
-+if DTRACE
-+
-+config DT_CORE
-+ tristate "DTrace core"
-+ default m
-+ help
-+ The core of DTrace: needed for all providers.
-+
-+if DT_CORE
-+
-+config DT_DT_TEST
-+ tristate "DTrace Test Probe"
-+ default m
-+ help
-+ A test provider used by the testsuite.
-+
-+config DT_DEBUG
-+ bool "DTrace debugging"
-+ default m
-+ help
-+ This controls the inclusion of various piece of code that perform
-+ internal checks within the DTrace core. It also enables all the
-+ assertions within the DTrace code.
-+
-+if DT_DEBUG
-+
-+config DT_DEBUG_MUTEX
-+ bool "DTrace mutex debugging"
-+ default n
-+ help
-+ This controls the use of DTrace specific wrappers to output debug
-+ messages whenever a mutex is locked or unlocked within the DTrace
-+ code (core and providers).
-+
-+endif # DT_DEBUG
-+
-+endif # DT_CORE
-+
-+endif #DTRACE
-diff --git a/kernel/dtrace/Makefile b/kernel/dtrace/Makefile
-new file mode 100644
-index 0000000000000000000000000000000000000000..872785327c3d8d9f1ec0e5555b86fd470e9d1fc2
---- /dev/null
-+++ b/kernel/dtrace/Makefile
-@@ -0,0 +1,12 @@
-+#
-+# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+#
-+
-+DT_CORE_ARCH_OBJS = $(addprefix ../../arch/$(SRCARCH)/kernel/, \
-+ dtrace_util.o)
-+
-+ifdef CONFIG_DT_CORE
-+obj-y += cyclic.o dtrace_os.o dtrace_cpu.o \
-+ dtrace_task.o dtrace_psinfo.o \
-+ $(DT_CORE_ARCH_OBJS)
-+endif
-diff --git a/kernel/dtrace/cyclic.c b/kernel/dtrace/cyclic.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..6497ceee378235267ca65c492f8a7e2656b34d5b
---- /dev/null
-+++ b/kernel/dtrace/cyclic.c
-@@ -0,0 +1,526 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: cyclic.c
-+ * DESCRIPTION: Minimal cyclic implementation
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/cpu.h>
-+#include <linux/cyclic.h>
-+#include <linux/hrtimer.h>
-+#include <linux/module.h>
-+#include <linux/proc_fs.h>
-+#include <linux/seq_file.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+#include <linux/workqueue.h>
-+
-+static int omni_enabled;
-+
-+#define _CYCLIC_CPU_UNDEF (-1)
-+#define _CYCLIC_CPU_OMNI (-2)
-+#define CYCLIC_IS_OMNI(cyc) ((cyc)->cpu == _CYCLIC_CPU_OMNI)
-+
-+struct cyclic_work {
-+ struct work_struct work;
-+ struct cyclic *cyc;
-+};
-+
-+struct cyclic {
-+ struct list_head list;
-+ int cpu;
-+ union {
-+ struct {
-+ struct cyc_time when;
-+ struct cyc_handler hdlr;
-+ uint32_t pend;
-+ struct hrtimer timr;
-+ struct cyclic_work work;
-+ } cyc;
-+ struct {
-+ struct cyc_omni_handler hdlr;
-+ struct list_head cycl;
-+ } omni;
-+ };
-+};
-+
-+static LIST_HEAD(cyclics);
-+
-+static void cyclic_fire(struct work_struct *work)
-+{
-+ struct cyclic_work *cwork = (struct cyclic_work *)work;
-+ struct cyclic *cyc = cwork->cyc;
-+ uint32_t cpnd, npnd;
-+
-+ do {
-+ /*
-+ * We know that the 'pend' counter for the cyclic is non-zero.
-+ * So, we can start with calling the handler at least once.
-+ */
-+ (*cyc->cyc.hdlr.cyh_func)(cyc->cyc.hdlr.cyh_arg);
-+
-+again:
-+ /*
-+ * The 'pend' counter may be modified by cyclic_expire() while
-+ * we go through this loop. We use an atomic compare-and-set
-+ * instruction to determine whether it got changed. If so, we
-+ * retrieve the updated 'pend' value and try this again.
-+ *
-+ * Note that when the cyclic is being removed, the hrtimer will
-+ * be cancelled first, which ensures that 'pend' will no longer
-+ * be incremented. When that happens, this loop will simply
-+ * run through the remaining pending calls, and terminate.
-+ */
-+ cpnd = cyc->cyc.pend;
-+ npnd = cpnd - 1;
-+ if (cmpxchg(&cyc->cyc.pend, cpnd, npnd) != cpnd)
-+ goto again;
-+ } while (npnd > 0);
-+}
-+
-+/*
-+ * Timer expiration handler for cyclic hrtimers. Cyclic worker functions must
-+ * be able to perform a variety of tasks (including calling functions that
-+ * could sleep), and therefore they cannot be called from interrupt context.
-+ *
-+ * We schedule a workqueue to do the actual work.
-+ *
-+ * But... under heavy load it is possible that the hrtimer will expire again
-+ * before the workqueue had a chance to run. That would lead to missed events
-+ * which isn't quite acceptable. Therefore, we use a counter to record how
-+ * many times the timer has expired vs how many times the handler has been
-+ * called. The counter is incremented by this function upon hrtimer expiration
-+ * and decremented by the cyclic_fire. Note that the workqueue is responsible
-+ * for calling the handler multiple times if the counter indicates that multiple
-+ * invocation are pending.
-+ *
-+ * This function is called as hrtimer handler, and therefore runs in interrupt
-+ * context, which by definition will ensure that manipulation of the 'pend'
-+ * counter in the cyclic can be done without locking, and changes will appear
-+ * atomic to the cyclic_fire().
-+ *
-+ * Moral of the story: the handler may not get called at the absolute times as
-+ * requested, but it will be called the correct number of times.
-+ */
-+static enum hrtimer_restart cyclic_expire(struct hrtimer *timr)
-+{
-+ struct cyclic *cyc = container_of(timr, struct cyclic, cyc.timr);
-+
-+ /*
-+ * High priority cyclics call directly into their handler. This means
-+ * that the handler must satisfy all requirements for executing code in
-+ * interrupt context.
-+ */
-+ if (cyc->cyc.hdlr.cyh_level == CY_HIGH_LEVEL) {
-+ (*cyc->cyc.hdlr.cyh_func)(cyc->cyc.hdlr.cyh_arg);
-+ goto done;
-+ }
-+
-+ /*
-+ * Increment the 'pend' counter, in case the work is already set to
-+ * run. If the counter was 0 upon entry, we need to schedule the
-+ * work. If the increment wraps the counter back to 0, we admit
-+ * defeat, and reset it to its max value.
-+ */
-+ if (cyc->cyc.pend++ == 0)
-+ schedule_work_on(cyc->cpu,
-+ (struct work_struct *)&cyc->cyc.work);
-+ else if (cyc->cyc.pend == 0)
-+ cyc->cyc.pend = UINT_MAX;
-+
-+done:
-+ /*
-+ * Prepare the timer for the next expiration.
-+ */
-+ if (cyc->cyc.when.cyt_interval == CY_INTERVAL_INF)
-+ return HRTIMER_NORESTART;
-+
-+ hrtimer_forward_now(timr, cyc->cyc.when.cyt_interval);
-+
-+ return HRTIMER_RESTART;
-+}
-+
-+struct cyclic *cyclic_new(int omni)
-+{
-+ struct cyclic *cyc;
-+
-+ cyc = kmalloc(sizeof(struct cyclic), GFP_KERNEL);
-+ if (cyc == NULL)
-+ return NULL;
-+
-+ INIT_LIST_HEAD(&cyc->list);
-+
-+ if (!omni) {
-+ cyc->cpu = _CYCLIC_CPU_UNDEF;
-+ cyc->cyc.pend = 0;
-+ hrtimer_init(&cyc->cyc.timr, CLOCK_MONOTONIC,
-+ HRTIMER_MODE_REL_PINNED);
-+ cyc->cyc.timr.function = cyclic_expire;
-+ cyc->cyc.work.cyc = cyc;
-+ INIT_WORK((struct work_struct *)&cyc->cyc.work, cyclic_fire);
-+ } else {
-+ cyc->cpu = _CYCLIC_CPU_OMNI;
-+ INIT_LIST_HEAD(&cyc->omni.cycl);
-+ }
-+
-+ return cyc;
-+}
-+
-+static inline void cyclic_restart(struct cyclic *cyc)
-+{
-+ if (cyc->cyc.when.cyt_interval == CY_INTERVAL_INF)
-+ return;
-+
-+ if (cyc->cyc.when.cyt_when == 0)
-+ hrtimer_start(&cyc->cyc.timr, cyc->cyc.when.cyt_interval,
-+ HRTIMER_MODE_REL_PINNED);
-+ else
-+ hrtimer_start(&cyc->cyc.timr, cyc->cyc.when.cyt_when,
-+ HRTIMER_MODE_ABS_PINNED);
-+}
-+
-+/*
-+ * Add a new cyclic to the system.
-+ */
-+cyclic_id_t cyclic_add(struct cyc_handler *hdlr, struct cyc_time *when)
-+{
-+ struct cyclic *cyc;
-+
-+ if (hdlr == NULL || when == NULL)
-+ return CYCLIC_NONE;
-+
-+ cyc = cyclic_new(0);
-+ if (cyc == NULL)
-+ return CYCLIC_NONE;
-+
-+ list_add(&cyc->list, &cyclics);
-+ cyc->cpu = smp_processor_id();
-+ cyc->cyc.when = *when;
-+ cyc->cyc.hdlr = *hdlr;
-+
-+ cyclic_restart(cyc);
-+
-+ return (cyclic_id_t)cyc;
-+}
-+EXPORT_SYMBOL(cyclic_add);
-+
-+static void cyclic_omni_xcall(struct cyclic *cyc)
-+{
-+ cyclic_restart(cyc);
-+}
-+
-+/*
-+ * Add a new cyclic to the system.
-+ */
-+static void cyclic_add_pinned(int cpu, struct cyclic *omni,
-+ struct cyc_handler *hdlr, struct cyc_time *when)
-+{
-+ struct cyclic *cyc;
-+
-+ cyc = cyclic_new(0);
-+ if (cyc == NULL)
-+ return;
-+
-+ list_add(&cyc->list, &omni->omni.cycl);
-+ cyc->cpu = cpu;
-+ cyc->cyc.when = *when;
-+ cyc->cyc.hdlr = *hdlr;
-+
-+ smp_call_function_single(cpu, (smp_call_func_t)cyclic_omni_xcall,
-+ cyc, 1);
-+}
-+
-+/*
-+ * Start a cyclic on a specific CPU as sub-cyclic to an omni-present cyclic.
-+ */
-+static void cyclic_omni_start(struct cyclic *omni, int cpu)
-+{
-+ struct cyc_time when;
-+ struct cyc_handler hdlr;
-+
-+ omni->omni.hdlr.cyo_online(omni->omni.hdlr.cyo_arg, cpu, &hdlr, &when);
-+ cyclic_add_pinned(cpu, omni, &hdlr, &when);
-+}
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+static int cyclic_cpu_offline(unsigned int cpu)
-+{
-+ struct cyclic *cyc;
-+
-+ list_for_each_entry(cyc, &cyclics, list) {
-+ struct cyclic *c, *n;
-+
-+ if (!CYCLIC_IS_OMNI(cyc))
-+ continue;
-+
-+ list_for_each_entry_safe(c, n, &cyc->omni.cycl, list) {
-+ if (c->cpu == cpu)
-+ cyclic_remove((cyclic_id_t)c);
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int cyclic_cpu_online(unsigned int cpu)
-+{
-+ struct cyclic *cyc;
-+
-+ list_for_each_entry(cyc, &cyclics, list) {
-+ struct cyclic *c, *n;
-+
-+ if (!CYCLIC_IS_OMNI(cyc))
-+ continue;
-+
-+ list_for_each_entry_safe(c, n, &cyc->omni.cycl, list) {
-+ if (c->cpu == cpu)
-+ break;
-+ }
-+
-+ if (c->cpu == cpu)
-+ continue;
-+
-+ cyclic_omni_start(cyc, cpu);
-+ }
-+ return 0;
-+}
-+#endif
-+
-+/*
-+ * Add a new omnipresent cyclic to the system.
-+ */
-+cyclic_id_t cyclic_add_omni(struct cyc_omni_handler *omni)
-+{
-+ int cpu;
-+ struct cyclic *cyc;
-+
-+ cyc = cyclic_new(1);
-+ if (cyc == NULL)
-+ return CYCLIC_NONE;
-+
-+ list_add(&cyc->list, &cyclics);
-+ cyc->omni.hdlr = *omni;
-+
-+ for_each_online_cpu(cpu)
-+ cyclic_omni_start(cyc, cpu);
-+
-+ return (cyclic_id_t)cyc;
-+}
-+EXPORT_SYMBOL(cyclic_add_omni);
-+
-+/*
-+ * Remove a specific cyclic from the system.
-+ */
-+void cyclic_remove(cyclic_id_t id)
-+{
-+ struct cyclic *cyc = (struct cyclic *)id;
-+
-+ if (CYCLIC_IS_OMNI(cyc)) {
-+ struct cyclic *child, *n;
-+
-+ /*
-+ * If this is an omni-present cyclic, we first need to remove
-+ * all the associated per-CPU cyclics. Note that the recursive
-+ * call into cyclic_remove() for a child cyclic will remove it
-+ * from the list of per-CPU cyclics associated with the
-+ * omni-present cyclic, so we do not need to handle that here.
-+ */
-+ list_for_each_entry_safe(child, n, &cyc->omni.cycl, list)
-+ cyclic_remove((cyclic_id_t)child);
-+ } else {
-+ /*
-+ * We know that hrtimer_cancel() will wait for the timer
-+ * callback to finish if it is being executed at the time of
-+ * making this call. It is therefore guaranteed that 'pend'
-+ * will no longer get incremented.
-+ *
-+ * The call to cancel_work_sync() will wait for the workqueue
-+ * handler to finish also, and since the handler always brings
-+ * 'pend' down to zero prior to returning, it is guaranteed that
-+ * (1) all pending handler calls will be made before
-+ * cyclic_remove() returns
-+ * (2) the amount of work to do before returning is finite.
-+ */
-+ hrtimer_cancel(&cyc->cyc.timr);
-+ cancel_work_sync((struct work_struct *)&cyc->cyc.work);
-+ }
-+
-+ list_del(&cyc->list);
-+ kfree(cyc);
-+}
-+EXPORT_SYMBOL(cyclic_remove);
-+
-+struct cyclic_reprog {
-+ cyclic_id_t cycid;
-+ ktime_t delta;
-+};
-+
-+static void cyclic_reprogram_xcall(struct cyclic_reprog *creprog)
-+{
-+ cyclic_reprogram(creprog->cycid, creprog->delta);
-+}
-+
-+/*
-+ * Reprogram cyclic to fire with given delta from now.
-+ *
-+ * The underlying design makes it safe to call cyclic_reprogram from whithin a
-+ * cyclic handler without race with cyclic_remove. If called from outside of the
-+ * cyclic handler it is up to the owner to ensure to not call cyclic_reprogram
-+ * after call to cyclic_remove.
-+ *
-+ * This function cannot be called from interrupt/bottom half contexts.
-+ */
-+void cyclic_reprogram(cyclic_id_t id, ktime_t delta)
-+{
-+ struct cyclic *cyc = (struct cyclic *)id;
-+
-+ /*
-+ * For omni present cyclic we reprogram child for current CPU.
-+ */
-+ if (CYCLIC_IS_OMNI(cyc)) {
-+ struct cyclic *c, *n;
-+
-+ list_for_each_entry_safe(c, n, &cyc->omni.cycl, list) {
-+ if (c->cpu != smp_processor_id())
-+ continue;
-+
-+ hrtimer_start(&c->cyc.timr, delta,
-+ HRTIMER_MODE_ABS_PINNED);
-+
-+ break;
-+ }
-+
-+ return;
-+ }
-+
-+ /*
-+ * Regular cyclic reprogram must ensure that the timer remains bound
-+ * to the CPU it was registered on. In case we are called from
-+ * different CPU we use xcall to trigger reprogram from correct cpu.
-+ */
-+ if (cyc->cpu != smp_processor_id()) {
-+ struct cyclic_reprog creprog = {
-+ .cycid = id,
-+ .delta = delta,
-+ };
-+
-+ smp_call_function_single(cyc->cpu, (smp_call_func_t)
-+ cyclic_reprogram_xcall, &creprog, 1);
-+ } else {
-+ hrtimer_start(&cyc->cyc.timr, delta, HRTIMER_MODE_REL_PINNED);
-+ }
-+}
-+EXPORT_SYMBOL(cyclic_reprogram);
-+
-+static void *s_start(struct seq_file *seq, loff_t *pos)
-+{
-+ loff_t n = *pos;
-+ struct cyclic *cyc;
-+
-+ list_for_each_entry(cyc, &cyclics, list) {
-+ if (n == 0)
-+ return cyc;
-+
-+ n--;
-+ }
-+
-+ return NULL;
-+}
-+
-+static void *s_next(struct seq_file *seq, void *p, loff_t *pos)
-+{
-+ struct cyclic *cyc = p;
-+
-+ ++*pos;
-+
-+ cyc = list_entry(cyc->list.next, struct cyclic, list);
-+ if (&cyc->list == &cyclics)
-+ return NULL;
-+
-+ return cyc;
-+}
-+
-+static void s_stop(struct seq_file *seq, void *p)
-+{
-+}
-+
-+static int s_show(struct seq_file *seq, void *p)
-+{
-+ struct cyclic *cyc = p;
-+
-+ if (CYCLIC_IS_OMNI(cyc)) {
-+ struct cyclic *c;
-+
-+ seq_puts(seq, "Omni-present cyclic:\n");
-+ list_for_each_entry(c, &cyc->omni.cycl, list)
-+ seq_printf(seq,
-+ " CPU-%d: %c %lld ns hdlr %pB arg %llx\n",
-+ c->cpu,
-+ c->cyc.hdlr.cyh_level == CY_HIGH_LEVEL
-+ ? 'H' : 'l',
-+ c->cyc.when.cyt_interval,
-+ c->cyc.hdlr.cyh_func,
-+ (uint64_t)c->cyc.hdlr.cyh_arg);
-+ } else
-+ seq_printf(seq, "CPU-%d: %c %lld ns hdlr %pB arg %llx\n",
-+ cyc->cpu,
-+ cyc->cyc.hdlr.cyh_level == CY_HIGH_LEVEL
-+ ? 'H' : 'l',
-+ cyc->cyc.when.cyt_interval,
-+ cyc->cyc.hdlr.cyh_func,
-+ (uint64_t)cyc->cyc.hdlr.cyh_arg);
-+
-+ return 0;
-+}
-+
-+static const struct seq_operations cyclicinfo_ops = {
-+ .start = s_start,
-+ .next = s_next,
-+ .stop = s_stop,
-+ .show = s_show,
-+};
-+
-+static int cyclicinfo_open(struct inode *inode, struct file *file)
-+{
-+ return seq_open(file, &cyclicinfo_ops);
-+}
-+
-+static const struct proc_ops proc_cyclicinfo_ops = {
-+ .proc_open = cyclicinfo_open,
-+ .proc_read = seq_read,
-+ .proc_lseek = seq_lseek,
-+ .proc_release = seq_release,
-+};
-+
-+static int __init cyclic_init(void)
-+{
-+ int ret;
-+
-+ proc_create("cyclicinfo", 0400, NULL, &proc_cyclicinfo_ops);
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+ if (!omni_enabled) {
-+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_CYCLIC_STARTING,
-+ "Cyclic omni-timer starting",
-+ cyclic_cpu_online,
-+ cyclic_cpu_offline);
-+ if (ret)
-+ pr_warn_once("Cannot enable cyclic omni timer\n");
-+ else
-+ omni_enabled = 1;
-+ }
-+#endif
-+
-+ return 0;
-+}
-+module_init(cyclic_init);
-diff --git a/kernel/dtrace/dtrace_cpu.c b/kernel/dtrace/dtrace_cpu.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..1bc6e3bb4ce01141e5c94a52766f0553793e49c0
---- /dev/null
-+++ b/kernel/dtrace/dtrace_cpu.c
-@@ -0,0 +1,61 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_cpu.c
-+ * DESCRIPTION: DTrce - per-CPU state
-+ *
-+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/module.h>
-+#include <asm/dtrace_cpuinfo.h>
-+
-+DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_core, dtrace_cpu_core);
-+EXPORT_PER_CPU_SYMBOL(dtrace_cpu_core);
-+
-+DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo, dtrace_cpu_info);
-+EXPORT_PER_CPU_SYMBOL(dtrace_cpu_info);
-+
-+void dtrace_cpu_init(void)
-+{
-+ int cpu;
-+
-+ /*
-+ * Force this type into the CTF for the sake of userspace's
-+ * ABI requirements.
-+ */
-+ cpuinfo_t *dummy __attribute__((__unused__)) = NULL;
-+
-+ for_each_present_cpu(cpu) {
-+ cpuinfo_arch_t *ci = &cpu_data(cpu);
-+ struct cpuinfo *cpui = per_cpu_info(cpu);
-+ struct cpu_core *cpuc = per_cpu_core(cpu);
-+
-+ cpui->cpu_id = cpu;
-+ cpui->cpu_pset = 0;
-+ cpui->cpu_chip = dtrace_cpuinfo_chip(ci);
-+ cpui->cpu_lgrp = 0;
-+ cpui->cpu_info = ci;
-+
-+ cpuc->cpuc_dtrace_flags = 0;
-+ cpuc->cpuc_dcpc_intr_state = 0;
-+ cpuc->cpuc_dtrace_illval = 0;
-+ mutex_init(&cpuc->cpuc_pid_lock);
-+
-+ cpuc->cpu_dtrace_regs = NULL;
-+ cpuc->cpu_dtrace_caller = 0;
-+ rwlock_init(&cpuc->cpu_ft_lock);
-+
-+ cpuc->cpuc_current_probe = DTRACE_IDNONE;
-+ }
-+}
-diff --git a/kernel/dtrace/dtrace_os.c b/kernel/dtrace/dtrace_os.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..d023f3913323b42678aee5a7467a4b39c378c8cc
---- /dev/null
-+++ b/kernel/dtrace/dtrace_os.c
-@@ -0,0 +1,332 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_os.c
-+ * DESCRIPTION: DTrace - OS support functions
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/binfmts.h>
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/fs.h>
-+#include <linux/hardirq.h>
-+#include <linux/interrupt.h>
-+#include <linux/kdebug.h>
-+#include <linux/module.h>
-+#include <linux/moduleloader.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/stacktrace.h>
-+#include <linux/timekeeping.h>
-+#include <linux/vmalloc.h>
-+#include <linux/kallsyms.h>
-+#include <linux/uaccess.h>
-+#include <linux/workqueue.h>
-+#include <asm/ptrace.h>
-+#include <linux/init_task.h>
-+#include <linux/sched/mm.h>
-+#include <linux/shmem_fs.h>
-+#include <linux/dtrace_task_impl.h>
-+
-+/*
-+ * OS SPECIFIC DTRACE SETUP
-+ */
-+
-+/*
-+ * DTrace pseudo module that represents vmlinux (the kernel itself).
-+ * Since we populate its sdt data members only once, it can be marked
-+ * as RO after init.
-+ */
-+struct module *dtrace_kmod __ro_after_init = NULL;
-+EXPORT_SYMBOL(dtrace_kmod);
-+
-+int dtrace_ustackdepth_max = 2048;
-+
-+struct kmem_cache *dtrace_pdata_cachep = NULL;
-+
-+void __init dtrace_os_init(void)
-+{
-+ /*
-+ * Setup for module handling.
-+ */
-+ dtrace_pdata_cachep = kmem_cache_create("dtrace_pdata_cache",
-+ sizeof(struct dtrace_module), 0,
-+ SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
-+ if (dtrace_pdata_cachep == NULL)
-+ pr_debug("Can't allocate kmem cache for pdata\n");
-+
-+ /*
-+ * We need to set up a psinfo structure for PID 0 (swapper).
-+ */
-+ dtrace_task_os_init();
-+ dtrace_psinfo_os_init();
-+ dtrace_task_init(&init_task);
-+ dtrace_psinfo_alloc(&init_task);
-+}
-+
-+/*
-+ * MODULE SUPPORT FUNCTIONS
-+ */
-+extern struct list_head *dtrace_modules;
-+
-+/*
-+ * Iterate over all loaded kernel modules. This is required until the linux
-+ * kernel receives its own module iterator.
-+ */
-+void dtrace_for_each_module(for_each_module_fn func, void *arg)
-+{
-+ struct module *mp;
-+
-+ if (func == NULL)
-+ return;
-+
-+ /* The dtrace fake module is not in the list. */
-+ func(arg, dtrace_kmod);
-+
-+ list_for_each_entry(mp, dtrace_modules, list) {
-+
-+#ifdef MODULES_VADDR
-+ if ((uintptr_t)mp < MODULES_VADDR ||
-+ (uintptr_t)mp >= MODULES_END)
-+ continue;
-+#else
-+ if ((uintptr_t)mp < VMALLOC_START ||
-+ (uintptr_t)mp >= VMALLOC_END)
-+ continue;
-+#endif
-+
-+ func(arg, mp);
-+ }
-+}
-+EXPORT_SYMBOL_GPL(dtrace_for_each_module);
-+
-+
-+void dtrace_mod_pdata_alloc(struct module *mp)
-+{
-+ struct dtrace_module *pdata;
-+
-+ pdata = kmem_cache_alloc(dtrace_pdata_cachep, GFP_KERNEL | __GFP_ZERO);
-+ if (pdata == NULL) {
-+ mp->pdata = NULL;
-+ return;
-+ }
-+
-+ dtrace_mod_pdata_init(pdata);
-+ mp->pdata = pdata;
-+}
-+
-+void dtrace_mod_pdata_free(struct module *mp)
-+{
-+ struct dtrace_module *pdata = mp->pdata;
-+
-+ if (mp->pdata == NULL)
-+ return;
-+
-+ mp->pdata = NULL;
-+ dtrace_mod_pdata_cleanup(pdata);
-+ kmem_cache_free(dtrace_pdata_cachep, pdata);
-+}
-+
-+/*
-+ * This function is called with module_mutex held.
-+ */
-+int dtrace_destroy_prov(struct module *mp)
-+{
-+ struct dtrace_module *pdata = mp->pdata;
-+
-+ if (pdata != NULL && pdata->prov_exit != NULL)
-+ return pdata->prov_exit();
-+
-+ return 1;
-+}
-+
-+/*---------------------------------------------------------------------------*\
-+(* TIME SUPPORT FUNCTIONS *)
-+\*---------------------------------------------------------------------------*/
-+enum dtrace_vtime_state dtrace_vtime_active = 0;
-+
-+/*
-+ * Until Linux kernel gains lock-free realtime clock access we are maintaining
-+ * our own version for lock-free access from within a probe context.
-+ */
-+static struct dtrace_time_fast {
-+ seqcount_latch_t dtwf_seq;
-+ ktime_t dtwf_offsreal[2];
-+} dtrace_time ____cacheline_aligned;
-+
-+/*
-+ * Callback from timekeeper code that allows dtrace to update its own time data.
-+ */
-+void dtrace_update_time(struct timekeeper *tk)
-+{
-+ raw_write_seqcount_latch(&dtrace_time.dtwf_seq);
-+ dtrace_time.dtwf_offsreal[0] = tk->offs_real;
-+ raw_write_seqcount_latch(&dtrace_time.dtwf_seq);
-+ dtrace_time.dtwf_offsreal[1] = tk->offs_real;
-+}
-+
-+/* Lock free walltime */
-+ktime_t dtrace_get_walltime(void)
-+{
-+ u64 nsec = ktime_get_mono_fast_ns();
-+ unsigned int seq;
-+ ktime_t offset;
-+
-+ do {
-+ seq = raw_read_seqcount_latch(&dtrace_time.dtwf_seq);
-+ offset = dtrace_time.dtwf_offsreal[seq & 0x1];
-+ } while (read_seqcount_latch_retry(&dtrace_time.dtwf_seq, seq));
-+
-+ return ktime_add_ns(offset, nsec);
-+}
-+EXPORT_SYMBOL(dtrace_get_walltime);
-+
-+ktime_t dtrace_gethrtime(void)
-+{
-+ return ns_to_ktime(ktime_get_raw_fast_ns());
-+}
-+EXPORT_SYMBOL(dtrace_gethrtime);
-+
-+/* Needed for lockstat probes where we cannot include ktime.h */
-+u64 dtrace_gethrtime_ns(void)
-+{
-+ return ktime_get_raw_fast_ns();
-+}
-+EXPORT_SYMBOL(dtrace_gethrtime_ns);
-+
-+void dtrace_vtime_enable(void)
-+{
-+ enum dtrace_vtime_state old, new;
-+
-+ do {
-+ old = dtrace_vtime_active;
-+ if (old == DTRACE_VTIME_ACTIVE) {
-+ pr_warn_once("DTrace virtual time already enabled");
-+ return;
-+ }
-+
-+ new = DTRACE_VTIME_ACTIVE;
-+ } while (cmpxchg(&dtrace_vtime_active, old, new) != old);
-+}
-+EXPORT_SYMBOL(dtrace_vtime_enable);
-+
-+void dtrace_vtime_disable(void)
-+{
-+ int old, new;
-+
-+ do {
-+ old = dtrace_vtime_active;
-+ if (old == DTRACE_VTIME_INACTIVE) {
-+ pr_warn_once("DTrace virtual time already disabled");
-+ return;
-+ }
-+
-+ new = DTRACE_VTIME_INACTIVE;
-+ } while (cmpxchg(&dtrace_vtime_active, old, new) != old);
-+}
-+EXPORT_SYMBOL(dtrace_vtime_disable);
-+
-+void dtrace_vtime_switch(struct task_struct *prev, struct task_struct *next)
-+{
-+ struct dtrace_task *dprev = prev->dt_task;
-+ struct dtrace_task *dnext = next->dt_task;
-+ ktime_t now = dtrace_gethrtime();
-+
-+ if (dprev != NULL && ktime_nz(dprev->dt_start)) {
-+ dprev->dt_vtime = ktime_add(dprev->dt_vtime,
-+ ktime_sub(now,
-+ dprev->dt_start));
-+ dprev->dt_start = ktime_set(0, 0);
-+ }
-+
-+ if (dnext != NULL)
-+ dnext->dt_start = now;
-+}
-+
-+void dtrace_stacktrace(struct stacktrace_state *st)
-+{
-+ int i;
-+
-+ if ((st->flags & STACKTRACE_TYPE) == STACKTRACE_USER) {
-+ dtrace_user_stacktrace(st);
-+ return;
-+ }
-+
-+ if (st->pcs == NULL) {
-+ st->depth = 0;
-+ return;
-+ }
-+
-+ st->depth = stack_trace_save((long unsigned int *) st->pcs,
-+ st->limit ? st->limit : 512, st->depth);
-+
-+ /*
-+ * For entirely unknown reasons, the save_stack_trace() implementation
-+ * on x86_64 adds a ULONG_MAX entry after the last stack trace entry.
-+ * This might be a sentinel value, but given that struct stack_trace
-+ * already contains a nr_entries counter, this seems rather pointless.
-+ * Alas, we need to add a special case for that... And to make matters
-+ * worse, it actually does this only when there is room for it (i.e.
-+ * when nr_entries < max_entries).
-+ * Since ULONG_MAX is never a valid PC, we can just check for that.
-+ */
-+#if defined(CONFIG_X86_64) || defined(CONFIG_ARM64)
-+ if (st->depth && st->pcs[st->depth - 1] == ULONG_MAX)
-+ st->depth--;
-+#endif
-+
-+ if (st->fps != NULL) {
-+ for (i = 0; i < st->limit; i++)
-+ st->fps[i] = 0;
-+ }
-+}
-+EXPORT_SYMBOL(dtrace_stacktrace);
-+
-+/*
-+ * INVALID OPCODE AND PAGE FAULT HANDLING
-+ */
-+static struct notifier_block dtrace_die = {
-+ .notifier_call = dtrace_die_notifier,
-+ .priority = 0x7fffffff
-+};
-+
-+static int dtrace_enabled;
-+
-+/*
-+ * DTrace enable/disable must be called with dtrace_lock being held. It is not
-+ * possible to check for safety here with an ASSERT as the lock itself is in the
-+ * DTrace Framework kernel module.
-+ */
-+int dtrace_enable(void)
-+{
-+ if (dtrace_enabled)
-+ return 0;
-+
-+ if (register_die_notifier(&dtrace_die) != 0)
-+ return 1;
-+
-+ dtrace_enabled = 1;
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_enable);
-+
-+void dtrace_disable(void)
-+{
-+ if (!dtrace_enabled)
-+ return;
-+
-+ unregister_die_notifier(&dtrace_die);
-+ dtrace_enabled = 0;
-+}
-+EXPORT_SYMBOL(dtrace_disable);
-diff --git a/kernel/dtrace/dtrace_psinfo.c b/kernel/dtrace/dtrace_psinfo.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..bb5f6fc2ce63a487a5ade3a022c51fc15e3e42ae
---- /dev/null
-+++ b/kernel/dtrace/dtrace_psinfo.c
-@@ -0,0 +1,212 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_psinfo.c
-+ * DESCRIPTION: DTrace - DTrace psinfo implementation
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/binfmts.h>
-+#include <linux/dtrace_psinfo.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/mm.h>
-+#include <linux/sched.h>
-+#include <linux/sched/mm.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+
-+struct kmem_cache *dtrace_psinfo_cachep;
-+
-+/*
-+ * Free the psinfo_t structure.
-+ */
-+void dtrace_psinfo_free(struct dtrace_psinfo *psinfo)
-+{
-+ kfree(psinfo->dtps_argv);
-+ kfree(psinfo->dtps_envp);
-+ kmem_cache_free(dtrace_psinfo_cachep, psinfo);
-+}
-+
-+/*
-+ * Allocate a new dtrace_psinfo_t structure.
-+ */
-+void dtrace_psinfo_alloc(struct task_struct *tsk)
-+{
-+ struct dtrace_psinfo *psinfo;
-+ struct mm_struct *mm = NULL;
-+
-+ if (unlikely(tsk->dt_task == NULL))
-+ return;
-+
-+ if (likely(tsk->dt_task->dt_psinfo != NULL)) {
-+ struct dtrace_psinfo *tmp = tsk->dt_task->dt_psinfo;
-+ tsk->dt_task->dt_psinfo = NULL;
-+
-+ dtrace_psinfo_put(tmp);
-+ }
-+
-+ psinfo = kmem_cache_alloc(dtrace_psinfo_cachep, GFP_KERNEL);
-+ if (psinfo == NULL)
-+ goto fail;
-+
-+ mm = get_task_mm(tsk);
-+ if (mm) {
-+ size_t len = mm->arg_end - mm->arg_start;
-+ int i = 0;
-+ char *p;
-+
-+ /*
-+ * Construct the psargs string.
-+ */
-+ if (len > 0) {
-+ if (len >= PR_PSARGS_SZ)
-+ len = PR_PSARGS_SZ - 1;
-+
-+ i = access_process_vm(tsk, mm->arg_start,
-+ psinfo->dtps_psargs, len, 0);
-+
-+ if (i > 0) {
-+ if (i < len)
-+ len = i;
-+
-+ for (i = 0, --len; i < len; i++) {
-+ if (psinfo->dtps_psargs[i] == '\0')
-+ psinfo->dtps_psargs[i] = ' ';
-+ }
-+ }
-+ }
-+
-+ if (i < 0)
-+ i = 0;
-+
-+ while (i < PR_PSARGS_SZ)
-+ psinfo->dtps_psargs[i++] = 0;
-+
-+ /*
-+ * Determine the number of arguments.
-+ */
-+ psinfo->dtps_argc = 0;
-+ for (p = (char *)mm->arg_start; p < (char *)mm->arg_end;
-+ psinfo->dtps_argc++) {
-+ size_t l = strnlen_user(p, MAX_ARG_STRLEN);
-+
-+ if (!l)
-+ break;
-+
-+ p += l + 1;
-+ }
-+
-+ /*
-+ * Limit the number of stored argument pointers.
-+ */
-+ len = psinfo->dtps_argc;
-+ if (len >= PR_ARGV_SZ)
-+ len = PR_ARGV_SZ - 1;
-+
-+ psinfo->dtps_argv = kmalloc((len + 1) * sizeof(char *),
-+ GFP_KERNEL);
-+ if (psinfo->dtps_argv == NULL)
-+ goto fail;
-+
-+ /*
-+ * Now populate the array of argument strings.
-+ */
-+ for (i = 0, p = (char *)mm->arg_start; i < len; i++) {
-+ psinfo->dtps_argv[i] = p;
-+ p += strnlen_user(p, MAX_ARG_STRLEN) + 1;
-+ }
-+ psinfo->dtps_argv[len] = NULL;
-+
-+ /*
-+ * Determine the number of environment variables.
-+ */
-+ psinfo->dtps_envc = 0;
-+ for (p = (char *)mm->env_start; p < (char *)mm->env_end;
-+ psinfo->dtps_envc++) {
-+ size_t l = strnlen_user(p, MAX_ARG_STRLEN);
-+
-+ if (!l)
-+ break;
-+
-+ p += l + 1;
-+ }
-+
-+ /*
-+ * Limit the number of stored environment pointers.
-+ */
-+ len = psinfo->dtps_envc;
-+ if (len >= PR_ENVP_SZ)
-+ len = PR_ENVP_SZ - 1;
-+
-+ psinfo->dtps_envp = kmalloc((len + 1) * sizeof(char *),
-+ GFP_KERNEL);
-+ if (psinfo->dtps_envp == NULL)
-+ goto fail;
-+
-+ /*
-+ * Now populate the array of environment variable strings.
-+ */
-+ for (i = 0, p = (char *)mm->env_start; i < len; i++) {
-+ psinfo->dtps_envp[i] = p;
-+ p += strnlen_user(p, MAX_ARG_STRLEN) + 1;
-+ }
-+ psinfo->dtps_envp[len] = NULL;
-+
-+ mmput(mm);
-+ } else {
-+ size_t len = min(TASK_COMM_LEN, PR_PSARGS_SZ);
-+ int i;
-+
-+ /*
-+ * We end up here for tasks that do not have managed memory at
-+ * all, which generally means that this is a kernel thread.
-+ * If it is not, this is still safe because we know that tasks
-+ * always have the comm member populated with something (even
-+ * if it would be an empty string).
-+ */
-+ memcpy(psinfo->dtps_psargs, tsk->comm, len);
-+ for (i = len; i < PR_PSARGS_SZ; i++)
-+ psinfo->dtps_psargs[i] = 0;
-+
-+ psinfo->dtps_argc = 0;
-+ psinfo->dtps_argv = kmalloc(sizeof(char *), GFP_KERNEL);
-+ psinfo->dtps_argv[0] = NULL;
-+ psinfo->dtps_envc = 0;
-+ psinfo->dtps_envp = kmalloc(sizeof(char *), GFP_KERNEL);
-+ psinfo->dtps_envp[0] = NULL;
-+ }
-+
-+ atomic_set(&psinfo->dtps_usage, 1);
-+ tsk->dt_task->dt_psinfo = psinfo; /* new one */
-+
-+ return;
-+
-+fail:
-+ if (mm)
-+ mmput(mm);
-+
-+ if (psinfo)
-+ dtrace_psinfo_free(psinfo);
-+}
-+
-+/*
-+ * Initialize DTrace's psinfo subsystem.
-+ */
-+void __init dtrace_psinfo_os_init(void)
-+{
-+ dtrace_psinfo_cachep = kmem_cache_create("dtrace_psinfo_cache",
-+ sizeof(struct dtrace_psinfo), 0,
-+ SLAB_HWCACHE_ALIGN | SLAB_PANIC,
-+ NULL);
-+
-+}
-diff --git a/kernel/dtrace/dtrace_task.c b/kernel/dtrace/dtrace_task.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..02bcc6b7e0a26a04f61448ac6c8d5653344b6f40
---- /dev/null
-+++ b/kernel/dtrace/dtrace_task.c
-@@ -0,0 +1,237 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_task.c
-+ * DESCRIPTION: DTrace - per-task data
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/sched/mm.h>
-+#include <linux/slab.h>
-+
-+struct kmem_cache *dtrace_task_cachep;
-+
-+void (*dtrace_helpers_fork)(struct task_struct *, struct task_struct *);
-+EXPORT_SYMBOL(dtrace_helpers_fork);
-+
-+/*
-+ * Reset per-task sate to default values. Modifies only part of
-+ * the state that does not persist across process forks.
-+ */
-+static void dtrace_task_reinit(struct dtrace_task *dtsk)
-+{
-+ dtsk->dt_predcache = 0;
-+ dtsk->dt_stop = 0;
-+ dtsk->dt_sig = 0;
-+
-+ dtsk->dt_helpers = NULL;
-+ dtsk->dt_probes = 0;
-+ dtsk->dt_tp_count = 0;
-+}
-+
-+/*
-+ * Allocate new per-task structure and initialize it with default
-+ * values.
-+ */
-+static struct dtrace_task *dtrace_task_alloc(void)
-+{
-+ struct dtrace_task *dtsk;
-+
-+ /* Try to allocate new task. */
-+ dtsk = kmem_cache_alloc(dtrace_task_cachep, GFP_KERNEL);
-+ if (dtsk == NULL)
-+ return NULL;
-+
-+ /* Initialize new task. */
-+ dtrace_task_reinit(dtsk);
-+
-+ dtsk->dt_vtime = ktime_set(0, 0);
-+ dtsk->dt_start = ktime_set(0, 0);
-+ dtsk->dt_psinfo = NULL;
-+ dtsk->dt_ustack = NULL;
-+
-+ return dtsk;
-+}
-+
-+/*
-+ * Cleans all attached resources to the per-task structure so it is ready to be
-+ * reused or freed.
-+ */
-+static void dtrace_task_cleanup(struct task_struct *tsk)
-+{
-+ struct dtrace_psinfo *psinfo;
-+
-+ /* Nothing to remove. */
-+ if (tsk->dt_task == NULL)
-+ return;
-+
-+ /* Release psinfo if any. */
-+ psinfo = tsk->dt_task->dt_psinfo;
-+ if (psinfo != NULL) {
-+ tsk->dt_task->dt_psinfo = NULL;
-+ dtrace_psinfo_put(psinfo);
-+ }
-+}
-+
-+/*
-+ * Kernel hooks for per-task events.
-+ */
-+
-+/*
-+ * Called when a new task has been created.
-+ *
-+ * It tries to allocate new per-task data strcture and initialize
-+ * it with default values.
-+ */
-+void dtrace_task_init(struct task_struct *tsk)
-+{
-+ struct mm_struct *mm = NULL;
-+
-+ /* Initialize new task structure */
-+ tsk->dt_task = dtrace_task_alloc();
-+ if (tsk->dt_task == NULL)
-+ return;
-+
-+ /* Try to setup initial userspace stack. */
-+ mm = get_task_mm(tsk);
-+ if (mm) {
-+ tsk->dt_task->dt_ustack = (void *)mm->start_stack;
-+ mmput(mm);
-+ }
-+}
-+
-+/*
-+ * Called when a task has been duplicated.
-+ *
-+ * When a task is duplicated this is called early to provide new instance
-+ * of per-task data. This hook is called very early after a dup has been
-+ * performed. The new task shares almost everything with its parent and
-+ * locking performed must be aligned with locking of the kernel.
-+ *
-+ * DTrace resets new task to its default values.
-+ */
-+void dtrace_task_dup(struct task_struct *src, struct task_struct *dst)
-+{
-+ struct dtrace_psinfo *psinfo;
-+ struct dtrace_task *dtsk;
-+
-+ /* Nothing to clone. */
-+ if (src->dt_task == NULL)
-+ return;
-+
-+ /* Allocate and reinitialize new task. */
-+ dtsk = dtrace_task_alloc();
-+ if (dtsk == NULL) {
-+ dst->dt_task = NULL;
-+ return;
-+ }
-+ dtrace_task_reinit(dtsk);
-+
-+ /* Share psinfo if it is available. */
-+ psinfo = src->dt_task->dt_psinfo;
-+ if (psinfo != NULL) {
-+ dtrace_psinfo_get(psinfo);
-+ dtsk->dt_psinfo = psinfo;
-+ }
-+
-+ /* Copy remaining attributes of the source task. */
-+ dtsk->dt_ustack = src->dt_task->dt_ustack;
-+ dst->dt_task = dtsk;
-+}
-+
-+/*
-+ * Called when a process has been copied.
-+ *
-+ * If the original task has helpers attached fork them too.
-+ */
-+void dtrace_task_copy(struct task_struct *tsk, struct task_struct *child)
-+{
-+ if (tsk->dt_task == NULL)
-+ return;
-+
-+ if (child->dt_task == NULL)
-+ return;
-+
-+ /* Handle helpers for this task. */
-+ if (likely(dtrace_helpers_fork == NULL))
-+ return;
-+
-+ if (tsk->dt_task->dt_helpers != NULL)
-+ (*dtrace_helpers_fork)(tsk, child);
-+}
-+
-+/*
-+ * Called when a task has performed exec.
-+ *
-+ * If DTrace's per-task structure is already allocated it is reused for
-+ * the new task. If it is not present an allocation attempt is made.
-+ */
-+void dtrace_task_exec(struct task_struct *tsk)
-+{
-+ struct mm_struct *mm = NULL;
-+
-+ /* Try to reuse existing dtrace task. */
-+ if (tsk->dt_task != NULL) {
-+ dtrace_task_cleanup(tsk);
-+ dtrace_task_reinit(tsk->dt_task);
-+
-+ /* Try to set up initial userspace stack. */
-+ mm = get_task_mm(tsk);
-+ if (mm) {
-+ tsk->dt_task->dt_ustack = (void *)mm->start_stack;
-+ mmput(mm);
-+ }
-+ } else {
-+ dtrace_task_init(tsk);
-+
-+ /* No luck, we won't be able to trace this task. */
-+ if (tsk->dt_task == NULL)
-+ return;
-+ }
-+
-+ /* Finalize init of the per-task structure. */
-+ dtrace_psinfo_alloc(tsk);
-+}
-+
-+/*
-+ * Called when a task is about to be released.
-+ *
-+ * The DTrace's per-task data are disconnected and freed.
-+ */
-+void dtrace_task_free(struct task_struct *tsk)
-+{
-+ struct dtrace_task *dtsk = tsk->dt_task;
-+
-+ /* Nothing to do. */
-+ if (dtsk == NULL)
-+ return;
-+
-+ /* Release the per-task data. */
-+ dtrace_task_cleanup(tsk);
-+ tsk->dt_task = NULL;
-+ kmem_cache_free(dtrace_task_cachep, dtsk);
-+}
-+
-+/*
-+ * Initialize DTrace's task subsystem.
-+ */
-+void __init dtrace_task_os_init(void)
-+{
-+ /* Will panic if not initialized so no need to check for errors. */
-+ dtrace_task_cachep = kmem_cache_create("dtrace_task_cache",
-+ sizeof(struct dtrace_task), 0,
-+ SLAB_HWCACHE_ALIGN | SLAB_PANIC,
-+ NULL);
-+}
-+
-diff --git a/kernel/exit.c b/kernel/exit.c
-index 5c5859a9ba75afff23fcdffcb01eef159724c6df..da498c5f029c20d162f8665cee6cd49c6de9a06c 100644
---- a/kernel/exit.c
-+++ b/kernel/exit.c
-@@ -64,6 +64,7 @@
- #include <linux/rcuwait.h>
- #include <linux/compat.h>
- #include <linux/io_uring.h>
-+#include <linux/dtrace_os.h>
-
- #include <linux/uaccess.h>
- #include <asm/unistd.h>
-@@ -795,6 +796,9 @@ void __noreturn do_exit(long code)
- tsk->exit_code = code;
- taskstats_exit(tsk, group_dead);
-
-+ /* Remove DTrace state for this task */
-+ dtrace_task_free(tsk);
-+
- exit_mm();
-
- if (group_dead)
-diff --git a/kernel/fork.c b/kernel/fork.c
-index c675fdbd3dce1377480c4a70a496e5d1680d88ea..0d8a2b12fd90565fccba06804f9c0a58cbc6a064 100644
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -96,6 +96,7 @@
- #include <linux/kasan.h>
- #include <linux/scs.h>
- #include <linux/io_uring.h>
-+#include <linux/dtrace_task_impl.h>
-
- #include <asm/pgalloc.h>
- #include <linux/uaccess.h>
-@@ -442,6 +443,7 @@ void put_task_stack(struct task_struct *tsk)
- void free_task(struct task_struct *tsk)
- {
- scs_release(tsk);
-+ dtrace_task_free(tsk);
-
- #ifndef CONFIG_THREAD_INFO_IN_TASK
- /*
-@@ -943,6 +945,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
- #ifdef CONFIG_MEMCG
- tsk->active_memcg = NULL;
- #endif
-+
-+ dtrace_task_dup(orig, tsk);
- return tsk;
-
- free_stack:
-@@ -2300,6 +2304,25 @@ static __latent_entropy struct task_struct *copy_process(
- syscall_tracepoint_update(p);
- write_unlock_irq(&tasklist_lock);
-
-+#ifdef CONFIG_DTRACE
-+ /*
-+ * We make this call fairly late into the copy_process() handling,
-+ * because we need to ensure that we can look up this task based on
-+ * its pid using find_task_by_vpid(). We also must ensure that the
-+ * tasklist_lock has been released.
-+ */
-+ dtrace_task_copy(current, p);
-+
-+ /*
-+ * If we're called with stack_start != 0, this is almost certainly a
-+ * thread being created in current. Make sure it gets its own psinfo
-+ * data, because we need to record a new bottom of stack value.
-+ */
-+ if (p->mm && args->stack)
-+ if (p->dt_task != NULL)
-+ p->dt_task->dt_ustack = (void *)args->stack;
-+#endif
-+
- proc_fork_connector(p);
- sched_post_fork(p);
- cgroup_post_fork(p, args);
-diff --git a/kernel/module.c b/kernel/module.c
-index 9e471dbedc83a1a080612bf4f4ffabf09f3b8aa8..f4269dabc63837a9055eeed1bab211e30422413e 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -46,6 +46,7 @@
- #include <asm/mmu_context.h>
- #include <linux/license.h>
- #include <asm/sections.h>
-+#include <linux/dtrace_os.h>
- #include <linux/tracepoint.h>
- #include <linux/ftrace.h>
- #include <linux/livepatch.h>
-@@ -90,6 +91,9 @@
- DEFINE_MUTEX(module_mutex);
- EXPORT_SYMBOL_GPL(module_mutex);
- static LIST_HEAD(modules);
-+#ifdef CONFIG_DTRACE
-+struct list_head *dtrace_modules = &modules;
-+#endif /* CONFIG_DTRACE */
-
- /* Work queue for freeing init sections in success case */
- static void do_free_init(struct work_struct *w);
-@@ -1023,6 +1027,12 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
- }
- }
-
-+ /* Try destroying DTrace provider. */
-+ if (!dtrace_destroy_prov(mod)) {
-+ ret = -EBUSY;
-+ goto out;
-+ }
-+
- /* Stop the machine so refcounts can't move and disable module. */
- ret = try_stop_module(mod, flags, &forced);
- if (ret != 0)
-@@ -2212,6 +2222,7 @@ void __weak module_arch_freeing_init(struct module *mod)
- /* Free a module, remove from lists, etc. */
- static void free_module(struct module *mod)
- {
-+ dtrace_mod_pdata_free(mod);
- trace_module_free(mod);
-
- mod_sysfs_teardown(mod);
-@@ -3943,6 +3954,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
- /* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
- ftrace_module_init(mod);
-
-+ /* Allocate DTrace per-module data. */
-+ dtrace_mod_pdata_alloc(mod);
-+
- /* Finally it's fully formed, ready to start executing. */
- err = complete_formation(mod, info);
- if (err)
-diff --git a/kernel/sched/core.c b/kernel/sched/core.c
-index 77aa0e788b9b76b9cd13ac3a0bda6fa9e9b0a1b2..db893818f3ea5d645ae2418906acd27889722a65 100644
---- a/kernel/sched/core.c
-+++ b/kernel/sched/core.c
-@@ -13,6 +13,7 @@
- #include "sched.h"
-
- #include <linux/nospec.h>
-+#include <linux/dtrace_os.h>
-
- #include <linux/kcov.h>
- #include <linux/scs.h>
-@@ -3600,6 +3601,11 @@ static struct rq *finish_task_switch(struct task_struct *prev)
-
- rq->prev_mm = NULL;
-
-+#ifdef CONFIG_DTRACE
-+ if (dtrace_vtime_active)
-+ dtrace_vtime_switch(prev, current);
-+#endif
-+
- /*
- * A task struct has one reference for the use as "current".
- * If a task dies, then it sets TASK_DEAD in tsk->state and calls
-@@ -7195,6 +7201,10 @@ void __init sched_init(void)
- #endif /* CONFIG_SMP */
- hrtick_rq_init(rq);
- atomic_set(&rq->nr_iowait, 0);
-+
-+#ifdef CONFIG_DTRACE
-+ rq->dtrace_cpu_info = per_cpu_info(i);
-+#endif
- }
-
- set_load_weight(&init_task, false);
-diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
-index c122176c627ec3223cfb1bbcbacf585071bf2579..f917e368e4f88fefafc62b38edfaf7ec6527aa59 100644
---- a/kernel/sched/sched.h
-+++ b/kernel/sched/sched.h
-@@ -345,6 +345,7 @@ extern bool dl_cpu_busy(unsigned int cpu);
- #ifdef CONFIG_CGROUP_SCHED
-
- #include <linux/cgroup.h>
-+#include <linux/dtrace_cpu.h>
- #include <linux/psi.h>
-
- struct cfs_rq;
-@@ -1042,6 +1043,9 @@ struct rq {
- /* Must be inspected within a rcu lock section */
- struct cpuidle_state *idle_state;
- #endif
-+#ifdef CONFIG_DTRACE
-+ struct cpuinfo *dtrace_cpu_info;
-+#endif
- };
-
- #ifdef CONFIG_FAIR_GROUP_SCHED
-diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
-index 6858a31364b6456f036bbf38da4d0eca89ec3aaf..b74807546fba4907b7e054111882f6d3fa18f2ae 100644
---- a/kernel/time/timekeeping.c
-+++ b/kernel/time/timekeeping.c
-@@ -22,6 +22,7 @@
- #include <linux/pvclock_gtod.h>
- #include <linux/compiler.h>
- #include <linux/audit.h>
-+#include <linux/dtrace_os.h>
-
- #include "tick-internal.h"
- #include "ntp_internal.h"
-@@ -743,6 +744,7 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
- tk_update_ktime_data(tk);
-
- update_vsyscall(tk);
-+ dtrace_update_time(tk);
- update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
-
- tk->tkr_mono.base_real = tk->tkr_mono.base + tk->offs_real;
-diff --git a/scripts/coccinelle/dtrace/enum-elision.cocci b/scripts/coccinelle/dtrace/enum-elision.cocci
-new file mode 100644
-index 0000000000000000000000000000000000000000..77a5b33bd1661d7bf024afd82c29bec9e1c9a751
---- /dev/null
-+++ b/scripts/coccinelle/dtrace/enum-elision.cocci
-@@ -0,0 +1,29 @@
-+/// Reduce uses of typedefs of named enums to the name of the enum
-+
-+virtual patch
-+virtual context
-+virtual org
-+virtual report
-+
-+@td@
-+type T;
-+identifier E;
-+@@
-+- typedef enum E
-++ enum E
-+ { ...
-+- } T;
-++ };
-+@@
-+type td.T;
-+identifier td.E;
-+@@
-+- T
-++ enum E
-+
-+@@
-+type td.T;
-+identifier td.E;
-+@@
-+- const T
-++ const enum E
-diff --git a/scripts/coccinelle/dtrace/typedef-elision.cocci b/scripts/coccinelle/dtrace/typedef-elision.cocci
-new file mode 100644
-index 0000000000000000000000000000000000000000..bc4caf375b607b624b9c566bf1a2e471e463f01e
---- /dev/null
-+++ b/scripts/coccinelle/dtrace/typedef-elision.cocci
-@@ -0,0 +1,83 @@
-+/// Reduce uses of typedefs of named structures to the name of the structure
-+
-+virtual patch
-+virtual context
-+virtual org
-+virtual report
-+
-+@td@
-+type T;
-+identifier S;
-+@@
-+(
-+- typedef struct S
-++ struct S
-+ { ...
-+- } T;
-++ };
-+|
-+ struct S;
-+- typedef struct S T;
-+)
-+@@
-+type td.T;
-+identifier td.S;
-+@@
-+- T
-++ struct S
-+
-+@@
-+type td.T;
-+identifier td.S;
-+@@
-+- const T
-++ const struct S
-+
-+/// Now structures declared with typedefs of opaque structs, one by one
-+@@
-+typedef dtrace_ecb_t;
-+@@
-+- dtrace_ecb_t
-++ struct dtrace_ecb
-+
-+@@
-+typedef dtrace_actdesc_t;
-+@@
-+- dtrace_actdesc_t
-++ struct dtrace_actdesc
-+
-+@@
-+typedef dtrace_state_t;
-+@@
-+- dtrace_state_t
-++ struct dtrace_state
-+
-+@@
-+typedef dtrace_vstate_t;
-+@@
-+- dtrace_vstate_t
-++ struct dtrace_vstate
-+
-+@@
-+typedef dtrace_mstate_t;
-+@@
-+- dtrace_mstate_t
-++ struct dtrace_mstate
-+
-+@@
-+typedef dtrace_task_t;
-+@@
-+- dtrace_task_t
-++ struct dtrace_task
-+
-+@@
-+typedef dtrace_psinfo_t;
-+@@
-+- dtrace_psinfo_t
-++ struct dtrace_psinfo
-+
-+@@
-+typedef dt_fbt_bl_entry_t;
-+@@
-+- dt_fbt_bl_entry_t
-++ struct dt_fbt_bl_entry
-diff --git a/scripts/package/mkspec b/scripts/package/mkspec
-index e9ff22c6fb4c7c7082767c7c9b164e94735ea1e7..cba5be72adb926cb6a96fb9d8d497a362e6080b9 100755
---- a/scripts/package/mkspec
-+++ b/scripts/package/mkspec
-@@ -150,6 +150,7 @@ $M %exclude /lib/modules/$KERNELRELEASE/source
- %files headers
- %defattr (-, root, root)
- /usr/include
-+ %exclude /usr/include/linux/dtrace
- $S$M
- $S$M %files devel
- $S$M %defattr (-, root, root)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0005-dtrace-modular-components-and-x86-support.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0005-dtrace-modular-components-and-x86-support.patch
deleted file mode 100644
index 7f95d00dba49..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0005-dtrace-modular-components-and-x86-support.patch
+++ /dev/null
@@ -1,18392 +0,0 @@
-From 4b3eec83a54c9bd853648e4b256fb28a078a36aa Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 17:52:54 +0000
-Subject: [PATCH 05/19] dtrace: modular components and x86 support
-
-This implements the core DTrace module (including the entire DIF
-interpreter and support for all built-in D variables and functions) and
-one test provider, dt_test.ko. It uses the machinery added in the last
-few commits. An x86 implementation of the architecture-dependent parts
-is also added so that one platform at least can compile it.
-
-At this stage, almost no probes will exist: they are added by the
-following commits, that add providers and SDT probes.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- Makefile | 1 +
- arch/x86/dtrace/Makefile.arch | 11 +
- arch/x86/dtrace/dtrace_asm_x86_64.S | 228 ++
- arch/x86/dtrace/dtrace_isa_x86_64.c | 228 ++
- dtrace/Makefile | 19 +
- dtrace/ctf_api.h | 33 +
- dtrace/dt_test.h | 30 +
- dtrace/dt_test_dev.c | 176 +
- dtrace/dt_test_mod.c | 52 +
- dtrace/dtrace.h | 35 +
- dtrace/dtrace_actdesc.c | 91 +
- dtrace/dtrace_anon.c | 144 +
- dtrace/dtrace_buffer.c | 490 +++
- dtrace/dtrace_debug.h | 118 +
- dtrace/dtrace_dev.c | 1599 +++++++++
- dtrace/dtrace_dev.h | 35 +
- dtrace/dtrace_dif.c | 4905 +++++++++++++++++++++++++++
- dtrace/dtrace_dof.c | 2504 ++++++++++++++
- dtrace/dtrace_ecb.c | 936 +++++
- dtrace/dtrace_enable.c | 449 +++
- dtrace/dtrace_fmt.c | 104 +
- dtrace/dtrace_hash.c | 266 ++
- dtrace/dtrace_isa.c | 361 ++
- dtrace/dtrace_match.c | 364 ++
- dtrace/dtrace_mod.c | 45 +
- dtrace/dtrace_predicate.c | 80 +
- dtrace/dtrace_priv.c | 120 +
- dtrace/dtrace_probe.c | 1542 +++++++++
- dtrace/dtrace_probe_ctx.c | 659 ++++
- dtrace/dtrace_ptofapi.c | 649 ++++
- dtrace/dtrace_spec.c | 434 +++
- dtrace/dtrace_state.c | 1108 ++++++
- dtrace/dtrace_util.c | 282 ++
- 33 files changed, 18098 insertions(+)
- create mode 100644 arch/x86/dtrace/Makefile.arch
- create mode 100644 arch/x86/dtrace/dtrace_asm_x86_64.S
- create mode 100644 arch/x86/dtrace/dtrace_isa_x86_64.c
- create mode 100644 dtrace/Makefile
- create mode 100644 dtrace/ctf_api.h
- create mode 100644 dtrace/dt_test.h
- create mode 100644 dtrace/dt_test_dev.c
- create mode 100644 dtrace/dt_test_mod.c
- create mode 100644 dtrace/dtrace.h
- create mode 100644 dtrace/dtrace_actdesc.c
- create mode 100644 dtrace/dtrace_anon.c
- create mode 100644 dtrace/dtrace_buffer.c
- create mode 100644 dtrace/dtrace_debug.h
- create mode 100644 dtrace/dtrace_dev.c
- create mode 100644 dtrace/dtrace_dev.h
- create mode 100644 dtrace/dtrace_dif.c
- create mode 100644 dtrace/dtrace_dof.c
- create mode 100644 dtrace/dtrace_ecb.c
- create mode 100644 dtrace/dtrace_enable.c
- create mode 100644 dtrace/dtrace_fmt.c
- create mode 100644 dtrace/dtrace_hash.c
- create mode 100644 dtrace/dtrace_isa.c
- create mode 100644 dtrace/dtrace_match.c
- create mode 100644 dtrace/dtrace_mod.c
- create mode 100644 dtrace/dtrace_predicate.c
- create mode 100644 dtrace/dtrace_priv.c
- create mode 100644 dtrace/dtrace_probe.c
- create mode 100644 dtrace/dtrace_probe_ctx.c
- create mode 100644 dtrace/dtrace_ptofapi.c
- create mode 100644 dtrace/dtrace_spec.c
- create mode 100644 dtrace/dtrace_state.c
- create mode 100644 dtrace/dtrace_util.c
-
-diff --git a/Makefile b/Makefile
-index fb9393fa10f082c29ab717aefcc812e34f8caf9d..4b25be692ac15ae9f6eb52c4a5f135da70598b05 100644
---- a/Makefile
-+++ b/Makefile
-@@ -651,6 +651,7 @@ drivers-y := drivers/ sound/
- drivers-$(CONFIG_SAMPLES) += samples/
- drivers-y += net/ virt/
- libs-y := lib/
-+dtrace-y := dtrace/
- endif # KBUILD_EXTMOD
-
- # The all: target is the default when no target is given on the
-diff --git a/arch/x86/dtrace/Makefile.arch b/arch/x86/dtrace/Makefile.arch
-new file mode 100644
-index 0000000000000000000000000000000000000000..ffb9ef4d1722b673511418c5744067ac501d49c5
---- /dev/null
-+++ b/arch/x86/dtrace/Makefile.arch
-@@ -0,0 +1,11 @@
-+#
-+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
-+#
-+
-+DTARCHDIR = ../arch/x86/dtrace
-+
-+ccflags-y += -I$(srctree)/arch/x86/dtrace/include -Idtrace
-+
-+dtrace-obj += dtrace_asm_x86_64.o dtrace_isa_x86_64.o
-+
-+dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
-diff --git a/arch/x86/dtrace/dtrace_asm_x86_64.S b/arch/x86/dtrace/dtrace_asm_x86_64.S
-new file mode 100644
-index 0000000000000000000000000000000000000000..46d3fe1b9703f05126686ad81c00d8d76fa10cf2
---- /dev/null
-+++ b/arch/x86/dtrace/dtrace_asm_x86_64.S
-@@ -0,0 +1,228 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - x86 specific assembly
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/linkage.h>
-+#include <asm/smap.h>
-+
-+#define CPU_DTRACE_BADADDR 0x0004 /* DTrace fault: bad address */
-+
-+#if defined(__x86_64__)
-+ SYM_CODE_START(dtrace_caller)
-+ movq $-1, %rax
-+ ret
-+ SYM_CODE_END(dtrace_caller)
-+
-+#elif defined(__i386__)
-+
-+ SYM_CODE_START(dtrace_caller)
-+ movl $-1, %eax
-+ ret
-+ SYM_CODE_END(dtrace_caller)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_FUNC_START(dtrace_copy)
-+ pushq %rbp
-+ movq %rsp, %rbp
-+
-+ ASM_STAC
-+ xchgq %rdi, %rsi # make %rsi source, %rdi dest
-+ movq %rdx, %rcx # load count
-+ repz # repeat for count ...
-+ smovb # move from %ds:rsi to %ed:rdi
-+ ASM_CLAC
-+ leave
-+ ret
-+ SYM_FUNC_END(dtrace_copy)
-+
-+#elif defined(__i386__)
-+
-+ SYM_FUNC_START(dtrace_copy)
-+ pushl %ebp
-+ movl %esp, %ebp
-+ pushl %esi
-+ pushl %edi
-+
-+ movl 8(%ebp), %esi # Load source address
-+ movl 12(%ebp), %edi # Load destination address
-+ movl 16(%ebp), %ecx # Load count
-+ repz # Repeat for count...
-+ smovb # move from %ds:si to %es:di
-+
-+ popl %edi
-+ popl %esi
-+ movl %ebp, %esp
-+ popl %ebp
-+ ret
-+ SYM_FUNC_END(dtrace_copy)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_FUNC_START(dtrace_copystr)
-+ pushq %rbp
-+ movq %rsp, %rbp
-+
-+ ASM_STAC
-+0:
-+ movb (%rdi), %al # load from source
-+ movb %al, (%rsi) # store to destination
-+ addq $1, %rdi # increment source pointer
-+ addq $1, %rsi # increment destination pointer
-+ subq $1, %rdx # decrement remaining count
-+ cmpb $0, %al
-+ je 2f
-+ testq $0xfff, %rdx # test if count is 4k-aligned
-+ jnz 1f # if not, continue with copying
-+ testq $CPU_DTRACE_BADADDR, (%rcx) # load and test dtrace flags
-+ jnz 2f
-+1:
-+ cmpq $0, %rdx
-+ jne 0b
-+2:
-+ ASM_CLAC
-+ leave
-+ ret
-+
-+ SYM_FUNC_END(dtrace_copystr)
-+
-+#elif defined(__i386__)
-+
-+ SYM_FUNC_START(dtrace_copystr)
-+
-+ pushl %ebp # Setup stack frame
-+ movl %esp, %ebp
-+ pushl %ebx # Save registers
-+
-+ movl 8(%ebp), %ebx # Load source address
-+ movl 12(%ebp), %edx # Load destination address
-+ movl 16(%ebp), %ecx # Load count
-+
-+0:
-+ movb (%ebx), %al # Load from source
-+ movb %al, (%edx) # Store to destination
-+ incl %ebx # Increment source pointer
-+ incl %edx # Increment destination pointer
-+ decl %ecx # Decrement remaining count
-+ cmpb $0, %al
-+ je 2f
-+ testl $0xfff, %ecx # Check if count is 4k-aligned
-+ jnz 1f
-+ movl 20(%ebp), %eax # load flags pointer
-+ testl $CPU_DTRACE_BADADDR, (%eax) # load and test dtrace flags
-+ jnz 2f
-+1:
-+ cmpl $0, %ecx
-+ jne 0b
-+
-+2:
-+ popl %ebx
-+ movl %ebp, %esp
-+ popl %ebp
-+ ret
-+
-+ SYM_FUNC_END(dtrace_copystr)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_CODE_START(dtrace_fuword8_nocheck)
-+ xorq %rax, %rax
-+ ASM_STAC
-+ movb (%rdi), %al
-+ ASM_CLAC
-+ ret
-+ SYM_CODE_END(dtrace_fuword8_nocheck)
-+
-+#elif defined(__i386__)
-+
-+ SYM_CODE_START(dtrace_fuword8_nocheck)
-+ movl 4(%esp), %ecx
-+ xorl %eax, %eax
-+ movzbl (%ecx), %eax
-+ ret
-+ SYM_CODE_END(dtrace_fuword8_nocheck)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_CODE_START(dtrace_fuword16_nocheck)
-+ xorq %rax, %rax
-+ ASM_STAC
-+ movw (%rdi), %ax
-+ ASM_CLAC
-+ ret
-+ SYM_CODE_END(dtrace_fuword16_nocheck)
-+
-+#elif defined(__i386__)
-+
-+ SYM_CODE_START(dtrace_fuword16_nocheck)
-+ movl 4(%esp), %ecx
-+ xorl %eax, %eax
-+ movzwl (%ecx), %eax
-+ ret
-+ SYM_CODE_END(dtrace_fuword16_nocheck)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_CODE_START(dtrace_fuword32_nocheck)
-+ xorq %rax, %rax
-+ ASM_STAC
-+ movl (%rdi), %eax
-+ ASM_CLAC
-+ ret
-+ SYM_CODE_END(dtrace_fuword32_nocheck)
-+
-+#elif defined(__i386__)
-+
-+ SYM_CODE_START(dtrace_fuword32_nocheck)
-+ movl 4(%esp), %ecx
-+ xorl %eax, %eax
-+ movl (%ecx), %eax
-+ ret
-+ SYM_CODE_END(dtrace_fuword32_nocheck)
-+
-+#endif /* __i386__ */
-+
-+#if defined(__x86_64__)
-+
-+ SYM_CODE_START(dtrace_fuword64_nocheck)
-+ ASM_STAC
-+ movq (%rdi), %rax
-+ ASM_CLAC
-+ ret
-+ SYM_CODE_END(dtrace_fuword64_nocheck)
-+
-+#elif defined(__i386__)
-+
-+ SYM_CODE_START(dtrace_fuword64_nocheck)
-+ movl 4(%esp), %ecx
-+ xorl %eax, %eax
-+ xorl %edx, %edx
-+ movl (%ecx), %eax
-+ movl 4(%ecx), %edx
-+ ret
-+ SYM_CODE_END(dtrace_fuword64_nocheck)
-+
-+#endif /* __i386__ */
-diff --git a/arch/x86/dtrace/dtrace_isa_x86_64.c b/arch/x86/dtrace/dtrace_isa_x86_64.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..5accadc9f121ccc9d6fc2fb63488f711a9a878d2
---- /dev/null
-+++ b/arch/x86/dtrace/dtrace_isa_x86_64.c
-@@ -0,0 +1,228 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_isa_x86_64.c
-+ * DESCRIPTION: DTrace - x86_64 architecture specific support functions
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <asm/unwind.h>
-+
-+#include "dtrace.h"
-+
-+/* Register indices */
-+#define REG_TRAPNO 25
-+#define REG_GS 24
-+#define REG_FS 23
-+#define REG_ES 22
-+#define REG_DS 21
-+#define REG_SS 20
-+#define REG_RSP 19
-+#define REG_RFL 18
-+#define REG_CS 17
-+#define REG_RIP 16
-+#define REG_ERR 15
-+#define REG_RDI 14
-+#define REG_RSI 13
-+#define REG_RDX 12
-+#define REG_RCX 11
-+#define REG_RAX 10
-+#define REG_R8 9
-+#define REG_R9 8
-+#define REG_R10 7
-+#define REG_R11 6
-+#define REG_RBX 5
-+#define REG_RBP 4
-+#define REG_R12 3
-+#define REG_R13 2
-+#define REG_R14 1
-+#define REG_R15 0
-+
-+extern void dtrace_copy(uintptr_t, uintptr_t, size_t);
-+extern void dtrace_copystr(uintptr_t, uintptr_t, size_t,
-+ volatile uint16_t *);
-+
-+uintptr_t _userlimit = 0x00007fffffffffffLL;
-+uintptr_t kernelbase = 0xffff880000000000LL;
-+
-+static int dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
-+{
-+#ifdef FIXME
-+ ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
-+#else
-+ if (kaddr < kernelbase || kaddr + size < kaddr) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = kaddr;
-+ return 0;
-+ }
-+#endif
-+
-+ if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = uaddr;
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+void dtrace_copyin_arch(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_copycheck(uaddr, kaddr, size))
-+ dtrace_copy(uaddr, kaddr, size);
-+}
-+
-+void dtrace_copyout(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_copycheck(uaddr, kaddr, size))
-+ dtrace_copy(kaddr, uaddr, size);
-+}
-+
-+void dtrace_copyinstr_arch(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_copycheck(uaddr, kaddr, size))
-+ dtrace_copystr(uaddr, kaddr, size, flags);
-+}
-+
-+void dtrace_copyoutstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_copycheck(uaddr, kaddr, size))
-+ dtrace_copystr(kaddr, uaddr, size, flags);
-+}
-+
-+#define DTRACE_FUWORD(bits) \
-+ uint##bits##_t dtrace_fuword##bits(void *uaddr) \
-+ { \
-+ extern uint##bits##_t dtrace_fuword##bits##_nocheck(void *);\
-+ \
-+ if ((uintptr_t)uaddr > _userlimit) { \
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); \
-+ this_cpu_core->cpuc_dtrace_illval = (uintptr_t)uaddr; \
-+ return 0; \
-+ } \
-+ \
-+ return dtrace_fuword##bits##_nocheck(uaddr); \
-+ }
-+
-+DTRACE_FUWORD(8)
-+DTRACE_FUWORD(16)
-+DTRACE_FUWORD(32)
-+DTRACE_FUWORD(64)
-+
-+uint64_t dtrace_getarg(int argno, int aframes)
-+{
-+ unsigned long bp;
-+ uint64_t *st;
-+ uint64_t val;
-+ int i;
-+ struct unwind_state state;
-+
-+ if (this_cpu_core->cpu_dtrace_regs)
-+ bp = this_cpu_core->cpu_dtrace_regs->bp;
-+ else {
-+ unwind_start(&state, current, NULL, NULL);
-+ for (i = 0; !unwind_done(&state) && i < aframes;
-+ unwind_next_frame(&state)) {
-+ i++;
-+ }
-+
-+ bp = (unsigned long)state.bp;
-+ }
-+
-+ ASSERT(argno >= 5);
-+
-+ /*
-+ * The first 5 arguments (arg0 through arg4) are passed in registers
-+ * to dtrace_probe(). The remaining arguments (arg5 through arg9) are
-+ * passed on the stack.
-+ *
-+ * Stack layout:
-+ * bp[0] = pushed bp from caller
-+ * bp[1] = return address
-+ * bp[2] = 6th argument (arg5 -> argno = 5)
-+ * bp[3] = 7th argument (arg6 -> argno = 6)
-+ * ...
-+ */
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ st = (uint64_t *)bp;
-+ val = st[2 + (argno - 5)];
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return val;
-+}
-+
-+ulong_t dtrace_getreg(struct task_struct *task, uint_t reg)
-+{
-+ struct pt_regs *rp = task_pt_regs(task);
-+
-+ int regmap[] = {
-+ REG_RBX, /* 0 -> EBX */
-+ REG_RCX, /* 1 -> ECX */
-+ REG_RDX, /* 2 -> EDX */
-+ REG_RSI, /* 3 -> ESI */
-+ REG_RDI, /* 4 -> EDI */
-+ REG_RBP, /* 5 -> EBP */
-+ REG_RAX, /* 6 -> EAX */
-+ REG_DS, /* 7 -> DS */
-+ REG_ES, /* 8 -> ES */
-+ REG_FS, /* 9 -> FS */
-+ REG_GS, /* 10 -> GS */
-+ REG_TRAPNO, /* 11 -> TRAPNO */
-+ REG_RIP, /* 12 -> EIP */
-+ REG_CS, /* 13 -> CS */
-+ REG_RFL, /* 14 -> EFL */
-+ REG_RSP, /* 15 -> UESP */
-+ REG_SS, /* 16 -> SS */
-+ };
-+
-+ if (reg > REG_TRAPNO) {
-+ /*
-+ * Convert register alias index into register mapping index.
-+ */
-+ reg -= REG_GS + 1;
-+
-+ if (reg >= sizeof(regmap) / sizeof(int)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return 0;
-+ }
-+
-+ reg = regmap[reg];
-+ }
-+
-+ /*
-+ * Most common case: direct index into pt_regs structure.
-+ */
-+ if (reg <= REG_SS)
-+ return (&rp->r15)[reg];
-+
-+ switch (reg) {
-+ case REG_DS:
-+ return task->thread.ds;
-+ case REG_ES:
-+ return task->thread.es;
-+ case REG_FS:
-+ return task->thread.fsbase;
-+ case REG_GS:
-+ return task->thread.gsbase;
-+ case REG_TRAPNO:
-+ return task->thread.trap_nr;
-+ default:
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return 0;
-+ }
-+}
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-new file mode 100644
-index 0000000000000000000000000000000000000000..36a4b97b922c4d2baecb0679e41b2d384f56a5b5
---- /dev/null
-+++ b/dtrace/Makefile
-@@ -0,0 +1,19 @@
-+#
-+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
-+#
-+
-+obj-$(CONFIG_DT_CORE) += dtrace.o
-+obj-$(CONFIG_DT_DT_TEST) += dt_test.o
-+
-+dtrace-y := dtrace_mod.o dtrace_dev.o \
-+ dtrace_actdesc.o dtrace_anon.o \
-+ dtrace_buffer.o dtrace_dif.o dtrace_dof.o \
-+ dtrace_ecb.o dtrace_enable.o \
-+ dtrace_fmt.o dtrace_hash.o dtrace_isa.o \
-+ dtrace_match.o dtrace_priv.o \
-+ dtrace_probe.o dtrace_probe_ctx.o \
-+ dtrace_ptofapi.o dtrace_predicate.o \
-+ dtrace_spec.o dtrace_state.o dtrace_util.o
-+dt_test-y := dt_test_mod.o dt_test_dev.o
-+
-+-include arch/$(SRCARCH)/dtrace/Makefile.arch
-diff --git a/dtrace/ctf_api.h b/dtrace/ctf_api.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..e09bafc676f4407c1228b3ac473de15c997e2cf6
---- /dev/null
-+++ b/dtrace/ctf_api.h
-@@ -0,0 +1,33 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Compact C Type format
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef __CTF_API_H_
-+#define __CTF_API_H_
-+
-+/*
-+ * The CTF data model is inferred to be the caller's data model or the data
-+ * model of the given object, unless ctf_setmodel() is explicitly called.
-+ */
-+#define CTF_MODEL_ILP32 1 /* object data model is ILP32 */
-+#define CTF_MODEL_LP64 2 /* object data model is LP64 */
-+#ifdef CONFIG_64BIT
-+# define CTF_MODEL_NATIVE CTF_MODEL_LP64
-+#else
-+# define CTF_MODEL_NATIVE CTF_MODEL_ILP32
-+#endif
-+
-+#endif /* __CTF_API_H_ */
-diff --git a/dtrace/dt_test.h b/dtrace/dt_test.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..6efe4656001b387b424fa4e4cd7aca4c2a323f50
---- /dev/null
-+++ b/dtrace/dt_test.h
-@@ -0,0 +1,30 @@
-+/*
-+ * Dynamic Tracing for Linux - test provider
-+ *
-+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _DT_TEST_H_
-+#define _DT_TEST_H_
-+
-+extern void dt_test_provide(void *, const struct dtrace_probedesc *);
-+extern int dt_test_enable(void *arg, dtrace_id_t, void *);
-+extern void dt_test_disable(void *arg, dtrace_id_t, void *);
-+extern void dt_test_destroy(void *, dtrace_id_t, void *);
-+
-+extern dtrace_provider_id_t dt_test_id;
-+
-+extern int dt_test_dev_init(void);
-+extern void dt_test_dev_exit(void);
-+
-+#endif /* _DT_TEST_H_ */
-diff --git a/dtrace/dt_test_dev.c b/dtrace/dt_test_dev.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..8e1f5bab8a128bdc29a345e422467e6e9d294cf0
---- /dev/null
-+++ b/dtrace/dt_test_dev.c
-@@ -0,0 +1,176 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dt_test_dev.c
-+ * DESCRIPTION: DTrace - test provider device driver
-+ *
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/types.h>
-+#include <trace/syscall.h>
-+#include <asm/unistd.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "dt_test.h"
-+
-+static dtrace_id_t pid = DTRACE_IDNONE;
-+static int enabled;
-+
-+/*
-+ * Some arrays of structures of different sizes populated with
-+ * unchanging randomly-chosen numbers, for padding tests.
-+ */
-+
-+static struct dt_test_int_char
-+{
-+ int foo;
-+ char bar;
-+} intish[2] __attribute__((used)) = { { 47204473, 48 },
-+ { 18472, 62 } };
-+
-+static struct dt_test_long_int
-+{
-+ long foo;
-+ int bar;
-+} longish[2] __attribute__((used)) = { { 43737975, 240724 },
-+ { 24924709, 526 } };
-+
-+static struct dt_test_longlong_long
-+{
-+ long long foo;
-+ long bar;
-+} longlongish[2] __attribute__((used)) = { { 4294479287, 4395957 },
-+ { 5239637, 249750 } };
-+
-+static struct dt_test_like_a_scatterlist
-+{
-+ unsigned long a;
-+ unsigned int b;
-+ unsigned int c;
-+ u64 d;
-+ unsigned int e;
-+} scatter_failure[2] __attribute__((used)) = { { .a = 1, .b = 2,
-+ .c = 3, .d = 4, .e = 5 },
-+ { .a = 6, .b = 7,
-+ .c = 8, .d = 9, .e = 10 } };
-+
-+void dt_test_provide(void *arg, const struct dtrace_probedesc *desc)
-+{
-+ dtrace_id_t probe;
-+
-+ probe = dtrace_probe_lookup(dt_test_id, "dt_test", NULL, "test");
-+ if (probe != DTRACE_IDNONE)
-+ return;
-+
-+ pid = dtrace_probe_create(dt_test_id, "dt_test", NULL, "test", 1, NULL);
-+}
-+
-+int dt_test_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ enabled = 1;
-+
-+ return 0;
-+}
-+
-+void dt_test_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ enabled = 0;
-+}
-+
-+void dt_test_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+}
-+
-+void probe_p(dtrace_id_t pid, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2,
-+ uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6,
-+ uintptr_t arg7, uintptr_t arg8, uintptr_t arg9)
-+{
-+}
-+
-+/*
-+ * Direct calling into dtrace_probe() when passing more than 5 parameters to
-+ * the probe requires a stub function. Otherwise we may not be able to get
-+ * to the value of all arguments correctly.
-+ */
-+void dt_test_probe(uintptr_t arg0, uintptr_t arg1, uintptr_t arg2,
-+ uintptr_t arg3, uintptr_t arg4, uintptr_t arg5,
-+ uintptr_t arg6, uintptr_t arg7, uintptr_t arg8,
-+ uintptr_t arg9)
-+{
-+ /*
-+ * Yes, this is not nice.
-+ * Not at all...
-+ * But we're doing it anyway...
-+ */
-+ typeof(probe_p) *probe_fn = (void *)&dtrace_probe;
-+
-+ probe_fn(pid, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-+ arg9);
-+}
-+
-+static long dt_test_ioctl(struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ if (enabled) {
-+ dt_test_probe(cmd, arg, 2ULL, 3ULL, 4ULL, 5ULL, 6ULL, 7ULL,
-+ 8ULL, 9ULL);
-+
-+ return 0;
-+ }
-+
-+ return -EAGAIN;
-+}
-+
-+static int dt_test_open(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static int dt_test_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations dt_test_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = dt_test_ioctl,
-+ .open = dt_test_open,
-+ .release = dt_test_close,
-+};
-+
-+static struct miscdevice dt_test_dev = {
-+ .minor = DT_DEV_DT_TEST_MINOR,
-+ .name = "dt_test",
-+ .nodename = "dtrace/provider/dt_test",
-+ .fops = &dt_test_fops,
-+};
-+
-+int dt_test_dev_init(void)
-+{
-+ int ret = 0;
-+
-+ ret = misc_register(&dt_test_dev);
-+ if (ret)
-+ pr_err("%s: Can't register misc device %d\n",
-+ dt_test_dev.name, dt_test_dev.minor);
-+
-+ return ret;
-+}
-+
-+void dt_test_dev_exit(void)
-+{
-+ misc_deregister(&dt_test_dev);
-+}
-diff --git a/dtrace/dt_test_mod.c b/dtrace/dt_test_mod.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..d8af71665a37ad3157f1bf9d2ce14cb0a23f7508
---- /dev/null
-+++ b/dtrace/dt_test_mod.c
-@@ -0,0 +1,52 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dt_test_mod.c
-+ * DESCRIPTION: DTrace - test provider kernel module
-+ *
-+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "dt_test.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("DTrace Test Probe");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+static const struct dtrace_pattr dt_test_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pops dt_test_pops = {
-+ .dtps_provide = dt_test_provide,
-+ .dtps_provide_module = NULL,
-+ .dtps_destroy_module = NULL,
-+ .dtps_enable = dt_test_enable,
-+ .dtps_disable = dt_test_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = NULL,
-+ .dtps_getargval = NULL,
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = dt_test_destroy
-+};
-+
-+DT_PROVIDER_MODULE(dt_test, DTRACE_PRIV_USER)
-diff --git a/dtrace/dtrace.h b/dtrace/dtrace.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..f632b910ac30b60a4584ea87a5087e4bba4060fc
---- /dev/null
-+++ b/dtrace/dtrace.h
-@@ -0,0 +1,35 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _DTRACE_H_
-+#define _DTRACE_H_
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/sched.h>
-+#include <linux/types.h>
-+
-+#include "dtrace_debug.h"
-+
-+#include <dtrace/types.h>
-+
-+#include <linux/dtrace/dtrace.h>
-+
-+#include <dtrace/provider.h>
-+#include <dtrace/dtrace_impl.h>
-+
-+#endif /* _DTRACE_H_ */
-diff --git a/dtrace/dtrace_actdesc.c b/dtrace/dtrace_actdesc.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..fada47a6e5eb08ebf47d7905eeb8dfab3bb36941
---- /dev/null
-+++ b/dtrace/dtrace_actdesc.c
-@@ -0,0 +1,91 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_actdesc.c
-+ * DESCRIPTION: DTrace - action implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+struct dtrace_actdesc *dtrace_actdesc_create(dtrace_actkind_t kind,
-+ uint32_t ntuple,
-+ uint64_t uarg, uint64_t arg)
-+{
-+ struct dtrace_actdesc *act;
-+
-+#ifdef FIXME
-+ ASSERT(!DTRACEACT_ISPRINTFLIKE(kind) ||
-+ (arg != 0 && (uintptr_t)arg >= KERNELBASE) ||
-+ (arg == 0 && kind == DTRACEACT_PRINTA));
-+#else
-+ ASSERT(!DTRACEACT_ISPRINTFLIKE(kind) ||
-+ (arg != 0) ||
-+ (arg == 0 && kind == DTRACEACT_PRINTA));
-+#endif
-+
-+ act = kzalloc(sizeof(struct dtrace_actdesc), GFP_KERNEL);
-+ if (act == NULL)
-+ return NULL;
-+
-+ act->dtad_kind = kind;
-+ act->dtad_ntuple = ntuple;
-+ act->dtad_uarg = uarg;
-+ act->dtad_arg = arg;
-+ act->dtad_refcnt = 1;
-+
-+ return act;
-+}
-+
-+void dtrace_actdesc_hold(struct dtrace_actdesc *act)
-+{
-+ ASSERT(act->dtad_refcnt >= 1);
-+
-+ act->dtad_refcnt++;
-+}
-+
-+void dtrace_actdesc_release(struct dtrace_actdesc *act,
-+ struct dtrace_vstate *vstate)
-+{
-+ dtrace_actkind_t kind = act->dtad_kind;
-+ struct dtrace_difo *dp;
-+
-+ ASSERT(act->dtad_refcnt >= 1);
-+
-+ if (--act->dtad_refcnt != 0)
-+ return;
-+
-+ dp = act->dtad_difo;
-+ if (dp != NULL)
-+ dtrace_difo_release(dp, vstate);
-+
-+ if (DTRACEACT_ISPRINTFLIKE(kind)) {
-+ char *str = (char *)(uintptr_t)act->dtad_arg;
-+
-+#ifdef FIXME
-+ ASSERT((str != NULL && (uintptr_t)str >= KERNELBASE) ||
-+ (str == NULL && act->dtad_kind == DTRACEACT_PRINTA));
-+#else
-+ ASSERT((str != NULL) ||
-+ (str == NULL && act->dtad_kind == DTRACEACT_PRINTA));
-+#endif
-+
-+ if (str != NULL)
-+ vfree(str);
-+ }
-+
-+ kfree(act);
-+}
-diff --git a/dtrace/dtrace_anon.c b/dtrace/dtrace_anon.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..80d0d9c1a9fd1f515a2aa5ec22d648f7f7f1a46c
---- /dev/null
-+++ b/dtrace/dtrace_anon.c
-@@ -0,0 +1,144 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_anon.c
-+ * DESCRIPTION: DTrace - Anonymous state implementation
-+ *
-+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include "dtrace.h"
-+
-+struct dtrace_anon dtrace_anon;
-+
-+struct dtrace_state *dtrace_anon_grab(void)
-+{
-+ struct dtrace_state *state;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ state = dtrace_anon.dta_state;
-+ if (state == NULL) {
-+ ASSERT(dtrace_anon.dta_enabling == NULL);
-+
-+ return NULL;
-+ }
-+
-+ ASSERT(dtrace_anon.dta_enabling != NULL);
-+ ASSERT(dtrace_retained != NULL);
-+
-+ dtrace_enabling_destroy(dtrace_anon.dta_enabling);
-+ dtrace_anon.dta_enabling = NULL;
-+ dtrace_anon.dta_state = NULL;
-+
-+ return state;
-+}
-+
-+void dtrace_anon_property(void)
-+{
-+ int i, rv;
-+ struct dtrace_state *state;
-+ struct dof_hdr *dof;
-+ char c[32]; /* enough for "dof-data-" + digits */
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+ for (i = 0; ; i++) {
-+ snprintf(c, sizeof(c), "dof-data-%d", i);
-+
-+ dtrace_err_verbose = 1;
-+
-+ dof = dtrace_dof_property(c);
-+ if (dof == NULL) {
-+ dtrace_err_verbose = 0;
-+ break;
-+ }
-+
-+#ifdef FIXME
-+ /*
-+ * We want to create anonymous state, so we need to transition
-+ * the kernel debugger to indicate that DTrace is active. If
-+ * this fails (e.g. because the debugger has modified text in
-+ * some way), we won't continue with the processing.
-+ */
-+ if (kdi_dtrace_set(KDI_DTSET_DTRACE_ACTIVATE) != 0) {
-+ pr_info("kernel debugger active; "
-+ "anonymous enabling ignored.");
-+ dtrace_dof_destroy(dof);
-+ break;
-+ }
-+#endif
-+
-+ /*
-+ * If we haven't allocated an anonymous state, we'll do so now.
-+ */
-+ state = dtrace_anon.dta_state;
-+ if (state == NULL) {
-+ state = dtrace_state_create(NULL);
-+ dtrace_anon.dta_state = state;
-+
-+ if (state == NULL) {
-+ /*
-+ * This basically shouldn't happen: there is no
-+ * failure mode from dtrace_state_create().
-+ * Still, the interface allows for a failure
-+ * mode, and we want to fail as gracefully as
-+ * possible: we'll emit an error message and
-+ * cease processing anonymous state in this
-+ * case.
-+ */
-+ pr_warn("failed to create anonymous state");
-+ dtrace_dof_destroy(dof);
-+ break;
-+ }
-+ }
-+
-+ rv = dtrace_dof_slurp(dof, &state->dts_vstate, current_cred(),
-+ &dtrace_anon.dta_enabling, 0, TRUE);
-+
-+ if (rv == 0)
-+ rv = dtrace_dof_options(dof, state);
-+
-+ dtrace_err_verbose = 0;
-+ dtrace_dof_destroy(dof);
-+
-+ if (rv != 0) {
-+ /*
-+ * This is malformed DOF; chuck any anonymous state
-+ * that we created.
-+ */
-+ ASSERT(dtrace_anon.dta_enabling == NULL);
-+ dtrace_state_destroy(state);
-+ dtrace_anon.dta_state = NULL;
-+ break;
-+ }
-+
-+ ASSERT(dtrace_anon.dta_enabling != NULL);
-+ }
-+
-+ if (dtrace_anon.dta_enabling != NULL) {
-+ int rval;
-+
-+ /*
-+ * dtrace_enabling_retain() can only fail because we are
-+ * trying to retain more enablings than are allowed -- but
-+ * we only have one anonymous enabling, and we are guaranteed
-+ * to be allowed at least one retained enabling; we assert
-+ * that dtrace_enabling_retain() returns success.
-+ */
-+ rval = dtrace_enabling_retain(dtrace_anon.dta_enabling);
-+ ASSERT(rval == 0);
-+
-+ dtrace_enabling_dump(dtrace_anon.dta_enabling);
-+ }
-+}
-diff --git a/dtrace/dtrace_buffer.c b/dtrace/dtrace_buffer.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..9e7faebc51b7002fd286579d94770a958e44e972
---- /dev/null
-+++ b/dtrace/dtrace_buffer.c
-@@ -0,0 +1,490 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_buffer.c
-+ * DESCRIPTION: DTrace - buffer implementation
-+ *
-+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+dtrace_optval_t dtrace_nonroot_maxsize = (16 * 1024 * 1024);
-+
-+/*
-+ * Note: called from cross call context. This function switches the two
-+ * buffers on a given CPU. The atomicity of this operation is assured by
-+ * disabling interrupts while the actual switch takes place; the disabling of
-+ * interrupts serializes the execution with any execution of dtrace_probe() on
-+ * the same CPU.
-+ */
-+void dtrace_buffer_switch(struct dtrace_buffer *buf)
-+{
-+ caddr_t tomax = buf->dtb_tomax;
-+ caddr_t xamot = buf->dtb_xamot;
-+ dtrace_icookie_t cookie;
-+
-+ ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH));
-+ ASSERT(!(buf->dtb_flags & DTRACEBUF_RING));
-+
-+ local_irq_save(cookie);
-+
-+ dt_dbg_buf("Switch (CPU %d): tomax %p (%lld) <-> xamot %p (%lld)\n",
-+ smp_processor_id(), tomax, buf->dtb_offset,
-+ xamot, buf->dtb_xamot_offset);
-+
-+ buf->dtb_tomax = xamot;
-+ buf->dtb_xamot = tomax;
-+ buf->dtb_xamot_drops = buf->dtb_drops;
-+ buf->dtb_xamot_offset = buf->dtb_offset;
-+ buf->dtb_xamot_errors = buf->dtb_errors;
-+ buf->dtb_xamot_flags = buf->dtb_flags;
-+ buf->dtb_offset = 0;
-+ buf->dtb_drops = 0;
-+ buf->dtb_errors = 0;
-+ buf->dtb_flags &= ~(DTRACEBUF_ERROR | DTRACEBUF_DROPPED);
-+
-+ local_irq_restore(cookie);
-+}
-+
-+/*
-+ * Note: called from cross call context. This function activates a buffer
-+ * on a CPU. As with dtrace_buffer_switch(), the atomicity of the operation
-+ * is guaranteed by the disabling of interrupts.
-+ */
-+void dtrace_buffer_activate(struct dtrace_state *state)
-+{
-+ struct dtrace_buffer *buf;
-+ dtrace_icookie_t cookie;
-+
-+ local_irq_save(cookie);
-+
-+ buf = &state->dts_buffer[smp_processor_id()];
-+
-+ if (buf->dtb_tomax != NULL)
-+ /*
-+ * We might like to assert that the buffer is marked inactive,
-+ * but this isn't necessarily true: the buffer for the CPU
-+ * that processes the BEGIN probe has its buffer activated
-+ * manually. In this case, we take the (harmless) action
-+ * re-clearing the bit INACTIVE bit.
-+ */
-+ buf->dtb_flags &= ~DTRACEBUF_INACTIVE;
-+
-+ local_irq_restore(cookie);
-+}
-+
-+int dtrace_buffer_alloc(struct dtrace_buffer *bufs, size_t size, int flags,
-+ processorid_t cpuid)
-+{
-+ processorid_t cpu;
-+ struct dtrace_buffer *buf;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+#ifdef FIXME
-+ if (size > dtrace_nonroot_maxsize &&
-+ !PRIV_POLICY_CHOICE(current_cred(), PRIV_ALL, FALSE))
-+ return -EFBIG;
-+#endif
-+
-+ for_each_online_cpu(cpu) {
-+ if (cpuid != DTRACE_CPUALL && cpuid != cpu)
-+ continue;
-+
-+ buf = &bufs[cpu];
-+
-+ /*
-+ * If there is already a buffer allocated for this CPU, it
-+ * is only possible that this is a DR event. In this case,
-+ * the buffer size must match our specified size.
-+ */
-+ if (buf->dtb_tomax != NULL) {
-+ ASSERT(buf->dtb_size == size);
-+ continue;
-+ }
-+
-+ ASSERT(buf->dtb_xamot == NULL);
-+
-+ buf->dtb_tomax = dtrace_vzalloc_try(size);
-+ if (buf->dtb_tomax == NULL)
-+ goto err;
-+
-+ buf->dtb_size = size;
-+ buf->dtb_flags = flags;
-+ buf->dtb_offset = 0;
-+ buf->dtb_drops = 0;
-+
-+ if (flags & DTRACEBUF_NOSWITCH)
-+ continue;
-+
-+ buf->dtb_xamot = dtrace_vzalloc_try(size);
-+ if (buf->dtb_xamot == NULL)
-+ goto err;
-+ }
-+
-+ return 0;
-+
-+err:
-+ for_each_online_cpu(cpu) {
-+ if (cpuid != DTRACE_CPUALL && cpuid != cpu)
-+ continue;
-+
-+ buf = &bufs[cpu];
-+
-+ if (buf->dtb_xamot != NULL) {
-+ ASSERT(buf->dtb_tomax != NULL);
-+ ASSERT(buf->dtb_size == size);
-+ vfree(buf->dtb_xamot);
-+ }
-+
-+ if (buf->dtb_tomax != NULL) {
-+ ASSERT(buf->dtb_size == size);
-+ vfree(buf->dtb_tomax);
-+ }
-+
-+ buf->dtb_tomax = NULL;
-+ buf->dtb_xamot = NULL;
-+ buf->dtb_size = 0;
-+ }
-+
-+ return -ENOMEM;
-+}
-+void dtrace_buffer_drop(struct dtrace_buffer *buf)
-+{
-+ buf->dtb_drops++;
-+}
-+
-+intptr_t dtrace_buffer_reserve(struct dtrace_buffer *buf, size_t needed,
-+ size_t align, struct dtrace_state *state,
-+ struct dtrace_mstate *mstate)
-+{
-+ intptr_t offs = buf->dtb_offset, soffs;
-+ intptr_t woffs;
-+ caddr_t tomax;
-+ size_t total;
-+
-+ if (buf->dtb_flags & DTRACEBUF_INACTIVE)
-+ return -1;
-+
-+ tomax = buf->dtb_tomax;
-+ if (tomax == NULL) {
-+ dtrace_buffer_drop(buf);
-+ return -1;
-+ }
-+
-+ if (!(buf->dtb_flags & (DTRACEBUF_RING | DTRACEBUF_FILL))) {
-+ while (offs & (align - 1)) {
-+ /*
-+ * Assert that our alignment is off by a number which
-+ * is itself sizeof (uint32_t) aligned.
-+ */
-+ ASSERT(!((align - (offs & (align - 1))) &
-+ (sizeof(uint32_t) - 1)));
-+ DTRACE_STORE(uint32_t, tomax, offs, DTRACE_EPIDNONE);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- EPIDNONE "
-+ "(from %s::%d)\n",
-+ buf, offs, offs + sizeof(uint32_t) - 1,
-+ __func__, __LINE__);
-+ offs += sizeof(uint32_t);
-+ }
-+
-+ soffs = offs + needed;
-+ if (soffs > buf->dtb_size) {
-+ dtrace_buffer_drop(buf);
-+ return -1;
-+ }
-+
-+ if (mstate == NULL) {
-+ dt_dbg_buf(" Reserve: %p[%ld .. %ld]\n",
-+ buf, offs, offs + needed - 1);
-+ return offs;
-+ }
-+
-+ mstate->dtms_scratch_base = (uintptr_t)tomax + soffs;
-+ mstate->dtms_scratch_size = buf->dtb_size - soffs;
-+ mstate->dtms_scratch_ptr = mstate->dtms_scratch_base;
-+
-+ dt_dbg_buf(" Reserve: %p[%ld .. %ld]\n",
-+ buf, offs, offs + needed - 1);
-+ return offs;
-+ }
-+
-+ if (buf->dtb_flags & DTRACEBUF_FILL) {
-+ if (state->dts_activity != DTRACE_ACTIVITY_COOLDOWN &&
-+ (buf->dtb_flags & DTRACEBUF_FULL))
-+ return -1;
-+
-+ goto out;
-+ }
-+
-+ total = needed + (offs & (align - 1));
-+
-+ /*
-+ * For a ring buffer, life is quite a bit more complicated. Before
-+ * we can store any padding, we need to adjust our wrapping offset.
-+ * (If we've never before wrapped or we're not about to, no adjustment
-+ * is required.)
-+ */
-+ if ((buf->dtb_flags & DTRACEBUF_WRAPPED) ||
-+ offs + total > buf->dtb_size) {
-+ woffs = buf->dtb_xamot_offset;
-+
-+ if (offs + total > buf->dtb_size) {
-+ /*
-+ * We can't fit in the end of the buffer. First, a
-+ * sanity check that we can fit in the buffer at all.
-+ */
-+ if (total > buf->dtb_size) {
-+ dtrace_buffer_drop(buf);
-+ return -1;
-+ }
-+
-+ /*
-+ * We're going to be storing at the top of the buffer,
-+ * so now we need to deal with the wrapped offset. We
-+ * only reset our wrapped offset to 0 if it is
-+ * currently greater than the current offset. If it
-+ * is less than the current offset, it is because a
-+ * previous allocation induced a wrap -- but the
-+ * allocation didn't subsequently take the space due
-+ * to an error or false predicate evaluation. In this
-+ * case, we'll just leave the wrapped offset alone: if
-+ * the wrapped offset hasn't been advanced far enough
-+ * for this allocation, it will be adjusted in the
-+ * lower loop.
-+ */
-+ if (buf->dtb_flags & DTRACEBUF_WRAPPED) {
-+ if (woffs >= offs)
-+ woffs = 0;
-+ } else
-+ woffs = 0;
-+
-+ /*
-+ * Now we know that we're going to be storing to the
-+ * top of the buffer and that there is room for us
-+ * there. We need to clear the buffer from the current
-+ * offset to the end (there may be old gunk there).
-+ */
-+ while (offs < buf->dtb_size)
-+ tomax[offs++] = 0;
-+
-+ /*
-+ * We need to set our offset to zero. And because we
-+ * are wrapping, we need to set the bit indicating as
-+ * much. We can also adjust our needed space back
-+ * down to the space required by the ECB -- we know
-+ * that the top of the buffer is aligned.
-+ */
-+ offs = 0;
-+ total = needed;
-+ buf->dtb_flags |= DTRACEBUF_WRAPPED;
-+ } else {
-+ /*
-+ * There is room for us in the buffer, so we simply
-+ * need to check the wrapped offset.
-+ */
-+ if (woffs < offs) {
-+ /*
-+ * The wrapped offset is less than the offset.
-+ * This can happen if we allocated buffer space
-+ * that induced a wrap, but then we didn't
-+ * subsequently take the space due to an error
-+ * or false predicate evaluation. This is
-+ * okay; we know that _this_ allocation isn't
-+ * going to induce a wrap. We still can't
-+ * reset the wrapped offset to be zero,
-+ * however: the space may have been trashed in
-+ * the previous failed probe attempt. But at
-+ * least the wrapped offset doesn't need to
-+ * be adjusted at all...
-+ */
-+ goto out;
-+ }
-+ }
-+
-+ while (offs + total > woffs) {
-+ dtrace_epid_t epid = *(uint32_t *)(tomax + woffs);
-+ size_t size;
-+
-+ if (epid == DTRACE_EPIDNONE)
-+ size = sizeof(uint32_t);
-+ else {
-+ ASSERT(epid <= state->dts_necbs);
-+ ASSERT(state->dts_ecbs[epid - 1] != NULL);
-+
-+ size = state->dts_ecbs[epid - 1]->dte_size;
-+ }
-+
-+ ASSERT(woffs + size <= buf->dtb_size);
-+ ASSERT(size != 0);
-+
-+ if (woffs + size == buf->dtb_size) {
-+ /*
-+ * We've reached the end of the buffer; we want
-+ * to set the wrapped offset to 0 and break
-+ * out. However, if the offs is 0, then we're
-+ * in a strange edge-condition: the amount of
-+ * space that we want to reserve plus the size
-+ * of the record that we're overwriting is
-+ * space but subsequently don't consume it (due
-+ * to a failed predicate or error) the wrapped
-+ * offset will be 0 -- yet the EPID at offset 0
-+ * will not be committed. This situation is
-+ * relatively easy to deal with: if we're in
-+ * this case, the buffer is indistinguishable
-+ * from one that hasn't wrapped; we need only
-+ * finish the job by clearing the wrapped bit,
-+ * explicitly setting the offset to be 0, and
-+ * zero'ing out the old data in the buffer.
-+ */
-+ if (offs == 0) {
-+ buf->dtb_flags &= ~DTRACEBUF_WRAPPED;
-+ buf->dtb_offset = 0;
-+ woffs = total;
-+
-+ while (woffs < buf->dtb_size)
-+ tomax[woffs++] = 0;
-+ }
-+
-+ woffs = 0;
-+ break;
-+ }
-+
-+ woffs += size;
-+ }
-+
-+ /*
-+ * We have a wrapped offset. It may be that the wrapped offset
-+ * has become zero -- that's okay.
-+ */
-+ buf->dtb_xamot_offset = woffs;
-+ }
-+
-+out:
-+ /*
-+ * Now we can plow the buffer with any necessary padding.
-+ */
-+ while (offs & (align - 1)) {
-+ /*
-+ * Assert that our alignment is off by a number which
-+ * is itself sizeof(uint32_t) aligned.
-+ */
-+ ASSERT(!((align - (offs & (align - 1))) &
-+ (sizeof(uint32_t) - 1)));
-+ DTRACE_STORE(uint32_t, tomax, offs, DTRACE_EPIDNONE);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- EPIDNONE "
-+ "(from %s::%d)\n",
-+ buf, offs, offs + sizeof(uint32_t) - 1,
-+ __func__, __LINE__);
-+ offs += sizeof(uint32_t);
-+ }
-+
-+ if (buf->dtb_flags & DTRACEBUF_FILL) {
-+ if (offs + needed > buf->dtb_size - state->dts_reserve) {
-+ buf->dtb_flags |= DTRACEBUF_FULL;
-+ return -1;
-+ }
-+ }
-+
-+ if (mstate == NULL) {
-+ dt_dbg_buf(" Reserve: %p[%ld .. %ld]\n",
-+ buf, offs, offs + needed - 1);
-+ return offs;
-+ }
-+
-+ /*
-+ * For ring buffers and fill buffers, the scratch space is always
-+ * the inactive buffer.
-+ */
-+ mstate->dtms_scratch_base = (uintptr_t)buf->dtb_xamot;
-+ mstate->dtms_scratch_size = buf->dtb_size;
-+ mstate->dtms_scratch_ptr = mstate->dtms_scratch_base;
-+
-+ dt_dbg_buf(" Reserve: %p[%ld .. %ld]\n",
-+ buf, offs, offs + needed - 1);
-+ return offs;
-+}
-+
-+void dtrace_buffer_polish(struct dtrace_buffer *buf)
-+{
-+ ASSERT(buf->dtb_flags & DTRACEBUF_RING);
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (!(buf->dtb_flags & DTRACEBUF_WRAPPED))
-+ return;
-+
-+ /*
-+ * We need to polish the ring buffer. There are three cases:
-+ *
-+ * - The first (and presumably most common) is that there is no gap
-+ * between the buffer offset and the wrapped offset. In this case,
-+ * there is nothing in the buffer that isn't valid data; we can
-+ * mark the buffer as polished and return.
-+ *
-+ * - The second (less common than the first but still more common
-+ * than the third) is that there is a gap between the buffer offset
-+ * and the wrapped offset, and the wrapped offset is larger than the
-+ * buffer offset. This can happen because of an alignment issue, or
-+ * can happen because of a call to dtrace_buffer_reserve() that
-+ * didn't subsequently consume the buffer space. In this case,
-+ * we need to zero the data from the buffer offset to the wrapped
-+ * offset.
-+ *
-+ * - The third (and least common) is that there is a gap between the
-+ * buffer offset and the wrapped offset, but the wrapped offset is
-+ * _less_ than the buffer offset. This can only happen because a
-+ * call to dtrace_buffer_reserve() induced a wrap, but the space
-+ * was not subsequently consumed. In this case, we need to zero the
-+ * space from the offset to the end of the buffer _and_ from the
-+ * top of the buffer to the wrapped offset.
-+ */
-+ if (buf->dtb_offset < buf->dtb_xamot_offset)
-+ memset(buf->dtb_tomax + buf->dtb_offset, 0,
-+ buf->dtb_xamot_offset - buf->dtb_offset);
-+
-+ if (buf->dtb_offset > buf->dtb_xamot_offset) {
-+ memset(buf->dtb_tomax + buf->dtb_offset, 0,
-+ buf->dtb_size - buf->dtb_offset);
-+ memset(buf->dtb_tomax, 0, buf->dtb_xamot_offset);
-+ }
-+}
-+
-+void dtrace_buffer_free(struct dtrace_buffer *bufs)
-+{
-+ int cpu;
-+
-+ for_each_online_cpu(cpu) {
-+ struct dtrace_buffer *buf = &bufs[cpu];
-+
-+ if (buf->dtb_tomax == NULL) {
-+ ASSERT(buf->dtb_xamot == NULL);
-+ ASSERT(buf->dtb_size == 0);
-+
-+ continue;
-+ }
-+
-+ if (buf->dtb_xamot != NULL) {
-+ ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH));
-+
-+ vfree(buf->dtb_xamot);
-+ buf->dtb_xamot = NULL;
-+ }
-+
-+ vfree(buf->dtb_tomax);
-+ buf->dtb_size = 0;
-+ buf->dtb_tomax = NULL;
-+ }
-+}
-diff --git a/dtrace/dtrace_debug.h b/dtrace/dtrace_debug.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..a55fd1a0436fdfd60e05290ea5ae0e3986bfc66c
---- /dev/null
-+++ b/dtrace/dtrace_debug.h
-@@ -0,0 +1,118 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _DTRACE_DEBUG_H_
-+#define _DTRACE_DEBUG_H_
-+
-+#ifdef CONFIG_DT_DEBUG
-+
-+/*
-+ * Enable all output and use dynamic debug when supported.
-+ */
-+# ifdef CONFIG_DYNAMIC_DEBUG
-+
-+# define DT_DBG_AGG
-+# define DT_DBG_BUF
-+# define DT_DBG_DIF
-+# define DT_DBG_DOF
-+# define DT_DBG_ENABLE
-+# define DT_DBG_IOCTL
-+# define DT_DBG_PROBE
-+# define DT_DBG_PROVIDER
-+
-+# define dt_dbg_print(fmt, ...) pr_debug(fmt, ## __VA_ARGS__)
-+
-+# else /* CONFIG_DYNAMIC_DEBUG */
-+
-+# undef DT_DBG_AGG
-+# undef DT_DBG_BUF
-+# undef DT_DBG_DIF
-+# undef DT_DBG_DOF
-+# undef DT_DBG_ENABLE
-+# undef DT_DBG_IOCTL
-+# undef DT_DBG_PROBE
-+# undef DT_DBG_PROVIDER
-+
-+# define dt_dbg_print(fmt, ...) pr_info(fmt, ## __VA_ARGS__)
-+
-+# endif /* CONFIG_DYNAMIC_DEBUG */
-+
-+#else /* CONFIG_DT_DEBUG */
-+
-+# undef DT_DBG_AGG
-+# undef DT_DBG_BUF
-+# undef DT_DBG_DIF
-+# undef DT_DBG_DOF
-+# undef DT_DBG_ENABLE
-+# undef DT_DBG_IOCTL
-+# undef DT_DBG_PROBE
-+# undef DT_DBG_PROVIDER
-+
-+#endif /* CONFIG_DT_DEBUG */
-+
-+/*
-+ * Here are the actual actions for the various debug cases.
-+ */
-+#ifdef DT_DBG_AGG
-+# define dt_dbg_agg(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_agg(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_BUF
-+# define dt_dbg_buf(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_buf(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_DIF
-+# define dt_dbg_dif(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_dif(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_DOF
-+# define dt_dbg_dof(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_dof(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_ENABLE
-+# define dt_dbg_enable(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_enable(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_IOCTL
-+# define dt_dbg_ioctl(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_ioctl(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_PROBE
-+# define dt_dbg_probe(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_probe(fmt, ...)
-+#endif
-+
-+#ifdef DT_DBG_PROVIDER
-+# define dt_dbg_prov(fmt, ...) dt_dbg_print(fmt, ## __VA_ARGS__)
-+#else
-+# define dt_dbg_prov(fmt, ...)
-+#endif
-+
-+#endif /* _DTRACE_DEBUG_H_ */
-diff --git a/dtrace/dtrace_dev.c b/dtrace/dtrace_dev.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..0e52c936b9e03bdf56d2a11e41528ed9b461af66
---- /dev/null
-+++ b/dtrace/dtrace_dev.c
-@@ -0,0 +1,1599 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_dev.c
-+ * DESCRIPTION: DTrace - Framework device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/delay.h>
-+#include <dtrace/types.h>
-+#include <linux/dtrace/ioctl.h>
-+#include <linux/fs.h>
-+#include <linux/jiffies.h>
-+#include <linux/kernel.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <linux/uaccess.h>
-+
-+#include "ctf_api.h"
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+
-+extern char *dtrace_helptrace_buffer;
-+extern int dtrace_helptrace_bufsize;
-+extern int dtrace_helptrace_enabled;
-+
-+int dtrace_opens;
-+int dtrace_err_verbose;
-+
-+struct dtrace_pops dtrace_provider_ops = {
-+ (void (*)(void *, const struct dtrace_probedesc *))dtrace_nullop,
-+ (void (*)(void *, struct module *))dtrace_nullop,
-+ (int (*)(void *, dtrace_id_t, void *))dtrace_enable_nullop,
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
-+ NULL,
-+ NULL,
-+ NULL,
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop,
-+ (void (*)(void *, struct module *))dtrace_nullop,
-+};
-+
-+static size_t dtrace_retain_max = 1024;
-+
-+struct dtrace_toxrange *dtrace_toxrange;
-+int dtrace_toxranges;
-+static int dtrace_toxranges_max;
-+
-+struct kmem_cache *dtrace_state_cachep;
-+
-+struct user_namespace *init_user_namespace;
-+
-+static struct dtrace_pattr dtrace_provider_attr = {
-+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
-+};
-+
-+DEFINE_MUTEX(dtrace_lock);
-+
-+void dtrace_nullop(void)
-+{
-+}
-+
-+int dtrace_enable_nullop(void)
-+{
-+ return 0;
-+}
-+
-+
-+#ifdef CONFIG_DT_DEBUG
-+static void dtrace_ioctl_sizes(void)
-+{
-+#define DBG_PRINT(x) dt_dbg_ioctl("Size of %s: %lx\n", #x, sizeof(x))
-+ DBG_PRINT(struct dtrace_providerdesc);
-+ DBG_PRINT(struct dtrace_probedesc);
-+ DBG_PRINT(struct dtrace_bufdesc);
-+ DBG_PRINT(struct dtrace_eprobedesc);
-+ DBG_PRINT(struct dtrace_argdesc);
-+ DBG_PRINT(struct dtrace_conf);
-+ DBG_PRINT(struct dtrace_status);
-+ DBG_PRINT(processorid_t);
-+ DBG_PRINT(struct dtrace_aggdesc);
-+ DBG_PRINT(struct dtrace_fmtdesc);
-+ DBG_PRINT(struct dof_hdr);
-+#undef DBG_PRINT
-+}
-+
-+#endif
-+
-+static int dtrace_open(struct inode *inode, struct file *file)
-+{
-+ struct dtrace_state *state;
-+ uint32_t priv;
-+ kuid_t uid;
-+
-+ dtrace_cred2priv(file->f_cred, &priv, &uid);
-+ if (priv == DTRACE_PRIV_NONE)
-+ return -EACCES;
-+
-+#ifdef CONFIG_DT_DEBUG
-+ dtrace_ioctl_sizes();
-+#endif
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ dtrace_probe_provide(NULL, NULL);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ /*
-+ * Do not let a consumer continue if it is not possible to enable
-+ * DTrace.
-+ */
-+ if (dtrace_enable() != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+ return -EBUSY;
-+ }
-+
-+ dtrace_opens++;
-+ dtrace_membar_producer();
-+
-+ state = dtrace_state_create(file);
-+ mutex_unlock(&cpu_lock);
-+
-+ if (state == NULL) {
-+ if (--dtrace_opens == 0 && dtrace_anon.dta_enabling == NULL)
-+ dtrace_disable();
-+ mutex_unlock(&dtrace_lock);
-+
-+ return -EAGAIN;
-+ }
-+
-+ file->private_data = state;
-+ mutex_unlock(&dtrace_lock);
-+
-+ return 0;
-+}
-+
-+static long dtrace_ioctl(struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ struct dtrace_state *state;
-+ int rval;
-+ void __user *argp = (void __user *)arg;
-+
-+ state = (struct dtrace_state *) file->private_data;
-+ if (state->dts_anon) {
-+ ASSERT(dtrace_anon.dta_state == NULL);
-+ state = state->dts_anon;
-+ }
-+
-+ switch (cmd) {
-+ case DTRACEIOC_PROVIDER: {
-+ struct dtrace_providerdesc pvd;
-+ struct dtrace_provider *pvp;
-+
-+ dt_dbg_ioctl("IOCTL PROVIDER (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&pvd, argp, sizeof(pvd)) != 0)
-+ return -EFAULT;
-+
-+ pvd.dtvd_name[DTRACE_PROVNAMELEN - 1] = '\0';
-+ mutex_lock(&dtrace_provider_lock);
-+
-+ for (pvp = dtrace_provider; pvp != NULL; pvp = pvp->dtpv_next) {
-+ if (strcmp(pvp->dtpv_name, pvd.dtvd_name) == 0)
-+ break;
-+ }
-+
-+ mutex_unlock(&dtrace_provider_lock);
-+
-+ dt_dbg_ioctl(" Provider '%s' %sfound\n",
-+ pvd.dtvd_name, pvp ? "" : "not ");
-+ if (pvp == NULL)
-+ return -ESRCH;
-+
-+ memcpy(&pvd.dtvd_priv, &pvp->dtpv_priv,
-+ sizeof(struct dtrace_ppriv));
-+ memcpy(&pvd.dtvd_attr, &pvp->dtpv_attr,
-+ sizeof(struct dtrace_pattr));
-+
-+ if (copy_to_user(argp, &pvd, sizeof(pvd)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_EPROBE: {
-+ struct dtrace_eprobedesc epdesc;
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_action *act;
-+ void *buf;
-+ size_t size;
-+ uint8_t *dest;
-+ int nrecs;
-+
-+ dt_dbg_ioctl("IOCTL EPROBE (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&epdesc, argp, sizeof(epdesc)) != 0)
-+ return -EFAULT;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ ecb = dtrace_epid2ecb(state, epdesc.dtepd_epid);
-+ if (ecb == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+
-+ if (ecb->dte_probe == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+
-+ epdesc.dtepd_probeid = ecb->dte_probe->dtpr_id;
-+ epdesc.dtepd_uarg = ecb->dte_uarg;
-+ epdesc.dtepd_size = ecb->dte_size;
-+
-+ nrecs = epdesc.dtepd_nrecs;
-+ epdesc.dtepd_nrecs = 0;
-+ for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
-+ if (DTRACEACT_ISAGG(act->dta_kind) || act->dta_intuple)
-+ continue;
-+
-+ epdesc.dtepd_nrecs++;
-+ }
-+
-+ /*
-+ * Now that we have the size, we need to allocate a temporary
-+ * buffer in which to store the complete description. We need
-+ * the temporary buffer to be able to drop dtrace_lock()
-+ * across the copy_to_user(), below.
-+ */
-+ size = sizeof(struct dtrace_eprobedesc) +
-+ (epdesc.dtepd_nrecs * sizeof(struct dtrace_recdesc));
-+
-+ buf = vmalloc(size);
-+ if (buf == NULL)
-+ return -ENOMEM;
-+
-+ dest = buf;
-+ memcpy(dest, &epdesc, sizeof(epdesc));
-+ dest += offsetof(struct dtrace_eprobedesc, dtepd_rec[0]);
-+
-+ for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
-+ if (DTRACEACT_ISAGG(act->dta_kind) || act->dta_intuple)
-+ continue;
-+
-+ if (nrecs-- == 0)
-+ break;
-+
-+ memcpy(dest, &act->dta_rec,
-+ sizeof(struct dtrace_recdesc));
-+ dest += sizeof(struct dtrace_recdesc);
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (copy_to_user(argp, buf,
-+ (uintptr_t)(dest - (uint8_t *)buf)) != 0) {
-+ vfree(buf);
-+ return -EFAULT;
-+ }
-+
-+ vfree(buf);
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_AGGDESC: {
-+ struct dtrace_aggdesc aggdesc;
-+ struct dtrace_action *act;
-+ struct dtrace_aggregation *agg;
-+ int nrecs;
-+ uint32_t offs;
-+ struct dtrace_recdesc *lrec;
-+ void *buf;
-+ size_t size;
-+ uint8_t *dest;
-+
-+ dt_dbg_ioctl("IOCTL AGGDESC (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&aggdesc, argp, sizeof(aggdesc)) != 0)
-+ return -EFAULT;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ agg = dtrace_aggid2agg(state, aggdesc.dtagd_id);
-+ if (agg == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+
-+ aggdesc.dtagd_epid = agg->dtag_ecb->dte_epid;
-+
-+ nrecs = aggdesc.dtagd_nrecs;
-+ aggdesc.dtagd_nrecs = 0;
-+
-+ offs = agg->dtag_base;
-+ lrec = &agg->dtag_action.dta_rec;
-+ aggdesc.dtagd_size = lrec->dtrd_offset + lrec->dtrd_size -
-+ offs;
-+
-+ for (act = agg->dtag_first; ; act = act->dta_next) {
-+ ASSERT(act->dta_intuple ||
-+ DTRACEACT_ISAGG(act->dta_kind));
-+
-+ /*
-+ * If this action has a record size of zero, it
-+ * denotes an argument to the aggregating action.
-+ * Because the presence of this record doesn't (or
-+ * shouldn't) affect the way the data is interpreted,
-+ * we don't copy it out to save user-level the
-+ * confusion of dealing with a zero-length record.
-+ */
-+ if (act->dta_rec.dtrd_size == 0) {
-+ ASSERT(agg->dtag_hasarg);
-+ continue;
-+ }
-+
-+ aggdesc.dtagd_nrecs++;
-+
-+ if (act == &agg->dtag_action)
-+ break;
-+ }
-+
-+ /*
-+ * Now that we have the size, we need to allocate a temporary
-+ * buffer in which to store the complete description. We need
-+ * the temporary buffer to be able to drop dtrace_lock()
-+ * across the copyout(), below.
-+ */
-+ size = sizeof(struct dtrace_aggdesc) +
-+ (aggdesc.dtagd_nrecs * sizeof(struct dtrace_recdesc));
-+
-+ buf = vmalloc(size);
-+ if (buf == NULL)
-+ return -ENOMEM;
-+
-+ dest = buf;
-+ memcpy(dest, &aggdesc, sizeof(aggdesc));
-+ dest += offsetof(struct dtrace_aggdesc, dtagd_rec[0]);
-+
-+ for (act = agg->dtag_first; ; act = act->dta_next) {
-+ struct dtrace_recdesc rec = act->dta_rec;
-+
-+ /*
-+ * See the comment in the above loop for why we pass
-+ * over zero-length records.
-+ */
-+ if (rec.dtrd_size == 0) {
-+ ASSERT(agg->dtag_hasarg);
-+ continue;
-+ }
-+
-+ if (nrecs-- == 0)
-+ break;
-+
-+ rec.dtrd_offset -= offs;
-+ memcpy(dest, &rec, sizeof(rec));
-+ dest += sizeof(struct dtrace_recdesc);
-+
-+ if (act == &agg->dtag_action)
-+ break;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (copy_to_user(argp, buf,
-+ (uintptr_t)(dest - (uint8_t *)buf)) != 0) {
-+ vfree(buf);
-+ return -EFAULT;
-+ }
-+
-+ vfree(buf);
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_ENABLE: {
-+ struct dof_hdr *dof;
-+ struct dtrace_enabling *enab = NULL;
-+ struct dtrace_vstate *vstate;
-+ int err = 0;
-+ int rv;
-+
-+ dt_dbg_ioctl("IOCTL ENABLE (cmd %#x), argp %p\n", cmd, argp);
-+
-+ rv = 0;
-+
-+ /*
-+ * If a NULL argument has been passed, we take this as our
-+ * cue to reevaluate our enablings.
-+ */
-+ if (argp == NULL) {
-+ dtrace_enabling_matchall();
-+
-+ return 0;
-+ }
-+
-+ dof = dtrace_dof_copyin(argp, &rval);
-+ if (dof == NULL)
-+ return rval;
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&dtrace_lock);
-+ vstate = &state->dts_vstate;
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+ dtrace_dof_destroy(dof);
-+ return -EBUSY;
-+ }
-+
-+ if (dtrace_dof_slurp(dof, vstate, file->f_cred, &enab, 0,
-+ TRUE) != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+ dtrace_dof_destroy(dof);
-+ return -EINVAL;
-+ }
-+
-+ rval = dtrace_dof_options(dof, state);
-+ if (rval != 0) {
-+ dtrace_enabling_destroy(enab);
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+ dtrace_dof_destroy(dof);
-+ return rval;
-+ }
-+
-+ err = dtrace_enabling_match(enab, &rv);
-+ if (err == 0)
-+ err = dtrace_enabling_retain(enab);
-+ else
-+ dtrace_enabling_destroy(enab);
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+ dtrace_dof_destroy(dof);
-+
-+ return err == 0 ? rv : err;
-+ }
-+
-+ case DTRACEIOC_REPLICATE: {
-+ struct dtrace_repldesc desc;
-+ struct dtrace_probedesc *match = &desc.dtrpd_match;
-+ struct dtrace_probedesc *create = &desc.dtrpd_create;
-+ int err;
-+
-+ dt_dbg_ioctl("IOCTL REPLICATE (cmd %#x), argp %p\n",
-+ cmd, argp);
-+
-+ if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ match->dtpd_provider[DTRACE_PROVNAMELEN - 1] = '\0';
-+ match->dtpd_mod[DTRACE_MODNAMELEN - 1] = '\0';
-+ match->dtpd_func[DTRACE_FUNCNAMELEN - 1] = '\0';
-+ match->dtpd_name[DTRACE_NAMELEN - 1] = '\0';
-+
-+ create->dtpd_provider[DTRACE_PROVNAMELEN - 1] = '\0';
-+ create->dtpd_mod[DTRACE_MODNAMELEN - 1] = '\0';
-+ create->dtpd_func[DTRACE_FUNCNAMELEN - 1] = '\0';
-+ create->dtpd_name[DTRACE_NAMELEN - 1] = '\0';
-+
-+ mutex_lock(&dtrace_lock);
-+ err = dtrace_enabling_replicate(state, match, create);
-+ mutex_unlock(&dtrace_lock);
-+
-+ return err;
-+ }
-+
-+ case DTRACEIOC_PROBEMATCH:
-+ case DTRACEIOC_PROBES: {
-+ int id;
-+ struct dtrace_probe *probe = NULL;
-+ struct dtrace_probedesc desc;
-+ struct dtrace_probekey pkey;
-+ uint32_t priv;
-+ kuid_t uid;
-+
-+ dt_dbg_ioctl("IOCTL %s (cmd %#x), argp %p\n",
-+ cmd == DTRACEIOC_PROBES ? "PROBES"
-+ : "PROBEMATCH",
-+ cmd, argp);
-+
-+ if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ desc.dtpd_provider[DTRACE_PROVNAMELEN - 1] = '\0';
-+ desc.dtpd_mod[DTRACE_MODNAMELEN - 1] = '\0';
-+ desc.dtpd_func[DTRACE_FUNCNAMELEN - 1] = '\0';
-+ desc.dtpd_name[DTRACE_NAMELEN - 1] = '\0';
-+ dt_dbg_ioctl(" Probe ID %d %s:%s:%s:%s\n",
-+ desc.dtpd_id, desc.dtpd_provider, desc.dtpd_mod,
-+ desc.dtpd_func, desc.dtpd_name);
-+
-+ /*
-+ * Before we attempt to match this probe, we want to give
-+ * all providers the opportunity to provide it.
-+ */
-+ if (desc.dtpd_id == DTRACE_IDNONE) {
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ dtrace_probe_provide(&desc, NULL);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+ }
-+
-+ if (cmd == DTRACEIOC_PROBEMATCH) {
-+ dtrace_probekey(&desc, &pkey);
-+ pkey.dtpk_id = DTRACE_IDNONE;
-+ }
-+
-+ dtrace_cred2priv(file->f_cred, &priv, &uid);
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ id = desc.dtpd_id;
-+ if (cmd == DTRACEIOC_PROBEMATCH) {
-+ int m = 0;
-+
-+ while ((probe = dtrace_probe_get_next(&id))
-+ != NULL) {
-+ m = dtrace_match_probe(probe, &pkey, priv, uid);
-+ if (m)
-+ break;
-+
-+ id++;
-+ }
-+
-+ if (m < 0) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+ } else {
-+ while ((probe = dtrace_probe_get_next(&id))
-+ != NULL) {
-+ if (dtrace_match_priv(probe, priv, uid))
-+ break;
-+
-+ id++;
-+ }
-+ }
-+
-+ if (probe == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ return -ESRCH;
-+ }
-+
-+ dtrace_probe_description(probe, &desc);
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (copy_to_user(argp, &desc, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_PROBEARG: {
-+ struct dtrace_argdesc desc;
-+ struct dtrace_probe *probe;
-+ struct dtrace_provider *prov;
-+
-+ dt_dbg_ioctl("IOCTL PROBEARG (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ if (desc.dtargd_id == DTRACE_IDNONE)
-+ return -EINVAL;
-+
-+ if (desc.dtargd_ndx == DTRACE_ARGNONE)
-+ return -EINVAL;
-+
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ probe = dtrace_probe_lookup_id(desc.dtargd_id);
-+ if (probe == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ return -EINVAL;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ prov = probe->dtpr_provider;
-+
-+ if (prov->dtpv_pops.dtps_getargdesc == NULL) {
-+ /*
-+ * There isn't any typed information for this probe.
-+ * Set the argument number to DTRACE_ARGNONE.
-+ */
-+ desc.dtargd_ndx = DTRACE_ARGNONE;
-+ } else {
-+ desc.dtargd_native[0] = '\0';
-+ desc.dtargd_xlate[0] = '\0';
-+ desc.dtargd_mapping = desc.dtargd_ndx;
-+
-+ prov->dtpv_pops.dtps_getargdesc(
-+ prov->dtpv_arg, probe->dtpr_id,
-+ probe->dtpr_arg, &desc);
-+ }
-+
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ if (copy_to_user(argp, &desc, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_GO: {
-+ processorid_t cpuid;
-+
-+ dt_dbg_ioctl("IOCTL GO (cmd %#x), argp %p\n", cmd, argp);
-+
-+ rval = dtrace_state_go(state, &cpuid);
-+
-+ if (rval != 0)
-+ return rval;
-+
-+ if (copy_to_user(argp, &cpuid, sizeof(cpuid)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_STOP: {
-+ processorid_t cpuid;
-+
-+ dt_dbg_ioctl("IOCTL STOP (cmd %#x), argp %p\n", cmd, argp);
-+
-+ mutex_lock(&dtrace_lock);
-+ rval = dtrace_state_stop(state, &cpuid);
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (rval != 0)
-+ return rval;
-+
-+ if (copy_to_user(argp, &cpuid, sizeof(cpuid)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_DOFGET: {
-+ struct dof_hdr hdr, *dof;
-+ uint64_t len;
-+
-+ dt_dbg_ioctl("IOCTL DOFGET (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&hdr, argp, sizeof(hdr)) != 0)
-+ return -EFAULT;
-+
-+ mutex_lock(&dtrace_lock);
-+ dof = dtrace_dof_create(state);
-+ mutex_unlock(&dtrace_lock);
-+ if (dof == NULL)
-+ return -ENOMEM;
-+
-+ len = min(hdr.dofh_loadsz, dof->dofh_loadsz);
-+ rval = copy_to_user(argp, dof, len);
-+ dtrace_dof_destroy(dof);
-+
-+ return rval == 0 ? 0 : -EFAULT;
-+ }
-+
-+ case DTRACEIOC_AGGSNAP:
-+ case DTRACEIOC_BUFSNAP: {
-+ struct dtrace_bufdesc desc;
-+ caddr_t cached;
-+ struct dtrace_buffer *buf;
-+
-+ dt_dbg_ioctl("IOCTL %s (cmd %#x), argp %p\n",
-+ cmd == DTRACEIOC_AGGSNAP ? "AGGSNAP"
-+ : "BUFSNAP",
-+ cmd, argp);
-+
-+ if (copy_from_user(&desc, argp, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ if (desc.dtbd_cpu < 0 || desc.dtbd_cpu >= NR_CPUS)
-+ return -EINVAL;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ if (cmd == DTRACEIOC_BUFSNAP)
-+ buf = &state->dts_buffer[desc.dtbd_cpu];
-+ else
-+ buf = &state->dts_aggbuffer[desc.dtbd_cpu];
-+
-+ if (buf->dtb_flags & (DTRACEBUF_RING | DTRACEBUF_FILL)) {
-+ size_t sz = buf->dtb_offset;
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_STOPPED) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EBUSY;
-+ }
-+
-+ /*
-+ * If this buffer has already been consumed, we're
-+ * going to indicate that there's nothing left here
-+ * to consume.
-+ */
-+ if (buf->dtb_flags & DTRACEBUF_CONSUMED) {
-+ mutex_unlock(&dtrace_lock);
-+
-+ desc.dtbd_size = 0;
-+ desc.dtbd_drops = 0;
-+ desc.dtbd_errors = 0;
-+ desc.dtbd_oldest = 0;
-+ sz = sizeof(desc);
-+
-+ if (copy_to_user(argp, &desc, sz) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ /*
-+ * If this is a ring buffer that has wrapped, we want
-+ * to copy the whole thing out.
-+ */
-+ if (buf->dtb_flags & DTRACEBUF_WRAPPED) {
-+ dtrace_buffer_polish(buf);
-+ sz = buf->dtb_size;
-+ }
-+
-+ if (copy_to_user(desc.dtbd_data, buf->dtb_tomax,
-+ sz) != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EFAULT;
-+ }
-+
-+ desc.dtbd_size = sz;
-+ desc.dtbd_drops = buf->dtb_drops;
-+ desc.dtbd_errors = buf->dtb_errors;
-+ desc.dtbd_oldest = buf->dtb_xamot_offset;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (copy_to_user(argp, &desc, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ buf->dtb_flags |= DTRACEBUF_CONSUMED;
-+
-+ return 0;
-+ }
-+
-+ if (buf->dtb_tomax == NULL) {
-+ ASSERT(buf->dtb_xamot == NULL);
-+ mutex_unlock(&dtrace_lock);
-+ return -ENOENT;
-+ }
-+
-+ cached = buf->dtb_tomax;
-+
-+ dtrace_xcall(desc.dtbd_cpu,
-+ (dtrace_xcall_t)dtrace_buffer_switch, buf);
-+
-+ state->dts_errors += buf->dtb_xamot_errors;
-+
-+ /*
-+ * If the buffers did not actually switch, then the cross call
-+ * did not take place -- presumably because the given CPU is
-+ * not in the ready set. If this is the case, we'll return
-+ * ENOENT.
-+ */
-+ if (buf->dtb_tomax == cached) {
-+ ASSERT(buf->dtb_xamot != cached);
-+ mutex_unlock(&dtrace_lock);
-+ return -ENOENT;
-+ }
-+
-+ ASSERT(cached == buf->dtb_xamot);
-+
-+ /*
-+ * We have our snapshot; now copy it out.
-+ */
-+ if (copy_to_user(desc.dtbd_data, buf->dtb_xamot,
-+ buf->dtb_xamot_offset) != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EFAULT;
-+ }
-+
-+ desc.dtbd_size = buf->dtb_xamot_offset;
-+ desc.dtbd_drops = buf->dtb_xamot_drops;
-+ desc.dtbd_errors = buf->dtb_xamot_errors;
-+ desc.dtbd_oldest = 0;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ /*
-+ * Finally, copy out the buffer description.
-+ */
-+ if (copy_to_user(argp, &desc, sizeof(desc)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_CONF: {
-+ struct dtrace_conf conf;
-+
-+ dt_dbg_ioctl("IOCTL CONF (cmd %#x), argp %p\n", cmd, argp);
-+
-+ memset(&conf, 0, sizeof(conf));
-+ conf.dtc_difversion = DIF_VERSION;
-+ conf.dtc_difintregs = DIF_DIR_NREGS;
-+ conf.dtc_diftupregs = DIF_DTR_NREGS;
-+ conf.dtc_ctfmodel = CTF_MODEL_NATIVE;
-+ conf.dtc_maxbufs = nr_cpu_ids;
-+
-+ if (copy_to_user(argp, &conf, sizeof(conf)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_STATUS: {
-+ struct dtrace_status stat;
-+ struct dtrace_dstate *dstate;
-+ int i, j;
-+ uint64_t nerrs;
-+
-+ dt_dbg_ioctl("IOCTL STATUS (cmd %#x), argp %p\n", cmd, argp);
-+
-+ /*
-+ * See the comment in dtrace_state_deadman() for the reason
-+ * for setting dts_laststatus to UINT64_MAX before setting
-+ * it to the correct value.
-+ */
-+ state->dts_laststatus = ns_to_ktime(UINT64_MAX);
-+ dtrace_membar_producer();
-+ state->dts_laststatus = dtrace_gethrtime();
-+
-+ memset(&stat, 0, sizeof(stat));
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ if (state->dts_activity == DTRACE_ACTIVITY_INACTIVE) {
-+ mutex_unlock(&dtrace_lock);
-+ return -ENOENT;
-+ }
-+
-+ if (state->dts_activity == DTRACE_ACTIVITY_DRAINING)
-+ stat.dtst_exiting = 1;
-+
-+ nerrs = state->dts_errors;
-+ dstate = &state->dts_vstate.dtvs_dynvars;
-+
-+ for (i = 0; i < NR_CPUS; i++) {
-+ struct dtrace_dstate_percpu *dcpu;
-+
-+ dcpu = &dstate->dtds_percpu[i];
-+ stat.dtst_dyndrops += dcpu->dtdsc_drops;
-+ stat.dtst_dyndrops_dirty += dcpu->dtdsc_dirty_drops;
-+ stat.dtst_dyndrops_rinsing += dcpu->dtdsc_rinsing_drops;
-+
-+ if (state->dts_buffer[i].dtb_flags & DTRACEBUF_FULL)
-+ stat.dtst_filled++;
-+
-+ nerrs += state->dts_buffer[i].dtb_errors;
-+
-+ for (j = 0; j < state->dts_nspeculations; j++) {
-+ struct dtrace_speculation *spec;
-+ struct dtrace_buffer *buf;
-+
-+ spec = &state->dts_speculations[j];
-+ buf = &spec->dtsp_buffer[i];
-+ stat.dtst_specdrops += buf->dtb_xamot_drops;
-+ }
-+ }
-+
-+ stat.dtst_specdrops_busy = state->dts_speculations_busy;
-+ stat.dtst_specdrops_unavail = state->dts_speculations_unavail;
-+ stat.dtst_stkstroverflows = state->dts_stkstroverflows;
-+ stat.dtst_dblerrors = state->dts_dblerrors;
-+ stat.dtst_killed = (state->dts_activity ==
-+ DTRACE_ACTIVITY_KILLED);
-+ stat.dtst_errors = nerrs;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (copy_to_user(argp, &stat, sizeof(stat)) != 0)
-+ return -EFAULT;
-+
-+ return 0;
-+ }
-+
-+ case DTRACEIOC_FORMAT: {
-+ struct dtrace_fmtdesc fmt;
-+ char *str;
-+ int len;
-+
-+ dt_dbg_ioctl("IOCTL FORMAT (cmd %#x), argp %p\n", cmd, argp);
-+
-+ if (copy_from_user(&fmt, argp, sizeof(fmt)) != 0)
-+ return -EFAULT;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ if (fmt.dtfd_format == 0 ||
-+ fmt.dtfd_format > state->dts_nformats) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * Format strings are allocated contiguously and they are
-+ * never freed; if a format index is less than the number
-+ * of formats, we can assert that the format map is non-NULL
-+ * and that the format for the specified index is non-NULL.
-+ */
-+ ASSERT(state->dts_formats != NULL);
-+ str = state->dts_formats[fmt.dtfd_format - 1];
-+ ASSERT(str != NULL);
-+
-+ len = strlen(str) + 1;
-+
-+ if (len > fmt.dtfd_length) {
-+ fmt.dtfd_length = len;
-+
-+ if (copy_to_user(argp, &fmt, sizeof(fmt)) != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+ } else {
-+ if (copy_to_user(fmt.dtfd_string, str, len) != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ return -EINVAL;
-+ }
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ return 0;
-+ }
-+
-+ default:
-+ dt_dbg_ioctl("IOCTL ??? (cmd %#x), argp %p\n",
-+ cmd, argp);
-+ break;
-+ }
-+
-+ return -ENOTTY;
-+}
-+
-+static int dtrace_close(struct inode *inode, struct file *file)
-+{
-+ struct dtrace_state *state = file->private_data;
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ /*
-+ * If there is anonymous state, destroy that first.
-+ */
-+ if (state->dts_anon) {
-+ ASSERT(dtrace_anon.dta_state == NULL);
-+ dtrace_state_destroy(state->dts_anon);
-+ }
-+
-+ dtrace_state_destroy(state);
-+ ASSERT(dtrace_opens > 0);
-+
-+ if (--dtrace_opens == 0 && dtrace_anon.dta_enabling == NULL)
-+ dtrace_disable();
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+
-+ return 0;
-+}
-+
-+static int dtrace_helper_open(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static long dtrace_helper_ioctl(struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ int rval;
-+ struct dof_helper help, *dhp = NULL;
-+ void __user *argp = (void __user *)arg;
-+
-+ switch (cmd) {
-+ case DTRACEHIOC_ADDDOF:
-+ dt_dbg_ioctl("Helper IOCTL ADDDOF (cmd %#x), argp %p\n",
-+ cmd, argp);
-+
-+ if (copy_from_user(&help, argp, sizeof(help)) != 0) {
-+ dtrace_dof_error(NULL, "failed to copy DOF helper");
-+ return -EFAULT;
-+ }
-+
-+ dhp = &help;
-+ argp = (void __user *)help.dofhp_dof;
-+
-+ /* fallthrough */
-+
-+ case DTRACEHIOC_ADD: {
-+ struct dof_hdr *dof = dtrace_dof_copyin(argp, &rval);
-+
-+ if (dof == NULL)
-+ return rval;
-+
-+ if (cmd == DTRACEHIOC_ADD)
-+ dt_dbg_ioctl("Helper IOCTL ADD (cmd %#x), argp %p\n",
-+ cmd, argp);
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ /*
-+ * The dtrace_helper_slurp() routine takes responsibility for
-+ * the dof -- it may free it now, or it may save it and free it
-+ * later.
-+ */
-+ rval = dtrace_helper_slurp(dof, dhp);
-+ if (rval == -1)
-+ rval = -EINVAL;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ dt_dbg_ioctl("Helper IOCTL %s returning %d\n",
-+ cmd == DTRACEHIOC_ADD ? "ADD"
-+ : "ADDDOF",
-+ rval);
-+
-+ return rval;
-+ }
-+
-+ case DTRACEHIOC_REMOVE:
-+ dt_dbg_ioctl("Helper IOCTL REMOVE (cmd %#x), argp %p\n",
-+ cmd, argp);
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ rval = dtrace_helper_destroygen((uintptr_t)argp);
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ dt_dbg_ioctl("Helper IOCTL REMOVE returning %d\n", rval);
-+
-+ return rval;
-+ default:
-+ dt_dbg_ioctl("Helper IOCTL ??? (cmd %#x), argp %p\n",
-+ cmd, argp);
-+ break;
-+ }
-+
-+ return -ENOTTY;
-+}
-+
-+static int dtrace_helper_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations dtrace_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = dtrace_ioctl,
-+ .open = dtrace_open,
-+ .release = dtrace_close,
-+};
-+
-+static const struct file_operations helper_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = dtrace_helper_ioctl,
-+ .compat_ioctl = dtrace_helper_ioctl,
-+ .open = dtrace_helper_open,
-+ .release = dtrace_helper_close,
-+};
-+
-+static struct miscdevice dtrace_dev = {
-+ .minor = DT_DEV_DTRACE_MINOR,
-+ .name = "dtrace",
-+ .nodename = "dtrace/dtrace",
-+ .fops = &dtrace_fops,
-+};
-+
-+static struct miscdevice helper_dev = {
-+ .minor = DT_DEV_HELPER_MINOR,
-+ .name = "helper",
-+ .nodename = "dtrace/helper",
-+ .fops = &helper_fops,
-+};
-+
-+static void dtrace_module_loaded(struct module *mp)
-+{
-+ struct dtrace_provider *prv;
-+
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+
-+ /*
-+ * Give all providers a chance to register probes for this module.
-+ */
-+ for (prv = dtrace_provider; prv != NULL; prv = prv->dtpv_next)
-+ prv->dtpv_pops.dtps_provide_module(prv->dtpv_arg, mp);
-+
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ /*
-+ * If we have any retained enablings, we need to match against them.
-+ */
-+ mutex_lock(&dtrace_lock);
-+
-+ if (dtrace_retained == NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ return;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+ dtrace_enabling_matchall();
-+}
-+
-+static void dtrace_module_unloaded(struct module *mp)
-+{
-+ struct dtrace_probe template, *probe, *first, *next;
-+ struct dtrace_provider *prv;
-+
-+ template.dtpr_mod = mp->name;
-+
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (dtrace_bymod == NULL) {
-+ /*
-+ * The DTrace module is loaded (obviously) but not attached;
-+ * we don't have any work to do.
-+ */
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+ return;
-+ }
-+
-+ for (probe = first = dtrace_hash_lookup(dtrace_bymod, &template);
-+ probe != NULL; probe = probe->dtpr_nextmod) {
-+ if (probe->dtpr_ecb != NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ /*
-+ * This shouldn't _actually_ be possible -- we're
-+ * unloading a module that has an enabled probe in it.
-+ * (It's normally up to the provider to make sure that
-+ * this can't happen.) However, because dtps_enable()
-+ * doesn't have a failure mode, there can be an
-+ * enable/unload race. Upshot: we don't want to
-+ * assert, but we're not going to disable the
-+ * probe, either.
-+ */
-+ if (dtrace_err_verbose) {
-+ pr_warn("unloaded module '%s' "
-+ "had enabled probes", mp->name);
-+ }
-+
-+ return;
-+ }
-+ }
-+
-+ probe = first;
-+
-+ for (first = NULL; probe != NULL; probe = next) {
-+ dtrace_probe_remove_id(probe->dtpr_id);
-+
-+ next = probe->dtpr_nextmod;
-+ dtrace_hash_remove(dtrace_bymod, probe);
-+ dtrace_hash_remove(dtrace_byfunc, probe);
-+ dtrace_hash_remove(dtrace_byname, probe);
-+
-+ if (first == NULL) {
-+ first = probe;
-+ probe->dtpr_nextmod = NULL;
-+ } else {
-+ probe->dtpr_nextmod = first;
-+ first = probe;
-+ }
-+ }
-+
-+ /*
-+ * We've removed all of the module's probes from the hash chains and
-+ * from the probe array. Now issue a dtrace_sync() to be sure that
-+ * everyone has cleared out from any probe array processing.
-+ */
-+ dtrace_sync();
-+
-+ for (probe = first; probe != NULL; probe = first) {
-+ first = probe->dtpr_nextmod;
-+ prv = probe->dtpr_provider;
-+ prv->dtpv_pops.dtps_destroy(prv->dtpv_arg, probe->dtpr_id,
-+ probe->dtpr_arg);
-+ kfree(probe->dtpr_mod);
-+ kfree(probe->dtpr_func);
-+ kfree(probe->dtpr_name);
-+ kfree(probe);
-+ }
-+
-+ /*
-+ * Notify providers to cleanup per-module data for this module.
-+ */
-+ for (prv = dtrace_provider; prv != NULL; prv = prv->dtpv_next)
-+ if (prv->dtpv_pops.dtps_destroy_module != NULL)
-+ prv->dtpv_pops.dtps_destroy_module(prv->dtpv_arg, mp);
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+}
-+
-+/*
-+ * Register a toxic range.
-+ */
-+static void dtrace_toxrange_add(uintptr_t base, uintptr_t limit)
-+{
-+ if (dtrace_toxranges >= dtrace_toxranges_max) {
-+ int osize, nsize;
-+ struct dtrace_toxrange *range;
-+
-+ osize = dtrace_toxranges_max * sizeof(struct dtrace_toxrange);
-+
-+ if (osize == 0) {
-+ ASSERT(dtrace_toxrange == NULL);
-+ ASSERT(dtrace_toxranges_max == 0);
-+
-+ dtrace_toxranges_max = 1;
-+ } else
-+ dtrace_toxranges_max <<= 1;
-+
-+ nsize = dtrace_toxranges_max * sizeof(struct dtrace_toxrange);
-+ range = vzalloc(nsize);
-+ if (range == NULL) {
-+ pr_warn("Failed to add toxic range: out of memory\n");
-+ return;
-+ }
-+
-+ if (dtrace_toxrange != NULL) {
-+ ASSERT(osize != 0);
-+
-+ memcpy(range, dtrace_toxrange, osize);
-+ vfree(dtrace_toxrange);
-+ }
-+
-+ dtrace_toxrange = range;
-+ }
-+
-+ ASSERT(dtrace_toxrange[dtrace_toxranges].dtt_base == (uintptr_t)NULL);
-+ ASSERT(dtrace_toxrange[dtrace_toxranges].dtt_limit == (uintptr_t)NULL);
-+
-+ dtrace_toxrange[dtrace_toxranges].dtt_base = base;
-+ dtrace_toxrange[dtrace_toxranges].dtt_limit = limit;
-+ dtrace_toxranges++;
-+}
-+
-+/*
-+ * Check if an address falls within a toxic region.
-+ */
-+int dtrace_istoxic(uintptr_t kaddr, size_t size)
-+{
-+ uintptr_t taddr, tsize;
-+ int i;
-+
-+ for (i = 0; i < dtrace_toxranges; i++) {
-+ taddr = dtrace_toxrange[i].dtt_base;
-+ tsize = dtrace_toxrange[i].dtt_limit - taddr;
-+
-+ if (kaddr - taddr < tsize) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = kaddr;
-+ return 1;
-+ }
-+
-+ if (taddr - kaddr < size) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = kaddr;
-+ return 1;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int dtrace_mod_notifier(struct notifier_block *nb, unsigned long val,
-+ void *args)
-+{
-+ struct module *mp = args;
-+
-+ if (!mp)
-+ return NOTIFY_DONE;
-+
-+ switch (val) {
-+ case MODULE_STATE_LIVE:
-+ dtrace_module_loaded(mp);
-+ break;
-+
-+ case MODULE_STATE_GOING:
-+ dtrace_module_unloaded(mp);
-+ break;
-+ }
-+
-+ return NOTIFY_DONE;
-+}
-+
-+static struct notifier_block dtrace_modmgmt = {
-+ .notifier_call = dtrace_mod_notifier,
-+};
-+
-+/*
-+ * Initialize the DTrace core.
-+ *
-+ * Equivalent to: dtrace_attach()
-+ */
-+int dtrace_dev_init(void)
-+{
-+ dtrace_provider_id_t id;
-+ int rc = 0;
-+ struct cred *cred;
-+
-+ /*
-+ * Register the device for the DTrace core.
-+ */
-+ rc = misc_register(&dtrace_dev);
-+ if (rc) {
-+ pr_err("%s: Can't register misc device %d\n",
-+ dtrace_dev.name, dtrace_dev.minor);
-+
-+ return rc;
-+ }
-+
-+ /*
-+ * Register the device for the DTrace helper.
-+ */
-+ rc = misc_register(&helper_dev);
-+ if (rc) {
-+ pr_err("%s: Can't register misc device %d\n",
-+ helper_dev.name, helper_dev.minor);
-+
-+ misc_deregister(&dtrace_dev);
-+ return rc;
-+ }
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ rc = dtrace_probe_init();
-+ if (rc) {
-+ pr_err("Failed to initialize DTrace core\n");
-+
-+ goto errout;
-+ }
-+
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+ dtrace_helpers_cleanup = dtrace_helpers_destroy;
-+ dtrace_helpers_fork = dtrace_helpers_duplicate;
-+#endif
-+#ifdef FIXME
-+ dtrace_cpu_init = dtrace_cpu_setup_initial;
-+ dtrace_cpustart_init = dtrace_suspend;
-+ dtrace_cpustart_fini = dtrace_resume;
-+ dtrace_debugger_init = dtrace_suspend;
-+ dtrace_debugger_fini = dtrace_resume;
-+
-+ register_cpu_setup_func((cpu_setup_func_t *)dtrace_cpu_setup, NULL);
-+#endif
-+
-+#ifdef FIXME
-+ dtrace_taskq = taskq_create("dtrace_taskq", 1, maxclsyspri, 1, INT_MAX,
-+ 0);
-+#endif
-+
-+ dtrace_state_cachep = kmem_cache_create("dtrace_state_cache",
-+ sizeof(struct dtrace_dstate_percpu) * NR_CPUS,
-+ 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
-+
-+ /* From now on the failures are results of failed allocations. */
-+ rc = -ENOMEM;
-+
-+ /*
-+ * Create the probe hashtables.
-+ */
-+ dtrace_bymod = dtrace_hash_create(
-+ offsetof(struct dtrace_probe, dtpr_mod),
-+ offsetof(struct dtrace_probe, dtpr_nextmod),
-+ offsetof(struct dtrace_probe, dtpr_prevmod));
-+ if (dtrace_bymod == NULL)
-+ goto errout;
-+
-+ dtrace_byfunc = dtrace_hash_create(
-+ offsetof(struct dtrace_probe, dtpr_func),
-+ offsetof(struct dtrace_probe, dtpr_nextfunc),
-+ offsetof(struct dtrace_probe, dtpr_prevfunc));
-+ if (dtrace_byfunc == NULL)
-+ goto errout;
-+
-+ dtrace_byname = dtrace_hash_create(
-+ offsetof(struct dtrace_probe, dtpr_name),
-+ offsetof(struct dtrace_probe, dtpr_nextname),
-+ offsetof(struct dtrace_probe, dtpr_prevname));
-+ if (dtrace_byname == NULL)
-+ goto errout;
-+
-+ /*
-+ * Initialize cred.
-+ */
-+ cred = prepare_kernel_cred(NULL);
-+ if (cred == NULL)
-+ goto errout;
-+
-+ init_user_namespace = cred->user_ns;
-+ put_cred(cred);
-+
-+ /*
-+ * Ensure that the X configuration parameter has a legal value.
-+ */
-+ if (dtrace_retain_max < 1) {
-+ pr_warn("Illegal value (%lu) for dtrace_retain_max; "
-+ "setting to 1", (unsigned long)dtrace_retain_max);
-+
-+ dtrace_retain_max = 1;
-+ }
-+
-+ /*
-+ * Discover our toxic ranges.
-+ */
-+ dtrace_toxic_ranges(dtrace_toxrange_add);
-+
-+ /*
-+ * Register ourselves as a provider.
-+ */
-+ dtrace_register("dtrace", &dtrace_provider_attr, DTRACE_PRIV_NONE, 0,
-+ &dtrace_provider_ops, NULL, &id);
-+
-+ ASSERT(dtrace_provider != NULL);
-+ ASSERT((dtrace_provider_id_t)dtrace_provider == id);
-+
-+ /*
-+ * Create BEGIN, END, and ERROR probes.
-+ */
-+ dtrace_probeid_begin = dtrace_probe_create(
-+ (dtrace_provider_id_t)dtrace_provider, NULL,
-+ NULL, "BEGIN", 0, NULL);
-+ if (dtrace_probeid_begin == DTRACE_IDNONE)
-+ goto errout;
-+
-+ dtrace_probeid_end = dtrace_probe_create(
-+ (dtrace_provider_id_t)dtrace_provider, NULL,
-+ NULL, "END", 0, NULL);
-+ if (dtrace_probeid_end == DTRACE_IDNONE)
-+ goto errout;
-+
-+ dtrace_probeid_error = dtrace_probe_create(
-+ (dtrace_provider_id_t)dtrace_provider, NULL,
-+ NULL, "ERROR", 1, NULL);
-+ if (dtrace_probeid_error == DTRACE_IDNONE)
-+ goto errout;
-+
-+ dtrace_anon_property();
-+
-+ /*
-+ * If DTrace helper tracing is enabled, we need to allocate a trace
-+ * buffer.
-+ */
-+ if (dtrace_helptrace_enabled) {
-+ ASSERT(dtrace_helptrace_buffer == NULL);
-+
-+ dtrace_helptrace_buffer = vzalloc(dtrace_helptrace_bufsize);
-+
-+ if (dtrace_helptrace_buffer == NULL) {
-+ pr_warn("Cannot allocate helptrace buffer; "
-+ "disabling dtrace_helptrace\n");
-+ dtrace_helptrace_enabled = 0;
-+ }
-+ }
-+
-+#ifdef FIXME
-+ /*
-+ * There is usually code here to handle the case where there already
-+ * are providers when we get to this code. On Linux, that does not
-+ * seem to be possible since the DTrace core module (this code) is
-+ * loaded as a dependency for each provider, and thus this
-+ * initialization code is executed prior to the initialization code of
-+ * the first provider causing the core to be loaded.
-+ */
-+#endif
-+
-+ if (register_module_notifier(&dtrace_modmgmt))
-+ goto errout;
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+ mutex_unlock(&cpu_lock);
-+
-+ return 0;
-+
-+errout:
-+ if (dtrace_provider != NULL)
-+ (void) dtrace_unregister((dtrace_provider_id_t)dtrace_provider);
-+
-+ dtrace_hash_destroy(dtrace_bymod);
-+ dtrace_hash_destroy(dtrace_byfunc);
-+ dtrace_hash_destroy(dtrace_byname);
-+
-+ misc_deregister(&helper_dev);
-+ misc_deregister(&dtrace_dev);
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+ mutex_unlock(&cpu_lock);
-+
-+ return rc;
-+}
-+
-+void dtrace_dev_exit(void)
-+{
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ dtrace_unregister((dtrace_provider_id_t)dtrace_provider);
-+ dtrace_provider = NULL;
-+
-+ dtrace_probe_exit();
-+
-+ unregister_module_notifier(&dtrace_modmgmt);
-+
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+ dtrace_helpers_cleanup = NULL;
-+ dtrace_helpers_fork = NULL;
-+#endif
-+#ifdef FIXME
-+ dtrace_cpu_init = NULL;
-+ dtrace_cpustart_init = NULL;
-+ dtrace_cpustart_fini = NULL;
-+ dtrace_debugger_init = NULL;
-+ dtrace_debugger_fini = NULL;
-+
-+ unregister_cpu_setup_func((cpu_setup_func_t *)dtrace_cpu_setup, NULL);
-+#endif
-+
-+ mutex_unlock(&cpu_lock);
-+
-+ dtrace_hash_destroy(dtrace_bymod);
-+ dtrace_hash_destroy(dtrace_byfunc);
-+ dtrace_hash_destroy(dtrace_byname);
-+ dtrace_bymod = NULL;
-+ dtrace_byfunc = NULL;
-+ dtrace_byname = NULL;
-+
-+ /*
-+ * If DTrace helper tracing is enabled, we need to free the trace
-+ * buffer.
-+ */
-+ if (dtrace_helptrace_enabled || dtrace_helptrace_buffer)
-+ vfree(dtrace_helptrace_buffer);
-+
-+ kmem_cache_destroy(dtrace_state_cachep);
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ misc_deregister(&helper_dev);
-+ misc_deregister(&dtrace_dev);
-+}
-diff --git a/dtrace/dtrace_dev.h b/dtrace/dtrace_dev.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..11ae2deb17a15ac27c95b021f95455417b3c15e4
---- /dev/null
-+++ b/dtrace/dtrace_dev.h
-@@ -0,0 +1,35 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _DTRACE_DEV_H_
-+#define _DTRACE_DEV_H_
-+
-+#define DT_DEV_DTRACE_MINOR (16)
-+#define DT_DEV_HELPER_MINOR (DT_DEV_DTRACE_MINOR + 1)
-+#define DT_DEV_PROFILE_MINOR (DT_DEV_HELPER_MINOR + 1)
-+#define DT_DEV_SYSTRACE_MINOR (DT_DEV_PROFILE_MINOR + 1)
-+#define DT_DEV_FBT_MINOR (DT_DEV_SYSTRACE_MINOR + 1)
-+#define DT_DEV_SDT_MINOR (DT_DEV_FBT_MINOR + 1)
-+#define DT_DEV_FASTTRAP_MINOR (DT_DEV_SDT_MINOR + 1)
-+#define DT_DEV_LOCKSTAT_MINOR (DT_DEV_FASTTRAP_MINOR + 1)
-+#define DT_DEV_DT_TEST_MINOR (DT_DEV_LOCKSTAT_MINOR + 1)
-+#define DT_DEV_DT_PERF_MINOR (DT_DEV_DT_TEST_MINOR + 1)
-+
-+extern int dtrace_dev_init(void);
-+extern void dtrace_dev_exit(void);
-+
-+#endif /* _DTRACE_DEV_H_ */
-diff --git a/dtrace/dtrace_dif.c b/dtrace/dtrace_dif.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..ae7f01b4ed9b76ea957dbfe080e1ac8fda995329
---- /dev/null
-+++ b/dtrace/dtrace_dif.c
-@@ -0,0 +1,4905 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_dif.c
-+ * DESCRIPTION: DTrace - DIF object implementation
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/fdtable.h>
-+#include <linux/hardirq.h>
-+#include <linux/if_arp.h>
-+#include <linux/if_ether.h>
-+#include <linux/if_infiniband.h>
-+#include <linux/in6.h>
-+#include <linux/inet.h>
-+#include <linux/kdev_t.h>
-+#include <linux/slab.h>
-+#include <linux/socket.h>
-+#include <linux/vmalloc.h>
-+#include <net/ipv6.h>
-+#include <asm/byteorder.h>
-+
-+#include <linux/mount.h>
-+
-+#include "dtrace.h"
-+
-+size_t dtrace_global_maxsize = 16 * 1024;
-+
-+/*
-+ * This externally visible variable (accessible through the backtick (`)
-+ * syntax is provided as a source of well-known, zero-filled memory. Some
-+ * translators use this in their implementation.
-+ */
-+const char dtrace_zero[256] = { 0, };
-+
-+uint64_t dtrace_vtime_references;
-+
-+static const char hexdigits[] = "0123456789abcdef";
-+
-+static int dtrace_difo_err(uint_t pc, const char *format, ...)
-+{
-+ char buf[256];
-+
-+ if (dtrace_err_verbose) {
-+ va_list alist;
-+ size_t len = strlen(format);
-+
-+ pr_err("dtrace DIF object error: [%u]: ", pc);
-+
-+ if (len >= 256 - sizeof(KERN_ERR)) {
-+ pr_err("<invalid format string>");
-+ return 1;
-+ }
-+
-+ memcpy(buf, KERN_ERR, sizeof(KERN_ERR));
-+ memcpy(buf + sizeof(KERN_ERR), format, len);
-+
-+ va_start(alist, format);
-+ vprintk(buf, alist);
-+ va_end(alist);
-+ }
-+
-+ return 1;
-+}
-+
-+/*
-+ * Validate a DTrace DIF object by checking the IR instructions. The following
-+ * rules are currently enforced by dtrace_difo_validate():
-+ *
-+ * 1. Each instruction must have a valid opcode
-+ * 2. Each register, string, variable, or subroutine reference must be valid
-+ * 3. No instruction can modify register %r0 (must be zero)
-+ * 4. All instruction reserved bits must be set to zero
-+ * 5. The last instruction must be a "ret" instruction
-+ * 6. All branch targets must reference a valid instruction _after_ the branch
-+ */
-+int dtrace_difo_validate(struct dtrace_difo *dp, struct dtrace_vstate *vstate,
-+ uint_t nregs, const struct cred *cr)
-+{
-+ int err = 0, i;
-+ int (*efunc)(uint_t pc, const char *, ...) = dtrace_difo_err;
-+ int kcheckload = 0;
-+ uint_t pc;
-+
-+ kcheckload = cr == NULL ||
-+ (vstate->dtvs_state->dts_cred.dcr_visible &
-+ DTRACE_CRV_KERNEL) == 0;
-+
-+ dp->dtdo_destructive = 0;
-+
-+ for (pc = 0; pc < dp->dtdo_len && err == 0; pc++) {
-+ dif_instr_t instr = dp->dtdo_buf[pc];
-+ uint_t r1 = DIF_INSTR_R1(instr);
-+ uint_t r2 = DIF_INSTR_R2(instr);
-+ uint_t rd = DIF_INSTR_RD(instr);
-+ uint_t rs = DIF_INSTR_RS(instr);
-+ uint_t label = DIF_INSTR_LABEL(instr);
-+ uint_t v = DIF_INSTR_VAR(instr);
-+ uint_t subr = DIF_INSTR_SUBR(instr);
-+ uint_t diftype = DIF_INSTR_TYPE(instr);
-+ uint_t op = DIF_INSTR_OP(instr);
-+
-+ switch (op) {
-+ case DIF_OP_OR:
-+ case DIF_OP_XOR:
-+ case DIF_OP_AND:
-+ case DIF_OP_SLL:
-+ case DIF_OP_SRL:
-+ case DIF_OP_SRA:
-+ case DIF_OP_SUB:
-+ case DIF_OP_ADD:
-+ case DIF_OP_MUL:
-+ case DIF_OP_SDIV:
-+ case DIF_OP_UDIV:
-+ case DIF_OP_SREM:
-+ case DIF_OP_UREM:
-+ case DIF_OP_COPYS:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r2);
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_NOT:
-+ case DIF_OP_MOV:
-+ case DIF_OP_ALLOCS:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_LDSB:
-+ case DIF_OP_LDSH:
-+ case DIF_OP_LDSW:
-+ case DIF_OP_LDUB:
-+ case DIF_OP_LDUH:
-+ case DIF_OP_LDUW:
-+ case DIF_OP_LDX:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ if (kcheckload)
-+ dp->dtdo_buf[pc] = DIF_INSTR_LOAD(
-+ op + DIF_OP_RLDSB -
-+ DIF_OP_LDSB,
-+ r1, rd);
-+ break;
-+ case DIF_OP_RLDSB:
-+ case DIF_OP_RLDSH:
-+ case DIF_OP_RLDSW:
-+ case DIF_OP_RLDUB:
-+ case DIF_OP_RLDUH:
-+ case DIF_OP_RLDUW:
-+ case DIF_OP_RLDX:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_ULDSB:
-+ case DIF_OP_ULDSH:
-+ case DIF_OP_ULDSW:
-+ case DIF_OP_ULDUB:
-+ case DIF_OP_ULDUH:
-+ case DIF_OP_ULDUW:
-+ case DIF_OP_ULDX:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_STB:
-+ case DIF_OP_STH:
-+ case DIF_OP_STW:
-+ case DIF_OP_STX:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to 0 address\n");
-+ break;
-+ case DIF_OP_CMP:
-+ case DIF_OP_SCMP:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r2);
-+ if (rd != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ break;
-+ case DIF_OP_TST:
-+ if (r1 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r1);
-+ if (r2 != 0 || rd != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ break;
-+ case DIF_OP_BA:
-+ case DIF_OP_BE:
-+ case DIF_OP_BNE:
-+ case DIF_OP_BG:
-+ case DIF_OP_BGU:
-+ case DIF_OP_BGE:
-+ case DIF_OP_BGEU:
-+ case DIF_OP_BL:
-+ case DIF_OP_BLU:
-+ case DIF_OP_BLE:
-+ case DIF_OP_BLEU:
-+ if (label >= dp->dtdo_len)
-+ err += efunc(pc, "invalid branch target %u\n",
-+ label);
-+ if (label <= pc)
-+ err += efunc(pc, "backward branch to %u\n",
-+ label);
-+ break;
-+ case DIF_OP_RET:
-+ if (r1 != 0 || r2 != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ break;
-+ case DIF_OP_NOP:
-+ case DIF_OP_POPTS:
-+ case DIF_OP_FLUSHTS:
-+ if (r1 != 0 || r2 != 0 || rd != 0)
-+ err += efunc(pc, "non-zero reserved bits\n");
-+ break;
-+ case DIF_OP_SETX:
-+ if (DIF_INSTR_INTEGER(instr) >= dp->dtdo_intlen)
-+ err += efunc(pc, "invalid integer ref %u\n",
-+ DIF_INSTR_INTEGER(instr));
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_SETS:
-+ if (DIF_INSTR_STRING(instr) >= dp->dtdo_strlen)
-+ err += efunc(pc, "invalid string ref %u\n",
-+ DIF_INSTR_STRING(instr));
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_LDGA:
-+ case DIF_OP_LDTA:
-+ if (r1 > DIF_VAR_ARRAY_MAX)
-+ err += efunc(pc, "invalid array %u\n", r1);
-+ if (r2 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r2);
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_LDGS:
-+ case DIF_OP_LDTS:
-+ case DIF_OP_LDLS:
-+ case DIF_OP_LDGAA:
-+ case DIF_OP_LDTAA:
-+ if (v < DIF_VAR_OTHER_MIN || v > DIF_VAR_OTHER_MAX)
-+ err += efunc(pc, "invalid variable %u\n", v);
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+ break;
-+ case DIF_OP_STGS:
-+ case DIF_OP_STTS:
-+ case DIF_OP_STLS:
-+ case DIF_OP_STGAA:
-+ case DIF_OP_STTAA:
-+ if (v < DIF_VAR_OTHER_UBASE || v > DIF_VAR_OTHER_MAX)
-+ err += efunc(pc, "invalid variable %u\n", v);
-+ if (rs >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ break;
-+ case DIF_OP_CALL:
-+ if (subr > DIF_SUBR_MAX)
-+ err += efunc(pc, "invalid subr %u\n", subr);
-+ if (rd >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rd);
-+ if (rd == 0)
-+ err += efunc(pc, "cannot write to %r0\n");
-+
-+ if (subr == DIF_SUBR_COPYOUT ||
-+ subr == DIF_SUBR_COPYOUTSTR)
-+ dp->dtdo_destructive = 1;
-+ break;
-+ case DIF_OP_PUSHTR:
-+ if (diftype != DIF_TYPE_STRING && diftype != DIF_TYPE_CTF)
-+ err += efunc(pc, "invalid ref type %u\n",
-+ diftype);
-+ if (r2 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r2);
-+ if (rs >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rs);
-+ break;
-+ case DIF_OP_PUSHTV:
-+ if (diftype != DIF_TYPE_CTF)
-+ err += efunc(pc, "invalid val type %u\n",
-+ diftype);
-+ if (r2 >= nregs)
-+ err += efunc(pc, "invalid register %u\n", r2);
-+ if (rs >= nregs)
-+ err += efunc(pc, "invalid register %u\n", rs);
-+ break;
-+ default:
-+ err += efunc(pc, "invalid opcode %u\n",
-+ DIF_INSTR_OP(instr));
-+ }
-+ }
-+
-+ if (dp->dtdo_len != 0 &&
-+ DIF_INSTR_OP(dp->dtdo_buf[dp->dtdo_len - 1]) != DIF_OP_RET) {
-+ err += efunc(dp->dtdo_len - 1,
-+ "expected 'ret' as last DIF instruction\n");
-+ }
-+
-+ if (!(dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF)) {
-+ /*
-+ * If we're not returning by reference, the size must be either
-+ * 0 or the size of one of the base types.
-+ */
-+ switch (dp->dtdo_rtype.dtdt_size) {
-+ case 0:
-+ case sizeof(uint8_t):
-+ case sizeof(uint16_t):
-+ case sizeof(uint32_t):
-+ case sizeof(uint64_t):
-+ break;
-+
-+ default:
-+ err += efunc(dp->dtdo_len - 1, "bad return size\n");
-+ }
-+ }
-+
-+ for (i = 0; i < dp->dtdo_varlen && err == 0; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i],
-+ *existing = NULL;
-+ struct dtrace_diftype *vt, *et;
-+ uint_t id, ndx;
-+
-+ if (v->dtdv_scope != DIFV_SCOPE_GLOBAL &&
-+ v->dtdv_scope != DIFV_SCOPE_THREAD &&
-+ v->dtdv_scope != DIFV_SCOPE_LOCAL) {
-+ err += efunc(i, "unrecognized variable scope %d\n",
-+ v->dtdv_scope);
-+ break;
-+ }
-+
-+ if (v->dtdv_kind != DIFV_KIND_ARRAY &&
-+ v->dtdv_kind != DIFV_KIND_SCALAR) {
-+ err += efunc(i, "unrecognized variable type %d\n",
-+ v->dtdv_kind);
-+ break;
-+ }
-+
-+ id = v->dtdv_id;
-+ if (id > DIF_VARIABLE_MAX) {
-+ err += efunc(i, "%d exceeds variable id limit\n", id);
-+ break;
-+ }
-+
-+ if (id < DIF_VAR_OTHER_UBASE)
-+ continue;
-+
-+ /*
-+ * For user-defined variables, we need to check that this
-+ * definition is identical to any previous definition that we
-+ * encountered.
-+ */
-+ ndx = id - DIF_VAR_OTHER_UBASE;
-+
-+ switch (v->dtdv_scope) {
-+ case DIFV_SCOPE_GLOBAL:
-+ if (ndx < vstate->dtvs_nglobals) {
-+ struct dtrace_statvar *svar;
-+
-+ svar = vstate->dtvs_globals[ndx];
-+ if (svar != NULL)
-+ existing = &svar->dtsv_var;
-+ }
-+
-+ break;
-+
-+ case DIFV_SCOPE_THREAD:
-+ if (ndx < vstate->dtvs_ntlocals)
-+ existing = &vstate->dtvs_tlocals[ndx];
-+ break;
-+
-+ case DIFV_SCOPE_LOCAL:
-+ if (ndx < vstate->dtvs_nlocals) {
-+ struct dtrace_statvar *svar;
-+
-+ svar = vstate->dtvs_locals[ndx];
-+ if (svar != NULL)
-+ existing = &svar->dtsv_var;
-+ }
-+
-+ break;
-+ }
-+
-+ vt = &v->dtdv_type;
-+
-+ if (vt->dtdt_flags & DIF_TF_BYREF) {
-+ if (vt->dtdt_size == 0) {
-+ err += efunc(i, "zero-sized variable\n");
-+ break;
-+ }
-+
-+ if (v->dtdv_scope == DIFV_SCOPE_GLOBAL &&
-+ vt->dtdt_size > dtrace_global_maxsize) {
-+ err += efunc(i, "oversized by-ref global\n");
-+ break;
-+ }
-+ }
-+
-+ if (existing == NULL || existing->dtdv_id == 0)
-+ continue;
-+
-+ ASSERT(existing->dtdv_id == v->dtdv_id);
-+ ASSERT(existing->dtdv_scope == v->dtdv_scope);
-+
-+ if (existing->dtdv_kind != v->dtdv_kind)
-+ err += efunc(i, "%d changed variable kind\n", id);
-+
-+ et = &existing->dtdv_type;
-+
-+ if (vt->dtdt_flags != et->dtdt_flags) {
-+ err += efunc(i, "%d changed variable type flags\n", id);
-+ break;
-+ }
-+
-+ if (vt->dtdt_size != 0 && vt->dtdt_size != et->dtdt_size) {
-+ err += efunc(i, "%d changed variable type size\n", id);
-+ break;
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+/*
-+ * Validate a DTrace DIF object that it is to be used as a helper. Helpers
-+ * are much more constrained than normal DIFOs. Specifically, they may
-+ * not:
-+ *
-+ * 1. Make calls to subroutines other than copyin(), copyinstr() or
-+ * miscellaneous string routines
-+ * 2. Access DTrace variables other than the args[] array, and the
-+ * curthread, pid, ppid, tid, execname, zonename, uid and gid variables.
-+ * 3. Have thread-local variables.
-+ * 4. Have dynamic variables.
-+ */
-+int dtrace_difo_validate_helper(struct dtrace_difo *dp)
-+{
-+ int (*efunc)(uint_t pc, const char *, ...) = dtrace_difo_err;
-+ int err = 0;
-+ uint_t pc;
-+
-+ for (pc = 0; pc < dp->dtdo_len; pc++) {
-+ dif_instr_t instr = dp->dtdo_buf[pc];
-+ uint_t v = DIF_INSTR_VAR(instr);
-+ uint_t subr = DIF_INSTR_SUBR(instr);
-+ uint_t op = DIF_INSTR_OP(instr);
-+
-+ switch (op) {
-+ case DIF_OP_OR:
-+ case DIF_OP_XOR:
-+ case DIF_OP_AND:
-+ case DIF_OP_SLL:
-+ case DIF_OP_SRL:
-+ case DIF_OP_SRA:
-+ case DIF_OP_SUB:
-+ case DIF_OP_ADD:
-+ case DIF_OP_MUL:
-+ case DIF_OP_SDIV:
-+ case DIF_OP_UDIV:
-+ case DIF_OP_SREM:
-+ case DIF_OP_UREM:
-+ case DIF_OP_COPYS:
-+ case DIF_OP_NOT:
-+ case DIF_OP_MOV:
-+ case DIF_OP_RLDSB:
-+ case DIF_OP_RLDSH:
-+ case DIF_OP_RLDSW:
-+ case DIF_OP_RLDUB:
-+ case DIF_OP_RLDUH:
-+ case DIF_OP_RLDUW:
-+ case DIF_OP_RLDX:
-+ case DIF_OP_ULDSB:
-+ case DIF_OP_ULDSH:
-+ case DIF_OP_ULDSW:
-+ case DIF_OP_ULDUB:
-+ case DIF_OP_ULDUH:
-+ case DIF_OP_ULDUW:
-+ case DIF_OP_ULDX:
-+ case DIF_OP_STB:
-+ case DIF_OP_STH:
-+ case DIF_OP_STW:
-+ case DIF_OP_STX:
-+ case DIF_OP_ALLOCS:
-+ case DIF_OP_CMP:
-+ case DIF_OP_SCMP:
-+ case DIF_OP_TST:
-+ case DIF_OP_BA:
-+ case DIF_OP_BE:
-+ case DIF_OP_BNE:
-+ case DIF_OP_BG:
-+ case DIF_OP_BGU:
-+ case DIF_OP_BGE:
-+ case DIF_OP_BGEU:
-+ case DIF_OP_BL:
-+ case DIF_OP_BLU:
-+ case DIF_OP_BLE:
-+ case DIF_OP_BLEU:
-+ case DIF_OP_RET:
-+ case DIF_OP_NOP:
-+ case DIF_OP_POPTS:
-+ case DIF_OP_FLUSHTS:
-+ case DIF_OP_SETX:
-+ case DIF_OP_SETS:
-+ case DIF_OP_LDGA:
-+ case DIF_OP_LDLS:
-+ case DIF_OP_STGS:
-+ case DIF_OP_STLS:
-+ case DIF_OP_PUSHTR:
-+ case DIF_OP_PUSHTV:
-+ break;
-+
-+ case DIF_OP_LDGS:
-+ if (v >= DIF_VAR_OTHER_UBASE)
-+ break;
-+
-+ if (v >= DIF_VAR_ARG0 && v <= DIF_VAR_ARG9)
-+ break;
-+
-+ if (v == DIF_VAR_CURTHREAD || v == DIF_VAR_PID ||
-+ v == DIF_VAR_PPID || v == DIF_VAR_TID ||
-+ v == DIF_VAR_EXECNAME || v == DIF_VAR_ZONENAME ||
-+ v == DIF_VAR_UID || v == DIF_VAR_GID)
-+ break;
-+
-+ err += efunc(pc, "illegal variable %u\n", v);
-+ break;
-+
-+ case DIF_OP_LDTA:
-+ case DIF_OP_LDGAA:
-+ case DIF_OP_LDTAA:
-+ err += efunc(pc, "illegal dynamic variable load\n");
-+ break;
-+
-+ case DIF_OP_STTS:
-+ case DIF_OP_STGAA:
-+ case DIF_OP_STTAA:
-+ err += efunc(pc, "illegal dynamic variable store\n");
-+ break;
-+
-+ case DIF_OP_CALL:
-+ if (subr == DIF_SUBR_ALLOCA ||
-+ subr == DIF_SUBR_BCOPY ||
-+ subr == DIF_SUBR_COPYIN ||
-+ subr == DIF_SUBR_COPYINTO ||
-+ subr == DIF_SUBR_COPYINSTR ||
-+ subr == DIF_SUBR_INDEX ||
-+ subr == DIF_SUBR_INET_NTOA ||
-+ subr == DIF_SUBR_INET_NTOA6 ||
-+ subr == DIF_SUBR_INET_NTOP ||
-+ subr == DIF_SUBR_LINK_NTOP ||
-+ subr == DIF_SUBR_LLTOSTR ||
-+ subr == DIF_SUBR_RINDEX ||
-+ subr == DIF_SUBR_STRCHR ||
-+ subr == DIF_SUBR_STRJOIN ||
-+ subr == DIF_SUBR_STRRCHR ||
-+ subr == DIF_SUBR_STRSTR ||
-+ subr == DIF_SUBR_HTONS ||
-+ subr == DIF_SUBR_HTONL ||
-+ subr == DIF_SUBR_HTONLL ||
-+ subr == DIF_SUBR_NTOHS ||
-+ subr == DIF_SUBR_NTOHL ||
-+ subr == DIF_SUBR_NTOHLL)
-+ break;
-+
-+ err += efunc(pc, "invalid subr %u\n", subr);
-+ break;
-+
-+ default:
-+ err += efunc(pc, "invalid opcode %u\n",
-+ DIF_INSTR_OP(instr));
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+/*
-+ * Returns 1 if the expression in the DIF object can be cached on a per-thread
-+ * basis; 0 if not.
-+ */
-+int dtrace_difo_cacheable(struct dtrace_difo *dp)
-+{
-+ int i;
-+
-+ if (dp == NULL)
-+ return 0;
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+
-+ if (v->dtdv_scope != DIFV_SCOPE_GLOBAL)
-+ continue;
-+
-+ switch (v->dtdv_id) {
-+ case DIF_VAR_CURTHREAD:
-+ case DIF_VAR_PID:
-+ case DIF_VAR_TID:
-+ case DIF_VAR_EXECNAME:
-+ case DIF_VAR_ZONENAME:
-+ break;
-+
-+ default:
-+ return 0;
-+ }
-+ }
-+
-+ /*
-+ * This DIF object may be cacheable. Now we need to look for any
-+ * array loading instructions, any memory loading instructions, or
-+ * any stores to thread-local variables.
-+ */
-+ for (i = 0; i < dp->dtdo_len; i++) {
-+ uint_t op = DIF_INSTR_OP(dp->dtdo_buf[i]);
-+
-+ if ((op >= DIF_OP_LDSB && op <= DIF_OP_LDX) ||
-+ (op >= DIF_OP_ULDSB && op <= DIF_OP_ULDX) ||
-+ (op >= DIF_OP_RLDSB && op <= DIF_OP_RLDX) ||
-+ op == DIF_OP_LDGA || op == DIF_OP_STTS)
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+/*
-+ * This routine calculates the dynamic variable chunksize for a given DIF
-+ * object. The calculation is not fool-proof, and can probably be tricked by
-+ * malicious DIF -- but it works for all compiler-generated DIF. Because this
-+ * calculation is likely imperfect, dtrace_dynvar() is able to gracefully fail
-+ * if a dynamic variable size exceeds the chunksize.
-+ */
-+static void dtrace_difo_chunksize(struct dtrace_difo *dp,
-+ struct dtrace_vstate *vstate)
-+{
-+ uint64_t sval = 0;
-+ struct dtrace_key tupregs[DIF_DTR_NREGS + 2]; /* + thread + id */
-+ const dif_instr_t *text = dp->dtdo_buf;
-+ uint_t pc, srd = 0;
-+ uint_t ttop = 0;
-+ size_t size, ksize;
-+ uint_t id, i;
-+
-+ for (pc = 0; pc < dp->dtdo_len; pc++) {
-+ dif_instr_t instr = text[pc];
-+ uint_t op = DIF_INSTR_OP(instr);
-+ uint_t rd = DIF_INSTR_RD(instr);
-+ uint_t r1 = DIF_INSTR_R1(instr);
-+ uint_t nkeys = 0;
-+ uchar_t scope;
-+ struct dtrace_key *key = tupregs;
-+
-+ switch (op) {
-+ case DIF_OP_SETX:
-+ sval = dp->dtdo_inttab[DIF_INSTR_INTEGER(instr)];
-+ srd = rd;
-+ continue;
-+
-+ case DIF_OP_STTS:
-+ key = &tupregs[DIF_DTR_NREGS];
-+ key[0].dttk_size = 0;
-+ key[1].dttk_size = 0;
-+ nkeys = 2;
-+ scope = DIFV_SCOPE_THREAD;
-+ break;
-+
-+ case DIF_OP_STGAA:
-+ case DIF_OP_STTAA:
-+ nkeys = ttop;
-+
-+ if (DIF_INSTR_OP(instr) == DIF_OP_STTAA)
-+ key[nkeys++].dttk_size = 0;
-+
-+ key[nkeys++].dttk_size = 0;
-+
-+ if (op == DIF_OP_STTAA)
-+ scope = DIFV_SCOPE_THREAD;
-+ else
-+ scope = DIFV_SCOPE_GLOBAL;
-+
-+ break;
-+
-+ case DIF_OP_PUSHTR:
-+ if (ttop == DIF_DTR_NREGS)
-+ return;
-+
-+ /*
-+ * If the register for the size of the "pushtr" is %r0
-+ * (or the value is 0) and the type is a string, we'll
-+ * use the system-wide default string size.
-+ */
-+ if ((srd == 0 || sval == 0) && r1 == DIF_TYPE_STRING)
-+ tupregs[ttop++].dttk_size =
-+ dtrace_strsize_default;
-+ else {
-+ if (srd == 0)
-+ return;
-+
-+ tupregs[ttop++].dttk_size = sval;
-+ }
-+
-+ break;
-+
-+ case DIF_OP_PUSHTV:
-+ if (ttop == DIF_DTR_NREGS)
-+ return;
-+
-+ tupregs[ttop++].dttk_size = 0;
-+ break;
-+
-+ case DIF_OP_FLUSHTS:
-+ ttop = 0;
-+ break;
-+
-+ case DIF_OP_POPTS:
-+ if (ttop != 0)
-+ ttop--;
-+ break;
-+ }
-+
-+ sval = 0;
-+ srd = 0;
-+
-+ if (nkeys == 0)
-+ continue;
-+
-+ /*
-+ * We have a dynamic variable allocation; calculate its size.
-+ */
-+ for (ksize = 0, i = 0; i < nkeys; i++)
-+ ksize += P2ROUNDUP(key[i].dttk_size, sizeof(uint64_t));
-+
-+ size = sizeof(struct dtrace_dynvar);
-+ size += sizeof(struct dtrace_key) * (nkeys - 1);
-+ size += ksize;
-+
-+ /*
-+ * Now we need to determine the size of the stored data.
-+ */
-+ id = DIF_INSTR_VAR(instr);
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+
-+ if (v->dtdv_id == id && v->dtdv_scope == scope) {
-+ size += v->dtdv_type.dtdt_size;
-+ break;
-+ }
-+ }
-+
-+ if (i == dp->dtdo_varlen)
-+ return;
-+
-+ /*
-+ * We have the size. If this is larger than the chunk size
-+ * for our dynamic variable state, reset the chunk size.
-+ */
-+ size = P2ROUNDUP(size, sizeof(uint64_t));
-+
-+ if (size > vstate->dtvs_dynvars.dtds_chunksize)
-+ vstate->dtvs_dynvars.dtds_chunksize = size;
-+ }
-+}
-+
-+void dtrace_difo_hold(struct dtrace_difo *dp)
-+{
-+ int i;
-+
-+ dp->dtdo_refcnt++;
-+ ASSERT(dp->dtdo_refcnt != 0);
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+
-+ if (v->dtdv_id != DIF_VAR_VTIMESTAMP)
-+ continue;
-+
-+ if (dtrace_vtime_references++ == 0)
-+ dtrace_vtime_enable();
-+ }
-+}
-+
-+void dtrace_difo_init(struct dtrace_difo *dp, struct dtrace_vstate *vstate)
-+{
-+ int i, oldsvars, osz, nsz, otlocals, ntlocals;
-+ uint_t id;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dp->dtdo_buf != NULL && dp->dtdo_len != 0);
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+ struct dtrace_statvar *svar, ***svarp;
-+ size_t dsize = 0;
-+ uint8_t scope = v->dtdv_scope;
-+ int *np;
-+
-+ id = v->dtdv_id;
-+ if (id < DIF_VAR_OTHER_UBASE)
-+ continue;
-+
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ switch (scope) {
-+ case DIFV_SCOPE_THREAD:
-+ while (id >= (otlocals = vstate->dtvs_ntlocals)) {
-+ struct dtrace_difv *tlocals;
-+
-+ ntlocals = otlocals << 1;
-+ if (ntlocals == 0)
-+ ntlocals = 1;
-+
-+ osz = otlocals * sizeof(struct dtrace_difv);
-+ nsz = ntlocals * sizeof(struct dtrace_difv);
-+
-+ tlocals = vzalloc(nsz);
-+
-+ if (osz != 0) {
-+ memcpy(tlocals, vstate->dtvs_tlocals,
-+ osz);
-+ vfree(vstate->dtvs_tlocals);
-+ }
-+
-+ vstate->dtvs_tlocals = tlocals;
-+ vstate->dtvs_ntlocals = ntlocals;
-+ }
-+
-+ vstate->dtvs_tlocals[id] = *v;
-+ continue;
-+
-+ case DIFV_SCOPE_LOCAL:
-+ np = &vstate->dtvs_nlocals;
-+ svarp = &vstate->dtvs_locals;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF)
-+ dsize = NR_CPUS *
-+ (v->dtdv_type.dtdt_size +
-+ sizeof(uint64_t));
-+ else
-+ dsize = NR_CPUS * sizeof(uint64_t);
-+
-+ break;
-+
-+ case DIFV_SCOPE_GLOBAL:
-+ np = &vstate->dtvs_nglobals;
-+ svarp = &vstate->dtvs_globals;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF)
-+ dsize = v->dtdv_type.dtdt_size +
-+ sizeof(uint64_t);
-+
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ continue; /* not reached */
-+ }
-+
-+ while (id >= (oldsvars = *np)) {
-+ struct dtrace_statvar **statics;
-+ int newsvars, oldsize, newsize;
-+
-+ newsvars = oldsvars << 1;
-+ if (newsvars == 0)
-+ newsvars = 1;
-+
-+ oldsize = oldsvars * sizeof(struct dtrace_statvar *);
-+ newsize = newsvars * sizeof(struct dtrace_statvar *);
-+
-+ statics = vzalloc(newsize);
-+
-+ if (oldsize != 0) {
-+ memcpy(statics, *svarp, oldsize);
-+ vfree(*svarp);
-+ }
-+
-+ *svarp = statics;
-+ *np = newsvars;
-+ }
-+
-+ svar = (*svarp)[id];
-+ if (svar == NULL) {
-+ svar = kzalloc(sizeof(struct dtrace_statvar),
-+ GFP_KERNEL);
-+ svar->dtsv_var = *v;
-+
-+ svar->dtsv_size = dsize;
-+ if (svar->dtsv_size != 0) {
-+ svar->dtsv_data =
-+ (uint64_t)(uintptr_t)vzalloc(dsize);
-+ }
-+
-+ (*svarp)[id] = svar;
-+ }
-+
-+ svar->dtsv_refcnt++;
-+ }
-+
-+ dtrace_difo_chunksize(dp, vstate);
-+ dtrace_difo_hold(dp);
-+}
-+
-+struct dtrace_difo *dtrace_difo_duplicate(struct dtrace_difo *dp,
-+ struct dtrace_vstate *vstate)
-+{
-+ struct dtrace_difo *new;
-+ size_t sz;
-+
-+ ASSERT(dp->dtdo_buf != NULL);
-+ ASSERT(dp->dtdo_refcnt != 0);
-+
-+ new = kzalloc(sizeof(struct dtrace_difo), GFP_KERNEL);
-+
-+ ASSERT(dp->dtdo_buf != NULL);
-+ sz = dp->dtdo_len * sizeof(dif_instr_t);
-+ new->dtdo_buf = vmalloc(sz);
-+ memcpy(new->dtdo_buf, dp->dtdo_buf, sz);
-+ new->dtdo_len = dp->dtdo_len;
-+
-+ if (dp->dtdo_strtab != NULL) {
-+ ASSERT(dp->dtdo_strlen != 0);
-+ new->dtdo_strtab = vmalloc(dp->dtdo_strlen);
-+ memcpy(new->dtdo_strtab, dp->dtdo_strtab, dp->dtdo_strlen);
-+ new->dtdo_strlen = dp->dtdo_strlen;
-+ }
-+
-+ if (dp->dtdo_inttab != NULL) {
-+ ASSERT(dp->dtdo_intlen != 0);
-+ sz = dp->dtdo_intlen * sizeof(uint64_t);
-+ new->dtdo_inttab = vmalloc(sz);
-+ memcpy(new->dtdo_inttab, dp->dtdo_inttab, sz);
-+ new->dtdo_intlen = dp->dtdo_intlen;
-+ }
-+
-+ if (dp->dtdo_vartab != NULL) {
-+ ASSERT(dp->dtdo_varlen != 0);
-+ sz = dp->dtdo_varlen * sizeof(struct dtrace_difv);
-+ new->dtdo_vartab = vmalloc(sz);
-+ memcpy(new->dtdo_vartab, dp->dtdo_vartab, sz);
-+ new->dtdo_varlen = dp->dtdo_varlen;
-+ }
-+
-+ dtrace_difo_init(new, vstate);
-+
-+ return new;
-+}
-+
-+void dtrace_difo_destroy(struct dtrace_difo *dp, struct dtrace_vstate *vstate)
-+{
-+ int i;
-+
-+ ASSERT(dp->dtdo_refcnt == 0);
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+ struct dtrace_statvar *svar, **svarp;
-+ uint_t id;
-+ uint8_t scope = v->dtdv_scope;
-+ int *np;
-+
-+ switch (scope) {
-+ case DIFV_SCOPE_THREAD:
-+ continue;
-+
-+ case DIFV_SCOPE_LOCAL:
-+ np = &vstate->dtvs_nlocals;
-+ svarp = vstate->dtvs_locals;
-+ break;
-+
-+ case DIFV_SCOPE_GLOBAL:
-+ np = &vstate->dtvs_nglobals;
-+ svarp = vstate->dtvs_globals;
-+ break;
-+
-+ default:
-+ BUG();
-+ }
-+
-+ id = v->dtdv_id;
-+ if (id < DIF_VAR_OTHER_UBASE)
-+ continue;
-+
-+ id -= DIF_VAR_OTHER_UBASE;
-+ ASSERT(id < *np);
-+
-+ svar = svarp[id];
-+ ASSERT(svar != NULL);
-+ ASSERT(svar->dtsv_refcnt > 0);
-+
-+ if (--svar->dtsv_refcnt > 0)
-+ continue;
-+
-+ if (svar->dtsv_size != 0) {
-+ ASSERT((void *)(uintptr_t)svar->dtsv_data != NULL);
-+ vfree((void *)(uintptr_t)svar->dtsv_data);
-+ }
-+
-+ kfree(svar);
-+ svarp[id] = NULL;
-+ }
-+
-+ vfree(dp->dtdo_buf);
-+ vfree(dp->dtdo_inttab);
-+ vfree(dp->dtdo_strtab);
-+ vfree(dp->dtdo_vartab);
-+ kfree(dp);
-+}
-+
-+void dtrace_difo_release(struct dtrace_difo *dp, struct dtrace_vstate *vstate)
-+{
-+ int i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dp->dtdo_refcnt != 0);
-+
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+
-+ if (v->dtdv_id != DIF_VAR_VTIMESTAMP)
-+ continue;
-+
-+ ASSERT(dtrace_vtime_references > 0);
-+
-+ if (--dtrace_vtime_references == 0)
-+ dtrace_vtime_disable();
-+ }
-+
-+ if (--dp->dtdo_refcnt == 0)
-+ dtrace_difo_destroy(dp, vstate);
-+}
-+
-+/*
-+ * The key for a thread-local variable consists of the lower 60 bits of the
-+ * task pid, prefixed by a 4 bits indicating whether a hard_irq is active.
-+ * This accounts for a case where some older drivers re-enable interrupts
-+ * and can nest in hard irq context.
-+ *
-+ * All per-cpu idle threads share same pid 0. In this special case we replace
-+ * the pid with cpu id (an idle thread is bound to a single cpu). If pid is
-+ * not 0 then a NR_CPUS is added. This assures that the thread key for idle
-+ * thread never conflicts with regular pids in range 0..NR_CPUS.
-+ *
-+ * We add DIF_VARIABLE_MAX to the pid to assure that the thread key is never
-+ * equal to a variable identifier. This is necessary (but not sufficient) to
-+ * assure that global associative arrays never collide with thread-local
-+ * variables. To guarantee that they cannot collide, we must also define the
-+ * order for keying dynamic variables. That order is:
-+ *
-+ * [ key0 ] ... [ keyn ] [ variable-key ] [ tls-key ]
-+ *
-+ * Because the variable-key and the tls-key are in orthogonal spaces, there is
-+ * no way for a global variable key signature to match a thread-local key
-+ * signature.
-+ */
-+#define DTRACE_TLS_THRKEY(where) \
-+ { \
-+ uint_t intr = hardirq_count() >> HARDIRQ_SHIFT; \
-+ uint_t cpu = (current->flags & PF_IDLE) ? \
-+ smp_processor_id() : NR_CPUS; \
-+ \
-+ (where) = ((current->pid + cpu + DIF_VARIABLE_MAX) & \
-+ (((uint64_t)1 << 60) - 1)) | \
-+ ((uint64_t)intr << 60); \
-+ }
-+
-+#ifndef FIXME
-+# define DTRACE_ALIGNCHECK(addr, size, flags)
-+#endif
-+
-+/*
-+ * Test whether a range of memory starting at testaddr of size testsz falls
-+ * within the range of memory described by addr, sz. We take care to avoid
-+ * problems with overflow and underflow of the unsigned quantities, and
-+ * disallow all negative sizes. Ranges of size 0 are allowed.
-+ */
-+#define DTRACE_INRANGE(testaddr, testsz, baseaddr, basesz) \
-+ ((testaddr) - (baseaddr) < (basesz) && \
-+ (testaddr) + (testsz) - (baseaddr) <= (basesz) && \
-+ (testaddr) + (testsz) >= (testaddr))
-+
-+#define DTRACE_LOADFUNC(bits) \
-+ uint##bits##_t dtrace_load##bits(uintptr_t addr) \
-+ { \
-+ size_t size = bits / NBBY; \
-+ uint##bits##_t rval; \
-+ int i; \
-+ volatile uint16_t *flags = (volatile uint16_t *) \
-+ &this_cpu_core->cpuc_dtrace_flags; \
-+ \
-+ /* \
-+ * Deviation from the OpenSolaris code... Protect \
-+ * against dereferencing the NULL pointer since that \
-+ * really causes us a lot of grief (crash). \
-+ */ \
-+ if (addr == 0) { \
-+ *flags |= CPU_DTRACE_BADADDR; \
-+ this_cpu_core->cpuc_dtrace_illval = addr; \
-+ return 0; \
-+ } \
-+ \
-+ DTRACE_ALIGNCHECK(addr, size, flags); \
-+ \
-+ for (i = 0; i < dtrace_toxranges; i++) { \
-+ if (addr >= dtrace_toxrange[i].dtt_limit) \
-+ continue; \
-+ \
-+ if (addr + size <= dtrace_toxrange[i].dtt_base) \
-+ continue; \
-+ \
-+ /* \
-+ * This address falls within a toxic region. \
-+ */ \
-+ *flags |= CPU_DTRACE_BADADDR; \
-+ this_cpu_core->cpuc_dtrace_illval = addr; \
-+ return 0; \
-+ } \
-+ \
-+ *flags |= CPU_DTRACE_NOFAULT; \
-+ rval = *((volatile uint##bits##_t *)addr); \
-+ *flags &= ~CPU_DTRACE_NOFAULT; \
-+ \
-+ return !(*flags & CPU_DTRACE_FAULT) ? rval : 0; \
-+ }
-+
-+/*
-+ * Use the DTRACE_LOADFUNC macro to define functions for each of loading a
-+ * uint8_t, a uint16_t, a uint32_t and a uint64_t.
-+ */
-+DTRACE_LOADFUNC(8)
-+DTRACE_LOADFUNC(16)
-+DTRACE_LOADFUNC(32)
-+DTRACE_LOADFUNC(64)
-+
-+#define DT_BSWAP_8(x) ((x) & 0xff)
-+#define DT_BSWAP_16(x) ((DT_BSWAP_8(x) << 8) | DT_BSWAP_8((x) >> 8))
-+#define DT_BSWAP_32(x) ((DT_BSWAP_16(x) << 16) | DT_BSWAP_16((x) >> 16))
-+#define DT_BSWAP_64(x) ((DT_BSWAP_32(x) << 32) | DT_BSWAP_32((x) >> 32))
-+
-+static int dtrace_inscratch(uintptr_t dest, size_t size,
-+ struct dtrace_mstate *mstate)
-+{
-+ if (dest < mstate->dtms_scratch_base)
-+ return 0;
-+
-+ if (dest + size < dest)
-+ return 0;
-+
-+ if (dest + size > mstate->dtms_scratch_ptr)
-+ return 0;
-+
-+ return 1;
-+}
-+
-+static int dtrace_canstore_statvar(uint64_t addr, size_t sz,
-+ struct dtrace_statvar **svars, int nsvars)
-+{
-+ int i;
-+
-+ for (i = 0; i < nsvars; i++) {
-+ struct dtrace_statvar *svar = svars[i];
-+
-+ if (svar == NULL || svar->dtsv_size == 0)
-+ continue;
-+
-+ if (DTRACE_INRANGE(addr, sz, svar->dtsv_data, svar->dtsv_size))
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Check to see if the address is within a memory region to which a store may
-+ * be issued. This includes the DTrace scratch areas, and any DTrace variable
-+ * region. The caller of dtrace_canstore() is responsible for performing any
-+ * alignment checks that are needed before stores are actually executed.
-+ */
-+static int dtrace_canstore(uint64_t addr, size_t sz,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate)
-+{
-+ /*
-+ * First, check to see if the address is in scratch space...
-+ */
-+ if (DTRACE_INRANGE(addr, sz, mstate->dtms_scratch_base,
-+ mstate->dtms_scratch_size))
-+ return 1;
-+
-+ /*
-+ * Now check to see if it's a dynamic variable. This check will pick
-+ * up both thread-local variables and any global dynamically-allocated
-+ * variables.
-+ */
-+ if (DTRACE_INRANGE(addr, sz, (uintptr_t)vstate->dtvs_dynvars.dtds_base,
-+ vstate->dtvs_dynvars.dtds_size)) {
-+ struct dtrace_dstate *dstate = &vstate->dtvs_dynvars;
-+ uintptr_t base = (uintptr_t)dstate->dtds_base +
-+ (dstate->dtds_hashsize *
-+ sizeof(struct dtrace_dynhash));
-+ uintptr_t chunkoffs;
-+ uint64_t num;
-+
-+ /*
-+ * Before we assume that we can store here, we need to make
-+ * sure that it isn't in our metadata -- storing to our
-+ * dynamic variable metadata would corrupt our state. For
-+ * the range to not include any dynamic variable metadata,
-+ * it must:
-+ *
-+ * (1) Start above the hash table that is at the base of
-+ * the dynamic variable space
-+ *
-+ * (2) Have a starting chunk offset that is beyond the
-+ * dtrace_dynvar_t that is at the base of every chunk
-+ *
-+ * (3) Not span a chunk boundary
-+ */
-+ if (addr < base)
-+ return 0;
-+
-+ num = addr - base;
-+ chunkoffs = do_div(num, dstate->dtds_chunksize);
-+
-+ if (chunkoffs < sizeof(struct dtrace_dynvar))
-+ return 0;
-+
-+ if (chunkoffs + sz > dstate->dtds_chunksize)
-+ return 0;
-+
-+ return 1;
-+ }
-+
-+ /*
-+ * Finally, check the static local and global variables. These checks
-+ * take the longest, so we perform them last.
-+ */
-+ if (dtrace_canstore_statvar(addr, sz, vstate->dtvs_locals,
-+ vstate->dtvs_nlocals))
-+ return 1;
-+
-+ if (dtrace_canstore_statvar(addr, sz, vstate->dtvs_globals,
-+ vstate->dtvs_nglobals))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Convenience routine to check to see if the address is within a memory
-+ * region in which a load may be issued given the user's privilege level;
-+ * if not, it sets the appropriate error flags and loads 'addr' into the
-+ * illegal value slot.
-+ *
-+ * DTrace subroutines (DIF_SUBR_*) should use this helper to implement
-+ * appropriate memory access protection.
-+ */
-+int
-+dtrace_canload(uintptr_t addr, size_t sz, struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate)
-+{
-+ volatile uintptr_t *illval = &this_cpu_core->cpuc_dtrace_illval;
-+
-+ /*
-+ * If we hold the privilege to read from kernel memory, then
-+ * everything is readable.
-+ */
-+ if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0)
-+ return 1;
-+
-+ /*
-+ * You can obviously read that which you can store.
-+ */
-+ if (dtrace_canstore(addr, sz, mstate, vstate))
-+ return 1;
-+
-+ /*
-+ * We're allowed to read from our own string table.
-+ */
-+ if (DTRACE_INRANGE(addr, sz, (uintptr_t)mstate->dtms_difo->dtdo_strtab,
-+ mstate->dtms_difo->dtdo_strlen))
-+ return 1;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
-+ *illval = addr;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Convenience routine to check to see if a given string is within a memory
-+ * region in which a load may be issued given the user's privilege level;
-+ * this exists so that we don't need to issue unnecessary dtrace_strlen()
-+ * calls in the event that the user has all privileges.
-+ */
-+static int
-+dtrace_strcanload(uint64_t addr, size_t sz, struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate)
-+{
-+ size_t strsz;
-+
-+ /*
-+ * If we hold the privilege to read from kernel memory, then
-+ * everything is readable.
-+ */
-+ if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0)
-+ return 1;
-+
-+ strsz = 1 + dtrace_strlen((char *)(uintptr_t)addr, sz);
-+ if (dtrace_canload(addr, strsz, mstate, vstate))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Convenience routine to check to see if a given variable is within a memory
-+ * region in which a load may be issued given the user's privilege level.
-+ */
-+int dtrace_vcanload(void *src, struct dtrace_diftype *diftype,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate)
-+{
-+ size_t sz;
-+
-+ ASSERT(diftype->dtdt_flags & DIF_TF_BYREF);
-+
-+ /*
-+ * If we hold the privilege to read from kernel memory, then
-+ * everything is readable.
-+ */
-+ if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0)
-+ return 1;
-+
-+ if (diftype->dtdt_kind == DIF_TYPE_STRING)
-+ sz = dtrace_strlen(
-+ src,
-+ vstate->dtvs_state->dts_options[DTRACEOPT_STRSIZE]
-+ ) + 1;
-+ else
-+ sz = diftype->dtdt_size;
-+
-+ return dtrace_canload((uintptr_t)src, sz, mstate, vstate);
-+}
-+
-+/*
-+ * Copy src to dst using safe memory accesses. The src is assumed to be unsafe
-+ * memory specified by the DIF program. The dst is assumed to be safe memory
-+ * that we can store to directly because it is managed by DTrace. As with
-+ * standard bcopy, overlapping copies are handled properly.
-+ */
-+static void dtrace_bcopy(const void *src, void *dst, size_t len)
-+{
-+ if (len != 0) {
-+ uint8_t *s1 = dst;
-+ const uint8_t *s2 = src;
-+
-+ if (s1 <= s2) {
-+ do {
-+ *s1++ = dtrace_load8((uintptr_t)s2++);
-+ } while (--len != 0);
-+ } else {
-+ s2 += len;
-+ s1 += len;
-+
-+ do {
-+ *--s1 = dtrace_load8((uintptr_t)--s2);
-+ } while (--len != 0);
-+ }
-+ }
-+}
-+
-+/*
-+ * Copy src to dst using safe memory accesses, up to either the specified
-+ * length, or the point that a nul byte is encountered. The src is assumed to
-+ * be unsafe memory specified by the DIF program. The dst is assumed to be
-+ * safe memory that we can store to directly because it is managed by DTrace.
-+ * Unlike dtrace_bcopy(), overlapping regions are not handled.
-+ */
-+static void dtrace_strcpy(const void *src, void *dst, size_t len)
-+{
-+ if (len != 0) {
-+ uint8_t *s1 = dst, c;
-+ const uint8_t *s2 = src;
-+
-+ do {
-+ *s1++ = c = dtrace_load8((uintptr_t)s2++);
-+ } while (--len != 0 && c != '\0');
-+ }
-+}
-+/*
-+ * Copy src to dst, deriving the size and type from the specified (BYREF)
-+ * variable type. The src is assumed to be unsafe memory specified by the DIF
-+ * program. The dst is assumed to be DTrace variable memory that is of the
-+ * specified type; we assume that we can store to directly.
-+ */
-+static void dtrace_vcopy(void *src, void *dst, struct dtrace_diftype *diftype)
-+{
-+ ASSERT(diftype->dtdt_flags & DIF_TF_BYREF);
-+
-+ if (diftype->dtdt_kind == DIF_TYPE_STRING)
-+ dtrace_strcpy(src, dst, diftype->dtdt_size);
-+ else
-+ dtrace_bcopy(src, dst, diftype->dtdt_size);
-+}
-+
-+/*
-+ * Compare s1 to s2 using safe memory accesses. The s1 data is assumed to be
-+ * unsafe memory specified by the DIF program. The s2 data is assumed to be
-+ * safe memory that we can access directly because it is managed by DTrace.
-+ */
-+static int dtrace_bcmp(const void *s1, const void *s2, size_t len)
-+{
-+ volatile uint16_t *flags;
-+
-+ flags = (volatile uint16_t *)&this_cpu_core->cpuc_dtrace_flags;
-+
-+ if (s1 == s2)
-+ return 0;
-+
-+ if (s1 == NULL || s2 == NULL)
-+ return 1;
-+
-+ if (s1 != s2 && len != 0) {
-+ const uint8_t *ps1 = s1;
-+ const uint8_t *ps2 = s2;
-+
-+ do {
-+ if (dtrace_load8((uintptr_t)ps1++) != *ps2++)
-+ return 1;
-+ } while (--len != 0 && !(*flags & CPU_DTRACE_FAULT));
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Zero the specified region using a simple byte-by-byte loop. Note that this
-+ * is for safe DTrace-managed memory only.
-+ */
-+void dtrace_bzero(void *dst, size_t len)
-+{
-+ uchar_t *cp;
-+
-+ for (cp = dst; len != 0; len--)
-+ *cp++ = 0;
-+}
-+
-+#define DTRACE_DYNHASH_FREE 0
-+#define DTRACE_DYNHASH_SINK 1
-+#define DTRACE_DYNHASH_VALID 2
-+
-+/*
-+ * Depending on the value of the op parameter, this function looks-up,
-+ * allocates or deallocates an arbitrarily-keyed dynamic variable. If an
-+ * allocation is requested, this function will return a pointer to a
-+ * dtrace_dynvar_t corresponding to the allocated variable -- or NULL if no
-+ * variable can be allocated. If NULL is returned, the appropriate counter
-+ * will be incremented.
-+ */
-+static struct dtrace_dynvar *dtrace_dynvar(struct dtrace_dstate *dstate,
-+ uint_t nkeys,
-+ struct dtrace_key *key,
-+ size_t dsize,
-+ enum dtrace_dynvar_op op,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate)
-+{
-+ uint64_t hashval = DTRACE_DYNHASH_VALID;
-+ struct dtrace_dynhash *hash = dstate->dtds_hash;
-+ struct dtrace_dynvar *free, *new_free, *next, *dvar, *start,
-+ *prev = NULL;
-+ processorid_t me = smp_processor_id(), cpu = me;
-+ struct dtrace_dstate_percpu *dcpu = &dstate->dtds_percpu[me];
-+ size_t bucket, ksize;
-+ size_t chunksize = dstate->dtds_chunksize;
-+ uintptr_t kdata, lock;
-+ enum dtrace_dstate_state nstate;
-+ uint_t i;
-+
-+ ASSERT(nkeys != 0);
-+
-+ /*
-+ * Hash the key. As with aggregations, we use Jenkins' "One-at-a-time"
-+ * algorithm. For the by-value portions, we perform the algorithm in
-+ * 16-bit chunks (as opposed to 8-bit chunks). This speeds things up a
-+ * bit, and seems to have only a minute effect on distribution. For
-+ * the by-reference data, we perform "One-at-a-time" iterating (safely)
-+ * over each referenced byte. It's painful to do this, but it's much
-+ * better than pathological hash distribution. The efficacy of the
-+ * hashing algorithm (and a comparison with other algorithms) may be
-+ * found by running the ::dtrace_dynstat MDB dcmd.
-+ */
-+ for (i = 0; i < nkeys; i++) {
-+ if (key[i].dttk_size == 0) {
-+ uint64_t val = key[i].dttk_value;
-+
-+ hashval += (val >> 48) & 0xffff;
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+
-+ hashval += (val >> 32) & 0xffff;
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+
-+ hashval += (val >> 16) & 0xffff;
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+
-+ hashval += val & 0xffff;
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+ } else {
-+ /*
-+ * This is incredibly painful, but it beats the hell
-+ * out of the alternative.
-+ */
-+ uint64_t j, size = key[i].dttk_size;
-+ uintptr_t base = (uintptr_t)key[i].dttk_value;
-+
-+ if (!dtrace_canload(base, size, mstate, vstate))
-+ break;
-+
-+ for (j = 0; j < size; j++) {
-+ hashval += dtrace_load8(base + j);
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+ }
-+ }
-+ }
-+
-+ if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
-+ return NULL;
-+
-+ hashval += (hashval << 3);
-+ hashval ^= (hashval >> 11);
-+ hashval += (hashval << 15);
-+
-+ /*
-+ * There is a remote chance (ideally, 1 in 2^31) that our hashval
-+ * comes out to be one of our two sentinel hash values. If this
-+ * actually happens, we set the hashval to be a value known to be a
-+ * non-sentinel value.
-+ */
-+ if (hashval == DTRACE_DYNHASH_FREE || hashval == DTRACE_DYNHASH_SINK)
-+ hashval = DTRACE_DYNHASH_VALID;
-+
-+ /*
-+ * Yes, it's painful to do a divide here. If the cycle count becomes
-+ * important here, tricks can be pulled to reduce it. (However, it's
-+ * critical that hash collisions be kept to an absolute minimum;
-+ * they're much more painful than a divide.) It's better to have a
-+ * solution that generates few collisions and still keeps things
-+ * relatively simple.
-+ *
-+ * Linux cannot do a straight 64-bit divide without gcc requiring
-+ * linking in code that the kernel doesn't link, so we need to use an
-+ * alternative.
-+ *
-+ * bucket = hashval % dstate->dtds_hashsize;
-+ */
-+ {
-+ uint64_t num;
-+
-+ num = hashval;
-+ bucket = do_div(num, dstate->dtds_hashsize);
-+ }
-+
-+ if (op == DTRACE_DYNVAR_DEALLOC) {
-+ volatile uintptr_t *lockp = &hash[bucket].dtdh_lock;
-+
-+ for (;;) {
-+ while ((lock = *lockp) & 1)
-+ continue;
-+
-+ if (cmpxchg(lockp, lock, (lock + 1)) == lock)
-+ break;
-+ }
-+
-+ dtrace_membar_producer();
-+ }
-+
-+top:
-+ prev = NULL;
-+ lock = hash[bucket].dtdh_lock;
-+
-+ dtrace_membar_consumer();
-+
-+ start = hash[bucket].dtdh_chain;
-+ ASSERT(start != NULL && (start->dtdv_hashval == DTRACE_DYNHASH_SINK ||
-+ start->dtdv_hashval != DTRACE_DYNHASH_FREE ||
-+ op != DTRACE_DYNVAR_DEALLOC));
-+
-+ for (dvar = start; dvar != NULL; dvar = dvar->dtdv_next) {
-+ struct dtrace_tuple *dtuple = &dvar->dtdv_tuple;
-+ struct dtrace_key *dkey = &dtuple->dtt_key[0];
-+
-+ if (dvar->dtdv_hashval != hashval) {
-+ if (dvar->dtdv_hashval == DTRACE_DYNHASH_SINK) {
-+ /*
-+ * We've reached the sink, and therefore the
-+ * end of the hash chain; we can kick out of
-+ * the loop knowing that we have seen a valid
-+ * snapshot of state.
-+ */
-+ ASSERT(dvar->dtdv_next == NULL);
-+ ASSERT(dvar == &dtrace_dynhash_sink);
-+ break;
-+ }
-+
-+ if (dvar->dtdv_hashval == DTRACE_DYNHASH_FREE) {
-+ /*
-+ * We've gone off the rails: somewhere along
-+ * the line, one of the members of this hash
-+ * chain was deleted. Note that we could also
-+ * detect this by simply letting this loop run
-+ * to completion, as we would eventually hit
-+ * the end of the dirty list. However, we
-+ * want to avoid running the length of the
-+ * dirty list unnecessarily (it might be quite
-+ * long), so we catch this as early as
-+ * possible by detecting the hash marker. In
-+ * this case, we simply set dvar to NULL and
-+ * break; the conditional after the loop will
-+ * send us back to top.
-+ */
-+ dvar = NULL;
-+ break;
-+ }
-+
-+ goto next;
-+ }
-+
-+ if (dtuple->dtt_nkeys != nkeys)
-+ goto next;
-+
-+ for (i = 0; i < nkeys; i++, dkey++) {
-+ if (dkey->dttk_size != key[i].dttk_size)
-+ goto next; /* size or type mismatch */
-+
-+ if (dkey->dttk_size != 0) {
-+ if (dtrace_bcmp(
-+ (void *)(uintptr_t)key[i].dttk_value,
-+ (void *)(uintptr_t)dkey->dttk_value,
-+ dkey->dttk_size))
-+ goto next;
-+ } else {
-+ if (dkey->dttk_value != key[i].dttk_value)
-+ goto next;
-+ }
-+ }
-+
-+ if (op != DTRACE_DYNVAR_DEALLOC)
-+ return dvar;
-+
-+ ASSERT(dvar->dtdv_next == NULL ||
-+ dvar->dtdv_next->dtdv_hashval != DTRACE_DYNHASH_FREE);
-+
-+ if (prev != NULL) {
-+ ASSERT(hash[bucket].dtdh_chain != dvar);
-+ ASSERT(start != dvar);
-+ ASSERT(prev->dtdv_next == dvar);
-+ prev->dtdv_next = dvar->dtdv_next;
-+ } else {
-+ if (cmpxchg(&hash[bucket].dtdh_chain, start,
-+ dvar->dtdv_next) != start) {
-+ /*
-+ * We have failed to atomically swing the
-+ * hash table head pointer, presumably because
-+ * of a conflicting allocation on another CPU.
-+ * We need to reread the hash chain and try
-+ * again.
-+ */
-+ goto top;
-+ }
-+ }
-+
-+ dtrace_membar_producer();
-+
-+ /*
-+ * Now set the hash value to indicate that it's free.
-+ */
-+ ASSERT(hash[bucket].dtdh_chain != dvar);
-+ dvar->dtdv_hashval = DTRACE_DYNHASH_FREE;
-+
-+ dtrace_membar_producer();
-+
-+ /*
-+ * Set the next pointer to point at the dirty list, and
-+ * atomically swing the dirty pointer to the newly freed dvar.
-+ */
-+ do {
-+ next = dcpu->dtdsc_dirty;
-+ dvar->dtdv_next = next;
-+ } while (cmpxchg(&dcpu->dtdsc_dirty, next, dvar) != next);
-+
-+ /*
-+ * Finally, unlock this hash bucket.
-+ */
-+ ASSERT(hash[bucket].dtdh_lock == lock);
-+ ASSERT(lock & 1);
-+ hash[bucket].dtdh_lock++;
-+
-+ return NULL;
-+next:
-+ prev = dvar;
-+ continue;
-+ }
-+
-+ if (dvar == NULL) {
-+ /*
-+ * If dvar is NULL, it is because we went off the rails:
-+ * one of the elements that we traversed in the hash chain
-+ * was deleted while we were traversing it. In this case,
-+ * we assert that we aren't doing a dealloc (deallocs lock
-+ * the hash bucket to prevent themselves from racing with
-+ * one another), and retry the hash chain traversal.
-+ */
-+ ASSERT(op != DTRACE_DYNVAR_DEALLOC);
-+ goto top;
-+ }
-+
-+ if (op != DTRACE_DYNVAR_ALLOC) {
-+ /*
-+ * If we are not to allocate a new variable, we want to
-+ * return NULL now. Before we return, check that the value
-+ * of the lock word hasn't changed. If it has, we may have
-+ * seen an inconsistent snapshot.
-+ */
-+ if (op == DTRACE_DYNVAR_NOALLOC) {
-+ if (hash[bucket].dtdh_lock != lock)
-+ goto top;
-+ } else {
-+ ASSERT(op == DTRACE_DYNVAR_DEALLOC);
-+ ASSERT(hash[bucket].dtdh_lock == lock);
-+ ASSERT(lock & 1);
-+ hash[bucket].dtdh_lock++;
-+ }
-+
-+ return NULL;
-+ }
-+
-+ /*
-+ * We need to allocate a new dynamic variable. The size we need is the
-+ * size of dtrace_dynvar plus the size of nkeys dtrace_key_t's plus the
-+ * size of any auxiliary key data (rounded up to 8-byte alignment) plus
-+ * the size of any referred-to data (dsize). We then round the final
-+ * size up to the chunksize for allocation.
-+ */
-+ for (ksize = 0, i = 0; i < nkeys; i++)
-+ ksize += P2ROUNDUP(key[i].dttk_size, sizeof(uint64_t));
-+
-+ /*
-+ * This should be pretty much impossible, but could happen if, say,
-+ * strange DIF specified the tuple. Ideally, this should be an
-+ * assertion and not an error condition -- but that requires that the
-+ * chunksize calculation in dtrace_difo_chunksize() be absolutely
-+ * bullet-proof. (That is, it must not be able to be fooled by
-+ * malicious DIF.) Given the lack of backwards branches in DIF,
-+ * solving this would presumably not amount to solving the Halting
-+ * Problem -- but it still seems awfully hard.
-+ */
-+ if (sizeof(struct dtrace_dynvar) +
-+ sizeof(struct dtrace_key) * (nkeys - 1) +
-+ ksize + dsize > chunksize) {
-+ dcpu->dtdsc_drops++;
-+ return NULL;
-+ }
-+
-+ nstate = DTRACE_DSTATE_EMPTY;
-+
-+ do {
-+retry:
-+ free = dcpu->dtdsc_free;
-+
-+ if (free == NULL) {
-+ struct dtrace_dynvar *clean = dcpu->dtdsc_clean;
-+ void *rval;
-+
-+ if (clean == NULL) {
-+ /*
-+ * We're out of dynamic variable space on
-+ * this CPU. Unless we have tried all CPUs,
-+ * we'll try to allocate from a different
-+ * CPU.
-+ */
-+ switch (dstate->dtds_state) {
-+ case DTRACE_DSTATE_CLEAN: {
-+ enum dtrace_dstate_state *sp =
-+ (enum dtrace_dstate_state *)
-+ &dstate->dtds_state;
-+
-+ if (++cpu >= NR_CPUS)
-+ cpu = 0;
-+
-+ if (dcpu->dtdsc_dirty != NULL &&
-+ nstate == DTRACE_DSTATE_EMPTY)
-+ nstate = DTRACE_DSTATE_DIRTY;
-+
-+ if (dcpu->dtdsc_rinsing != NULL)
-+ nstate = DTRACE_DSTATE_RINSING;
-+
-+ dcpu = &dstate->dtds_percpu[cpu];
-+
-+ if (cpu != me)
-+ goto retry;
-+
-+ cmpxchg(sp, DTRACE_DSTATE_CLEAN,
-+ nstate);
-+
-+ /*
-+ * To increment the correct bean
-+ * counter, take another lap.
-+ */
-+ goto retry;
-+ }
-+
-+ case DTRACE_DSTATE_DIRTY:
-+ dcpu->dtdsc_dirty_drops++;
-+ break;
-+
-+ case DTRACE_DSTATE_RINSING:
-+ dcpu->dtdsc_rinsing_drops++;
-+ break;
-+
-+ case DTRACE_DSTATE_EMPTY:
-+ dcpu->dtdsc_drops++;
-+ break;
-+ }
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_DROP);
-+ return NULL;
-+ }
-+
-+ /*
-+ * The clean list appears to be non-empty. We want to
-+ * move the clean list to the free list; we start by
-+ * moving the clean pointer aside.
-+ */
-+ if (cmpxchg(&dcpu->dtdsc_clean, clean, NULL) != clean)
-+ /*
-+ * We are in one of two situations:
-+ *
-+ * (a) The clean list was switched to the
-+ * free list by another CPU.
-+ *
-+ * (b) The clean list was added to by the
-+ * cleansing cyclic.
-+ *
-+ * In either of these situations, we can
-+ * just reattempt the free list allocation.
-+ */
-+ goto retry;
-+
-+ ASSERT(clean->dtdv_hashval == DTRACE_DYNHASH_FREE);
-+
-+ /*
-+ * Now we'll move the clean list to the free list.
-+ * It's impossible for this to fail: the only way
-+ * the free list can be updated is through this
-+ * code path, and only one CPU can own the clean list.
-+ * Thus, it would only be possible for this to fail if
-+ * this code were racing with dtrace_dynvar_clean().
-+ * (That is, if dtrace_dynvar_clean() updated the clean
-+ * list, and we ended up racing to update the free
-+ * list.) This race is prevented by the dtrace_sync()
-+ * in dtrace_dynvar_clean() -- which flushes the
-+ * owners of the clean lists out before resetting
-+ * the clean lists.
-+ */
-+ rval = cmpxchg(&dcpu->dtdsc_free, NULL, clean);
-+ ASSERT(rval == NULL);
-+
-+ goto retry;
-+ }
-+
-+ dvar = free;
-+ new_free = dvar->dtdv_next;
-+ } while (cmpxchg(&dcpu->dtdsc_free, free, new_free) != free);
-+
-+ /*
-+ * We have now allocated a new chunk. We copy the tuple keys into the
-+ * tuple array and copy any referenced key data into the data space
-+ * following the tuple array. As we do this, we relocate dttk_value
-+ * in the final tuple to point to the key data address in the chunk.
-+ */
-+ kdata = (uintptr_t)&dvar->dtdv_tuple.dtt_key[nkeys];
-+ dvar->dtdv_data = (void *)(kdata + ksize);
-+ dvar->dtdv_tuple.dtt_nkeys = nkeys;
-+
-+ for (i = 0; i < nkeys; i++) {
-+ struct dtrace_key *dkey = &dvar->dtdv_tuple.dtt_key[i];
-+ size_t kesize = key[i].dttk_size;
-+
-+ if (kesize != 0) {
-+ dtrace_bcopy(
-+ (const void *)(uintptr_t)key[i].dttk_value,
-+ (void *)kdata, kesize);
-+ dkey->dttk_value = kdata;
-+ kdata += P2ROUNDUP(kesize, sizeof(uint64_t));
-+ } else
-+ dkey->dttk_value = key[i].dttk_value;
-+
-+ dkey->dttk_size = kesize;
-+ }
-+
-+ ASSERT(dvar->dtdv_hashval == DTRACE_DYNHASH_FREE);
-+ dvar->dtdv_hashval = hashval;
-+ dvar->dtdv_next = start;
-+
-+ if (cmpxchg(&hash[bucket].dtdh_chain, start, dvar) == start)
-+ return dvar;
-+
-+ /*
-+ * The cas has failed. Either another CPU is adding an element to
-+ * this hash chain, or another CPU is deleting an element from this
-+ * hash chain. The simplest way to deal with both of these cases
-+ * (though not necessarily the most efficient) is to free our
-+ * allocated block and tail-call ourselves. Note that the free is
-+ * to the dirty list and _not_ to the free list. This is to prevent
-+ * races with allocators, above.
-+ */
-+ dvar->dtdv_hashval = DTRACE_DYNHASH_FREE;
-+
-+ dtrace_membar_producer();
-+
-+ do {
-+ free = dcpu->dtdsc_dirty;
-+ dvar->dtdv_next = free;
-+ } while (cmpxchg(&dcpu->dtdsc_dirty, free, dvar) != free);
-+
-+ return dtrace_dynvar(dstate, nkeys, key, dsize, op, mstate, vstate);
-+}
-+
-+/*
-+ * Return a string. In the event that the user lacks the privilege to access
-+ * arbitrary kernel memory, we copy the string out to scratch memory so that we
-+ * don't fail access checking.
-+ *
-+ * dtrace_dif_variable() uses this routine as a helper for various
-+ * builtin values such as 'execname' and 'probefunc.'
-+ */
-+static uintptr_t dtrace_dif_varstr(uintptr_t addr, struct dtrace_state *state,
-+ struct dtrace_mstate *mstate)
-+{
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ uintptr_t ret;
-+ size_t strsz;
-+
-+ /*
-+ * The easy case: this probe is allowed to read all of memory, so
-+ * we can just return this as a vanilla pointer.
-+ */
-+ if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0)
-+ return addr;
-+
-+ /*
-+ * This is the tougher case: we copy the string in question from
-+ * kernel memory into scratch memory and return it that way: this
-+ * ensures that we won't trip up when access checking tests the
-+ * BYREF return value.
-+ */
-+ strsz = dtrace_strlen((char *)addr, size) + 1;
-+
-+ if (mstate->dtms_scratch_ptr + strsz >
-+ mstate->dtms_scratch_base + mstate->dtms_scratch_size) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ return (uintptr_t)NULL;
-+ }
-+
-+ dtrace_strcpy((const void *)addr, (void *)mstate->dtms_scratch_ptr,
-+ strsz);
-+ ret = mstate->dtms_scratch_ptr;
-+ mstate->dtms_scratch_ptr += strsz;
-+
-+ return ret;
-+}
-+
-+/*
-+ * This function implements the DIF emulator's variable lookups. The emulator
-+ * passes a reserved variable identifier and optional built-in array index.
-+ *
-+ * This function is annotated to be always inlined in dtrace_dif_emulate()
-+ * because (1) that is the only place where it is called from, and (2) it has
-+ * come to our attention that some GCC versions inline it automatically while
-+ * others do not and that messes up the number of frames to skip (aframes).
-+ */
-+static __always_inline uint64_t dtrace_dif_variable(struct dtrace_mstate *mstate,
-+ struct dtrace_state *state,
-+ uint64_t v, uint64_t ndx)
-+{
-+ /*
-+ * If we're accessing one of the uncached arguments, we'll turn this
-+ * into a reference in the args array.
-+ */
-+ if (v >= DIF_VAR_ARG0 && v <= DIF_VAR_ARG9) {
-+ ndx = v - DIF_VAR_ARG0;
-+ v = DIF_VAR_ARGS;
-+ }
-+
-+ switch (v) {
-+ case DIF_VAR_ARGS:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_ARGS);
-+
-+ if (ndx >= DTRACE_MSTATE_ARGS_MAX) {
-+ int aframes =
-+ mstate->dtms_probe->dtpr_aframes + 1;
-+ struct dtrace_provider *pv;
-+ uint64_t val;
-+
-+ pv = mstate->dtms_probe->dtpr_provider;
-+ if (pv->dtpv_pops.dtps_getargval != NULL)
-+ val = pv->dtpv_pops.dtps_getargval(
-+ pv->dtpv_arg,
-+ mstate->dtms_probe->dtpr_id,
-+ mstate->dtms_probe->dtpr_arg,
-+ ndx, aframes);
-+ else
-+ val = dtrace_getarg(ndx, aframes);
-+
-+ /*
-+ * This is regrettably required to keep the compiler
-+ * from tail-optimizing the call to dtrace_getarg().
-+ * The condition always evaluates to true, but the
-+ * compiler has no way of figuring that out a priori.
-+ * (None of this would be necessary if the compiler
-+ * could be relied upon to _always_ tail-optimize
-+ * the call to dtrace_getarg() -- but it can't.)
-+ */
-+ if (mstate->dtms_probe != NULL)
-+ return val;
-+
-+ ASSERT(0);
-+ }
-+
-+ return mstate->dtms_arg[ndx];
-+
-+ case DIF_VAR_UREGS: {
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ return dtrace_getreg(current, ndx);
-+ }
-+
-+ case DIF_VAR_CURTHREAD:
-+ if (!dtrace_priv_kernel(state))
-+ return 0;
-+
-+ return (uint64_t)(uintptr_t)current;
-+
-+ case DIF_VAR_TIMESTAMP:
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_TIMESTAMP)) {
-+ mstate->dtms_timestamp = dtrace_gethrtime();
-+ mstate->dtms_present |= DTRACE_MSTATE_TIMESTAMP;
-+ }
-+
-+ return ktime_to_ns(mstate->dtms_timestamp);
-+
-+ case DIF_VAR_WALLTIMESTAMP:
-+ return ktime_to_ns(dtrace_get_walltime());
-+
-+ case DIF_VAR_VTIMESTAMP:
-+ ASSERT(dtrace_vtime_references != 0);
-+
-+ if (current->dt_task != NULL)
-+ return ktime_to_ns(current->dt_task->dt_vtime);
-+
-+ /*
-+ * This is not ideal but without any data available
-+ * there is no reasonable default value for vtimestamp
-+ * variable.
-+ */
-+ return ktime_to_ns(0);
-+
-+ case DIF_VAR_IPL:
-+ if (!dtrace_priv_kernel(state))
-+ return 0;
-+
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_IPL)) {
-+ mstate->dtms_ipl = dtrace_getipl();
-+ mstate->dtms_present |= DTRACE_MSTATE_IPL;
-+ }
-+
-+ return mstate->dtms_ipl;
-+
-+ case DIF_VAR_EPID:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_EPID);
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_EPID);
-+
-+ return mstate->dtms_epid;
-+
-+ case DIF_VAR_ID:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+ return mstate->dtms_probe->dtpr_id;
-+
-+ case DIF_VAR_STACKDEPTH:
-+ if (!dtrace_priv_kernel(state))
-+ return 0;
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_STACKDEPTH)) {
-+ int aframes = mstate->dtms_probe->dtpr_aframes + 2;
-+
-+ mstate->dtms_stackdepth = dtrace_getstackdepth(
-+ mstate, aframes);
-+ mstate->dtms_present |= DTRACE_MSTATE_STACKDEPTH;
-+ }
-+
-+ return mstate->dtms_stackdepth;
-+
-+ case DIF_VAR_USTACKDEPTH:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_USTACKDEPTH)) {
-+ /*
-+ * See comment in DIF_VAR_PID.
-+ */
-+ if (DTRACE_ANCHORED(mstate->dtms_probe) &&
-+ in_interrupt())
-+ mstate->dtms_ustackdepth = 0;
-+ else
-+ mstate->dtms_ustackdepth =
-+ dtrace_getustackdepth();
-+
-+ mstate->dtms_present |= DTRACE_MSTATE_USTACKDEPTH;
-+ }
-+
-+ return mstate->dtms_ustackdepth;
-+
-+ case DIF_VAR_CALLER:
-+ if (!dtrace_priv_kernel(state))
-+ return 0;
-+
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_CALLER)) {
-+ int aframes = mstate->dtms_probe->dtpr_aframes + 1;
-+
-+ if (!DTRACE_ANCHORED(mstate->dtms_probe)) {
-+ /*
-+ * If this is an unanchored probe, we are
-+ * required to go through the slow path:
-+ * dtrace_caller() only guarantees correct
-+ * results for anchored probes.
-+ */
-+ uint64_t caller[2];
-+
-+ dtrace_getpcstack(caller, 2, aframes,
-+ (uint32_t *)(uintptr_t)
-+ mstate->dtms_arg[0]);
-+ mstate->dtms_caller = caller[1];
-+ } else if ((mstate->dtms_caller =
-+ dtrace_caller(aframes, 0)) == -1) {
-+ /*
-+ * We have failed to do this the quick way;
-+ * we must resort to the slower approach of
-+ * calling dtrace_getpcstack().
-+ */
-+ uint64_t caller;
-+
-+ dtrace_getpcstack(&caller, 1, aframes, NULL);
-+ mstate->dtms_caller = caller;
-+ }
-+
-+ mstate->dtms_present |= DTRACE_MSTATE_CALLER;
-+ }
-+
-+ return mstate->dtms_caller;
-+
-+ case DIF_VAR_UCALLER:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ if (!(mstate->dtms_present & DTRACE_MSTATE_UCALLER)) {
-+ uint64_t ustack[4];
-+
-+ /*
-+ * dtrace_getupcstack() fills in the first uint64_t with
-+ * the current PID, and the second uint64_t with the
-+ * current TGID. The third uint64_t will be the
-+ * program counter at user-level. The fourth uint64_t
-+ * will contain the caller, which is what we're after.
-+ */
-+ ustack[3] = 0;
-+ dtrace_getupcstack(ustack, 4);
-+
-+ mstate->dtms_ucaller = ustack[3];
-+ mstate->dtms_present |= DTRACE_MSTATE_UCALLER;
-+ }
-+
-+ return mstate->dtms_ucaller;
-+
-+ case DIF_VAR_PROBEPROV:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+
-+ return dtrace_dif_varstr(
-+ (uintptr_t)mstate->dtms_probe->dtpr_provider->dtpv_name,
-+ state, mstate);
-+
-+ case DIF_VAR_PROBEMOD:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+ return dtrace_dif_varstr(
-+ (uintptr_t)mstate->dtms_probe->dtpr_mod, state,
-+ mstate);
-+
-+ case DIF_VAR_PROBEFUNC:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+
-+ return dtrace_dif_varstr(
-+ (uintptr_t)mstate->dtms_probe->dtpr_func, state,
-+ mstate);
-+
-+ case DIF_VAR_PROBENAME:
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+
-+ return dtrace_dif_varstr(
-+ (uintptr_t)mstate->dtms_probe->dtpr_name, state,
-+ mstate);
-+
-+ case DIF_VAR_PID:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * It is always safe to dereference current, it always points
-+ * to a valid task_struct.
-+ */
-+ return (uint64_t)current->tgid;
-+
-+ case DIF_VAR_PPID:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * It is always safe to dereference current, it always points
-+ * to a valid task_struct.
-+ *
-+ * Additionally, it is safe to dereference one's parent, since
-+ * it is never NULL after process birth.
-+ */
-+ return (uint64_t)current->real_parent->tgid;
-+
-+ case DIF_VAR_TID:
-+ return (uint64_t)current->pid;
-+
-+ case DIF_VAR_EXECNAME:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * It is always safe to dereference current, it always points
-+ * to a valid task_struct.
-+ */
-+ return dtrace_dif_varstr((uintptr_t)current->comm, state,
-+ mstate);
-+
-+ case DIF_VAR_ZONENAME:
-+ return 0;
-+
-+ case DIF_VAR_UID:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * It is always safe to dereference current, it always points
-+ * to a valid task_struct.
-+ *
-+ * Additionally, it is safe to dereference one's own process
-+ * credential, since this is never NULL after process birth.
-+ */
-+ return (uint64_t)from_kuid(current_user_ns(),
-+ current_real_cred()->uid);
-+
-+ case DIF_VAR_GID:
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * It is always safe to dereference current, it always points
-+ * to a valid task_struct.
-+ *
-+ * Additionally, it is safe to dereference one's own process
-+ * credential, since this is never NULL after process birth.
-+ */
-+ return (uint64_t)from_kgid(current_user_ns(),
-+ current_real_cred()->gid);
-+
-+ case DIF_VAR_ERRNO: {
-+ int64_t arg0;
-+
-+ ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
-+
-+ if (!dtrace_priv_proc(state))
-+ return 0;
-+
-+ /*
-+ * We need to do some magic here to get the correct semantics
-+ * for the 'errno' variable. It can only have a non-zero value
-+ * when executing a system call, and for Linux, only after the
-+ * actual system call implementation has completed, indicating
-+ * in its return value either an error code (-2048 < errno < 0)
-+ * or a valid result. So, the only time we can expect a valid
-+ * value in errno is during the processing of any return probe
-+ * in the syscall provider. In all other cases, it should have
-+ * the value 0.
-+ *
-+ * So, we only look at probes that match: syscall:::return
-+ */
-+ if (strncmp(mstate->dtms_probe->dtpr_provider->dtpv_name,
-+ "syscall", 7) != 0)
-+ return 0;
-+ if (strncmp(mstate->dtms_probe->dtpr_name, "return", 6) != 0)
-+ return 0;
-+
-+ /*
-+ * Error number is present if arg0 lies between 0 and -2048,
-+ * exclusive.
-+ */
-+ arg0 = (int64_t)mstate->dtms_arg[ndx];
-+ if (arg0 < 0 && arg0 > -2048)
-+ return (uint64_t)-arg0;
-+
-+ return 0;
-+ }
-+
-+ case DIF_VAR_CURCPU:
-+ return (uint64_t)(uintptr_t)this_cpu_info;
-+
-+ default:
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return 0;
-+ }
-+}
-+
-+#define DTRACE_V4MAPPED_OFFSET (sizeof(uint32_t) * 3)
-+
-+/*
-+ * Emulate the execution of DTrace ID subroutines invoked by the call opcode.
-+ * Notice that we don't bother validating the proper number of arguments or
-+ * their types in the tuple stack. This isn't needed because all argument
-+ * interpretation is safe because of our load safety -- the worst that can
-+ * happen is that a bogus program can obtain bogus results.
-+ */
-+static void dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
-+ struct dtrace_key *tupregs, int nargs,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_state *state)
-+{
-+ volatile uint16_t *flags = &this_cpu_core->cpuc_dtrace_flags;
-+ volatile uintptr_t *illval = &this_cpu_core->cpuc_dtrace_illval;
-+ struct dtrace_vstate *vstate = &state->dts_vstate;
-+ struct mutex mtx;
-+
-+ union {
-+ rwlock_t ri;
-+ uintptr_t rw;
-+ } r;
-+
-+ dt_dbg_dif(" Subroutine %d\n", subr);
-+
-+ switch (subr) {
-+ case DIF_SUBR_RAND:
-+ regs[rd] = ktime_to_ns(dtrace_gethrtime()) * 2416 + 374441;
-+ regs[rd] = do_div(regs[rd], 1771875);
-+ break;
-+
-+ case DIF_SUBR_MUTEX_OWNED:
-+ if (!dtrace_canload(tupregs[0].dttk_value,
-+ sizeof(struct mutex), mstate, vstate))
-+ break;
-+
-+ dtrace_bcopy((const void *)(uintptr_t)tupregs[0].dttk_value,
-+ &mtx, sizeof(struct mutex));
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+ regs[rd] = mutex_owned(&mtx);
-+ break;
-+
-+ case DIF_SUBR_MUTEX_OWNER:
-+ regs[rd] = 0;
-+ if (!dtrace_canload(tupregs[0].dttk_value,
-+ sizeof(struct mutex), mstate, vstate))
-+ break;
-+
-+ dtrace_bcopy((const void *)(uintptr_t)tupregs[0].dttk_value,
-+ &mtx, sizeof(struct mutex));
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+#ifdef CONFIG_SMP
-+ regs[rd] = (uintptr_t)__mutex_owner(&mtx);
-+#else
-+ regs[rd] = 0;
-+#endif
-+ break;
-+
-+ case DIF_SUBR_MUTEX_TYPE_ADAPTIVE:
-+ if (!dtrace_canload(tupregs[0].dttk_value,
-+ sizeof(struct mutex), mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * On Linux, all mutexes are adaptive.
-+ */
-+ regs[rd] = 1;
-+ break;
-+
-+ case DIF_SUBR_MUTEX_TYPE_SPIN:
-+ if (!dtrace_canload(tupregs[0].dttk_value,
-+ sizeof(struct mutex), mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * On Linux, all mutexes are adaptive.
-+ */
-+ regs[rd] = 0;
-+ break;
-+
-+ case DIF_SUBR_RW_READ_HELD: {
-+ if (!dtrace_canload(tupregs[0].dttk_value, sizeof(rwlock_t),
-+ mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ r.rw = dtrace_loadptr(tupregs[0].dttk_value);
-+ regs[rd] = !peek_write_can_lock(&r.ri) &&
-+ peek_read_can_lock(&r.ri);
-+ break;
-+ }
-+
-+ case DIF_SUBR_RW_WRITE_HELD:
-+ if (!dtrace_canload(tupregs[0].dttk_value, sizeof(rwlock_t),
-+ mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ r.rw = dtrace_loadptr(tupregs[0].dttk_value);
-+ regs[rd] = !peek_write_can_lock(&r.ri);
-+ break;
-+
-+ case DIF_SUBR_RW_ISWRITER:
-+ if (!dtrace_canload(tupregs[0].dttk_value, sizeof(rwlock_t),
-+ mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ r.rw = dtrace_loadptr(tupregs[0].dttk_value);
-+ /*
-+ * On Linux there is no way to determine whether someone is
-+ * trying to acquire a write lock.
-+ */
-+ regs[rd] = !peek_write_can_lock(&r.ri);
-+ break;
-+
-+ case DIF_SUBR_BCOPY: {
-+ /*
-+ * We need to be sure that the destination is in the scratch
-+ * region -- no other region is allowed.
-+ */
-+ uintptr_t src = tupregs[0].dttk_value;
-+ uintptr_t dest = tupregs[1].dttk_value;
-+ size_t size = tupregs[2].dttk_value;
-+
-+ if (!dtrace_inscratch(dest, size, mstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ if (!dtrace_canload(src, size, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ dtrace_bcopy((void *)src, (void *)dest, size);
-+ break;
-+ }
-+
-+ case DIF_SUBR_ALLOCA:
-+ case DIF_SUBR_COPYIN: {
-+ uintptr_t dest = P2ROUNDUP(mstate->dtms_scratch_ptr, 8);
-+ uint64_t size;
-+ size_t scratch_size;
-+
-+ size = tupregs[subr == DIF_SUBR_ALLOCA ? 0 : 1].dttk_value;
-+ scratch_size = (dest - mstate->dtms_scratch_ptr) + size;
-+
-+ /*
-+ * This action doesn't require any credential checks since
-+ * probes will not activate in user contexts to which the
-+ * enabling user does not have permissions.
-+ */
-+
-+ /*
-+ * Rounding up the user allocation size could have overflowed
-+ * a large, bogus allocation (like -1ULL) to 0.
-+ */
-+ if (scratch_size < size ||
-+ !DTRACE_INSCRATCH(mstate, scratch_size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (subr == DIF_SUBR_COPYIN) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_copyin(tupregs[0].dttk_value, dest, size, flags);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+ }
-+
-+ mstate->dtms_scratch_ptr += scratch_size;
-+ regs[rd] = dest;
-+ break;
-+ }
-+
-+ case DIF_SUBR_COPYINTO: {
-+ uint64_t size = tupregs[1].dttk_value;
-+ uintptr_t dest = tupregs[2].dttk_value;
-+
-+ /*
-+ * This action doesn't require any credential checks since
-+ * probes will not activate in user contexts to which the
-+ * enabling user does not have permissions.
-+ */
-+ if (!dtrace_inscratch(dest, size, mstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_copyin(tupregs[0].dttk_value, dest, size, flags);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+ break;
-+ }
-+
-+ case DIF_SUBR_COPYINSTR: {
-+ uintptr_t dest = mstate->dtms_scratch_ptr;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+
-+ if (nargs > 1 && tupregs[1].dttk_value < size)
-+ size = tupregs[1].dttk_value + 1;
-+
-+ /*
-+ * This action doesn't require any credential checks since
-+ * probes will not activate in user contexts to which the
-+ * enabling user does not have permissions.
-+ */
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_copyinstr(tupregs[0].dttk_value, dest, size, flags);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ ((char *)dest)[size - 1] = '\0';
-+ mstate->dtms_scratch_ptr += size;
-+ regs[rd] = dest;
-+ break;
-+ }
-+
-+#if 0 /* FIXME */
-+ case DIF_SUBR_MSGSIZE:
-+ case DIF_SUBR_MSGDSIZE: {
-+ uintptr_t baddr = tupregs[0].dttk_value, daddr;
-+ uintptr_t wptr, rptr;
-+ size_t count = 0;
-+ int cont = 0;
-+
-+ while (baddr != NULL && !(*flags & CPU_DTRACE_FAULT)) {
-+
-+ if (!dtrace_canload(baddr, sizeof(mblk_t), mstate,
-+ vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ wptr = dtrace_loadptr(baddr +
-+ offsetof(mblk_t, b_wptr));
-+
-+ rptr = dtrace_loadptr(baddr +
-+ offsetof(mblk_t, b_rptr));
-+
-+ if (wptr < rptr) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = tupregs[0].dttk_value;
-+ break;
-+ }
-+
-+ daddr = dtrace_loadptr(baddr +
-+ offsetof(mblk_t, b_datap));
-+
-+ baddr = dtrace_loadptr(baddr +
-+ offsetof(mblk_t, b_cont));
-+
-+ /*
-+ * We want to prevent against denial-of-service here,
-+ * so we're only going to search the list for
-+ * dtrace_msgdsize_max mblks.
-+ */
-+ if (cont++ > dtrace_msgdsize_max) {
-+ *flags |= CPU_DTRACE_ILLOP;
-+ break;
-+ }
-+
-+ if (subr == DIF_SUBR_MSGDSIZE) {
-+ if (dtrace_load8(daddr +
-+ offsetof(dblk_t, db_type)) != M_DATA)
-+ continue;
-+ }
-+
-+ count += wptr - rptr;
-+ }
-+
-+ if (!(*flags & CPU_DTRACE_FAULT))
-+ regs[rd] = count;
-+
-+ break;
-+ }
-+#endif
-+
-+ case DIF_SUBR_PROGENYOF: {
-+ pid_t pid = tupregs[0].dttk_value;
-+ struct task_struct *p;
-+ int rval = 0;
-+
-+ for (p = current; p != NULL; p = p->real_parent) {
-+ if (p->pid == pid) {
-+ rval = 1;
-+ break;
-+ }
-+
-+ if (p == p->real_parent)
-+ break;
-+ }
-+
-+ regs[rd] = rval;
-+ break;
-+ }
-+
-+ case DIF_SUBR_SPECULATION:
-+ regs[rd] = dtrace_speculation(state);
-+ break;
-+
-+ case DIF_SUBR_COPYOUT: {
-+ uintptr_t kaddr = tupregs[0].dttk_value;
-+ uintptr_t uaddr = tupregs[1].dttk_value;
-+ uint64_t size = tupregs[2].dttk_value;
-+
-+ if (!dtrace_destructive_disallow &&
-+ dtrace_priv_proc_control(state) &&
-+ !dtrace_istoxic(kaddr, size) &&
-+ dtrace_canload(kaddr, size, mstate, vstate)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_copyout(kaddr, uaddr, size, flags);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+ }
-+ break;
-+ }
-+
-+ case DIF_SUBR_COPYOUTSTR: {
-+ uintptr_t kaddr = tupregs[0].dttk_value;
-+ uintptr_t uaddr = tupregs[1].dttk_value;
-+ uint64_t size = tupregs[2].dttk_value;
-+
-+ if (!dtrace_destructive_disallow &&
-+ dtrace_priv_proc_control(state) &&
-+ !dtrace_istoxic(kaddr, size) &&
-+ dtrace_strcanload(kaddr, size, mstate, vstate)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_copyoutstr(kaddr, uaddr, size, flags);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+ }
-+ break;
-+ }
-+
-+ case DIF_SUBR_STRLEN: {
-+ size_t sz;
-+ uintptr_t addr = (uintptr_t)tupregs[0].dttk_value;
-+
-+ sz = dtrace_strlen((char *)addr,
-+ state->dts_options[DTRACEOPT_STRSIZE]);
-+
-+ if (!dtrace_canload(addr, sz + 1, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ regs[rd] = sz;
-+
-+ break;
-+ }
-+
-+ case DIF_SUBR_STRCHR:
-+ case DIF_SUBR_STRRCHR: {
-+ /*
-+ * We're going to iterate over the string looking for the
-+ * specified character. We will iterate until we have reached
-+ * the string length or we have found the character. If this
-+ * is DIF_SUBR_STRRCHR, we will look for the last occurrence
-+ * of the specified character instead of the first.
-+ */
-+ uintptr_t saddr = tupregs[0].dttk_value;
-+ uintptr_t addr = tupregs[0].dttk_value;
-+ uintptr_t limit = addr +
-+ state->dts_options[DTRACEOPT_STRSIZE];
-+ char c, target = (char)tupregs[1].dttk_value;
-+
-+ for (regs[rd] = 0; addr < limit; addr++) {
-+ c = dtrace_load8(addr);
-+ if (c == target) {
-+ regs[rd] = addr;
-+
-+ if (subr == DIF_SUBR_STRCHR)
-+ break;
-+ }
-+
-+ if (c == '\0')
-+ break;
-+ }
-+
-+ if (!dtrace_canload(saddr, addr - saddr, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ break;
-+ }
-+
-+ case DIF_SUBR_STRSTR:
-+ case DIF_SUBR_INDEX:
-+ case DIF_SUBR_RINDEX: {
-+ /*
-+ * We're going to iterate over the string looking for the
-+ * specified string. We will iterate until we have reached
-+ * the string length or we have found the string. (Yes, this
-+ * is done in the most naive way possible -- but considering
-+ * that the string we're searching for is likely to be
-+ * relatively short, the complexity of Rabin-Karp or similar
-+ * hardly seems merited.)
-+ */
-+ char *addr = (char *)(uintptr_t)
-+ tupregs[0].dttk_value;
-+ char *substr = (char *)(uintptr_t)
-+ tupregs[1].dttk_value;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ size_t len = dtrace_strlen(addr, size);
-+ size_t sublen = dtrace_strlen(substr, size);
-+ char *limit = addr + len, *orig = addr;
-+ int notfound = subr == DIF_SUBR_STRSTR ? 0 : -1;
-+ int inc = 1;
-+
-+ regs[rd] = notfound;
-+
-+ if (!dtrace_canload((uintptr_t)addr, len + 1, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!dtrace_canload((uintptr_t)substr, sublen + 1, mstate,
-+ vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * strstr() and index()/rindex() have similar semantics if
-+ * both strings are the empty string: strstr() returns a
-+ * pointer to the (empty) string, and index() and rindex()
-+ * both return index 0 (regardless of any position argument).
-+ */
-+ if (sublen == 0 && len == 0) {
-+ if (subr == DIF_SUBR_STRSTR)
-+ regs[rd] = (uintptr_t)addr;
-+ else
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (subr != DIF_SUBR_STRSTR) {
-+ if (subr == DIF_SUBR_RINDEX) {
-+ limit = orig - 1;
-+ addr += len;
-+ inc = -1;
-+ }
-+
-+ /*
-+ * Both index() and rindex() take an optional position
-+ * argument that denotes the starting position.
-+ */
-+ if (nargs == 3) {
-+ int64_t pos = (int64_t)tupregs[2].dttk_value;
-+
-+ /*
-+ * If the position argument to index() is
-+ * negative, Perl implicitly clamps it at
-+ * zero. This semantic is a little surprising
-+ * given the special meaning of negative
-+ * positions to similar Perl functions like
-+ * substr(), but it appears to reflect a
-+ * notion that index() can start from a
-+ * negative index and increment its way up to
-+ * the string. Given this notion, Perl's
-+ * rindex() is at least self-consistent in
-+ * that it implicitly clamps positions greater
-+ * than the string length to be the string
-+ * length. Where Perl completely loses
-+ * coherence, however, is when the specified
-+ * substring is the empty string (""). In
-+ * this case, even if the position is
-+ * negative, rindex() returns 0 -- and even if
-+ * the position is greater than the length,
-+ * index() returns the string length. These
-+ * semantics violate the notion that index()
-+ * should never return a value less than the
-+ * specified position and that rindex() should
-+ * never return a value greater than the
-+ * specified position. (One assumes that
-+ * these semantics are artifacts of Perl's
-+ * implementation and not the results of
-+ * deliberate design -- it beggars belief that
-+ * even Larry Wall could desire such oddness.)
-+ * While in the abstract one would wish for
-+ * consistent position semantics across
-+ * substr(), index() and rindex() -- or at the
-+ * very least self-consistent position
-+ * semantics for index() and rindex() -- we
-+ * instead opt to keep with the extant Perl
-+ * semantics, in all their broken glory. (Do
-+ * we have more desire to maintain Perl's
-+ * semantics than Perl does? Probably.)
-+ */
-+ if (subr == DIF_SUBR_RINDEX) {
-+ if (pos < 0) {
-+ if (sublen == 0)
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (pos > len)
-+ pos = len;
-+ } else {
-+ if (pos < 0)
-+ pos = 0;
-+
-+ if (pos >= len) {
-+ if (sublen == 0)
-+ regs[rd] = len;
-+ break;
-+ }
-+ }
-+
-+ addr = orig + pos;
-+ }
-+ }
-+
-+ for (regs[rd] = notfound; addr != limit; addr += inc) {
-+ if (dtrace_strncmp(addr, substr, sublen) == 0) {
-+ if (subr != DIF_SUBR_STRSTR) {
-+ /*
-+ * As D index() and rindex() are
-+ * modeled on Perl (and not on awk),
-+ * we return a zero-based (and not a
-+ * one-based) index. (For you Perl
-+ * weenies: no, we're not going to add
-+ * $[ -- and shouldn't you be at a con
-+ * or something?)
-+ */
-+ regs[rd] = (uintptr_t)(addr - orig);
-+ break;
-+ }
-+
-+ ASSERT(subr == DIF_SUBR_STRSTR);
-+ regs[rd] = (uintptr_t)addr;
-+ break;
-+ }
-+ }
-+
-+ break;
-+ }
-+
-+ case DIF_SUBR_STRTOK: {
-+ uintptr_t addr = tupregs[0].dttk_value;
-+ uintptr_t tokaddr = tupregs[1].dttk_value;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ uintptr_t limit, toklimit = tokaddr + size;
-+ uint8_t c = 0, tokmap[32]; /* 256 / 8 */
-+ char *dest = (char *)mstate->dtms_scratch_ptr;
-+ int i;
-+
-+ /*
-+ * Check both the token buffer and (later) the input buffer,
-+ * since both could be non-scratch addresses.
-+ */
-+ if (!dtrace_strcanload(tokaddr, size, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (addr == (uintptr_t)NULL) {
-+ /*
-+ * If the address specified is NULL, we use our saved
-+ * strtok pointer from the mstate. Note that this
-+ * means that the saved strtok pointer is _only_
-+ * valid within multiple enablings of the same probe --
-+ * it behaves like an implicit clause-local variable.
-+ */
-+ addr = mstate->dtms_strtok;
-+ } else {
-+ /*
-+ * If the user-specified address is non-NULL we must
-+ * access check it. This is the only time we have
-+ * a chance to do so, since this address may reside
-+ * in the string table of this clause-- future calls
-+ * (when we fetch addr from mstate->dtms_strtok)
-+ * would fail this access check.
-+ */
-+ if (!dtrace_strcanload(addr, size, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+ }
-+
-+ /*
-+ * First, zero the token map, and then process the token
-+ * string -- setting a bit in the map for every character
-+ * found in the token string.
-+ */
-+ for (i = 0; i < sizeof(tokmap); i++)
-+ tokmap[i] = 0;
-+
-+ for (; tokaddr < toklimit; tokaddr++) {
-+ c = dtrace_load8(tokaddr);
-+ if (c == '\0')
-+ break;
-+
-+ ASSERT((c >> 3) < sizeof(tokmap));
-+ tokmap[c >> 3] |= (1 << (c & 0x7));
-+ }
-+
-+ for (limit = addr + size; addr < limit; addr++) {
-+ /*
-+ * We're looking for a character that is _not_ contained
-+ * in the token string.
-+ */
-+ c = dtrace_load8(addr);
-+ if (c == '\0')
-+ break;
-+
-+ if (!(tokmap[c >> 3] & (1 << (c & 0x7))))
-+ break;
-+ }
-+
-+ if (c == '\0') {
-+ /*
-+ * We reached the end of the string without finding
-+ * any character that was not in the token string.
-+ * We return NULL in this case, and we set the saved
-+ * address to NULL as well.
-+ */
-+ regs[rd] = 0;
-+ mstate->dtms_strtok = (uintptr_t)NULL;
-+ break;
-+ }
-+
-+ /*
-+ * From here on, we're copying into the destination string.
-+ */
-+ for (i = 0; addr < limit && i < size - 1; addr++) {
-+ c = dtrace_load8(addr);
-+ if (c == '\0')
-+ break;
-+
-+ if (tokmap[c >> 3] & (1 << (c & 0x7)))
-+ break;
-+
-+ ASSERT(i < size);
-+ dest[i++] = c;
-+ }
-+
-+ ASSERT(i < size);
-+ dest[i] = '\0';
-+ regs[rd] = (uintptr_t)dest;
-+ mstate->dtms_scratch_ptr += size;
-+ mstate->dtms_strtok = addr;
-+ break;
-+ }
-+
-+ case DIF_SUBR_SUBSTR: {
-+ uintptr_t s = tupregs[0].dttk_value;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ char *d = (char *)mstate->dtms_scratch_ptr;
-+ int64_t index = (int64_t)tupregs[1].dttk_value;
-+ int64_t remaining = (int64_t)tupregs[2].dttk_value;
-+ size_t len = dtrace_strlen((char *)s, size);
-+ int64_t i = 0;
-+
-+ if (!dtrace_canload(s, len + 1, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (nargs <= 2)
-+ remaining = (int64_t)size;
-+
-+ if (index < 0) {
-+ index += len;
-+
-+ if (index < 0 && index + remaining > 0) {
-+ remaining += index;
-+ index = 0;
-+ }
-+ }
-+
-+ if (index >= len || index < 0)
-+ remaining = 0;
-+ else if (remaining < 0)
-+ remaining += len - index;
-+ else if (index + remaining > size)
-+ remaining = size - index;
-+
-+ for (i = 0; i < remaining; i++) {
-+ d[i] = dtrace_load8(s + index + i);
-+ if (d[i] == '\0')
-+ break;
-+ }
-+
-+ d[i] = '\0';
-+
-+ mstate->dtms_scratch_ptr += size;
-+ regs[rd] = (uintptr_t)d;
-+ break;
-+ }
-+
-+ case DIF_SUBR_GETMAJOR:
-+ regs[rd] = MAJOR(tupregs[0].dttk_value);
-+ break;
-+
-+ case DIF_SUBR_GETMINOR:
-+ regs[rd] = MINOR(tupregs[0].dttk_value);
-+ break;
-+
-+#if 0 /* FIXME */
-+ case DIF_SUBR_DDI_PATHNAME: {
-+ /*
-+ * This one is a galactic mess. We are going to roughly
-+ * emulate ddi_pathname(), but it's made more complicated
-+ * by the fact that we (a) want to include the minor name and
-+ * (b) must proceed iteratively instead of recursively.
-+ */
-+ uintptr_t dest = mstate->dtms_scratch_ptr;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ char *start = (char *)dest, *end = start + size - 1;
-+ uintptr_t daddr = tupregs[0].dttk_value;
-+ int64_t minor = (int64_t)tupregs[1].dttk_value;
-+ char *s;
-+ int i, len, depth = 0;
-+
-+ /*
-+ * Due to all the pointer jumping we do and context we must
-+ * rely upon, we just mandate that the user must have kernel
-+ * read privileges to use this routine.
-+ */
-+ if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) == 0) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = daddr;
-+ regs[rd] = 0;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ *end = '\0';
-+
-+ /*
-+ * We want to have a name for the minor. In order to do this,
-+ * we need to walk the minor list from the devinfo. We want
-+ * to be sure that we don't infinitely walk a circular list,
-+ * so we check for circularity by sending a scout pointer
-+ * ahead two elements for every element that we iterate over;
-+ * if the list is circular, these will ultimately point to the
-+ * same element. You may recognize this little trick as the
-+ * answer to a stupid interview question -- one that always
-+ * seems to be asked by those who had to have it laboriously
-+ * explained to them, and who can't even concisely describe
-+ * the conditions under which one would be forced to resort to
-+ * this technique. Needless to say, those conditions are
-+ * found here -- and probably only here. Is this the only use
-+ * of this infamous trick in shipping, production code? If it
-+ * isn't, it probably should be...
-+ */
-+ if (minor != -1) {
-+ uintptr_t maddr = dtrace_loadptr(daddr +
-+ offsetof(struct dev_info, devi_minor));
-+
-+ uintptr_t next = offsetof(struct ddi_minor_data, next);
-+ uintptr_t name = offsetof(struct ddi_minor_data,
-+ d_minor) + offsetof(struct ddi_minor, name);
-+ uintptr_t dev = offsetof(struct ddi_minor_data,
-+ d_minor) + offsetof(struct ddi_minor, dev);
-+ uintptr_t scout;
-+
-+ if (maddr != NULL)
-+ scout = dtrace_loadptr(maddr + next);
-+
-+ while (maddr != NULL && !(*flags & CPU_DTRACE_FAULT)) {
-+ uint64_t m;
-+#ifdef _LP64
-+ m = dtrace_load64(maddr + dev) & MAXMIN64;
-+#else
-+ m = dtrace_load32(maddr + dev) & MAXMIN;
-+#endif
-+ if (m != minor) {
-+ maddr = dtrace_loadptr(maddr + next);
-+
-+ if (scout == NULL)
-+ continue;
-+
-+ scout = dtrace_loadptr(scout + next);
-+
-+ if (scout == NULL)
-+ continue;
-+
-+ scout = dtrace_loadptr(scout + next);
-+
-+ if (scout == NULL)
-+ continue;
-+
-+ if (scout == maddr) {
-+ *flags |= CPU_DTRACE_ILLOP;
-+ break;
-+ }
-+
-+ continue;
-+ }
-+
-+ /*
-+ * We have the minor data. Now we need to
-+ * copy the minor's name into the end of the
-+ * pathname.
-+ */
-+ s = (char *)dtrace_loadptr(maddr + name);
-+ len = dtrace_strlen(s, size);
-+
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+ if (len != 0) {
-+ end -= len + 1;
-+ if (end < start)
-+ break;
-+
-+ *end = ':';
-+ }
-+
-+ for (i = 1; i <= len; i++)
-+ end[i] = dtrace_load8((uintptr_t)s++);
-+ break;
-+ }
-+ }
-+
-+ while (daddr != NULL && !(*flags & CPU_DTRACE_FAULT)) {
-+ ddi_node_state_t devi_state;
-+
-+ devi_state = dtrace_load32(daddr +
-+ offsetof(struct dev_info, devi_node_state));
-+
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+ if (devi_state >= DS_INITIALIZED) {
-+ s = (char *)dtrace_loadptr(daddr +
-+ offsetof(struct dev_info, devi_addr));
-+ len = dtrace_strlen(s, size);
-+
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+ if (len != 0) {
-+ end -= len + 1;
-+ if (end < start)
-+ break;
-+
-+ *end = '@';
-+ }
-+
-+ for (i = 1; i <= len; i++)
-+ end[i] = dtrace_load8((uintptr_t)s++);
-+ }
-+
-+ /*
-+ * Now for the node name...
-+ */
-+ s = (char *)dtrace_loadptr(daddr +
-+ offsetof(struct dev_info, devi_node_name));
-+
-+ daddr = dtrace_loadptr(daddr +
-+ offsetof(struct dev_info, devi_parent));
-+
-+ /*
-+ * If our parent is NULL (that is, if we're the root
-+ * node), we're going to use the special path
-+ * "devices".
-+ */
-+ if (daddr == NULL)
-+ s = "devices";
-+
-+ len = dtrace_strlen(s, size);
-+ if (*flags & CPU_DTRACE_FAULT)
-+ break;
-+
-+ end -= len + 1;
-+ if (end < start)
-+ break;
-+
-+ for (i = 1; i <= len; i++)
-+ end[i] = dtrace_load8((uintptr_t)s++);
-+ *end = '/';
-+
-+ if (depth++ > dtrace_devdepth_max) {
-+ *flags |= CPU_DTRACE_ILLOP;
-+ break;
-+ }
-+ }
-+
-+ if (end < start)
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+
-+ if (daddr == NULL) {
-+ regs[rd] = (uintptr_t)end;
-+ mstate->dtms_scratch_ptr += size;
-+ }
-+
-+ break;
-+ }
-+#endif
-+
-+ case DIF_SUBR_STRJOIN: {
-+ char *d = (char *)mstate->dtms_scratch_ptr;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ uintptr_t s1 = tupregs[0].dttk_value;
-+ uintptr_t s2 = tupregs[1].dttk_value;
-+ int i = 0;
-+
-+ if (!dtrace_strcanload(s1, size, mstate, vstate) ||
-+ !dtrace_strcanload(s2, size, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ for (;;) {
-+ if (i >= size) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ d[i] = dtrace_load8(s1++);
-+ if ((d[i++]) == '\0') {
-+ i--;
-+ break;
-+ }
-+ }
-+
-+ for (;;) {
-+ if (i >= size) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ d[i] = dtrace_load8(s2++);
-+ if ((d[i++]) == '\0')
-+ break;
-+ }
-+
-+ if (i < size) {
-+ mstate->dtms_scratch_ptr += i;
-+ regs[rd] = (uintptr_t)d;
-+ }
-+
-+ break;
-+ }
-+
-+ case DIF_SUBR_LLTOSTR: {
-+ int64_t i = (int64_t)tupregs[0].dttk_value;
-+ int64_t val = i < 0 ? i * -1 : i;
-+ uint64_t size = 22; /* room for 2^64 in dec */
-+ char *end = (char *)mstate->dtms_scratch_ptr + size
-+ - 1;
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * GCC on Linux introduces calls to functions that are not
-+ * linked into the kernel image, so we need to use the do_div()
-+ * function instead. It modifies the first argument in place
-+ * (replaces it with the quotient), and returns the remainder.
-+ *
-+ * Was:
-+ * for (*end-- = '\0'; val; val /= 10)
-+ * *end-- = '0' + (val % 10);
-+ */
-+ for (*end-- = '\0'; val; )
-+ *end-- = '0' + do_div(val, 10);
-+
-+ if (i == 0)
-+ *end-- = '0';
-+
-+ if (i < 0)
-+ *end-- = '-';
-+
-+ regs[rd] = (uintptr_t)end + 1;
-+ mstate->dtms_scratch_ptr += size;
-+ break;
-+ }
-+
-+ case DIF_SUBR_HTONS:
-+ case DIF_SUBR_NTOHS:
-+#ifdef __BIG_ENDIAN
-+ regs[rd] = (uint16_t)tupregs[0].dttk_value;
-+#else
-+ regs[rd] = DT_BSWAP_16((uint16_t)tupregs[0].dttk_value);
-+#endif
-+ break;
-+
-+
-+ case DIF_SUBR_HTONL:
-+ case DIF_SUBR_NTOHL:
-+#ifdef __BIG_ENDIAN
-+ regs[rd] = (uint32_t)tupregs[0].dttk_value;
-+#else
-+ regs[rd] = DT_BSWAP_32((uint32_t)tupregs[0].dttk_value);
-+#endif
-+ break;
-+
-+
-+ case DIF_SUBR_HTONLL:
-+ case DIF_SUBR_NTOHLL:
-+#ifdef __BIG_ENDIAN
-+ regs[rd] = (uint64_t)tupregs[0].dttk_value;
-+#else
-+ regs[rd] = DT_BSWAP_64((uint64_t)tupregs[0].dttk_value);
-+#endif
-+ break;
-+
-+
-+ case DIF_SUBR_DIRNAME:
-+ case DIF_SUBR_BASENAME: {
-+ char *dest = (char *)mstate->dtms_scratch_ptr;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ uintptr_t src = tupregs[0].dttk_value;
-+ int i, j, len = dtrace_strlen((char *)src, size);
-+ int lastbase = -1, firstbase = -1, lastdir = -1;
-+ int start, end;
-+
-+ if (!dtrace_canload(src, len + 1, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * The basename and dirname for a zero-length string is
-+ * defined to be "."
-+ */
-+ if (len == 0) {
-+ len = 1;
-+ src = (uintptr_t)".";
-+ }
-+
-+ /*
-+ * Start from the back of the string, moving back toward the
-+ * front until we see a character that isn't a slash. That
-+ * character is the last character in the basename.
-+ */
-+ for (i = len - 1; i >= 0; i--) {
-+ if (dtrace_load8(src + i) != '/')
-+ break;
-+ }
-+
-+ if (i >= 0)
-+ lastbase = i;
-+
-+ /*
-+ * Starting from the last character in the basename, move
-+ * towards the front until we find a slash. The character
-+ * that we processed immediately before that is the first
-+ * character in the basename.
-+ */
-+ for (; i >= 0; i--) {
-+ if (dtrace_load8(src + i) == '/')
-+ break;
-+ }
-+
-+ if (i >= 0)
-+ firstbase = i + 1;
-+
-+ /*
-+ * Now keep going until we find a non-slash character. That
-+ * character is the last character in the dirname.
-+ */
-+ for (; i >= 0; i--) {
-+ if (dtrace_load8(src + i) != '/')
-+ break;
-+ }
-+
-+ if (i >= 0)
-+ lastdir = i;
-+
-+ ASSERT(!(lastbase == -1 && firstbase != -1));
-+ ASSERT(!(firstbase == -1 && lastdir != -1));
-+
-+ if (lastbase == -1) {
-+ /*
-+ * We didn't find a non-slash character. We know that
-+ * the length is non-zero, so the whole string must be
-+ * slashes. In either the dirname or the basename
-+ * case, we return '/'.
-+ */
-+ ASSERT(firstbase == -1);
-+ firstbase = lastbase = lastdir = 0;
-+ }
-+
-+ if (firstbase == -1) {
-+ /*
-+ * The entire string consists only of a basename
-+ * component. If we're looking for dirname, we need
-+ * to change our string to be just "."; if we're
-+ * looking for a basename, we'll just set the first
-+ * character of the basename to be 0.
-+ */
-+ if (subr == DIF_SUBR_DIRNAME) {
-+ ASSERT(lastdir == -1);
-+ src = (uintptr_t)".";
-+ lastdir = 0;
-+ } else {
-+ firstbase = 0;
-+ }
-+ }
-+
-+ if (subr == DIF_SUBR_DIRNAME) {
-+ if (lastdir == -1) {
-+ /*
-+ * We know that we have a slash in the name --
-+ * or lastdir would be set to 0, above. And
-+ * because lastdir is -1, we know that this
-+ * slash must be the first character. (That
-+ * is, the full string must be of the form
-+ * "/basename".) In this case, the last
-+ * character of the directory name is 0.
-+ */
-+ lastdir = 0;
-+ }
-+
-+ start = 0;
-+ end = lastdir;
-+ } else {
-+ ASSERT(subr == DIF_SUBR_BASENAME);
-+ ASSERT(firstbase != -1 && lastbase != -1);
-+ start = firstbase;
-+ end = lastbase;
-+ }
-+
-+ for (i = start, j = 0; i <= end && j < size - 1; i++, j++)
-+ dest[j] = dtrace_load8(src + i);
-+
-+ dest[j] = '\0';
-+ regs[rd] = (uintptr_t)dest;
-+ mstate->dtms_scratch_ptr += size;
-+ break;
-+ }
-+
-+ case DIF_SUBR_CLEANPATH: {
-+ char *dest = (char *)mstate->dtms_scratch_ptr, c;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ uintptr_t src = tupregs[0].dttk_value;
-+ int i = 0, j = 0;
-+
-+ if (!dtrace_strcanload(src, size, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ /*
-+ * Move forward, loading each character.
-+ */
-+ do {
-+ c = dtrace_load8(src + i++);
-+next:
-+ if (j + 5 >= size) /* 5 = strlen("/..c\0") */
-+ break;
-+
-+ if (c != '/') {
-+ dest[j++] = c;
-+ continue;
-+ }
-+
-+ c = dtrace_load8(src + i++);
-+
-+ if (c == '/') {
-+ /*
-+ * We have two slashes -- we can just advance
-+ * to the next character.
-+ */
-+ goto next;
-+ }
-+
-+ if (c != '.') {
-+ /*
-+ * This is not "." and it's not ".." -- we can
-+ * just store the "/" and this character and
-+ * drive on.
-+ */
-+ dest[j++] = '/';
-+ dest[j++] = c;
-+ continue;
-+ }
-+
-+ c = dtrace_load8(src + i++);
-+
-+ if (c == '/') {
-+ /*
-+ * This is a "/./" component. We're not going
-+ * to store anything in the destination buffer;
-+ * we're just going to go to the next component.
-+ */
-+ goto next;
-+ }
-+
-+ if (c != '.') {
-+ /*
-+ * This is not ".." -- we can just store the
-+ * "/." and this character and continue
-+ * processing.
-+ */
-+ dest[j++] = '/';
-+ dest[j++] = '.';
-+ dest[j++] = c;
-+ continue;
-+ }
-+
-+ c = dtrace_load8(src + i++);
-+
-+ if (c != '/' && c != '\0') {
-+ /*
-+ * This is not ".." -- it's "..[mumble]".
-+ * We'll store the "/.." and this character
-+ * and continue processing.
-+ */
-+ dest[j++] = '/';
-+ dest[j++] = '.';
-+ dest[j++] = '.';
-+ dest[j++] = c;
-+ continue;
-+ }
-+
-+ /*
-+ * This is "/../" or "/..\0". We need to back up
-+ * our destination pointer until we find a "/".
-+ */
-+ i--;
-+ while (j != 0 && dest[--j] != '/')
-+ continue;
-+
-+ if (c == '\0')
-+ dest[++j] = '/';
-+ } while (c != '\0');
-+
-+ dest[j] = '\0';
-+ regs[rd] = (uintptr_t)dest;
-+ mstate->dtms_scratch_ptr += size;
-+ break;
-+ }
-+
-+ case DIF_SUBR_LINK_NTOP: {
-+ struct dtrace_hwtype_alen {
-+ int dhwa_hwtype;
-+ size_t dhwa_hwalen;
-+ } hwinfo[] = {
-+ { ARPHRD_ETHER, ETH_ALEN },
-+ { ARPHRD_INFINIBAND, INFINIBAND_ALEN },
-+ { -1, 0 }
-+ };
-+/*
-+ * Captures the maximum hardware address length among all the supported
-+ * hardware types. Please update this macro when adding a new hardware type.
-+ */
-+#define DTRACE_MAX_HWTYPE_ALEN (ETH_ALEN > INFINIBAND_ALEN ? \
-+ ETH_ALEN : INFINIBAND_ALEN)
-+ uintptr_t src = tupregs[1].dttk_value;
-+ int hwtype = tupregs[0].dttk_value;
-+ uint8_t hwaddr[DTRACE_MAX_HWTYPE_ALEN];
-+ char *base;
-+ size_t size, len;
-+ int i;
-+
-+ for (i = 0; hwinfo[i].dhwa_hwtype != -1; i++) {
-+ if (hwtype == hwinfo[i].dhwa_hwtype)
-+ break;
-+ }
-+ if (hwinfo[i].dhwa_hwtype == -1) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ regs[rd] = 0;
-+ break;
-+ }
-+ len = hwinfo[i].dhwa_hwalen;
-+
-+ /*
-+ * Safely load the hardware address.
-+ */
-+ if (!dtrace_canload(src, len, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+ dtrace_bcopy((void *)src, hwaddr, len);
-+
-+ /*
-+ * Check if a hardware address string will fit in scratch.
-+ * For every byte we need 3 characters (including ':').
-+ */
-+ size = len * 3;
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+ base = (char *)mstate->dtms_scratch_ptr;
-+
-+ /*
-+ * Build the Hardware address string by working through the
-+ * address from the beginning. Given a hardware address
-+ * {0xa0, 0xaa, 0xff, 0xc, 0, 1, 2} of length 6, it will build
-+ * a0:aa:ff:0c:00:01:02.
-+ */
-+ for (i = 0; i < len; i++) {
-+ if (hwaddr[i] < 16) {
-+ *base++ = '0';
-+ *base++ = hexdigits[hwaddr[i]];
-+ } else {
-+ *base++ = hexdigits[hwaddr[i] / 16];
-+ *base++ = hexdigits[hwaddr[i] % 16];
-+ }
-+
-+ if (i < len - 1)
-+ *base++ = ':';
-+ }
-+ *base++ = '\0';
-+ regs[rd] = mstate->dtms_scratch_ptr;
-+ mstate->dtms_scratch_ptr += size;
-+#undef DTRACE_MAX_HWTYPE_ALEN
-+ break;
-+ }
-+
-+ case DIF_SUBR_INET_NTOA:
-+ case DIF_SUBR_INET_NTOA6:
-+ case DIF_SUBR_INET_NTOP: {
-+ uintptr_t src;
-+ size_t size;
-+ int af, argi, i;
-+ char *base, *end;
-+
-+ if (subr == DIF_SUBR_INET_NTOP) {
-+ af = (int)tupregs[0].dttk_value;
-+ argi = 1;
-+ } else {
-+ af = subr == DIF_SUBR_INET_NTOA ? AF_INET : AF_INET6;
-+ argi = 0;
-+ }
-+
-+ src = tupregs[argi].dttk_value;
-+ if (af == AF_INET) {
-+ ipaddr_t ip4;
-+ ipaddr_t_p ptr4;
-+ uint8_t *ptr8, val;
-+
-+ /*
-+ * Safely load the IPv4 address.
-+ */
-+ if (!dtrace_canload(src, 4, mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+ ip4 = dtrace_load32(src);
-+
-+ /*
-+ * Check an IPv4 string will fit in scratch.
-+ */
-+ size = INET_ADDRSTRLEN;
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+ base = (char *)mstate->dtms_scratch_ptr;
-+ end = (char *)mstate->dtms_scratch_ptr + size - 1;
-+
-+ /*
-+ * Stringify as a dotted decimal quad.
-+ */
-+ *end-- = '\0';
-+ ptr4 = &ip4;
-+ ptr8 = (uint8_t *)ptr4;
-+ for (i = 3; i >= 0; i--) {
-+ val = ptr8[i];
-+
-+ if (val == 0) {
-+ *end-- = '0';
-+ } else {
-+ for (; val; val /= 10)
-+ *end-- = '0' + (val % 10);
-+ }
-+
-+ if (i > 0)
-+ *end-- = '.';
-+ }
-+ ASSERT(end + 1 >= base);
-+#if IS_ENABLED(CONFIG_IPV6)
-+ } else if (af == AF_INET6) {
-+ in6_addr_t ip6;
-+ int firstzero, tryzero, numzero, v6end;
-+ uint16_t val;
-+
-+ /*
-+ * Stringify using RFC 1884 convention 2 - 16 bit
-+ * hexadecimal values with a zero-run compression.
-+ * Lower case hexadecimal digits are used.
-+ * eg, fe80::214:4fff:fe0b:76c8.
-+ * The IPv4 embedded form is returned for inet_ntop,
-+ * just the IPv4 string is returned for inet_ntoa6.
-+ */
-+
-+ /*
-+ * Safely load the IPv6 address.
-+ */
-+ if (!dtrace_canload(src, sizeof(in6_addr_t), mstate,
-+ vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+ dtrace_bcopy((void *)src, (void *)(uintptr_t)&ip6,
-+ sizeof(in6_addr_t));
-+
-+ /*
-+ * Check an IPv6 string will fit in scratch.
-+ */
-+ size = INET6_ADDRSTRLEN;
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+ base = (char *)mstate->dtms_scratch_ptr;
-+ end = (char *)mstate->dtms_scratch_ptr + size - 1;
-+ *end-- = '\0';
-+
-+ /*
-+ * Find the longest run of 16 bit zero values
-+ * for the single allowed zero compression - "::".
-+ */
-+ firstzero = -1;
-+ tryzero = -1;
-+ numzero = 1;
-+ for (i = 0; i < sizeof(in6_addr_t); i++) {
-+ if (ip6.s6_addr[i] == 0 &&
-+ tryzero == -1 && i % 2 == 0) {
-+ tryzero = i;
-+ continue;
-+ }
-+
-+ if (tryzero != -1 &&
-+ (ip6.s6_addr[i] != 0 ||
-+ i == sizeof(in6_addr_t) - 1)) {
-+
-+ if (i - tryzero <= numzero) {
-+ tryzero = -1;
-+ continue;
-+ }
-+
-+ firstzero = tryzero;
-+ numzero = i - i % 2 - tryzero;
-+ tryzero = -1;
-+
-+ if (ip6.s6_addr[i] == 0 &&
-+ i == sizeof(in6_addr_t) - 1)
-+ numzero += 2;
-+ }
-+ }
-+ ASSERT(firstzero + numzero <= sizeof(in6_addr_t));
-+
-+ /*
-+ * Check for an IPv4 embedded address.
-+ */
-+ v6end = sizeof(in6_addr_t) - 2;
-+ if (ipv6_addr_type(&ip6) &
-+ (IPV6_ADDR_COMPATv4 | IPV6_ADDR_MAPPED)) {
-+ for (i = sizeof(in6_addr_t) - 1;
-+ i >= DTRACE_V4MAPPED_OFFSET; i--) {
-+ ASSERT(end >= base);
-+
-+ val = ip6.s6_addr[i];
-+
-+ if (val == 0) {
-+ *end-- = '0';
-+ } else {
-+ for (; val; val /= 10)
-+ *end-- = '0' + val % 10;
-+ }
-+
-+ if (i > DTRACE_V4MAPPED_OFFSET)
-+ *end-- = '.';
-+ }
-+
-+ if (subr == DIF_SUBR_INET_NTOA6)
-+ goto inetout;
-+
-+ /*
-+ * Set v6end to skip the IPv4 address that
-+ * we have already stringified.
-+ */
-+ v6end = 10;
-+ }
-+
-+ /*
-+ * Build the IPv6 string by working through the
-+ * address in reverse.
-+ */
-+ for (i = v6end; i >= 0; i -= 2) {
-+ ASSERT(end >= base);
-+
-+ if (i == firstzero + numzero - 2) {
-+ *end-- = ':';
-+ *end-- = ':';
-+ i -= numzero - 2;
-+ continue;
-+ }
-+
-+ if (i < 14 && i != firstzero - 2)
-+ *end-- = ':';
-+
-+ val = (ip6.s6_addr[i] << 8) +
-+ ip6.s6_addr[i + 1];
-+
-+ if (val == 0) {
-+ *end-- = '0';
-+ } else {
-+ for (; val; val /= 16)
-+ *end-- = hexdigits[val % 16];
-+ }
-+ }
-+ ASSERT(end + 1 >= base);
-+#endif
-+ } else {
-+ /*
-+ * The user didn't use AH_INET or AH_INET6.
-+ */
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+#if IS_ENABLED(CONFIG_IPV6)
-+inetout:
-+#endif
-+ regs[rd] = (uintptr_t)end + 1;
-+ mstate->dtms_scratch_ptr += size;
-+ break;
-+ }
-+
-+ case DIF_SUBR_D_PATH: {
-+ struct path *path = (struct path *)tupregs[0].dttk_value;
-+ char *dest = (char *)mstate->dtms_scratch_ptr;
-+ char *ptr;
-+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
-+ unsigned int fd;
-+ struct files_struct
-+ *files = current->files;
-+ struct fdtable *fdt;
-+
-+ if (!dtrace_canload((uintptr_t)path, sizeof(struct path),
-+ mstate, vstate)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (spin_is_locked(&files->file_lock) ||
-+ !spin_trylock(&files->file_lock)) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ fdt = files->fdt;
-+
-+ /*
-+ * We (currently) limit the d_path() subroutine to paths that
-+ * relate to open files in the current task.
-+ */
-+ for (fd = 0; fd < fdt->max_fds; fd++) {
-+ if (fdt->fd[fd] && &fdt->fd[fd]->f_path == path)
-+ break;
-+ }
-+
-+ spin_unlock(&files->file_lock);
-+
-+ if (fd >= fdt->max_fds) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = (uintptr_t)path;
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ ptr = d_path(path, dest, size);
-+ if (ptr < 0) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ regs[rd] = (uintptr_t)ptr;
-+ mstate->dtms_scratch_ptr += size;
-+ break;
-+ }
-+
-+ }
-+}
-+
-+/*
-+ * Emulate the execution of DTrace IR instructions specified by the given DIF
-+ * object. This function is deliberately void fo assertions as all of the
-+ * necessary checks are handled by a call to dtrace_difo_validate().
-+ */
-+uint64_t dtrace_dif_emulate(struct dtrace_difo *difo,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate,
-+ struct dtrace_state *state)
-+{
-+ const dif_instr_t *text = difo->dtdo_buf;
-+ const uint_t textlen = difo->dtdo_len;
-+ const char *strtab = difo->dtdo_strtab;
-+ const uint64_t *inttab = difo->dtdo_inttab;
-+
-+ uint64_t rval = 0;
-+ struct dtrace_statvar *svar;
-+ struct dtrace_dstate *dstate = &vstate->dtvs_dynvars;
-+ struct dtrace_difv *v;
-+ volatile uint16_t *flags = &this_cpu_core->cpuc_dtrace_flags;
-+ volatile uintptr_t *illval = &this_cpu_core->cpuc_dtrace_illval;
-+
-+ struct dtrace_key tupregs[DIF_DTR_NREGS + 2];
-+ /* +2 for thread and id */
-+ uint64_t regs[DIF_DIR_NREGS];
-+ uint64_t *tmp;
-+
-+ uint8_t cc_n = 0, cc_z = 0, cc_v = 0, cc_c = 0;
-+ int64_t cc_r;
-+ uint_t pc = 0, id, opc = 0;
-+ uint8_t ttop = 0;
-+ dif_instr_t instr;
-+ uint_t r1, r2, rd;
-+
-+ dt_dbg_dif(" DIF %p emulation (text %p, %d instructions)...\n",
-+ difo, text, textlen);
-+
-+ /*
-+ * We stash the current DIF object into the machine state: we need it
-+ * for subsequent access checking.
-+ */
-+ mstate->dtms_difo = difo;
-+
-+ regs[DIF_REG_R0] = 0; /* %r0 is fixed at zero */
-+
-+ while (pc < textlen && !(*flags & CPU_DTRACE_FAULT)) {
-+ opc = pc;
-+
-+ instr = text[pc++];
-+ r1 = DIF_INSTR_R1(instr);
-+ r2 = DIF_INSTR_R2(instr);
-+ rd = DIF_INSTR_RD(instr);
-+
-+ dt_dbg_dif(" Executing opcode %02x (%02x, %02x, %02x)\n",
-+ DIF_INSTR_OP(instr), r1, r2, rd);
-+
-+ switch (DIF_INSTR_OP(instr)) {
-+ case DIF_OP_OR:
-+ regs[rd] = regs[r1] | regs[r2];
-+ break;
-+ case DIF_OP_XOR:
-+ regs[rd] = regs[r1] ^ regs[r2];
-+ break;
-+ case DIF_OP_AND:
-+ regs[rd] = regs[r1] & regs[r2];
-+ break;
-+ case DIF_OP_SLL:
-+ regs[rd] = regs[r1] << regs[r2];
-+ break;
-+ case DIF_OP_SRL:
-+ regs[rd] = regs[r1] >> regs[r2];
-+ break;
-+ case DIF_OP_SUB:
-+ regs[rd] = regs[r1] - regs[r2];
-+ break;
-+ case DIF_OP_ADD:
-+ regs[rd] = regs[r1] + regs[r2];
-+ break;
-+ case DIF_OP_MUL:
-+ regs[rd] = regs[r1] * regs[r2];
-+ break;
-+ case DIF_OP_SDIV:
-+ if (regs[r2] == 0) {
-+ regs[rd] = 0;
-+ *flags |= CPU_DTRACE_DIVZERO;
-+ } else {
-+ int neg = 0;
-+
-+ /*
-+ * We cannot simply do a 64-bit division, since
-+ * gcc translates it into a call to a function
-+ * that is not linked into the kernel.
-+ *
-+ * regs[rd] = (int64_t)regs[r1] /
-+ * (int64_t)regs[r2];
-+ */
-+ if ((int64_t)regs[r1] < 0) {
-+ neg = !neg;
-+ regs[r1] = -(int64_t)regs[r1];
-+ }
-+ if ((int64_t)regs[r2] < 0) {
-+ neg = !neg;
-+ regs[r2] = -(int64_t)regs[r2];
-+ }
-+ regs[rd] = regs[r1];
-+ do_div(regs[rd], regs[r2]);
-+
-+ if (neg)
-+ regs[rd] = -(int64_t)regs[rd];
-+ }
-+ break;
-+
-+ case DIF_OP_UDIV:
-+ if (regs[r2] == 0) {
-+ regs[rd] = 0;
-+ *flags |= CPU_DTRACE_DIVZERO;
-+ } else {
-+ /*
-+ * We cannot simply do a 64-bit division, since
-+ * gcc translates it into a call to a function
-+ * that is not linked into the kernel.
-+ *
-+ * regs[rd] = regs[r1] / regs[r2];
-+ */
-+ regs[rd] = regs[r1];
-+ do_div(regs[rd], regs[r2]);
-+ }
-+ break;
-+
-+ case DIF_OP_SREM:
-+ if (regs[r2] == 0) {
-+ regs[rd] = 0;
-+ *flags |= CPU_DTRACE_DIVZERO;
-+ } else {
-+ int neg = 0;
-+
-+ /*
-+ * We cannot simply do a 64-bit division, since
-+ * gcc translates it into a call to a function
-+ * that is not linked into the kernel.
-+ *
-+ * regs[rd] = (int64_t)regs[r1] %
-+ * (int64_t)regs[r2];
-+ */
-+ if ((int64_t)regs[r1] < 0) {
-+ neg = !neg;
-+ regs[r1] = -(int64_t)regs[r1];
-+ }
-+ if ((int64_t)regs[r2] < 0) {
-+ neg = !neg;
-+ regs[r2] = -(int64_t)regs[r2];
-+ }
-+ regs[rd] = regs[r1];
-+ regs[rd] = do_div(regs[rd], regs[r2]);
-+
-+ if (neg)
-+ regs[rd] = -(int64_t)regs[rd];
-+ }
-+ break;
-+
-+ case DIF_OP_UREM:
-+ if (regs[r2] == 0) {
-+ regs[rd] = 0;
-+ *flags |= CPU_DTRACE_DIVZERO;
-+ } else {
-+ /*
-+ * We cannot simply do a 64-bit division, since
-+ * gcc translates it into a call to a function
-+ * that is not linked into the kernel.
-+ *
-+ * regs[rd] = regs[r1] % regs[r2];
-+ */
-+ regs[rd] = regs[r1];
-+ regs[rd] = do_div(regs[rd], regs[r2]);
-+ }
-+ break;
-+
-+ case DIF_OP_NOT:
-+ regs[rd] = ~regs[r1];
-+ break;
-+ case DIF_OP_MOV:
-+ regs[rd] = regs[r1];
-+ break;
-+ case DIF_OP_CMP:
-+ cc_r = regs[r1] - regs[r2];
-+ cc_n = cc_r < 0;
-+ cc_z = cc_r == 0;
-+ cc_v = 0;
-+ cc_c = regs[r1] < regs[r2];
-+ break;
-+ case DIF_OP_TST:
-+ cc_n = cc_v = cc_c = 0;
-+ cc_z = regs[r1] == 0;
-+ break;
-+ case DIF_OP_BA:
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BE:
-+ if (cc_z)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BNE:
-+ if (cc_z == 0)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BG:
-+ if ((cc_z | (cc_n ^ cc_v)) == 0)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BGU:
-+ if ((cc_c | cc_z) == 0)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BGE:
-+ if ((cc_n ^ cc_v) == 0)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BGEU:
-+ if (cc_c == 0)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BL:
-+ if (cc_n ^ cc_v)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BLU:
-+ if (cc_c)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BLE:
-+ if (cc_z | (cc_n ^ cc_v))
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_BLEU:
-+ if (cc_c | cc_z)
-+ pc = DIF_INSTR_LABEL(instr);
-+ break;
-+ case DIF_OP_RLDSB:
-+#ifdef FIXME_OPENSOLARIS_BUG
-+ if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
-+#else
-+ if (!dtrace_canload(regs[r1], 1, mstate, vstate)) {
-+#endif
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDSB:
-+ regs[rd] = (int8_t)dtrace_load8(regs[r1]);
-+ break;
-+ case DIF_OP_RLDSH:
-+ if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDSH:
-+ regs[rd] = (int16_t)dtrace_load16(regs[r1]);
-+ break;
-+ case DIF_OP_RLDSW:
-+ if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDSW:
-+ regs[rd] = (int32_t)dtrace_load32(regs[r1]);
-+ break;
-+ case DIF_OP_RLDUB:
-+ if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDUB:
-+ regs[rd] = dtrace_load8(regs[r1]);
-+ break;
-+ case DIF_OP_RLDUH:
-+ if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDUH:
-+ regs[rd] = dtrace_load16(regs[r1]);
-+ break;
-+ case DIF_OP_RLDUW:
-+ if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDUW:
-+ regs[rd] = dtrace_load32(regs[r1]);
-+ break;
-+ case DIF_OP_RLDX:
-+ if (!dtrace_canstore(regs[r1], 8, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_KPRIV;
-+ *illval = regs[r1];
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+ case DIF_OP_LDX:
-+ regs[rd] = dtrace_load64(regs[r1]);
-+ break;
-+ case DIF_OP_ULDSB:
-+ regs[rd] = (int8_t)dtrace_fuword8(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDSH:
-+ regs[rd] = (int16_t)dtrace_fuword16(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDSW:
-+ regs[rd] = (int32_t)dtrace_fuword32(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDUB:
-+ regs[rd] = dtrace_fuword8((void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDUH:
-+ regs[rd] = dtrace_fuword16(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDUW:
-+ regs[rd] = dtrace_fuword32(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_ULDX:
-+ regs[rd] = dtrace_fuword64(
-+ (void *)(uintptr_t)regs[r1]);
-+ break;
-+ case DIF_OP_RET:
-+ rval = regs[rd];
-+ pc = textlen;
-+ break;
-+ case DIF_OP_NOP:
-+ break;
-+ case DIF_OP_SETX:
-+ regs[rd] = inttab[DIF_INSTR_INTEGER(instr)];
-+ break;
-+ case DIF_OP_SETS:
-+ regs[rd] = (uint64_t)(uintptr_t)
-+ (strtab + DIF_INSTR_STRING(instr));
-+ break;
-+ case DIF_OP_SCMP: {
-+ size_t sz = state->dts_options[
-+ DTRACEOPT_STRSIZE];
-+ uintptr_t s1 = regs[r1];
-+ uintptr_t s2 = regs[r2];
-+
-+ if (s1 != (uintptr_t)NULL &&
-+ !dtrace_strcanload(s1, sz, mstate, vstate))
-+ break;
-+ if (s2 != (uintptr_t)NULL &&
-+ !dtrace_strcanload(s2, sz, mstate, vstate))
-+ break;
-+
-+ cc_r = dtrace_strncmp((char *)s1, (char *)s2, sz);
-+
-+ cc_n = cc_r < 0;
-+ cc_z = cc_r == 0;
-+ cc_v = cc_c = 0;
-+ break;
-+ }
-+ case DIF_OP_LDGA:
-+ regs[rd] = dtrace_dif_variable(mstate, state, r1,
-+ regs[r2]);
-+ break;
-+ case DIF_OP_LDGS:
-+ id = DIF_INSTR_VAR(instr);
-+
-+ if (id >= DIF_VAR_OTHER_UBASE) {
-+ uintptr_t a;
-+
-+ id -= DIF_VAR_OTHER_UBASE;
-+ svar = vstate->dtvs_globals[id];
-+ ASSERT(svar != NULL);
-+ v = &svar->dtsv_var;
-+
-+ if (!(v->dtdv_type.dtdt_flags & DIF_TF_BYREF)) {
-+ regs[rd] = svar->dtsv_data;
-+ break;
-+ }
-+
-+ a = (uintptr_t)svar->dtsv_data;
-+
-+ /*
-+ * If the 0th byte is set to UINT8_MAX then
-+ * this is to be treated as a reference to a
-+ * NULL variable.
-+ */
-+ if (*(uint8_t *)a == UINT8_MAX)
-+ regs[rd] = 0;
-+ else
-+ regs[rd] = a + sizeof(uint64_t);
-+
-+ break;
-+ }
-+
-+ regs[rd] = dtrace_dif_variable(mstate, state, id, 0);
-+ break;
-+
-+ case DIF_OP_STGS:
-+ id = DIF_INSTR_VAR(instr);
-+
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ svar = vstate->dtvs_globals[id];
-+ ASSERT(svar != NULL);
-+ v = &svar->dtsv_var;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) {
-+ uintptr_t a = (uintptr_t)svar->dtsv_data;
-+
-+ ASSERT(a != 0);
-+ ASSERT(svar->dtsv_size != 0);
-+
-+ if (regs[rd] == 0) {
-+ *(uint8_t *)a = UINT8_MAX;
-+ break;
-+ } else {
-+ *(uint8_t *)a = 0;
-+ a += sizeof(uint64_t);
-+ }
-+
-+ if (!dtrace_vcanload(
-+ (void *)(uintptr_t)regs[rd],
-+ &v->dtdv_type, mstate, vstate))
-+ break;
-+
-+ dtrace_vcopy((void *)(uintptr_t)regs[rd],
-+ (void *)a, &v->dtdv_type);
-+ break;
-+ }
-+
-+ svar->dtsv_data = regs[rd];
-+ break;
-+
-+ case DIF_OP_LDTA:
-+ /*
-+ * There are no DTrace built-in thread-local arrays at
-+ * present. This opcode is saved for future work.
-+ */
-+ *flags |= CPU_DTRACE_ILLOP;
-+ regs[rd] = 0;
-+ break;
-+
-+ case DIF_OP_LDLS:
-+ id = DIF_INSTR_VAR(instr);
-+
-+ if (id < DIF_VAR_OTHER_UBASE) {
-+ /*
-+ * For now, this has no meaning.
-+ */
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ ASSERT(id < vstate->dtvs_nlocals);
-+ ASSERT(vstate->dtvs_locals != NULL);
-+
-+ svar = vstate->dtvs_locals[id];
-+ ASSERT(svar != NULL);
-+ v = &svar->dtsv_var;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) {
-+ uintptr_t a = (uintptr_t)svar->dtsv_data;
-+ size_t sz = v->dtdv_type.dtdt_size;
-+
-+ sz += sizeof(uint64_t);
-+ ASSERT(svar->dtsv_size == NR_CPUS * sz);
-+ a += smp_processor_id() * sz;
-+
-+ if (*(uint8_t *)a == UINT8_MAX) {
-+ /*
-+ * If the 0th byte is set to UINT8_MAX
-+ * then this is to be treated as a
-+ * reference to a NULL variable.
-+ */
-+ regs[rd] = 0;
-+ } else
-+ regs[rd] = a + sizeof(uint64_t);
-+
-+ break;
-+ }
-+
-+ ASSERT(svar->dtsv_size == NR_CPUS * sizeof(uint64_t));
-+ tmp = (uint64_t *)(uintptr_t)svar->dtsv_data;
-+ regs[rd] = tmp[smp_processor_id()];
-+ break;
-+
-+ case DIF_OP_STLS:
-+ id = DIF_INSTR_VAR(instr);
-+
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+ ASSERT(id < vstate->dtvs_nlocals);
-+
-+ ASSERT(vstate->dtvs_locals != NULL);
-+ svar = vstate->dtvs_locals[id];
-+ ASSERT(svar != NULL);
-+ v = &svar->dtsv_var;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) {
-+ uintptr_t a = (uintptr_t)svar->dtsv_data;
-+ size_t sz = v->dtdv_type.dtdt_size;
-+
-+ sz += sizeof(uint64_t);
-+ ASSERT(svar->dtsv_size == NR_CPUS * sz);
-+ a += smp_processor_id() * sz;
-+
-+ if (regs[rd] == 0) {
-+ *(uint8_t *)a = UINT8_MAX;
-+ break;
-+ } else {
-+ *(uint8_t *)a = 0;
-+ a += sizeof(uint64_t);
-+ }
-+
-+ if (!dtrace_vcanload(
-+ (void *)(uintptr_t)regs[rd],
-+ &v->dtdv_type, mstate, vstate))
-+ break;
-+
-+ dtrace_vcopy((void *)(uintptr_t)regs[rd],
-+ (void *)a, &v->dtdv_type);
-+ break;
-+ }
-+
-+ ASSERT(svar->dtsv_size == NR_CPUS * sizeof(uint64_t));
-+ tmp = (uint64_t *)(uintptr_t)svar->dtsv_data;
-+ tmp[smp_processor_id()] = regs[rd];
-+ break;
-+
-+ case DIF_OP_LDTS: {
-+ struct dtrace_dynvar *dvar;
-+ struct dtrace_key *key;
-+
-+ id = DIF_INSTR_VAR(instr);
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+ v = &vstate->dtvs_tlocals[id];
-+
-+ key = &tupregs[DIF_DTR_NREGS];
-+ key[0].dttk_value = (uint64_t)id;
-+ key[0].dttk_size = 0;
-+ DTRACE_TLS_THRKEY(key[1].dttk_value);
-+ key[1].dttk_size = 0;
-+
-+ dvar = dtrace_dynvar(dstate, 2, key, sizeof(uint64_t),
-+ DTRACE_DYNVAR_NOALLOC, mstate,
-+ vstate);
-+
-+ if (dvar == NULL) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF)
-+ regs[rd] = (uint64_t)(uintptr_t)dvar->dtdv_data;
-+ else
-+ regs[rd] = *((uint64_t *)dvar->dtdv_data);
-+
-+ break;
-+ }
-+
-+ case DIF_OP_STTS: {
-+ struct dtrace_dynvar *dvar;
-+ struct dtrace_key *key;
-+
-+ id = DIF_INSTR_VAR(instr);
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ key = &tupregs[DIF_DTR_NREGS];
-+ key[0].dttk_value = (uint64_t)id;
-+ key[0].dttk_size = 0;
-+ DTRACE_TLS_THRKEY(key[1].dttk_value);
-+ key[1].dttk_size = 0;
-+ v = &vstate->dtvs_tlocals[id];
-+
-+ dvar = dtrace_dynvar(dstate, 2, key,
-+ v->dtdv_type.dtdt_size > sizeof(uint64_t)
-+ ? v->dtdv_type.dtdt_size
-+ : sizeof(uint64_t),
-+ regs[rd]
-+ ? DTRACE_DYNVAR_ALLOC
-+ : DTRACE_DYNVAR_DEALLOC,
-+ mstate, vstate);
-+
-+ /*
-+ * Given that we're storing to thread-local data,
-+ * we need to flush our predicate cache.
-+ */
-+ if (current->dt_task != NULL)
-+ current->dt_task->dt_predcache = 0;
-+
-+ if (dvar == NULL)
-+ break;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) {
-+ if (!dtrace_vcanload(
-+ (void *)(uintptr_t)regs[rd],
-+ &v->dtdv_type, mstate, vstate))
-+ break;
-+
-+ dtrace_vcopy((void *)(uintptr_t)regs[rd],
-+ dvar->dtdv_data, &v->dtdv_type);
-+ } else
-+ *((uint64_t *)dvar->dtdv_data) = regs[rd];
-+
-+ break;
-+ }
-+
-+ case DIF_OP_SRA:
-+ regs[rd] = (int64_t)regs[r1] >> regs[r2];
-+ break;
-+
-+ case DIF_OP_CALL:
-+ dtrace_dif_subr(DIF_INSTR_SUBR(instr), rd, regs,
-+ tupregs, ttop, mstate, state);
-+ break;
-+
-+ case DIF_OP_PUSHTR:
-+ if (ttop == DIF_DTR_NREGS) {
-+ *flags |= CPU_DTRACE_TUPOFLOW;
-+ break;
-+ }
-+
-+ if (r1 == DIF_TYPE_STRING)
-+ /*
-+ * If this is a string type and the size is 0,
-+ * we'll use the system-wide default string
-+ * size. Note that we are _not_ looking at
-+ * the value of the DTRACEOPT_STRSIZE option;
-+ * had this been set, we would expect to have
-+ * a non-zero size value in the "pushtr".
-+ */
-+ tupregs[ttop].dttk_size =
-+ dtrace_strlen(
-+ (char *)(uintptr_t)regs[rd],
-+ regs[r2]
-+ ? regs[r2]
-+ : dtrace_strsize_default
-+ ) + 1;
-+ else
-+ tupregs[ttop].dttk_size = regs[r2];
-+
-+ tupregs[ttop++].dttk_value = regs[rd];
-+ break;
-+
-+ case DIF_OP_PUSHTV:
-+ if (ttop == DIF_DTR_NREGS) {
-+ *flags |= CPU_DTRACE_TUPOFLOW;
-+ break;
-+ }
-+
-+ tupregs[ttop].dttk_value = regs[rd];
-+ tupregs[ttop++].dttk_size = 0;
-+ break;
-+
-+ case DIF_OP_POPTS:
-+ if (ttop != 0)
-+ ttop--;
-+ break;
-+
-+ case DIF_OP_FLUSHTS:
-+ ttop = 0;
-+ break;
-+
-+ case DIF_OP_LDGAA:
-+ case DIF_OP_LDTAA: {
-+ struct dtrace_dynvar *dvar;
-+ struct dtrace_key *key = tupregs;
-+ uint_t nkeys = ttop;
-+
-+ id = DIF_INSTR_VAR(instr);
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ key[nkeys].dttk_value = (uint64_t)id;
-+ key[nkeys++].dttk_size = 0;
-+
-+ if (DIF_INSTR_OP(instr) == DIF_OP_LDTAA) {
-+ DTRACE_TLS_THRKEY(key[nkeys].dttk_value);
-+ key[nkeys++].dttk_size = 0;
-+ v = &vstate->dtvs_tlocals[id];
-+ } else
-+ v = &vstate->dtvs_globals[id]->dtsv_var;
-+
-+ dvar = dtrace_dynvar(dstate, nkeys, key,
-+ v->dtdv_type.dtdt_size > sizeof(uint64_t) ?
-+ v->dtdv_type.dtdt_size : sizeof(uint64_t),
-+ DTRACE_DYNVAR_NOALLOC, mstate, vstate);
-+
-+ if (dvar == NULL) {
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF)
-+ regs[rd] = (uint64_t)(uintptr_t)dvar->dtdv_data;
-+ else
-+ regs[rd] = *((uint64_t *)dvar->dtdv_data);
-+
-+ break;
-+ }
-+
-+ case DIF_OP_STGAA:
-+ case DIF_OP_STTAA: {
-+ struct dtrace_dynvar *dvar;
-+ struct dtrace_key *key = tupregs;
-+ uint_t nkeys = ttop;
-+
-+ id = DIF_INSTR_VAR(instr);
-+ ASSERT(id >= DIF_VAR_OTHER_UBASE);
-+ id -= DIF_VAR_OTHER_UBASE;
-+
-+ key[nkeys].dttk_value = (uint64_t)id;
-+ key[nkeys++].dttk_size = 0;
-+
-+ if (DIF_INSTR_OP(instr) == DIF_OP_STTAA) {
-+ DTRACE_TLS_THRKEY(key[nkeys].dttk_value);
-+ key[nkeys++].dttk_size = 0;
-+ v = &vstate->dtvs_tlocals[id];
-+ } else
-+ v = &vstate->dtvs_globals[id]->dtsv_var;
-+
-+ dvar = dtrace_dynvar(dstate, nkeys, key,
-+ v->dtdv_type.dtdt_size > sizeof(uint64_t)
-+ ? v->dtdv_type.dtdt_size
-+ : sizeof(uint64_t),
-+ regs[rd] ? DTRACE_DYNVAR_ALLOC
-+ : DTRACE_DYNVAR_DEALLOC,
-+ mstate, vstate);
-+
-+ if (dvar == NULL)
-+ break;
-+
-+ if (v->dtdv_type.dtdt_flags & DIF_TF_BYREF) {
-+ if (!dtrace_vcanload(
-+ (void *)(uintptr_t)regs[rd],
-+ &v->dtdv_type, mstate, vstate))
-+ break;
-+
-+ dtrace_vcopy((void *)(uintptr_t)regs[rd],
-+ dvar->dtdv_data, &v->dtdv_type);
-+ } else
-+ *((uint64_t *)dvar->dtdv_data) = regs[rd];
-+
-+ break;
-+ }
-+
-+ case DIF_OP_ALLOCS: {
-+ uintptr_t ptr =
-+ P2ROUNDUP(mstate->dtms_scratch_ptr, 8);
-+ size_t size = ptr - mstate->dtms_scratch_ptr +
-+ regs[r1];
-+
-+ /*
-+ * Rounding up the user allocation size could have
-+ * overflowed large, bogus allocations (like -1ULL) to
-+ * 0.
-+ */
-+ if (size < regs[r1] ||
-+ !DTRACE_INSCRATCH(mstate, size)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ regs[rd] = 0;
-+ break;
-+ }
-+
-+ dtrace_bzero((void *) mstate->dtms_scratch_ptr, size);
-+ mstate->dtms_scratch_ptr += size;
-+ regs[rd] = ptr;
-+ break;
-+ }
-+
-+ case DIF_OP_COPYS:
-+ if (!dtrace_canstore(regs[rd], regs[r2], mstate,
-+ vstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ if (!dtrace_canload(regs[r1], regs[r2], mstate, vstate))
-+ break;
-+
-+ dtrace_bcopy((void *)(uintptr_t)regs[r1],
-+ (void *)(uintptr_t)regs[rd],
-+ (size_t)regs[r2]);
-+ break;
-+
-+ case DIF_OP_STB:
-+ if (!dtrace_canstore(regs[rd], 1, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ *((uint8_t *)(uintptr_t)regs[rd]) = (uint8_t)regs[r1];
-+ break;
-+
-+ case DIF_OP_STH:
-+ if (!dtrace_canstore(regs[rd], 2, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ if (regs[rd] & 1) {
-+ *flags |= CPU_DTRACE_BADALIGN;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ *((uint16_t *)(uintptr_t)regs[rd]) = (uint16_t)regs[r1];
-+ break;
-+
-+ case DIF_OP_STW:
-+ if (!dtrace_canstore(regs[rd], 4, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ if (regs[rd] & 3) {
-+ *flags |= CPU_DTRACE_BADALIGN;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ *((uint32_t *)(uintptr_t)regs[rd]) = (uint32_t)regs[r1];
-+ break;
-+
-+ case DIF_OP_STX:
-+ if (!dtrace_canstore(regs[rd], 8, mstate, vstate)) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ if (regs[rd] & 7) {
-+ *flags |= CPU_DTRACE_BADALIGN;
-+ *illval = regs[rd];
-+ break;
-+ }
-+
-+ *((uint64_t *)(uintptr_t)regs[rd]) = regs[r1];
-+ break;
-+ }
-+ }
-+
-+
-+ if (!(*flags & CPU_DTRACE_FAULT)) {
-+ dt_dbg_dif(" DIF %p completed, rval = %llx (flags %x)\n",
-+ difo, rval, *flags);
-+ return rval;
-+ }
-+
-+ dt_dbg_dif(" DIF %p emulation failed (flags %x)\n", difo, *flags);
-+
-+ mstate->dtms_fltoffs = opc * sizeof(dif_instr_t);
-+ mstate->dtms_present |= DTRACE_MSTATE_FLTOFFS;
-+
-+ return 0;
-+}
-diff --git a/dtrace/dtrace_dof.c b/dtrace/dtrace_dof.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..85ff9b21a205b6c3f87ed5290117ebaefa45a3da
---- /dev/null
-+++ b/dtrace/dtrace_dof.c
-@@ -0,0 +1,2504 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_dof.c
-+ * DESCRIPTION: DTrace - DOF implementation
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+#include <linux/vmalloc.h>
-+#include <linux/uaccess.h>
-+
-+#include "dtrace.h"
-+
-+size_t dtrace_difo_maxsize = 256 * 1024;
-+dtrace_optval_t dtrace_dof_maxsize = 256 * 1024;
-+size_t dtrace_actions_max = 16 * 1024;
-+dtrace_optval_t dtrace_helper_actions_max = 32;
-+dtrace_optval_t dtrace_helper_providers_max = 32;
-+
-+static int dtrace_helpers;
-+
-+static uint32_t dtrace_helptrace_next;
-+static uint32_t dtrace_helptrace_nlocals;
-+
-+#ifdef CONFIG_DT_DEBUG
-+int dtrace_helptrace_enabled = 1;
-+#else
-+int dtrace_helptrace_enabled = 0;
-+#endif
-+int dtrace_helptrace_bufsize = 512 * 1024;
-+char *dtrace_helptrace_buffer;
-+
-+void dtrace_dof_error(struct dof_hdr *dof, const char *str)
-+{
-+ if (dtrace_err_verbose)
-+ pr_warn("failed to process DOF: %s", str);
-+ else
-+ dt_dbg_dof("Failed to process DOF: %s\n", str);
-+
-+#ifdef DTRACE_ERRDEBUG
-+ dtrace_errdebug(str);
-+#endif
-+}
-+
-+/*
-+ * Create DOF out of a currently enabled state. Right now, we only create
-+ * DOF containing the run-time options -- but this could be expanded to create
-+ * complete DOF representing the enabled state.
-+ */
-+struct dof_hdr *dtrace_dof_create(struct dtrace_state *state)
-+{
-+ struct dof_hdr *dof;
-+ struct dof_sec *sec;
-+ struct dof_optdesc *opt;
-+
-+ int i, len = sizeof(struct dof_hdr) +
-+ roundup(sizeof(struct dof_sec),
-+ sizeof(uint64_t)) +
-+ sizeof(struct dof_optdesc) * DTRACEOPT_MAX;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ dof = vmalloc(len);
-+ if (dof == NULL)
-+ return NULL;
-+
-+ dof->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0;
-+ dof->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1;
-+ dof->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2;
-+ dof->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3;
-+
-+ dof->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_NATIVE;
-+ dof->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE;
-+ dof->dofh_ident[DOF_ID_VERSION] = DOF_VERSION;
-+ dof->dofh_ident[DOF_ID_DIFVERS] = DIF_VERSION;
-+ dof->dofh_ident[DOF_ID_DIFIREG] = DIF_DIR_NREGS;
-+ dof->dofh_ident[DOF_ID_DIFTREG] = DIF_DTR_NREGS;
-+
-+ dof->dofh_flags = 0;
-+ dof->dofh_hdrsize = sizeof(struct dof_hdr);
-+ dof->dofh_secsize = sizeof(struct dof_sec);
-+ dof->dofh_secnum = 1; /* only DOF_SECT_OPTDESC */
-+ dof->dofh_secoff = sizeof(struct dof_hdr);
-+ dof->dofh_loadsz = len;
-+ dof->dofh_filesz = len;
-+ dof->dofh_pad = 0;
-+
-+ /*
-+ * Fill in the option section header...
-+ */
-+ sec = (struct dof_sec *)((uintptr_t)dof + sizeof(struct dof_hdr));
-+ sec->dofs_type = DOF_SECT_OPTDESC;
-+ sec->dofs_align = sizeof(uint64_t);
-+ sec->dofs_flags = DOF_SECF_LOAD;
-+ sec->dofs_entsize = sizeof(struct dof_optdesc);
-+
-+ opt = (struct dof_optdesc *)((uintptr_t)sec +
-+ roundup(sizeof(struct dof_sec),
-+ sizeof(uint64_t)));
-+
-+ sec->dofs_offset = (uintptr_t)opt - (uintptr_t)dof;
-+ sec->dofs_size = sizeof(struct dof_optdesc) * DTRACEOPT_MAX;
-+
-+ for (i = 0; i < DTRACEOPT_MAX; i++) {
-+ opt[i].dofo_option = i;
-+ opt[i].dofo_strtab = DOF_SECIDX_NONE;
-+ opt[i].dofo_value = state->dts_options[i];
-+ }
-+
-+ return dof;
-+}
-+
-+struct dof_hdr *dtrace_dof_copyin(void __user *argp, int *errp)
-+{
-+ struct dof_hdr hdr, *dof;
-+
-+ ASSERT(!MUTEX_HELD(&dtrace_lock));
-+
-+ /*
-+ * First, we're going to copyin() the sizeof(dof_hdr_t).
-+ */
-+ if (copy_from_user(&hdr, argp, sizeof(hdr)) != 0) {
-+ dtrace_dof_error(NULL, "failed to copyin DOF header");
-+ *errp = -EFAULT;
-+ return NULL;
-+ }
-+
-+ /*
-+ * Now we'll allocate the entire DOF and copy it in -- provided
-+ * that the length isn't outrageous.
-+ */
-+ if (hdr.dofh_loadsz >= dtrace_dof_maxsize) {
-+ dtrace_dof_error(&hdr, "load size exceeds maximum");
-+ *errp = -E2BIG;
-+ return NULL;
-+ }
-+
-+ if (hdr.dofh_loadsz < sizeof(hdr)) {
-+ dtrace_dof_error(&hdr, "invalid load size");
-+ *errp = -EINVAL;
-+ return NULL;
-+ }
-+
-+ dof = vmalloc(hdr.dofh_loadsz);
-+ if (dof == NULL) {
-+ *errp = -ENOMEM;
-+ return NULL;
-+ }
-+
-+ if (copy_from_user(dof, argp, hdr.dofh_loadsz) != 0 ||
-+ dof->dofh_loadsz != hdr.dofh_loadsz) {
-+ vfree(dof);
-+ *errp = -EFAULT;
-+ return NULL;
-+ }
-+
-+ return dof;
-+}
-+
-+struct dof_hdr *dtrace_dof_property(const char *name)
-+{
-+ uchar_t *buf;
-+ uint64_t loadsz;
-+ unsigned int len, i;
-+ struct dof_hdr *dof;
-+
-+ /*
-+ * Unfortunately, array of values in .conf files are always (and
-+ * only) interpreted to be integer arrays. We must read our DOF
-+ * as an integer array, and then squeeze it into a byte array.
-+ */
-+#ifdef FIXME
-+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dtrace_devi, 0,
-+ (char *)name, (int **)&buf, &len) !=
-+ DDI_PROP_SUCCESS)
-+ return NULL;
-+#else
-+ return NULL;
-+#endif
-+
-+ for (i = 0; i < len; i++)
-+ buf[i] = (uchar_t)(((int *)buf)[i]);
-+
-+ if (len < sizeof(struct dof_hdr)) {
-+#ifdef FIXME
-+ ddi_prop_free(buf);
-+#endif
-+ dtrace_dof_error(NULL, "truncated header");
-+ return NULL;
-+ }
-+
-+ loadsz = ((struct dof_hdr *)buf)->dofh_loadsz;
-+ if (len < loadsz) {
-+#ifdef FIXME
-+ ddi_prop_free(buf);
-+#endif
-+ dtrace_dof_error(NULL, "truncated DOF");
-+ return NULL;
-+ }
-+
-+ if (loadsz >= dtrace_dof_maxsize) {
-+#ifdef FIXME
-+ ddi_prop_free(buf);
-+#endif
-+ dtrace_dof_error(NULL, "oversized DOF");
-+ return NULL;
-+ }
-+
-+ dof = vmalloc(loadsz);
-+ if (dof == NULL) {
-+ dtrace_dof_error(NULL, "out-of-memory");
-+ return NULL;
-+ }
-+ memcpy(dof, buf, loadsz);
-+#ifdef FIXME
-+ ddi_prop_free(buf);
-+#endif
-+
-+ return dof;
-+}
-+
-+void dtrace_dof_destroy(struct dof_hdr *dof)
-+{
-+ vfree(dof);
-+}
-+
-+/*
-+ * Return the dof_sec_t pointer corresponding to a given section index. If the
-+ * index is not valid, dtrace_dof_error() is called and NULL is returned. If
-+ * a type other than DOF_SECT_NONE is specified, the header is checked against
-+ * this type and NULL is returned if the types do not match.
-+ */
-+static struct dof_sec *dtrace_dof_sect(struct dof_hdr *dof, uint32_t doftype,
-+ dof_secidx_t i)
-+{
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(uintptr_t) ((uintptr_t)dof +
-+ dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (i >= dof->dofh_secnum) {
-+ dtrace_dof_error(dof, "referenced section index is invalid");
-+ return NULL;
-+ }
-+
-+ if (!(sec->dofs_flags & DOF_SECF_LOAD)) {
-+ dtrace_dof_error(dof, "referenced section is not loadable");
-+ return NULL;
-+ }
-+
-+ if (doftype != DOF_SECT_NONE && doftype != sec->dofs_type) {
-+ dtrace_dof_error(dof, "referenced section is the wrong type");
-+ return NULL;
-+ }
-+
-+ return sec;
-+}
-+
-+static struct dtrace_probedesc *dtrace_dof_probedesc(struct dof_hdr *dof,
-+ struct dof_sec *sec,
-+ struct dtrace_probedesc *desc)
-+{
-+ struct dof_probedesc *probe;
-+ struct dof_sec *strtab;
-+ uintptr_t daddr = (uintptr_t)dof;
-+ uintptr_t str;
-+ size_t size;
-+
-+ if (sec->dofs_type != DOF_SECT_PROBEDESC) {
-+ dtrace_dof_error(dof, "invalid probe section");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_align != sizeof(dof_secidx_t)) {
-+ dtrace_dof_error(dof, "bad alignment in probe description");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_offset + sizeof(struct dof_probedesc) >
-+ dof->dofh_loadsz) {
-+ dtrace_dof_error(dof, "truncated probe description");
-+ return NULL;
-+ }
-+
-+ probe = (struct dof_probedesc *)(uintptr_t)(daddr + sec->dofs_offset);
-+ strtab = dtrace_dof_sect(dof, DOF_SECT_STRTAB, probe->dofp_strtab);
-+
-+ if (strtab == NULL)
-+ return NULL;
-+
-+ str = daddr + strtab->dofs_offset;
-+ size = strtab->dofs_size;
-+
-+ if (probe->dofp_provider >= strtab->dofs_size) {
-+ dtrace_dof_error(dof, "corrupt probe provider");
-+ return NULL;
-+ }
-+
-+ strncpy(desc->dtpd_provider, (char *)(str + probe->dofp_provider),
-+ min((size_t)DTRACE_PROVNAMELEN - 1,
-+ size - probe->dofp_provider));
-+
-+ if (probe->dofp_mod >= strtab->dofs_size) {
-+ dtrace_dof_error(dof, "corrupt probe module");
-+ return NULL;
-+ }
-+
-+ strncpy(desc->dtpd_mod, (char *)(str + probe->dofp_mod),
-+ min((size_t)DTRACE_MODNAMELEN - 1, size - probe->dofp_mod));
-+
-+ if (probe->dofp_func >= strtab->dofs_size) {
-+ dtrace_dof_error(dof, "corrupt probe function");
-+ return NULL;
-+ }
-+
-+ strncpy(desc->dtpd_func, (char *)(str + probe->dofp_func),
-+ min((size_t)DTRACE_FUNCNAMELEN - 1, size - probe->dofp_func));
-+
-+ if (probe->dofp_name >= strtab->dofs_size) {
-+ dtrace_dof_error(dof, "corrupt probe name");
-+ return NULL;
-+ }
-+
-+ strncpy(desc->dtpd_name, (char *)(str + probe->dofp_name),
-+ min((size_t)DTRACE_NAMELEN - 1, size - probe->dofp_name));
-+
-+ dt_dbg_dof(" ECB Probe %s:%s:%s:%s\n",
-+ desc->dtpd_provider, desc->dtpd_mod, desc->dtpd_func,
-+ desc->dtpd_name);
-+
-+ return desc;
-+}
-+
-+static struct dtrace_difo *dtrace_dof_difo(struct dof_hdr *dof,
-+ struct dof_sec *sec,
-+ struct dtrace_vstate *vstate,
-+ const struct cred *cr)
-+{
-+ struct dtrace_difo *dp;
-+ size_t ttl = 0;
-+ struct dof_difohdr *dofd;
-+ uintptr_t daddr = (uintptr_t)dof;
-+ size_t max = dtrace_difo_maxsize;
-+ int i, l, n;
-+
-+ static const struct {
-+ int section;
-+ int bufoffs;
-+ int lenoffs;
-+ int entsize;
-+ int align;
-+ const char *msg;
-+ } difo[] = {
-+ {
-+ DOF_SECT_DIF,
-+ offsetof(struct dtrace_difo, dtdo_buf),
-+ offsetof(struct dtrace_difo, dtdo_len),
-+ sizeof(dif_instr_t),
-+ sizeof(dif_instr_t),
-+ "multiple DIF sections"
-+ },
-+ {
-+ DOF_SECT_INTTAB,
-+ offsetof(struct dtrace_difo, dtdo_inttab),
-+ offsetof(struct dtrace_difo, dtdo_intlen),
-+ sizeof(uint64_t),
-+ sizeof(uint64_t),
-+ "multiple integer tables"
-+ },
-+ {
-+ DOF_SECT_STRTAB,
-+ offsetof(struct dtrace_difo, dtdo_strtab),
-+ offsetof(struct dtrace_difo, dtdo_strlen),
-+ 0,
-+ sizeof(char),
-+ "multiple string tables"
-+ },
-+ {
-+ DOF_SECT_VARTAB,
-+ offsetof(struct dtrace_difo, dtdo_vartab),
-+ offsetof(struct dtrace_difo, dtdo_varlen),
-+ sizeof(struct dtrace_difv),
-+ sizeof(uint_t),
-+ "multiple variable tables"
-+ },
-+ {
-+ DOF_SECT_NONE,
-+ 0,
-+ 0,
-+ 0,
-+ 0,
-+ NULL
-+ }
-+ };
-+
-+ if (sec->dofs_type != DOF_SECT_DIFOHDR) {
-+ dtrace_dof_error(dof, "invalid DIFO header section");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_align != sizeof(dof_secidx_t)) {
-+ dtrace_dof_error(dof, "bad alignment in DIFO header");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_size < sizeof(struct dof_difohdr) ||
-+ sec->dofs_size % sizeof(dof_secidx_t)) {
-+ dtrace_dof_error(dof, "bad size in DIFO header");
-+ return NULL;
-+ }
-+
-+ dofd = (struct dof_difohdr *)(uintptr_t)(daddr + sec->dofs_offset);
-+ n = (sec->dofs_size - sizeof(*dofd)) / sizeof(dof_secidx_t) + 1;
-+
-+ dp = kzalloc(sizeof(struct dtrace_difo), GFP_KERNEL);
-+ if (dp == NULL) {
-+ dtrace_dof_error(dof, "out-of-memory");
-+ return NULL;
-+ }
-+ dp->dtdo_rtype = dofd->dofd_rtype;
-+
-+ for (l = 0; l < n; l++) {
-+ struct dof_sec *subsec;
-+ void **bufp;
-+ uint32_t *lenp;
-+
-+ subsec = dtrace_dof_sect(dof, DOF_SECT_NONE,
-+ dofd->dofd_links[l]);
-+ if (subsec == NULL)
-+ goto err; /* invalid section link */
-+
-+ if (ttl + subsec->dofs_size > max) {
-+ dtrace_dof_error(dof, "exceeds maximum size");
-+ goto err;
-+ }
-+
-+ ttl += subsec->dofs_size;
-+
-+ for (i = 0; difo[i].section != DOF_SECT_NONE; i++) {
-+ if (subsec->dofs_type != difo[i].section)
-+ continue;
-+
-+ if (!(subsec->dofs_flags & DOF_SECF_LOAD)) {
-+ dtrace_dof_error(dof, "section not loaded");
-+ goto err;
-+ }
-+
-+ if (subsec->dofs_align != difo[i].align) {
-+ dtrace_dof_error(dof, "bad alignment");
-+ goto err;
-+ }
-+
-+ bufp = (void **)((uintptr_t)dp + difo[i].bufoffs);
-+ lenp = (uint32_t *)((uintptr_t)dp + difo[i].lenoffs);
-+
-+ if (*bufp != NULL) {
-+ dtrace_dof_error(dof, difo[i].msg);
-+ goto err;
-+ }
-+
-+ if (difo[i].entsize != subsec->dofs_entsize) {
-+ dtrace_dof_error(dof, "entry size mismatch");
-+ goto err;
-+ }
-+
-+ if (subsec->dofs_entsize != 0) {
-+ uint64_t n = subsec->dofs_size;
-+
-+ if (do_div(n, subsec->dofs_entsize) != 0) {
-+ dtrace_dof_error(dof,
-+ "corrupt entry size");
-+ goto err;
-+ }
-+ }
-+
-+ *lenp = subsec->dofs_size;
-+ *bufp = vmalloc(subsec->dofs_size);
-+ if (*bufp == NULL) {
-+ dtrace_dof_error(dof, "out-of-memory");
-+ goto err;
-+ }
-+ memcpy(*bufp,
-+ (char *)(uintptr_t)(daddr + subsec->dofs_offset),
-+ subsec->dofs_size);
-+
-+ if (subsec->dofs_entsize != 0)
-+ *lenp /= subsec->dofs_entsize;
-+
-+ break;
-+ }
-+
-+ /*
-+ * If we encounter a loadable DIFO sub-section that is not
-+ * known to us, assume this is a broken program and fail.
-+ */
-+ if (difo[i].section == DOF_SECT_NONE &&
-+ (subsec->dofs_flags & DOF_SECF_LOAD)) {
-+ dtrace_dof_error(dof, "unrecognized DIFO subsection");
-+ goto err;
-+ }
-+ }
-+
-+ if (dp->dtdo_buf == NULL) {
-+ /*
-+ * We can't have a DIF object without DIF text.
-+ */
-+ dtrace_dof_error(dof, "missing DIF text");
-+ goto err;
-+ }
-+
-+ /*
-+ * Before we validate the DIF object, run through the variable table
-+ * looking for the strings -- if any of their size are under, we'll set
-+ * their size to be the system-wide default string size. Note that
-+ * this should _not_ happen if the "strsize" option has been set --
-+ * in this case, the compiler should have set the size to reflect the
-+ * setting of the option.
-+ */
-+ for (i = 0; i < dp->dtdo_varlen; i++) {
-+ struct dtrace_difv *v = &dp->dtdo_vartab[i];
-+ struct dtrace_diftype *t = &v->dtdv_type;
-+
-+ if (v->dtdv_id < DIF_VAR_OTHER_UBASE)
-+ continue;
-+
-+ if (t->dtdt_kind == DIF_TYPE_STRING && t->dtdt_size == 0)
-+ t->dtdt_size = dtrace_strsize_default;
-+ }
-+
-+ if (dtrace_difo_validate(dp, vstate, DIF_DIR_NREGS, cr) != 0)
-+ goto err;
-+
-+ dtrace_difo_init(dp, vstate);
-+ return dp;
-+
-+err:
-+ if (dp->dtdo_buf != NULL)
-+ vfree(dp->dtdo_buf);
-+ if (dp->dtdo_inttab != NULL)
-+ vfree(dp->dtdo_inttab);
-+ if (dp->dtdo_strtab != NULL)
-+ vfree(dp->dtdo_strtab);
-+ if (dp->dtdo_vartab != NULL)
-+ vfree(dp->dtdo_vartab);
-+
-+ kfree(dp);
-+
-+ return NULL;
-+}
-+
-+static struct dtrace_predicate *dtrace_dof_predicate(struct dof_hdr *dof,
-+ struct dof_sec *sec,
-+ struct dtrace_vstate *vstate,
-+ const struct cred *cr)
-+{
-+ struct dtrace_difo *dp;
-+
-+ if ((dp = dtrace_dof_difo(dof, sec, vstate, cr)) == NULL)
-+ return NULL;
-+
-+ return dtrace_predicate_create(dp);
-+}
-+
-+static struct dtrace_actdesc *dtrace_dof_actdesc(struct dof_hdr *dof,
-+ struct dof_sec *sec,
-+ struct dtrace_vstate *vstate,
-+ const struct cred *cr)
-+{
-+ struct dtrace_actdesc *act, *first = NULL, *last = NULL, *next;
-+ struct dof_actdesc *desc;
-+ struct dof_sec *difosec;
-+ size_t offs;
-+ uintptr_t daddr = (uintptr_t)dof;
-+ uint64_t arg;
-+ dtrace_actkind_t kind;
-+
-+ if (sec->dofs_type != DOF_SECT_ACTDESC) {
-+ dtrace_dof_error(dof, "invalid action section");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_offset + sizeof(struct dof_actdesc) > dof->dofh_loadsz) {
-+ dtrace_dof_error(dof, "truncated action description");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_align != sizeof(uint64_t)) {
-+ dtrace_dof_error(dof, "bad alignment in action description");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_size < sec->dofs_entsize) {
-+ dtrace_dof_error(dof, "section entry size exceeds total size");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_entsize != sizeof(struct dof_actdesc)) {
-+ dtrace_dof_error(dof, "bad entry size in action description");
-+ return NULL;
-+ }
-+
-+ /*
-+ * Was: sec->dofs_size / sec->dofs_entsize > dtrace_actions_max
-+ * but it is safer to simply avoid the division (it requires use of
-+ * a macro in Linux to cover 64-bit division in a 32-bit kernel.
-+ */
-+ if (sec->dofs_size > sec->dofs_entsize * dtrace_actions_max) {
-+ dtrace_dof_error(dof, "actions exceed dtrace_actions_max");
-+ return NULL;
-+ }
-+
-+ for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) {
-+ desc = (struct dof_actdesc *)(daddr +
-+ (uintptr_t)sec->dofs_offset + offs);
-+ kind = (dtrace_actkind_t)desc->dofa_kind;
-+
-+ if (DTRACEACT_ISPRINTFLIKE(kind) &&
-+ (kind != DTRACEACT_PRINTA ||
-+ desc->dofa_strtab != DOF_SECIDX_NONE)) {
-+ struct dof_sec *strtab;
-+ char *str, *fmt;
-+ uint64_t i;
-+
-+ /*
-+ * The printf()-like actions must have a format string.
-+ */
-+ strtab = dtrace_dof_sect(dof, DOF_SECT_STRTAB,
-+ desc->dofa_strtab);
-+ if (strtab == NULL)
-+ goto err;
-+
-+ str = (char *)((uintptr_t)dof +
-+ (uintptr_t)strtab->dofs_offset);
-+
-+ for (i = desc->dofa_arg; i < strtab->dofs_size; i++) {
-+ if (str[i] == '\0')
-+ break;
-+ }
-+
-+ if (i >= strtab->dofs_size) {
-+ dtrace_dof_error(dof, "bogus format string");
-+ goto err;
-+ }
-+
-+ if (i == desc->dofa_arg) {
-+ dtrace_dof_error(dof, "empty format string");
-+ goto err;
-+ }
-+
-+ i -= desc->dofa_arg;
-+ fmt = vmalloc(i + 1);
-+ if (fmt == NULL) {
-+ dtrace_dof_error(dof, "out-of-memory");
-+ goto err;
-+ }
-+ memcpy(fmt, &str[desc->dofa_arg], i + 1);
-+ arg = (uint64_t)(uintptr_t)fmt;
-+ } else {
-+ if (kind == DTRACEACT_PRINTA) {
-+ ASSERT(desc->dofa_strtab == DOF_SECIDX_NONE);
-+ arg = 0;
-+ } else
-+ arg = desc->dofa_arg;
-+ }
-+
-+ act = dtrace_actdesc_create(kind, desc->dofa_ntuple,
-+ desc->dofa_uarg, arg);
-+ if (act == NULL)
-+ goto err;
-+
-+ if (last != NULL)
-+ last->dtad_next = act;
-+ else
-+ first = act;
-+
-+ last = act;
-+
-+ if (desc->dofa_difo == DOF_SECIDX_NONE)
-+ continue;
-+
-+ difosec = dtrace_dof_sect(dof, DOF_SECT_DIFOHDR,
-+ desc->dofa_difo);
-+ if (difosec == NULL)
-+ goto err;
-+
-+ act->dtad_difo = dtrace_dof_difo(dof, difosec, vstate, cr);
-+
-+ if (act->dtad_difo == NULL)
-+ goto err;
-+ }
-+
-+ ASSERT(first != NULL);
-+ return first;
-+
-+err:
-+ for (act = first; act != NULL; act = next) {
-+ next = act->dtad_next;
-+ dtrace_actdesc_release(act, vstate);
-+ }
-+
-+ return NULL;
-+}
-+
-+static struct dtrace_ecbdesc *dtrace_dof_ecbdesc(struct dof_hdr *dof,
-+ struct dof_sec *sec,
-+ struct dtrace_vstate *vstate,
-+ const struct cred *cr)
-+{
-+ struct dtrace_ecbdesc *ep;
-+ struct dof_ecbdesc *ecb;
-+ struct dtrace_probedesc *desc;
-+ struct dtrace_predicate *pred = NULL;
-+
-+ if (sec->dofs_size < sizeof(struct dof_ecbdesc)) {
-+ dtrace_dof_error(dof, "truncated ECB description");
-+ return NULL;
-+ }
-+
-+ if (sec->dofs_align != sizeof(uint64_t)) {
-+ dtrace_dof_error(dof, "bad alignment in ECB description");
-+ return NULL;
-+ }
-+
-+ ecb = (struct dof_ecbdesc *)
-+ ((uintptr_t)dof + (uintptr_t)sec->dofs_offset);
-+ sec = dtrace_dof_sect(dof, DOF_SECT_PROBEDESC, ecb->dofe_probes);
-+
-+ if (sec == NULL)
-+ return NULL;
-+
-+ ep = kzalloc(sizeof(struct dtrace_ecbdesc), GFP_KERNEL);
-+ if (ep == NULL)
-+ return NULL;
-+ ep->dted_uarg = ecb->dofe_uarg;
-+ desc = &ep->dted_probe;
-+
-+ if (dtrace_dof_probedesc(dof, sec, desc) == NULL)
-+ goto err;
-+
-+ if (ecb->dofe_pred != DOF_SECIDX_NONE) {
-+ sec = dtrace_dof_sect(dof, DOF_SECT_DIFOHDR, ecb->dofe_pred);
-+ if (sec == NULL)
-+ goto err;
-+
-+ pred = dtrace_dof_predicate(dof, sec, vstate, cr);
-+ if (pred == NULL)
-+ goto err;
-+
-+ ep->dted_pred.dtpdd_predicate = pred;
-+ }
-+
-+ if (ecb->dofe_actions != DOF_SECIDX_NONE) {
-+ sec = dtrace_dof_sect(dof, DOF_SECT_ACTDESC, ecb->dofe_actions);
-+ if (sec == NULL)
-+ goto err;
-+
-+ ep->dted_action = dtrace_dof_actdesc(dof, sec, vstate, cr);
-+
-+ if (ep->dted_action == NULL)
-+ goto err;
-+ }
-+
-+ return ep;
-+
-+err:
-+ if (pred != NULL)
-+ dtrace_predicate_release(pred, vstate);
-+ kfree(ep);
-+ return NULL;
-+}
-+
-+/*
-+ * Apply the relocations from the specified 'sec' (a DOF_SECT_URELHDR) to the
-+ * specified DOF. At present, this amounts to simply adding 'ubase' to the
-+ * site of any user SETX relocations to account for load object base address.
-+ * In the future, if we need other relocations, this function can be extended.
-+ */
-+static int dtrace_dof_relocate(struct dof_hdr *dof, struct dof_sec *sec,
-+ uint64_t ubase)
-+{
-+ uintptr_t daddr = (uintptr_t)dof;
-+ struct dof_relohdr *dofr;
-+ struct dof_sec *ss, *rs, *ts;
-+ struct dof_relodesc *r;
-+ uint_t i, n;
-+
-+ dofr = (struct dof_relohdr *)(uintptr_t) (daddr + sec->dofs_offset);
-+
-+ if (sec->dofs_size < sizeof(struct dof_relohdr) ||
-+ sec->dofs_align != sizeof(dof_secidx_t)) {
-+ dtrace_dof_error(dof, "invalid relocation header");
-+ return -1;
-+ }
-+
-+ ss = dtrace_dof_sect(dof, DOF_SECT_STRTAB, dofr->dofr_strtab);
-+ rs = dtrace_dof_sect(dof, DOF_SECT_RELTAB, dofr->dofr_relsec);
-+ ts = dtrace_dof_sect(dof, DOF_SECT_NONE, dofr->dofr_tgtsec);
-+
-+ if (ss == NULL || rs == NULL || ts == NULL)
-+ return -1; /* dtrace_dof_error() has been called already */
-+
-+ if (rs->dofs_entsize < sizeof(struct dof_relodesc) ||
-+ rs->dofs_align != sizeof(uint64_t)) {
-+ dtrace_dof_error(dof, "invalid relocation section");
-+ return -1;
-+ }
-+
-+ r = (struct dof_relodesc *)(uintptr_t)(daddr + rs->dofs_offset);
-+ /*
-+ * Was: n = rs->dofs_size / rs->dofs_entsize;
-+ * but on Linux we need to use a macro for the division to handle the
-+ * possible case of 64-bit division on a 32-bit kernel.
-+ */
-+ n = rs->dofs_size;
-+ do_div(n, rs->dofs_entsize);
-+
-+ for (i = 0; i < n; i++) {
-+ uintptr_t taddr = daddr + ts->dofs_offset + r->dofr_offset;
-+
-+ switch (r->dofr_type) {
-+ case DOF_RELO_NONE:
-+ break;
-+ case DOF_RELO_SETX:
-+ if (r->dofr_offset >= ts->dofs_size ||
-+ r->dofr_offset + sizeof(uint64_t) >
-+ ts->dofs_size) {
-+ dtrace_dof_error(dof, "bad relocation offset");
-+ return -1;
-+ }
-+
-+ if (!IS_ALIGNED(taddr, sizeof(uint64_t))) {
-+ dtrace_dof_error(dof, "misaligned setx relo");
-+ return -1;
-+ }
-+
-+ /*
-+ * This is a bit ugly but it is necessary for arm64,
-+ * where the linking of shared libraries retains the
-+ * relocation records for the .SUNW_dof section. In
-+ * that case, the runtime loader already performed the
-+ * relocation, so we do not have to do anything here.
-+ *
-+ * We check for this situation by comparing the target
-+ * address against the base address (ubase). If it is
-+ * larger, we assume the relocation already took place.
-+ */
-+ if (*(uint64_t *)taddr > ubase)
-+ dt_dbg_dof(" Relocation by runtime " \
-+ "loader: 0x%llx (base 0x%llx)\n",
-+ *(uint64_t *)taddr, ubase);
-+ else {
-+ dt_dbg_dof(" Relocate 0x%llx + 0x%llx " \
-+ "= 0x%llx\n",
-+ *(uint64_t *)taddr, ubase,
-+ *(uint64_t *)taddr + ubase);
-+
-+ *(uint64_t *)taddr += ubase;
-+ }
-+
-+ break;
-+ default:
-+ dtrace_dof_error(dof, "invalid relocation type");
-+ return -1;
-+ }
-+
-+ r = (struct dof_relodesc *)((uintptr_t)r + rs->dofs_entsize);
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * The dof_hdr_t passed to dtrace_dof_slurp() should be a partially validated
-+ * header: it should be at the front of a memory region that is at least
-+ * sizeof(dof_hdr_t) in size -- and then at least dof_hdr.dofh_loadsz in
-+ * size. It need not be validated in any other way.
-+ */
-+int dtrace_dof_slurp(struct dof_hdr *dof, struct dtrace_vstate *vstate,
-+ const struct cred *cr, struct dtrace_enabling **enabp,
-+ uint64_t ubase, int noprobes)
-+{
-+ uint64_t len = dof->dofh_loadsz, seclen;
-+ uintptr_t daddr = (uintptr_t)dof;
-+ struct dtrace_ecbdesc *ep;
-+ struct dtrace_enabling *enab;
-+ uint_t i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dof->dofh_loadsz >= sizeof(struct dof_hdr));
-+
-+ dt_dbg_dof(" DOF 0x%p Slurping...\n", dof);
-+
-+ dt_dbg_dof(" DOF 0x%p Validating...\n", dof);
-+
-+ /*
-+ * Check the DOF header identification bytes. In addition to checking
-+ * valid settings, we also verify that unused bits/bytes are zeroed so
-+ * we can use them later without fear of regressing existing binaries.
-+ */
-+ if (memcmp(&dof->dofh_ident[DOF_ID_MAG0], DOF_MAG_STRING,
-+ DOF_MAG_STRLEN) != 0) {
-+ dtrace_dof_error(dof, "DOF magic string mismatch");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_MODEL] != DOF_MODEL_ILP32 &&
-+ dof->dofh_ident[DOF_ID_MODEL] != DOF_MODEL_LP64) {
-+ dtrace_dof_error(dof, "DOF has invalid data model");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_ENCODING] != DOF_ENCODE_NATIVE) {
-+ dtrace_dof_error(dof, "DOF encoding mismatch");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 &&
-+ dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_2) {
-+ dtrace_dof_error(dof, "DOF version mismatch");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_DIFVERS] != DIF_VERSION_2) {
-+ dtrace_dof_error(dof, "DOF uses unsupported instruction set");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_DIFIREG] > DIF_DIR_NREGS) {
-+ dtrace_dof_error(dof, "DOF uses too many integer registers");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_DIFTREG] > DIF_DTR_NREGS) {
-+ dtrace_dof_error(dof, "DOF uses too many tuple registers");
-+ return -1;
-+ }
-+
-+ for (i = DOF_ID_PAD; i < DOF_ID_SIZE; i++) {
-+ if (dof->dofh_ident[i] != 0) {
-+ dtrace_dof_error(dof, "DOF has invalid ident byte set");
-+ return -1;
-+ }
-+ }
-+
-+ if (dof->dofh_flags & ~DOF_FL_VALID) {
-+ dtrace_dof_error(dof, "DOF has invalid flag bits set");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_secsize == 0) {
-+ dtrace_dof_error(dof, "zero section header size");
-+ return -1;
-+ }
-+
-+ /*
-+ * Check that the section headers don't exceed the amount of DOF
-+ * data. Note that we cast the section size and number of sections
-+ * to uint64_t's to prevent possible overflow in the multiplication.
-+ */
-+ seclen = (uint64_t)dof->dofh_secnum * (uint64_t)dof->dofh_secsize;
-+
-+ if (dof->dofh_secoff > len || seclen > len ||
-+ dof->dofh_secoff + seclen > len) {
-+ dtrace_dof_error(dof, "truncated section headers");
-+ return -1;
-+ }
-+
-+ if (!IS_ALIGNED(dof->dofh_secoff, sizeof(uint64_t))) {
-+ dtrace_dof_error(dof, "misaligned section headers");
-+ return -1;
-+ }
-+
-+ if (!IS_ALIGNED(dof->dofh_secsize, sizeof(uint64_t))) {
-+ dtrace_dof_error(dof, "misaligned section size");
-+ return -1;
-+ }
-+
-+ /*
-+ * Take an initial pass through the section headers to be sure that
-+ * the headers don't have stray offsets. If the 'noprobes' flag is
-+ * set, do not permit sections relating to providers, probes, or args.
-+ */
-+ dt_dbg_dof(" DOF 0x%p Checking section offsets...\n", dof);
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(daddr + (uintptr_t)dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (noprobes) {
-+ switch (sec->dofs_type) {
-+ case DOF_SECT_PROVIDER:
-+ case DOF_SECT_PROBES:
-+ case DOF_SECT_PRARGS:
-+ case DOF_SECT_PROFFS:
-+ dtrace_dof_error(
-+ dof, "illegal sections for enabling");
-+ return -1;
-+ }
-+ }
-+
-+ if (DOF_SEC_ISLOADABLE(sec->dofs_type) &&
-+ !(sec->dofs_flags & DOF_SECF_LOAD)) {
-+ dtrace_dof_error(
-+ dof, "loadable section with load flag unset");
-+ return -1;
-+ }
-+
-+ /*
-+ * Just ignore non-loadable sections.
-+ */
-+ if (!(sec->dofs_flags & DOF_SECF_LOAD))
-+ continue;
-+
-+ if (sec->dofs_align & (sec->dofs_align - 1)) {
-+ dtrace_dof_error(dof, "bad section alignment");
-+ return -1;
-+ }
-+
-+ if (sec->dofs_offset & (sec->dofs_align - 1)) {
-+ dtrace_dof_error(dof, "misaligned section");
-+ return -1;
-+ }
-+
-+ if (sec->dofs_offset > len || sec->dofs_size > len ||
-+ sec->dofs_offset + sec->dofs_size > len) {
-+ dtrace_dof_error(dof, "corrupt section header");
-+ return -1;
-+ }
-+
-+ if (sec->dofs_type == DOF_SECT_STRTAB && *((char *)daddr +
-+ sec->dofs_offset + sec->dofs_size - 1) != '\0') {
-+ dtrace_dof_error(dof, "non-terminating string table");
-+ return -1;
-+ }
-+ }
-+
-+ /*
-+ * Take a second pass through the sections and locate and perform any
-+ * relocations that are present. We do this after the first pass to
-+ * be sure that all sections have had their headers validated.
-+ */
-+ dt_dbg_dof(" DOF 0x%p Performing relocations...\n", dof);
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(daddr + (uintptr_t)dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ /*
-+ * Skip sections that are not loadable.
-+ */
-+ if (!(sec->dofs_flags & DOF_SECF_LOAD))
-+ continue;
-+
-+ switch (sec->dofs_type) {
-+ case DOF_SECT_URELHDR:
-+ if (dtrace_dof_relocate(dof, sec, ubase) != 0)
-+ return -1;
-+ break;
-+ }
-+ }
-+
-+ dt_dbg_dof(" DOF 0x%p Processing enablings...\n", dof);
-+
-+ enab = *enabp;
-+ if (enab == NULL)
-+ enab = *enabp = dtrace_enabling_create(vstate);
-+
-+ if (enab == NULL) {
-+ dt_dbg_dof(" DOF 0x%p Done slurping - no enablings\n", dof);
-+ return -1;
-+ }
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(daddr + (uintptr_t)dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (sec->dofs_type != DOF_SECT_ECBDESC)
-+ continue;
-+
-+ ep = dtrace_dof_ecbdesc(dof, sec, vstate, cr);
-+ if (ep == NULL) {
-+ dt_dbg_dof(" DOF 0x%p Done slurping - ECB problem\n",
-+ dof);
-+ dtrace_enabling_destroy(enab);
-+ *enabp = NULL;
-+ return -1;
-+ }
-+
-+ dtrace_enabling_add(enab, ep);
-+ }
-+
-+ dt_dbg_dof(" DOF 0x%p Enablings processed\n", dof);
-+ dt_dbg_dof(" DOF 0x%p Done slurping\n", dof);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Process DOF for any options. This should be called after the DOF has been
-+ * processed by dtrace_dof_slurp().
-+ */
-+int dtrace_dof_options(struct dof_hdr *dof, struct dtrace_state *state)
-+{
-+ int i, rval;
-+ uint32_t entsize;
-+ size_t offs;
-+ struct dof_optdesc *desc;
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)((uintptr_t)dof +
-+ (uintptr_t)dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (sec->dofs_type != DOF_SECT_OPTDESC)
-+ continue;
-+
-+ if (sec->dofs_align != sizeof(uint64_t)) {
-+ dtrace_dof_error(
-+ dof, "bad alignment in option description");
-+ return -EINVAL;
-+ }
-+
-+ entsize = sec->dofs_entsize;
-+ if (entsize == 0) {
-+ dtrace_dof_error(dof, "zeroed option entry size");
-+ return -EINVAL;
-+ }
-+
-+ if (entsize < sizeof(struct dof_optdesc)) {
-+ dtrace_dof_error(dof, "bad option entry size");
-+ return -EINVAL;
-+ }
-+
-+ for (offs = 0; offs < sec->dofs_size; offs += entsize) {
-+ desc = (struct dof_optdesc *)((uintptr_t)dof +
-+ (uintptr_t)sec->dofs_offset +
-+ offs);
-+
-+ if (desc->dofo_strtab != DOF_SECIDX_NONE) {
-+ dtrace_dof_error(
-+ dof, "non-zero option string");
-+ return -EINVAL;
-+ }
-+
-+ if (desc->dofo_value == DTRACEOPT_UNSET) {
-+ dtrace_dof_error(dof, "unset option");
-+ return -EINVAL;
-+ }
-+
-+ rval = dtrace_state_option(state, desc->dofo_option,
-+ desc->dofo_value);
-+ if (rval != 0) {
-+ dtrace_dof_error(dof, "rejected option");
-+ return rval;
-+ }
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static struct dtrace_helpers *dtrace_helpers_create(struct task_struct *curr)
-+{
-+ struct dtrace_helpers *dth;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (curr->dt_task == NULL)
-+ return NULL;
-+
-+ ASSERT(curr->dt_task->dt_helpers == NULL);
-+
-+ dth = kzalloc(sizeof(struct dtrace_helpers), GFP_KERNEL);
-+ if (dth == NULL)
-+ return NULL;
-+
-+ dth->dthps_actions = vzalloc(sizeof(struct dtrace_helper_action *) *
-+ DTRACE_NHELPER_ACTIONS);
-+ if (dth->dthps_actions == NULL) {
-+ kfree(dth);
-+ return NULL;
-+ }
-+
-+ curr->dt_task->dt_helpers = dth;
-+ dtrace_helpers++;
-+
-+ dt_dbg_dof(" Helpers allocated for task 0x%p (%d system-wide)\n",
-+ curr, dtrace_helpers);
-+
-+ return dth;
-+}
-+
-+static int dtrace_helper_validate(struct dtrace_helper_action *helper)
-+{
-+ int err = 0, i;
-+ struct dtrace_difo *dp;
-+
-+ dp = helper->dtha_predicate;
-+ if (dp != NULL)
-+ err += dtrace_difo_validate_helper(dp);
-+
-+ for (i = 0; i < helper->dtha_nactions; i++)
-+ err += dtrace_difo_validate_helper(helper->dtha_actions[i]);
-+
-+ return (err == 0);
-+}
-+
-+static int dtrace_helper_provider_validate(struct dof_hdr *dof,
-+ struct dof_sec *sec)
-+{
-+ uintptr_t daddr = (uintptr_t)dof;
-+ struct dof_sec *str_sec, *prb_sec, *arg_sec, *off_sec,
-+ *enoff_sec;
-+ struct dof_provider *prov;
-+ struct dof_probe *prb;
-+ uint8_t *arg;
-+ char *strtab, *typestr;
-+ dof_stridx_t typeidx;
-+ size_t typesz;
-+ uint_t nprobes, j, k;
-+
-+ ASSERT(sec->dofs_type == DOF_SECT_PROVIDER);
-+
-+ if (sec->dofs_offset & (sizeof(uint_t) - 1)) {
-+ dtrace_dof_error(dof, "misaligned section offset");
-+ return -1;
-+ }
-+
-+ /*
-+ * The section needs to be large enough to contain the DOF provider
-+ * structure appropriate for the given version.
-+ */
-+ if (sec->dofs_size <
-+ ((dof->dofh_ident[DOF_ID_VERSION] == DOF_VERSION_1)
-+ ? offsetof(struct dof_provider, dofpv_prenoffs)
-+ : sizeof(struct dof_provider))) {
-+ dtrace_dof_error(dof, "provider section too small");
-+ return -1;
-+ }
-+
-+ prov = (struct dof_provider *)(uintptr_t)(daddr + sec->dofs_offset);
-+ str_sec = dtrace_dof_sect(dof, DOF_SECT_STRTAB, prov->dofpv_strtab);
-+ prb_sec = dtrace_dof_sect(dof, DOF_SECT_PROBES, prov->dofpv_probes);
-+ arg_sec = dtrace_dof_sect(dof, DOF_SECT_PRARGS, prov->dofpv_prargs);
-+ off_sec = dtrace_dof_sect(dof, DOF_SECT_PROFFS, prov->dofpv_proffs);
-+
-+ if (str_sec == NULL || prb_sec == NULL ||
-+ arg_sec == NULL || off_sec == NULL)
-+ return -1;
-+
-+ enoff_sec = NULL;
-+
-+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 &&
-+ prov->dofpv_prenoffs != DOF_SECT_NONE) {
-+ enoff_sec = dtrace_dof_sect(dof, DOF_SECT_PRENOFFS,
-+ prov->dofpv_prenoffs);
-+
-+ if (enoff_sec == NULL)
-+ return -1;
-+ }
-+
-+ strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset);
-+
-+ if (prov->dofpv_name >= str_sec->dofs_size ||
-+ strlen(strtab + prov->dofpv_name) >= DTRACE_PROVNAMELEN) {
-+ dtrace_dof_error(dof, "invalid provider name");
-+ return -1;
-+ }
-+
-+ if (prb_sec->dofs_entsize == 0 ||
-+ prb_sec->dofs_entsize > prb_sec->dofs_size) {
-+ dtrace_dof_error(dof, "invalid entry size");
-+ return -1;
-+ }
-+
-+ if (prb_sec->dofs_entsize & (sizeof(uintptr_t) - 1)) {
-+ dtrace_dof_error(dof, "misaligned entry size");
-+ return -1;
-+ }
-+
-+ if (off_sec->dofs_entsize != sizeof(uint32_t)) {
-+ dtrace_dof_error(dof, "invalid entry size");
-+ return -1;
-+ }
-+
-+ if (off_sec->dofs_offset & (sizeof(uint32_t) - 1)) {
-+ dtrace_dof_error(dof, "misaligned section offset");
-+ return -1;
-+ }
-+
-+ if (arg_sec->dofs_entsize != sizeof(uint8_t)) {
-+ dtrace_dof_error(dof, "invalid entry size");
-+ return -1;
-+ }
-+
-+ arg = (uint8_t *)(uintptr_t)(daddr + arg_sec->dofs_offset);
-+ nprobes = prb_sec->dofs_size / prb_sec->dofs_entsize;
-+
-+ dt_dbg_dof(" DOF 0x%p %s::: with %d probes\n",
-+ dof, strtab + prov->dofpv_name, nprobes);
-+
-+ /*
-+ * Take a pass through the probes to check for errors.
-+ */
-+ for (j = 0; j < nprobes; j++) {
-+ prb = (struct dof_probe *)(uintptr_t)
-+ (daddr + prb_sec->dofs_offset +
-+ j * prb_sec->dofs_entsize);
-+
-+ if (prb->dofpr_func >= str_sec->dofs_size) {
-+ dtrace_dof_error(dof, "invalid function name");
-+ return -1;
-+ }
-+
-+ if (strlen(strtab + prb->dofpr_func) >= DTRACE_FUNCNAMELEN) {
-+ dtrace_dof_error(dof, "function name too long");
-+ return -1;
-+ }
-+
-+ if (prb->dofpr_name >= str_sec->dofs_size ||
-+ strlen(strtab + prb->dofpr_name) >= DTRACE_NAMELEN) {
-+ dtrace_dof_error(dof, "invalid probe name");
-+ return -1;
-+ }
-+
-+ /*
-+ * The offset count must not wrap the index, and the offsets
-+ * must also not overflow the section's data.
-+ */
-+ if (prb->dofpr_offidx + prb->dofpr_noffs < prb->dofpr_offidx ||
-+ (prb->dofpr_offidx + prb->dofpr_noffs) *
-+ off_sec->dofs_entsize > off_sec->dofs_size) {
-+ dtrace_dof_error(dof, "invalid probe offset");
-+ return -1;
-+ }
-+
-+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1) {
-+ /*
-+ * If there's no is-enabled offset section, make sure
-+ * there aren't any is-enabled offsets. Otherwise
-+ * perform the same checks as for probe offsets
-+ * (immediately above).
-+ */
-+ if (enoff_sec == NULL) {
-+ if (prb->dofpr_enoffidx != 0 ||
-+ prb->dofpr_nenoffs != 0) {
-+ dtrace_dof_error(dof,
-+ "is-enabled offsets "
-+ "with null section");
-+ return -1;
-+ }
-+ } else if (prb->dofpr_enoffidx + prb->dofpr_nenoffs <
-+ prb->dofpr_enoffidx ||
-+ (prb->dofpr_enoffidx + prb->dofpr_nenoffs) *
-+ enoff_sec->dofs_entsize >
-+ enoff_sec->dofs_size) {
-+ dtrace_dof_error(dof, "invalid is-enabled "
-+ "offset");
-+ return -1;
-+ }
-+
-+ if (prb->dofpr_noffs + prb->dofpr_nenoffs == 0) {
-+ dtrace_dof_error(dof, "zero probe and "
-+ "is-enabled offsets");
-+ return -1;
-+ }
-+ } else if (prb->dofpr_noffs == 0) {
-+ dtrace_dof_error(dof, "zero probe offsets");
-+ return -1;
-+ }
-+
-+ if (prb->dofpr_argidx + prb->dofpr_xargc < prb->dofpr_argidx ||
-+ (prb->dofpr_argidx + prb->dofpr_xargc) *
-+ arg_sec->dofs_entsize > arg_sec->dofs_size) {
-+ dtrace_dof_error(dof, "invalid args");
-+ return -1;
-+ }
-+
-+ typeidx = prb->dofpr_nargv;
-+ typestr = strtab + prb->dofpr_nargv;
-+ for (k = 0; k < prb->dofpr_nargc; k++) {
-+ if (typeidx >= str_sec->dofs_size) {
-+ dtrace_dof_error(dof, "bad native argument "
-+ "type");
-+ return -1;
-+ }
-+
-+ typesz = strlen(typestr) + 1;
-+ if (typesz > DTRACE_ARGTYPELEN) {
-+ dtrace_dof_error(dof, "native argument type "
-+ "too long");
-+ return -1;
-+ }
-+
-+ typeidx += typesz;
-+ typestr += typesz;
-+ }
-+
-+ typeidx = prb->dofpr_xargv;
-+ typestr = strtab + prb->dofpr_xargv;
-+ for (k = 0; k < prb->dofpr_xargc; k++) {
-+ if (arg[prb->dofpr_argidx + k] > prb->dofpr_nargc) {
-+ dtrace_dof_error(dof, "bad native argument "
-+ "index");
-+ return -1;
-+ }
-+
-+ if (typeidx >= str_sec->dofs_size) {
-+ dtrace_dof_error(dof, "bad translated "
-+ "argument type");
-+ return -1;
-+ }
-+
-+ typesz = strlen(typestr) + 1;
-+ if (typesz > DTRACE_ARGTYPELEN) {
-+ dtrace_dof_error(dof, "translated argument "
-+ "type too long");
-+ return -1;
-+ }
-+
-+ typeidx += typesz;
-+ typestr += typesz;
-+ }
-+
-+ dt_dbg_dof(" Probe %d %s:%s:%s:%s with %d offsets, "
-+ "%d is-enabled offsets\n", j,
-+ strtab + prov->dofpv_name, "",
-+ strtab + prb->dofpr_func, strtab + prb->dofpr_name,
-+ prb->dofpr_noffs, prb->dofpr_nenoffs);
-+ }
-+
-+ return 0;
-+}
-+
-+static void dtrace_helper_action_destroy(struct dtrace_helper_action *helper,
-+ struct dtrace_vstate *vstate)
-+{
-+ int i;
-+
-+ if (helper->dtha_predicate != NULL)
-+ dtrace_difo_release(helper->dtha_predicate, vstate);
-+
-+ for (i = 0; i < helper->dtha_nactions; i++) {
-+ ASSERT(helper->dtha_actions[i] != NULL);
-+ dtrace_difo_release(helper->dtha_actions[i], vstate);
-+ }
-+
-+ vfree(helper->dtha_actions);
-+ kfree(helper);
-+}
-+
-+static int dtrace_helper_action_add(int which, struct dtrace_ecbdesc *ep)
-+{
-+ struct dtrace_helpers *dth;
-+ struct dtrace_helper_action *helper, *last;
-+ struct dtrace_actdesc *act;
-+ struct dtrace_vstate *vstate;
-+ struct dtrace_predicate *pred;
-+ int count = 0, nactions = 0, i;
-+
-+ if (which < 0 || which >= DTRACE_NHELPER_ACTIONS)
-+ return -EINVAL;
-+
-+ if (current->dt_task == NULL)
-+ return -ENOMEM;
-+
-+ dth = current->dt_task->dt_helpers;
-+ last = dth->dthps_actions[which];
-+ vstate = &dth->dthps_vstate;
-+
-+ for (count = 0; last != NULL; last = last->dtha_next) {
-+ count++;
-+ if (last->dtha_next == NULL)
-+ break;
-+ }
-+
-+ /*
-+ * If we already have dtrace_helper_actions_max helper actions for this
-+ * helper action type, we'll refuse to add a new one.
-+ */
-+ if (count >= dtrace_helper_actions_max)
-+ return -ENOSPC;
-+
-+ helper = kzalloc(sizeof(struct dtrace_helper_action), GFP_KERNEL);
-+ if (helper == NULL)
-+ return -ENOMEM;
-+
-+ helper->dtha_generation = dth->dthps_generation;
-+
-+ pred = ep->dted_pred.dtpdd_predicate;
-+ if (pred != NULL) {
-+ ASSERT(pred->dtp_difo != NULL);
-+ dtrace_difo_hold(pred->dtp_difo);
-+ helper->dtha_predicate = pred->dtp_difo;
-+ }
-+
-+ for (act = ep->dted_action; act != NULL; act = act->dtad_next) {
-+ if (act->dtad_kind != DTRACEACT_DIFEXPR)
-+ goto err;
-+
-+ if (act->dtad_difo == NULL)
-+ goto err;
-+
-+ nactions++;
-+ }
-+
-+ helper->dtha_actions = vzalloc(sizeof(struct dtrace_difo *) *
-+ (helper->dtha_nactions = nactions));
-+ if (helper->dtha_actions == NULL)
-+ goto err;
-+
-+ for (act = ep->dted_action, i = 0; act != NULL; act = act->dtad_next) {
-+ dtrace_difo_hold(act->dtad_difo);
-+ helper->dtha_actions[i++] = act->dtad_difo;
-+ }
-+
-+ if (!dtrace_helper_validate(helper))
-+ goto err;
-+
-+ if (last == NULL)
-+ dth->dthps_actions[which] = helper;
-+ else
-+ last->dtha_next = helper;
-+
-+ if (vstate->dtvs_nlocals > dtrace_helptrace_nlocals) {
-+ dtrace_helptrace_nlocals = vstate->dtvs_nlocals;
-+ dtrace_helptrace_next = 0;
-+ }
-+
-+ return 0;
-+
-+err:
-+ dtrace_helper_action_destroy(helper, vstate);
-+ if (helper->dtha_actions != NULL)
-+ vfree(helper->dtha_actions);
-+ else
-+ return -ENOMEM;
-+
-+ return -EINVAL;
-+}
-+
-+static int dtrace_helper_provider_add(struct dof_helper *dofhp, int gen)
-+{
-+ struct dtrace_helpers *dth;
-+ struct dtrace_helper_provider *hprov, **tmp_provs;
-+ uint_t tmp_maxprovs, i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (current->dt_task == NULL)
-+ return -ENOMEM;
-+
-+ dth = current->dt_task->dt_helpers;
-+ ASSERT(dth != NULL);
-+
-+ /*
-+ * If we already have dtrace_helper_providers_max helper providers,
-+ * we're refuse to add a new one.
-+ */
-+ if (dth->dthps_nprovs >= dtrace_helper_providers_max)
-+ return -ENOSPC;
-+
-+ /*
-+ * Check to make sure this isn't a duplicate.
-+ */
-+ for (i = 0; i < dth->dthps_nprovs; i++) {
-+ if (dofhp->dofhp_addr ==
-+ dth->dthps_provs[i]->dthp_prov.dofhp_addr)
-+ return -EALREADY;
-+ }
-+
-+ hprov = kzalloc(sizeof(struct dtrace_helper_provider), GFP_KERNEL);
-+ if (hprov == NULL)
-+ return -ENOMEM;
-+ hprov->dthp_prov = *dofhp;
-+ hprov->dthp_ref = 1;
-+ hprov->dthp_generation = gen;
-+
-+ /*
-+ * Allocate a bigger table for helper providers if it's already full.
-+ */
-+ if (dth->dthps_maxprovs == dth->dthps_nprovs) {
-+ tmp_maxprovs = dth->dthps_maxprovs;
-+ tmp_provs = dth->dthps_provs;
-+
-+ if (dth->dthps_maxprovs == 0)
-+ dth->dthps_maxprovs = 2;
-+ else
-+ dth->dthps_maxprovs *= 2;
-+
-+ if (dth->dthps_maxprovs > dtrace_helper_providers_max)
-+ dth->dthps_maxprovs = dtrace_helper_providers_max;
-+
-+ ASSERT(tmp_maxprovs < dth->dthps_maxprovs);
-+
-+ dth->dthps_provs =
-+ vzalloc(dth->dthps_maxprovs *
-+ sizeof(struct dtrace_helper_provider *));
-+
-+ if (dth->dthps_provs == NULL) {
-+ kfree(hprov);
-+ return -ENOMEM;
-+ }
-+
-+ if (tmp_provs != NULL) {
-+ memcpy(dth->dthps_provs, tmp_provs,
-+ tmp_maxprovs *
-+ sizeof(struct dtrace_helper_provider *));
-+ vfree(tmp_provs);
-+ }
-+ }
-+
-+ dth->dthps_provs[dth->dthps_nprovs] = hprov;
-+ dth->dthps_nprovs++;
-+
-+ return 0;
-+}
-+
-+static void dtrace_helper_provider_destroy(struct dtrace_helper_provider *hprov)
-+{
-+ mutex_lock(&dtrace_lock);
-+
-+ if (--hprov->dthp_ref == 0) {
-+ struct dof_hdr *dof;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ dof = (struct dof_hdr *)(uintptr_t)hprov->dthp_prov.dofhp_dof;
-+ dtrace_dof_destroy(dof);
-+ kfree(hprov);
-+ } else
-+ mutex_unlock(&dtrace_lock);
-+}
-+
-+static void dtrace_dofattr2attr(struct dtrace_attribute *attr,
-+ const dof_attr_t dofattr)
-+{
-+ attr->dtat_name = DOF_ATTR_NAME(dofattr);
-+ attr->dtat_data = DOF_ATTR_DATA(dofattr);
-+ attr->dtat_class = DOF_ATTR_CLASS(dofattr);
-+}
-+
-+static void dtrace_dofprov2hprov(struct dtrace_helper_provdesc *hprov,
-+ const struct dof_provider *dofprov,
-+ char *strtab)
-+{
-+ hprov->dthpv_provname = strtab + dofprov->dofpv_name;
-+ dtrace_dofattr2attr(&hprov->dthpv_pattr.dtpa_provider,
-+ dofprov->dofpv_provattr);
-+ dtrace_dofattr2attr(&hprov->dthpv_pattr.dtpa_mod,
-+ dofprov->dofpv_modattr);
-+ dtrace_dofattr2attr(&hprov->dthpv_pattr.dtpa_func,
-+ dofprov->dofpv_funcattr);
-+ dtrace_dofattr2attr(&hprov->dthpv_pattr.dtpa_name,
-+ dofprov->dofpv_nameattr);
-+ dtrace_dofattr2attr(&hprov->dthpv_pattr.dtpa_args,
-+ dofprov->dofpv_argsattr);
-+}
-+
-+static void dtrace_helper_provider_remove_one(struct dof_helper *dhp,
-+ struct dof_sec *sec, pid_t pid)
-+{
-+ uintptr_t daddr = (uintptr_t)dhp->dofhp_dof;
-+ struct dof_hdr *dof = (struct dof_hdr *)daddr;
-+ struct dof_sec *str_sec;
-+ struct dof_provider *prov;
-+ char *strtab;
-+ struct dtrace_helper_provdesc dhpv;
-+ struct dtrace_meta *meta = dtrace_meta_pid;
-+ struct dtrace_mops *mops = &meta->dtm_mops;
-+
-+ prov = (struct dof_provider *)(uintptr_t)(daddr + sec->dofs_offset);
-+ str_sec = (struct dof_sec *)(uintptr_t)(daddr + dof->dofh_secoff +
-+ prov->dofpv_strtab *
-+ dof->dofh_secsize);
-+
-+ strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset);
-+
-+ /*
-+ * Create the provider.
-+ */
-+ dtrace_dofprov2hprov(&dhpv, prov, strtab);
-+
-+ dt_dbg_dof(" Removing provider %s for PID %d\n",
-+ dhpv.dthpv_provname, pid);
-+
-+ mops->dtms_remove_pid(meta->dtm_arg, &dhpv, pid);
-+
-+ meta->dtm_count--;
-+}
-+
-+static void dtrace_helper_provider_remove(struct dof_helper *dhp, pid_t pid)
-+{
-+ uintptr_t daddr = (uintptr_t)dhp->dofhp_dof;
-+ struct dof_hdr *dof = (struct dof_hdr *)daddr;
-+ int i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_meta_lock));
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(uintptr_t) (daddr + dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (sec->dofs_type != DOF_SECT_PROVIDER)
-+ continue;
-+
-+ dtrace_helper_provider_remove_one(dhp, sec, pid);
-+ }
-+}
-+
-+static void dtrace_helper_provide_one(struct dof_helper *dhp,
-+ struct dof_sec *sec,
-+ pid_t pid)
-+{
-+ uintptr_t daddr = (uintptr_t)dhp->dofhp_dof;
-+ uint32_t *off, *enoff;
-+ uint8_t *arg;
-+ char *strtab;
-+ uint_t i, nprobes;
-+ void *parg;
-+
-+ struct dof_hdr *dof = (struct dof_hdr *)daddr;
-+ struct dof_sec *str_sec, *prb_sec, *arg_sec, *off_sec,
-+ *enoff_sec;
-+ struct dof_provider *prov;
-+ struct dof_probe *probe;
-+ struct dtrace_helper_provdesc dhpv;
-+ struct dtrace_helper_probedesc dhpb;
-+ struct dtrace_meta *meta = dtrace_meta_pid;
-+ struct dtrace_mops *mops = &meta->dtm_mops;
-+
-+ prov = (struct dof_provider *)(uintptr_t)(daddr + sec->dofs_offset);
-+ str_sec = (struct dof_sec *)(uintptr_t)(daddr + dof->dofh_secoff +
-+ prov->dofpv_strtab *
-+ dof->dofh_secsize);
-+ prb_sec = (struct dof_sec *)(uintptr_t)(daddr + dof->dofh_secoff +
-+ prov->dofpv_probes *
-+ dof->dofh_secsize);
-+ arg_sec = (struct dof_sec *)(uintptr_t)(daddr + dof->dofh_secoff +
-+ prov->dofpv_prargs *
-+ dof->dofh_secsize);
-+ off_sec = (struct dof_sec *)(uintptr_t)(daddr + dof->dofh_secoff +
-+ prov->dofpv_proffs *
-+ dof->dofh_secsize);
-+
-+ strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset);
-+ off = (uint32_t *)(uintptr_t)(daddr + off_sec->dofs_offset);
-+ arg = (uint8_t *)(uintptr_t)(daddr + arg_sec->dofs_offset);
-+ enoff = NULL;
-+
-+ /*
-+ * See dtrace_helper_provider_validate().
-+ */
-+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 &&
-+ prov->dofpv_prenoffs != DOF_SECT_NONE) {
-+ enoff_sec = (struct dof_sec *)(uintptr_t)
-+ (daddr + dof->dofh_secoff +
-+ prov->dofpv_prenoffs * dof->dofh_secsize);
-+ enoff = (uint32_t *)(uintptr_t)
-+ (daddr + enoff_sec->dofs_offset);
-+ }
-+
-+ nprobes = prb_sec->dofs_size / prb_sec->dofs_entsize;
-+
-+ /*
-+ * Create the provider.
-+ */
-+ dtrace_dofprov2hprov(&dhpv, prov, strtab);
-+
-+ dt_dbg_dof(" Creating provider %s for PID %d\n",
-+ strtab + prov->dofpv_name, pid);
-+
-+ /*
-+ * This used to just 'return;' when parg is NULL, but that causes the
-+ * cleanup code (dtrace_helper_provider_remove[_one]) to make a call
-+ * to dtms_remove_pid() for a provider that never got created.
-+ *
-+ * If we fail to provide this provider, mark it as something to ignore,
-+ * so we don't try to process it during cleanup.
-+ */
-+ parg = mops->dtms_provide_pid(meta->dtm_arg, &dhpv, pid);
-+ if (parg == NULL) {
-+ sec->dofs_type = DOF_SECT_NONE;
-+ return;
-+ }
-+
-+ meta->dtm_count++;
-+
-+ /*
-+ * Create the probes.
-+ */
-+ for (i = 0; i < nprobes; i++) {
-+ probe = (struct dof_probe *)(uintptr_t)(daddr +
-+ prb_sec->dofs_offset +
-+ i * prb_sec->dofs_entsize);
-+
-+ dhpb.dthpb_mod = dhp->dofhp_mod;
-+ dhpb.dthpb_func = strtab + probe->dofpr_func;
-+ dhpb.dthpb_name = strtab + probe->dofpr_name;
-+ dhpb.dthpb_base = probe->dofpr_addr;
-+ dhpb.dthpb_offs = off + probe->dofpr_offidx;
-+ dhpb.dthpb_noffs = probe->dofpr_noffs;
-+
-+ if (enoff != NULL) {
-+ dhpb.dthpb_enoffs = enoff + probe->dofpr_enoffidx;
-+ dhpb.dthpb_nenoffs = probe->dofpr_nenoffs;
-+ } else {
-+ dhpb.dthpb_enoffs = NULL;
-+ dhpb.dthpb_nenoffs = 0;
-+ }
-+
-+ dhpb.dthpb_args = arg + probe->dofpr_argidx;
-+ dhpb.dthpb_nargc = probe->dofpr_nargc;
-+ dhpb.dthpb_xargc = probe->dofpr_xargc;
-+ dhpb.dthpb_ntypes = strtab + probe->dofpr_nargv;
-+ dhpb.dthpb_xtypes = strtab + probe->dofpr_xargv;
-+
-+ dt_dbg_dof(" Creating probe %s:%s:%s:%s\n",
-+ strtab + prov->dofpv_name, "", dhpb.dthpb_func,
-+ dhpb.dthpb_name);
-+
-+ mops->dtms_create_probe(meta->dtm_arg, parg, &dhpb);
-+ }
-+}
-+
-+void dtrace_helper_provide(struct dof_helper *dhp, pid_t pid)
-+{
-+ uintptr_t daddr = (uintptr_t)dhp->dofhp_dof;
-+ struct dof_hdr *dof = (struct dof_hdr *)daddr;
-+ int i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_meta_lock));
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(uintptr_t) (daddr + dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (sec->dofs_type != DOF_SECT_PROVIDER)
-+ continue;
-+
-+ dtrace_helper_provide_one(dhp, sec, pid);
-+ }
-+
-+ /*
-+ * We may have just created probes, so we must now rematch against any
-+ * retained enablings. Note that this call will acquire both cpu_lock
-+ * and dtrace_lock; the fact that we are holding dtrace_meta_lock now
-+ * is what defines the ordering with respect to these three locks.
-+ */
-+ dt_dbg_dof(" Re-matching against any retained enablings\n");
-+ dtrace_enabling_matchall();
-+}
-+
-+static void dtrace_helper_provider_register(struct task_struct *tsk,
-+ struct dtrace_helpers *dth,
-+ struct dof_helper *dofhp)
-+{
-+ ASSERT(!MUTEX_HELD(&dtrace_lock));
-+
-+ mutex_lock(&dtrace_meta_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (!dtrace_attached() || dtrace_meta_pid == NULL) {
-+ dt_dbg_dof(" No meta provider registered -- deferred\n");
-+
-+ /*
-+ * If the dtrace module is loaded but not attached, or if there
-+ * isn't a meta provider registered to deal with these provider
-+ * descriptions, we need to postpone creating the actual
-+ * providers until later.
-+ */
-+ if (dth->dthps_next == NULL && dth->dthps_prev == NULL &&
-+ dtrace_deferred_pid != dth) {
-+ dth->dthps_deferred = 1;
-+ dth->dthps_pid = tsk->pid;
-+ dth->dthps_next = dtrace_deferred_pid;
-+ dth->dthps_prev = NULL;
-+ if (dtrace_deferred_pid != NULL)
-+ dtrace_deferred_pid->dthps_prev = dth;
-+ dtrace_deferred_pid = dth;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+ } else if (dofhp != NULL) {
-+ /*
-+ * If the dtrace module is loaded and we have a particular
-+ * helper provider description, pass that off to the meta
-+ * provider.
-+ */
-+ mutex_unlock(&dtrace_lock);
-+
-+ dtrace_helper_provide(dofhp, tsk->pid);
-+ } else {
-+ /*
-+ * Otherwise, just pass all the helper provider descriptions
-+ * off to the meta provider.
-+ */
-+ int i;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ for (i = 0; i < dth->dthps_nprovs; i++) {
-+ dtrace_helper_provide(&dth->dthps_provs[i]->dthp_prov,
-+ tsk->pid);
-+ }
-+ }
-+
-+ mutex_unlock(&dtrace_meta_lock);
-+}
-+
-+int dtrace_helper_slurp(struct dof_hdr *dof, struct dof_helper *dhp)
-+{
-+ struct dtrace_helpers *dth;
-+ struct dtrace_vstate *vstate;
-+ struct dtrace_enabling *enab = NULL;
-+ int i, gen, rv;
-+ int nhelpers = 0, nprovs = 0, destroy = 1;
-+ uintptr_t daddr = (uintptr_t)dof;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (current->dt_task == NULL)
-+ return -1;
-+
-+ dth = current->dt_task->dt_helpers;
-+ if (dth == NULL)
-+ dth = dtrace_helpers_create(current);
-+
-+ if (dth == NULL) {
-+ dtrace_dof_destroy(dof);
-+ return -1;
-+ }
-+
-+ dt_dbg_dof("DOF 0x%p from helper {'%s', %p, %p}...\n",
-+ dof, dhp ? dhp->dofhp_mod : "<none>",
-+ dhp ? (void *)(dhp->dofhp_addr) : NULL,
-+ dhp ? (void *)(dhp->dofhp_dof) : NULL);
-+
-+ vstate = &dth->dthps_vstate;
-+
-+ rv = dtrace_dof_slurp(dof, vstate, NULL, &enab,
-+ dhp != NULL ? dhp->dofhp_addr : 0, FALSE);
-+ if (rv != 0) {
-+ dtrace_dof_destroy(dof);
-+ return rv;
-+ }
-+
-+ /*
-+ * Look for helper providers and validate their descriptions.
-+ */
-+ if (dhp != NULL) {
-+ dt_dbg_dof(" DOF 0x%p Validating providers...\n", dof);
-+
-+ for (i = 0; i < dof->dofh_secnum; i++) {
-+ struct dof_sec *sec;
-+
-+ sec = (struct dof_sec *)(uintptr_t)
-+ (daddr + dof->dofh_secoff +
-+ i * dof->dofh_secsize);
-+
-+ if (sec->dofs_type != DOF_SECT_PROVIDER)
-+ continue;
-+
-+ if (dtrace_helper_provider_validate(dof, sec) != 0) {
-+ dtrace_enabling_destroy(enab);
-+ dtrace_dof_destroy(dof);
-+ return -1;
-+ }
-+
-+ nprovs++;
-+ }
-+ }
-+
-+ /*
-+ * Now we need to walk through the ECB descriptions in the enabling.
-+ */
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_ecbdesc *ep = enab->dten_desc[i];
-+ struct dtrace_probedesc *desc = &ep->dted_probe;
-+
-+ dt_dbg_dof(" ECB Desc %s:%s:%s:%s\n",
-+ desc->dtpd_provider, desc->dtpd_mod,
-+ desc->dtpd_func, desc->dtpd_name);
-+ if (strcmp(desc->dtpd_provider, "dtrace") != 0)
-+ continue;
-+
-+ if (strcmp(desc->dtpd_mod, "helper") != 0)
-+ continue;
-+
-+ if (strcmp(desc->dtpd_func, "ustack") != 0)
-+ continue;
-+
-+ rv = dtrace_helper_action_add(DTRACE_HELPER_ACTION_USTACK, ep);
-+ if (rv != 0) {
-+ /*
-+ * Adding this helper action failed -- we are now going
-+ * to rip out the entire generation and return failure.
-+ */
-+ dtrace_helper_destroygen(dth->dthps_generation);
-+ dtrace_enabling_destroy(enab);
-+ dtrace_dof_destroy(dof);
-+ return -1;
-+ }
-+
-+ nhelpers++;
-+ }
-+
-+ if (nhelpers < enab->dten_ndesc)
-+ dtrace_dof_error(dof, "unmatched helpers");
-+
-+ gen = dth->dthps_generation++;
-+ dtrace_enabling_destroy(enab);
-+
-+ if (dhp != NULL && nprovs > 0) {
-+ dt_dbg_dof(" DOF 0x%p Adding and registering providers\n",
-+ dof);
-+
-+ dhp->dofhp_dof = (uint64_t)(uintptr_t)dof;
-+ if (dtrace_helper_provider_add(dhp, gen) == 0) {
-+ mutex_unlock(&dtrace_lock);
-+ dtrace_helper_provider_register(current, dth, dhp);
-+ mutex_lock(&dtrace_lock);
-+
-+ destroy = 0;
-+ }
-+ }
-+
-+ if (destroy)
-+ dtrace_dof_destroy(dof);
-+
-+ return gen;
-+}
-+
-+void dtrace_helpers_destroy(struct task_struct *tsk)
-+{
-+ struct dtrace_helpers *help;
-+ struct dtrace_vstate *vstate;
-+ int i;
-+
-+ if (tsk->dt_task == NULL)
-+ return;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ ASSERT(tsk->dt_task->dt_helpers != NULL);
-+ ASSERT(dtrace_helpers > 0);
-+
-+ dt_dbg_dof("Helper cleanup: PID %d\n", tsk->pid);
-+
-+ help = tsk->dt_task->dt_helpers;
-+ vstate = &help->dthps_vstate;
-+
-+ /*
-+ * We're now going to lose the help from this process.
-+ */
-+ tsk->dt_task->dt_helpers = NULL;
-+ dtrace_sync();
-+
-+ /*
-+ * Destroy the helper actions.
-+ */
-+ for (i = 0; i < DTRACE_NHELPER_ACTIONS; i++) {
-+ struct dtrace_helper_action *h, *next;
-+
-+ for (h = help->dthps_actions[i]; h != NULL; h = next) {
-+ next = h->dtha_next;
-+ dtrace_helper_action_destroy(h, vstate);
-+ h = next;
-+ }
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ /*
-+ * Destroy the helper providers.
-+ */
-+ if (help->dthps_maxprovs > 0) {
-+ mutex_lock(&dtrace_meta_lock);
-+ if (dtrace_meta_pid != NULL) {
-+ ASSERT(dtrace_deferred_pid == NULL);
-+
-+ for (i = 0; i < help->dthps_nprovs; i++) {
-+ dtrace_helper_provider_remove(
-+ &help->dthps_provs[i]->dthp_prov,
-+ tsk->pid);
-+ }
-+ } else {
-+ mutex_lock(&dtrace_lock);
-+ ASSERT(help->dthps_deferred == 0 ||
-+ help->dthps_next != NULL ||
-+ help->dthps_prev != NULL ||
-+ help == dtrace_deferred_pid);
-+
-+ /*
-+ * Remove the helper from the deferred list.
-+ */
-+ if (help->dthps_next != NULL)
-+ help->dthps_next->dthps_prev = help->dthps_prev;
-+ if (help->dthps_prev != NULL)
-+ help->dthps_prev->dthps_next = help->dthps_next;
-+ if (dtrace_deferred_pid == help) {
-+ dtrace_deferred_pid = help->dthps_next;
-+ ASSERT(help->dthps_prev == NULL);
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+ }
-+
-+ mutex_unlock(&dtrace_meta_lock);
-+
-+ for (i = 0; i < help->dthps_nprovs; i++)
-+ dtrace_helper_provider_destroy(help->dthps_provs[i]);
-+
-+ vfree(help->dthps_provs);
-+ }
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ dtrace_vstate_fini(&help->dthps_vstate);
-+ vfree(help->dthps_actions);
-+ kfree(help);
-+
-+ --dtrace_helpers;
-+ mutex_unlock(&dtrace_lock);
-+}
-+
-+void dtrace_helpers_duplicate(struct task_struct *from, struct task_struct *to)
-+{
-+ struct dtrace_task *dfrom = from->dt_task;
-+ struct dtrace_task *dto = to->dt_task;
-+ struct dtrace_helpers *help, *newhelp;
-+ struct dtrace_helper_action *helper, *new, *last;
-+ struct dtrace_difo *dp;
-+ struct dtrace_vstate *vstate;
-+
-+ int i, j, sz, hasprovs = 0;
-+
-+ if (dfrom == NULL || dto == NULL)
-+ return;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ ASSERT(dfrom->dt_helpers != NULL);
-+ ASSERT(dtrace_helpers > 0);
-+
-+ help = dfrom->dt_helpers;
-+ newhelp = dtrace_helpers_create(to);
-+
-+ ASSERT(dto->dt_helpers != NULL);
-+
-+ newhelp->dthps_generation = help->dthps_generation;
-+ vstate = &newhelp->dthps_vstate;
-+
-+ /*
-+ * Duplicate the helper actions.
-+ */
-+ for (i = 0; i < DTRACE_NHELPER_ACTIONS; i++) {
-+ helper = help->dthps_actions[i];
-+ if (helper == NULL)
-+ continue;
-+
-+ for (last = NULL; helper != NULL; helper = helper->dtha_next) {
-+ new = kzalloc(sizeof(struct dtrace_helper_action),
-+ GFP_KERNEL);
-+ new->dtha_generation = helper->dtha_generation;
-+
-+ dp = helper->dtha_predicate;
-+ if (dp != NULL) {
-+ dp = dtrace_difo_duplicate(dp, vstate);
-+ new->dtha_predicate = dp;
-+ }
-+
-+ new->dtha_nactions = helper->dtha_nactions;
-+ sz = sizeof(struct dtrace_difo *) * new->dtha_nactions;
-+ new->dtha_actions = vmalloc(sz);
-+
-+ for (j = 0; j < new->dtha_nactions; j++) {
-+ struct dtrace_difo *dp;
-+
-+ dp = helper->dtha_actions[j];
-+ ASSERT(dp != NULL);
-+
-+ dp = dtrace_difo_duplicate(dp, vstate);
-+ new->dtha_actions[j] = dp;
-+ }
-+
-+ if (last != NULL)
-+ last->dtha_next = new;
-+ else
-+ newhelp->dthps_actions[i] = new;
-+
-+ last = new;
-+ }
-+ }
-+
-+ /*
-+ * Duplicate the helper providers and register them with the
-+ * DTrace framework.
-+ */
-+ if (help->dthps_nprovs > 0) {
-+ newhelp->dthps_nprovs = help->dthps_nprovs;
-+ newhelp->dthps_maxprovs = help->dthps_nprovs;
-+ newhelp->dthps_provs = vmalloc(
-+ newhelp->dthps_nprovs *
-+ sizeof(struct dtrace_helper_provider *));
-+
-+ for (i = 0; i < newhelp->dthps_nprovs; i++) {
-+ newhelp->dthps_provs[i] = help->dthps_provs[i];
-+ newhelp->dthps_provs[i]->dthp_ref++;
-+ }
-+
-+ hasprovs = 1;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ if (hasprovs)
-+ dtrace_helper_provider_register(to, newhelp, NULL);
-+}
-+
-+int dtrace_helper_destroygen(int gen)
-+{
-+ struct task_struct *p = current;
-+ struct dtrace_helpers *dth;
-+ struct dtrace_vstate *vstate;
-+ int i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (current->dt_task == NULL)
-+ return -ENOMEM;
-+
-+ dth = current->dt_task->dt_helpers;
-+
-+ if (dth == NULL || gen > dth->dthps_generation)
-+ return -EINVAL;
-+
-+ vstate = &dth->dthps_vstate;
-+
-+ for (i = 0; i < DTRACE_NHELPER_ACTIONS; i++) {
-+ struct dtrace_helper_action *last = NULL, *h, *next;
-+
-+ for (h = dth->dthps_actions[i]; h != NULL; h = next) {
-+ next = h->dtha_next;
-+
-+ dt_dbg_dof(" Comparing action (agen %d vs rgen %d)\n",
-+ h->dtha_generation, gen);
-+
-+ if (h->dtha_generation == gen) {
-+ if (last != NULL)
-+ last->dtha_next = next;
-+ else
-+ dth->dthps_actions[i] = next;
-+
-+ dtrace_helper_action_destroy(h, vstate);
-+ } else
-+ last = h;
-+ }
-+ }
-+
-+ /*
-+ * Iterate until we've cleared out all helper providers with the given
-+ * generation number.
-+ */
-+ for (;;) {
-+ struct dtrace_helper_provider *prov = NULL;
-+
-+ /*
-+ * Look for a helper provider with the right generation. We
-+ * have to start back at the beginning of the list each time
-+ * because we drop dtrace_lock. It's unlikely that we'll make
-+ * more than two passes.
-+ */
-+ for (i = 0; i < dth->dthps_nprovs; i++) {
-+ prov = dth->dthps_provs[i];
-+
-+ if (prov->dthp_generation == gen)
-+ break;
-+ }
-+
-+ /*
-+ * If there were no matches, we are done.
-+ */
-+ if (i == dth->dthps_nprovs)
-+ break;
-+
-+ dt_dbg_dof(" Found provider with gen %d\n", gen);
-+
-+ /*
-+ * Move the last helper provider into this slot.
-+ */
-+ dth->dthps_nprovs--;
-+ dth->dthps_provs[i] = dth->dthps_provs[dth->dthps_nprovs];
-+ dth->dthps_provs[dth->dthps_nprovs] = NULL;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ /*
-+ * If we have a meta provider, remove this helper provider.
-+ */
-+ mutex_lock(&dtrace_meta_lock);
-+
-+ if (dtrace_meta_pid != NULL) {
-+ ASSERT(dtrace_deferred_pid == NULL);
-+
-+ dtrace_helper_provider_remove(&prov->dthp_prov,
-+ p->pid);
-+ }
-+
-+ mutex_unlock(&dtrace_meta_lock);
-+
-+ dtrace_helper_provider_destroy(prov);
-+
-+ mutex_lock(&dtrace_lock);
-+ }
-+
-+ return 0;
-+}
-+
-+static void dtrace_helper_trace(struct dtrace_helper_action *helper,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate, int where)
-+{
-+ uint32_t size, next, nnext, i;
-+ struct dtrace_helptrace *ent;
-+ uint16_t flags = this_cpu_core->cpuc_dtrace_flags;
-+
-+ if (!dtrace_helptrace_enabled)
-+ return;
-+
-+ ASSERT(vstate->dtvs_nlocals <= dtrace_helptrace_nlocals);
-+
-+ /*
-+ * What would a tracing framework be without its own tracing
-+ * framework? (Well, a hell of a lot simpler, for starters...)
-+ */
-+ size = sizeof(struct dtrace_helptrace) + dtrace_helptrace_nlocals *
-+ sizeof(uint64_t) - sizeof(uint64_t);
-+
-+ /*
-+ * Iterate until we can allocate a slot in the trace buffer.
-+ */
-+ do {
-+ next = dtrace_helptrace_next;
-+
-+ if (next + size < dtrace_helptrace_bufsize)
-+ nnext = next + size;
-+ else
-+ nnext = size;
-+ } while (cmpxchg(&dtrace_helptrace_next, next, nnext) != next);
-+
-+ /*
-+ * We have our slot; fill it in.
-+ */
-+ if (nnext == size)
-+ next = 0;
-+
-+ ent = (struct dtrace_helptrace *)&dtrace_helptrace_buffer[next];
-+ ent->dtht_helper = helper;
-+ ent->dtht_where = where;
-+ ent->dtht_nlocals = vstate->dtvs_nlocals;
-+
-+ ent->dtht_fltoffs = (mstate->dtms_present & DTRACE_MSTATE_FLTOFFS)
-+ ? mstate->dtms_fltoffs
-+ : -1;
-+ ent->dtht_fault = DTRACE_FLAGS2FLT(flags);
-+ ent->dtht_illval = this_cpu_core->cpuc_dtrace_illval;
-+
-+ for (i = 0; i < vstate->dtvs_nlocals; i++) {
-+ struct dtrace_statvar *svar;
-+
-+ svar = vstate->dtvs_locals[i];
-+ if (svar == NULL)
-+ continue;
-+
-+ ASSERT(svar->dtsv_size >= NR_CPUS * sizeof(uint64_t));
-+ ent->dtht_locals[i] =
-+ ((uint64_t *)(uintptr_t)svar->dtsv_data)[
-+ smp_processor_id()];
-+ }
-+}
-+
-+uint64_t dtrace_helper(int which, struct dtrace_mstate *mstate,
-+ struct dtrace_state *state, uint64_t arg0,
-+ uint64_t arg1)
-+{
-+ uint16_t *flags = &this_cpu_core->cpuc_dtrace_flags;
-+ uint64_t sarg0 = mstate->dtms_arg[0];
-+ uint64_t sarg1 = mstate->dtms_arg[1];
-+ uint64_t rval = 0;
-+ struct dtrace_helpers *helpers;
-+ struct dtrace_helper_action *helper;
-+ struct dtrace_vstate *vstate;
-+ struct dtrace_difo *pred;
-+ int i, trace = dtrace_helptrace_enabled;
-+
-+ ASSERT(which >= 0 && which < DTRACE_NHELPER_ACTIONS);
-+
-+ if (current->dt_task == NULL)
-+ return 0;
-+
-+ helpers = current->dt_task->dt_helpers;
-+ if (helpers == NULL)
-+ return 0;
-+
-+ helper = helpers->dthps_actions[which];
-+ if (helper == NULL)
-+ return 0;
-+
-+ vstate = &helpers->dthps_vstate;
-+ mstate->dtms_arg[0] = arg0;
-+ mstate->dtms_arg[1] = arg1;
-+
-+ /*
-+ * Now iterate over each helper. If its predicate evaluates to 'true',
-+ * we'll call the corresponding actions. Note that the below calls
-+ * to dtrace_dif_emulate() may set faults in machine state. This is
-+ * okay: our caller (the outer dtrace_dif_emulate()) will simply plow
-+ * the stored DIF offset with its own (which is the desired behavior).
-+ * Also, note the calls to dtrace_dif_emulate() may allocate scratch
-+ * from machine state; this is okay, too.
-+ */
-+ for (; helper != NULL; helper = helper->dtha_next) {
-+ pred = helper->dtha_predicate;
-+ if (pred != NULL) {
-+ if (trace)
-+ dtrace_helper_trace(helper, mstate, vstate, 0);
-+
-+ if (!dtrace_dif_emulate(pred, mstate, vstate, state))
-+ goto next;
-+
-+ if (*flags & CPU_DTRACE_FAULT)
-+ goto err;
-+ }
-+
-+ for (i = 0; i < helper->dtha_nactions; i++) {
-+ if (trace)
-+ dtrace_helper_trace(helper, mstate, vstate,
-+ i + 1);
-+
-+ rval = dtrace_dif_emulate(helper->dtha_actions[i],
-+ mstate, vstate, state);
-+
-+ if (*flags & CPU_DTRACE_FAULT)
-+ goto err;
-+ }
-+
-+next:
-+ if (trace)
-+ dtrace_helper_trace(helper, mstate, vstate,
-+ DTRACE_HELPTRACE_NEXT);
-+ }
-+
-+ if (trace)
-+ dtrace_helper_trace(helper, mstate, vstate,
-+ DTRACE_HELPTRACE_DONE);
-+
-+ /*
-+ * Restore the arg0 that we saved upon entry.
-+ */
-+ mstate->dtms_arg[0] = sarg0;
-+ mstate->dtms_arg[1] = sarg1;
-+
-+ return rval;
-+
-+err:
-+ if (trace)
-+ dtrace_helper_trace(helper, mstate, vstate,
-+ DTRACE_HELPTRACE_ERR);
-+
-+ /*
-+ * Restore the arg0 that we saved upon entry.
-+ */
-+ mstate->dtms_arg[0] = sarg0;
-+ mstate->dtms_arg[1] = sarg1;
-+
-+ return 0;
-+}
-diff --git a/dtrace/dtrace_ecb.c b/dtrace/dtrace_ecb.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..cc04d1a14661b08694a09a3d741523d9380b0dd2
---- /dev/null
-+++ b/dtrace/dtrace_ecb.c
-@@ -0,0 +1,936 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_ecb.c
-+ * DESCRIPTION: DTrace - ECB implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+struct dtrace_ecb *dtrace_ecb_create_cache;
-+
-+static struct dtrace_action *
-+dtrace_ecb_aggregation_create(struct dtrace_ecb *ecb,
-+ struct dtrace_actdesc *desc)
-+{
-+ struct dtrace_aggregation *agg;
-+ size_t size = sizeof(uint64_t);
-+ int ntuple = desc->dtad_ntuple;
-+ struct dtrace_action *act;
-+ struct dtrace_recdesc *frec;
-+ dtrace_aggid_t aggid;
-+ struct dtrace_state *state = ecb->dte_state;
-+
-+ agg = kzalloc(sizeof(struct dtrace_aggregation), GFP_KERNEL);
-+ if (agg == NULL)
-+ return NULL;
-+
-+ agg->dtag_ecb = ecb;
-+
-+ ASSERT(DTRACEACT_ISAGG(desc->dtad_kind));
-+
-+ switch (desc->dtad_kind) {
-+ case DTRACEAGG_MIN:
-+ agg->dtag_initial = INT64_MAX;
-+ agg->dtag_aggregate = dtrace_aggregate_min;
-+ break;
-+
-+ case DTRACEAGG_MAX:
-+ agg->dtag_initial = INT64_MIN;
-+ agg->dtag_aggregate = dtrace_aggregate_max;
-+ break;
-+
-+ case DTRACEAGG_COUNT:
-+ agg->dtag_aggregate = dtrace_aggregate_count;
-+ break;
-+
-+ case DTRACEAGG_QUANTIZE:
-+ agg->dtag_aggregate = dtrace_aggregate_quantize;
-+ size = (((sizeof(uint64_t) * NBBY) - 1) * 2 + 1) *
-+ sizeof(uint64_t);
-+ break;
-+
-+ case DTRACEAGG_LQUANTIZE: {
-+ uint16_t step = DTRACE_LQUANTIZE_STEP(desc->dtad_arg);
-+ uint16_t levels =
-+ DTRACE_LQUANTIZE_LEVELS(desc->dtad_arg);
-+
-+ agg->dtag_initial = desc->dtad_arg;
-+ agg->dtag_aggregate = dtrace_aggregate_lquantize;
-+
-+ if (step == 0 || levels == 0)
-+ goto err;
-+
-+ size = levels * sizeof(uint64_t) + 3 * sizeof(uint64_t);
-+ break;
-+ }
-+
-+ case DTRACEAGG_LLQUANTIZE: {
-+ uint16_t factor = DTRACE_LLQUANTIZE_FACTOR(desc->dtad_arg);
-+ uint16_t lmag = DTRACE_LLQUANTIZE_LMAG(desc->dtad_arg);
-+ uint16_t hmag = DTRACE_LLQUANTIZE_HMAG(desc->dtad_arg);
-+ uint16_t steps = DTRACE_LLQUANTIZE_STEPS(desc->dtad_arg);
-+ uint64_t buf64s;
-+
-+ agg->dtag_initial = desc->dtad_arg;
-+ agg->dtag_aggregate = dtrace_aggregate_llquantize;
-+
-+ /*
-+ * 64 is the largest hmag can practically be (for the smallest
-+ * possible value of factor, 2). libdtrace has already checked
-+ * for overflow, so if hmag > 64, we have corrupted DOF.
-+ */
-+ if (factor < 2 || steps == 0 || hmag > 64)
-+ goto err;
-+
-+ /*
-+ * The size of the buffer for an llquantize() is given by:
-+ * (hmag-lmag+1) logarithmic ranges
-+ * x
-+ * (steps - steps/factor) bins per range
-+ * x
-+ * 2 signs
-+ * +
-+ * two overflow bins
-+ * +
-+ * one underflow bin
-+ * +
-+ * beginning word to encode factor,lmag,hmag,steps
-+ */
-+ buf64s = ((hmag-lmag+1)*(steps-steps/factor)*2+4);
-+ size = buf64s * sizeof(uint64_t);
-+ break;
-+ }
-+
-+ case DTRACEAGG_AVG:
-+ agg->dtag_aggregate = dtrace_aggregate_avg;
-+ size = sizeof(uint64_t) * 2;
-+ break;
-+
-+ case DTRACEAGG_STDDEV:
-+ agg->dtag_aggregate = dtrace_aggregate_stddev;
-+ size = sizeof(uint64_t) * 4;
-+ break;
-+
-+ case DTRACEAGG_SUM:
-+ agg->dtag_aggregate = dtrace_aggregate_sum;
-+ break;
-+
-+ default:
-+ goto err;
-+ }
-+
-+ agg->dtag_action.dta_rec.dtrd_size = size;
-+
-+ if (ntuple == 0)
-+ goto err;
-+
-+ for (act = ecb->dte_action_last; act != NULL; act = act->dta_prev) {
-+ if (DTRACEACT_ISAGG(act->dta_kind))
-+ break;
-+
-+ if (--ntuple == 0) {
-+ agg->dtag_first = act;
-+ goto success;
-+ }
-+ }
-+
-+ ASSERT(ntuple != 0);
-+err:
-+ kfree(agg);
-+ return NULL;
-+
-+success:
-+ ASSERT(ecb->dte_action_last != NULL);
-+ act = ecb->dte_action_last;
-+
-+ if (act->dta_kind == DTRACEACT_DIFEXPR) {
-+ ASSERT(act->dta_difo != NULL);
-+
-+ if (act->dta_difo->dtdo_rtype.dtdt_size == 0)
-+ agg->dtag_hasarg = 1;
-+ }
-+
-+ /*
-+ * Get an ID for the aggregation (add it to the idr).
-+ */
-+ idr_preload(GFP_KERNEL);
-+ aggid = idr_alloc_cyclic(&state->dts_agg_idr, agg, 0, 0, GFP_NOWAIT);
-+ idr_preload_end();
-+ if (aggid < 0) {
-+ /* FIXME: need to handle this */
-+ }
-+
-+ state->dts_naggs++;
-+ agg->dtag_id = aggid;
-+
-+ frec = &agg->dtag_first->dta_rec;
-+ if (frec->dtrd_alignment < sizeof(dtrace_aggid_t))
-+ frec->dtrd_alignment = sizeof(dtrace_aggid_t);
-+
-+ for (act = agg->dtag_first; act != NULL; act = act->dta_next) {
-+ ASSERT(!act->dta_intuple);
-+
-+ act->dta_intuple = 1;
-+ }
-+
-+ return &agg->dtag_action;
-+}
-+
-+void dtrace_ecb_aggregation_destroy(struct dtrace_ecb *ecb,
-+ struct dtrace_action *act)
-+{
-+ struct dtrace_aggregation *agg = (struct dtrace_aggregation *)act;
-+ struct dtrace_state *state = ecb->dte_state;
-+
-+ ASSERT(DTRACEACT_ISAGG(act->dta_kind));
-+
-+ idr_remove(&state->dts_agg_idr, agg->dtag_id);
-+ state->dts_naggs--;
-+
-+ kfree(agg);
-+}
-+
-+static int dtrace_ecb_action_add(struct dtrace_ecb *ecb,
-+ struct dtrace_actdesc *desc)
-+{
-+ struct dtrace_action *action, *last;
-+ struct dtrace_difo *dp = desc->dtad_difo;
-+ uint32_t size = 0, align = sizeof(uint8_t), mask;
-+ uint16_t format = 0;
-+ struct dtrace_recdesc *rec;
-+ struct dtrace_state *state = ecb->dte_state;
-+ dtrace_optval_t *opt = state->dts_options, nframes, strsize;
-+ uint64_t arg = desc->dtad_arg;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(ecb->dte_action == NULL || ecb->dte_action->dta_refcnt == 1);
-+
-+ if (DTRACEACT_ISAGG(desc->dtad_kind)) {
-+ struct dtrace_action *act;
-+
-+ for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
-+ if (act->dta_kind == DTRACEACT_COMMIT)
-+ return -EINVAL;
-+
-+ if (act->dta_kind == DTRACEACT_SPECULATE)
-+ return -EINVAL;
-+ }
-+
-+ action = dtrace_ecb_aggregation_create(ecb, desc);
-+ if (action == NULL)
-+ return -EINVAL;
-+ } else {
-+ if (DTRACEACT_ISDESTRUCTIVE(desc->dtad_kind) ||
-+ (desc->dtad_kind == DTRACEACT_DIFEXPR &&
-+ dp != NULL && dp->dtdo_destructive))
-+ state->dts_destructive = 1;
-+
-+ switch (desc->dtad_kind) {
-+ case DTRACEACT_PRINTF:
-+ case DTRACEACT_PRINTA:
-+ case DTRACEACT_SYSTEM:
-+ case DTRACEACT_FREOPEN:
-+ if ((void *)(uintptr_t)arg == NULL) {
-+ ASSERT(desc->dtad_kind == DTRACEACT_PRINTA);
-+
-+ format = 0;
-+ } else {
-+ ASSERT((void *)(uintptr_t)arg != NULL);
-+#ifdef FIXME
-+ ASSERT(arg > KERNELBASE);
-+#endif
-+
-+ format = dtrace_format_add(
-+ state, (char *)(uintptr_t)arg);
-+ }
-+ /* fallthru */
-+
-+ case DTRACEACT_TRACEMEM:
-+ case DTRACEACT_LIBACT:
-+ case DTRACEACT_DIFEXPR:
-+ if (dp == NULL)
-+ return -EINVAL;
-+
-+ size = dp->dtdo_rtype.dtdt_size;
-+ if (size != 0)
-+ break;
-+
-+ if (dp->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING) {
-+ if (!(dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF))
-+ return -EINVAL;
-+
-+ size = opt[DTRACEOPT_STRSIZE];
-+ }
-+
-+ break;
-+
-+ case DTRACEACT_STACK:
-+ nframes = arg;
-+ if (nframes == 0) {
-+ nframes = opt[DTRACEOPT_STACKFRAMES];
-+
-+ ASSERT(nframes > 0);
-+
-+ arg = nframes;
-+ }
-+
-+ size = nframes * sizeof(uint64_t);
-+ break;
-+
-+ case DTRACEACT_JSTACK:
-+ strsize = DTRACE_USTACK_STRSIZE(arg);
-+ if (strsize == 0)
-+ strsize = opt[DTRACEOPT_JSTACKSTRSIZE];
-+
-+ nframes = DTRACE_USTACK_NFRAMES(arg);
-+ if (nframes == 0)
-+ nframes = opt[DTRACEOPT_JSTACKFRAMES];
-+
-+ arg = DTRACE_USTACK_ARG(nframes, strsize);
-+ /* fallthru */
-+
-+ case DTRACEACT_USTACK:
-+ if (desc->dtad_kind != DTRACEACT_JSTACK &&
-+ (nframes = DTRACE_USTACK_NFRAMES(arg)) == 0) {
-+ strsize = DTRACE_USTACK_STRSIZE(arg);
-+ nframes = opt[DTRACEOPT_USTACKFRAMES];
-+
-+ ASSERT(nframes > 0);
-+
-+ arg = DTRACE_USTACK_ARG(nframes, strsize);
-+ }
-+
-+ size = (nframes + 2) * sizeof(uint64_t);
-+ size += DTRACE_USTACK_STRSIZE(arg);
-+ size = P2ROUNDUP(size, (uint32_t)(sizeof(uintptr_t)));
-+
-+ break;
-+
-+ case DTRACEACT_SYM:
-+ case DTRACEACT_MOD:
-+ if (dp == NULL || ((size = dp->dtdo_rtype.dtdt_size) !=
-+ sizeof(uint64_t)) ||
-+ (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF))
-+ return -EINVAL;
-+
-+ break;
-+
-+ case DTRACEACT_USYM:
-+ case DTRACEACT_UMOD:
-+ case DTRACEACT_UADDR:
-+ if (dp == NULL ||
-+ (dp->dtdo_rtype.dtdt_size != sizeof(uint64_t)) ||
-+ (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF))
-+ return -EINVAL;
-+
-+ size = 3 * sizeof(uint64_t);
-+
-+ break;
-+
-+ case DTRACEACT_STOP:
-+ case DTRACEACT_BREAKPOINT:
-+ case DTRACEACT_PANIC:
-+ break;
-+
-+ case DTRACEACT_CHILL:
-+ case DTRACEACT_DISCARD:
-+ case DTRACEACT_RAISE:
-+ if (dp == NULL)
-+ return -EINVAL;
-+
-+ break;
-+
-+ case DTRACEACT_EXIT:
-+ if (dp == NULL || (size = dp->dtdo_rtype.dtdt_size) !=
-+ sizeof(int) ||
-+ (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF))
-+ return -EINVAL;
-+
-+ break;
-+
-+ case DTRACEACT_SPECULATE:
-+ if (ecb->dte_size > sizeof(dtrace_epid_t))
-+ return -EINVAL;
-+
-+ if (dp == NULL)
-+ return -EINVAL;
-+
-+ state->dts_speculates = 1;
-+
-+ break;
-+
-+ case DTRACEACT_COMMIT: {
-+ struct dtrace_action *act = ecb->dte_action;
-+
-+ for (; act != NULL; act = act->dta_next) {
-+ if (act->dta_kind == DTRACEACT_COMMIT)
-+ return -EINVAL;
-+ }
-+
-+ if (dp == NULL)
-+ return -EINVAL;
-+
-+ break;
-+ }
-+
-+ case DTRACEACT_PCAP:
-+ size = dp->dtdo_rtype.dtdt_size;
-+ break;
-+
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ if (size != 0 || desc->dtad_kind == DTRACEACT_SPECULATE) {
-+ struct dtrace_action *act = ecb->dte_action;
-+
-+ for (; act != NULL; act = act->dta_next) {
-+ if (act->dta_kind == DTRACEACT_COMMIT)
-+ return -EINVAL;
-+ }
-+ }
-+
-+ action = kzalloc(sizeof(struct dtrace_action), GFP_KERNEL);
-+ if (action == NULL)
-+ return -ENOMEM;
-+
-+ action->dta_rec.dtrd_size = size;
-+ }
-+
-+ action->dta_refcnt = 1;
-+ rec = &action->dta_rec;
-+ size = rec->dtrd_size;
-+
-+ for (mask = sizeof(uint64_t) - 1; size != 0 && mask > 0; mask >>= 1) {
-+ if (!(size & mask)) {
-+ align = mask + 1;
-+
-+ break;
-+ }
-+ }
-+
-+ action->dta_kind = desc->dtad_kind;
-+
-+ action->dta_difo = dp;
-+ if (action->dta_difo != NULL)
-+ dtrace_difo_hold(dp);
-+
-+ rec->dtrd_action = action->dta_kind;
-+ rec->dtrd_arg = arg;
-+ rec->dtrd_uarg = desc->dtad_uarg;
-+ rec->dtrd_alignment = (uint16_t)align;
-+ rec->dtrd_format = format;
-+
-+ last = ecb->dte_action_last;
-+ if (last != NULL) {
-+ ASSERT(ecb->dte_action != NULL);
-+
-+ action->dta_prev = last;
-+ last->dta_next = action;
-+ } else {
-+ ASSERT(ecb->dte_action == NULL);
-+
-+ ecb->dte_action = action;
-+ }
-+
-+ ecb->dte_action_last = action;
-+
-+ return 0;
-+}
-+
-+static void dtrace_ecb_action_remove(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_action *act = ecb->dte_action, *next;
-+ struct dtrace_vstate *vstate = &ecb->dte_state->dts_vstate;
-+ struct dtrace_difo *dp;
-+ uint16_t format;
-+
-+ if (act != NULL && act->dta_refcnt > 1) {
-+ ASSERT(act->dta_next == NULL || act->dta_next->dta_refcnt == 1);
-+
-+ act->dta_refcnt--;
-+ } else {
-+ for (; act != NULL; act = next) {
-+ next = act->dta_next;
-+ ASSERT(next != NULL || act == ecb->dte_action_last);
-+ ASSERT(act->dta_refcnt == 1);
-+
-+ format = act->dta_rec.dtrd_format;
-+ if (format != 0)
-+ dtrace_format_remove(ecb->dte_state, format);
-+
-+ dp = act->dta_difo;
-+ if (dp != NULL)
-+ dtrace_difo_release(dp, vstate);
-+
-+ if (DTRACEACT_ISAGG(act->dta_kind))
-+ dtrace_ecb_aggregation_destroy(ecb, act);
-+ else
-+ kfree(act);
-+ }
-+ }
-+
-+ ecb->dte_action = NULL;
-+ ecb->dte_action_last = NULL;
-+ ecb->dte_size = sizeof(dtrace_epid_t);
-+}
-+
-+/*
-+ * Disable the ECB by removing it from its probe.
-+ */
-+void dtrace_ecb_disable(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_ecb *pecb, *prev = NULL;
-+ struct dtrace_probe *probe = ecb->dte_probe;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (probe == NULL)
-+ return;
-+
-+ for (pecb = probe->dtpr_ecb; pecb != NULL; pecb = pecb->dte_next) {
-+ if (pecb == ecb)
-+ break;
-+
-+ prev = pecb;
-+ }
-+
-+ ASSERT(pecb != NULL);
-+
-+ if (prev == NULL)
-+ probe->dtpr_ecb = ecb->dte_next;
-+ else
-+ prev->dte_next = ecb->dte_next;
-+
-+ if (ecb == probe->dtpr_ecb_last) {
-+ ASSERT(ecb->dte_next == NULL);
-+ probe->dtpr_ecb_last = prev;
-+ }
-+
-+ /*
-+ * The ECB has been disconnected from the probe; now sync to assure
-+ * that all CPUs have seen the change before returning.
-+ */
-+ dtrace_sync();
-+
-+ if (probe->dtpr_ecb == NULL) {
-+ /*
-+ * That was the last ECB on the probe; clear the predicate
-+ * cache ID for the probe, disable it and sync one more time
-+ * to assure that we'll never hit it again.
-+ */
-+ struct dtrace_provider *prov = probe->dtpr_provider;
-+
-+ ASSERT(ecb->dte_next == NULL);
-+ ASSERT(probe->dtpr_ecb_last == NULL);
-+
-+ probe->dtpr_predcache = DTRACE_CACHEIDNONE;
-+ prov->dtpv_pops.dtps_disable(prov->dtpv_arg,
-+ probe->dtpr_id, probe->dtpr_arg);
-+
-+ dtrace_sync();
-+ } else {
-+ /*
-+ * There is at least one ECB remaining on the probe. If there
-+ * is _exactly_ one, set the probe's predicate cache ID to be
-+ * the predicate cache ID of the remaining ECB.
-+ */
-+ ASSERT(probe->dtpr_ecb_last != NULL);
-+ ASSERT(probe->dtpr_predcache == DTRACE_CACHEIDNONE);
-+
-+ if (probe->dtpr_ecb == probe->dtpr_ecb_last) {
-+ struct dtrace_predicate *p =
-+ probe->dtpr_ecb->dte_predicate;
-+
-+ ASSERT(probe->dtpr_ecb->dte_next == NULL);
-+
-+ if (p != NULL)
-+ probe->dtpr_predcache = p->dtp_cacheid;
-+ }
-+
-+ ecb->dte_next = NULL;
-+ }
-+}
-+
-+static struct dtrace_ecb *dtrace_ecb_add(struct dtrace_state *state,
-+ struct dtrace_probe *probe)
-+{
-+ struct dtrace_ecb *ecb;
-+ dtrace_epid_t epid;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ ecb = kzalloc(sizeof(struct dtrace_ecb), GFP_KERNEL);
-+ if (ecb == NULL)
-+ return NULL;
-+
-+ ecb->dte_predicate = NULL;
-+ ecb->dte_probe = probe;
-+ ecb->dte_size = ecb->dte_needed = sizeof(dtrace_epid_t);
-+ ecb->dte_alignment = sizeof(dtrace_epid_t);
-+
-+ epid = state->dts_epid++;
-+
-+ if (epid - 1 >= state->dts_necbs) {
-+ struct dtrace_ecb **oecbs = state->dts_ecbs, **ecbs;
-+ int necbs = state->dts_necbs << 1;
-+
-+ ASSERT(epid == state->dts_necbs + 1);
-+
-+ if (necbs == 0) {
-+ ASSERT(oecbs == NULL);
-+
-+ necbs = 1;
-+ }
-+
-+ ecbs = vzalloc(necbs * sizeof(*ecbs));
-+ if (ecbs == NULL) {
-+ kfree(ecb);
-+ return NULL;
-+ }
-+
-+ if (oecbs != NULL)
-+ memcpy(ecbs, oecbs, state->dts_necbs * sizeof(*ecbs));
-+
-+ dtrace_membar_producer();
-+
-+ state->dts_ecbs = ecbs;
-+
-+ if (oecbs != NULL) {
-+ if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE)
-+ dtrace_sync();
-+
-+ vfree(oecbs);
-+ }
-+
-+ dtrace_membar_producer();
-+
-+ state->dts_necbs = necbs;
-+ }
-+
-+ ecb->dte_state = state;
-+
-+ ASSERT(state->dts_ecbs[epid - 1] == NULL);
-+
-+ dtrace_membar_producer();
-+
-+ state->dts_ecbs[(ecb->dte_epid = epid) - 1] = ecb;
-+
-+ return ecb;
-+}
-+
-+static struct dtrace_ecb * dtrace_ecb_create(struct dtrace_state *state,
-+ struct dtrace_probe *probe,
-+ struct dtrace_enabling *enab)
-+{
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_predicate *pred;
-+ struct dtrace_actdesc *act;
-+ struct dtrace_provider *prov;
-+ struct dtrace_ecbdesc *desc = enab->dten_current;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(state != NULL);
-+
-+ ecb = dtrace_ecb_add(state, probe);
-+ if (ecb == NULL)
-+ return NULL;
-+
-+ ecb->dte_uarg = desc->dted_uarg;
-+
-+ pred = desc->dted_pred.dtpdd_predicate;
-+ if (pred != NULL) {
-+ dtrace_predicate_hold(pred);
-+ ecb->dte_predicate = pred;
-+ }
-+
-+ if (probe != NULL) {
-+ prov = probe->dtpr_provider;
-+
-+ if (!(state->dts_cred.dcr_visible & DTRACE_CRV_ALLPROC) &&
-+ (prov->dtpv_priv.dtpp_flags & DTRACE_PRIV_USER))
-+ ecb->dte_cond |= DTRACE_COND_OWNER;
-+
-+ if (!(state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL) &&
-+ (prov->dtpv_priv.dtpp_flags & DTRACE_PRIV_KERNEL))
-+ ecb->dte_cond |= DTRACE_COND_USERMODE;
-+ }
-+
-+ if (dtrace_ecb_create_cache != NULL) {
-+ struct dtrace_ecb *cached = dtrace_ecb_create_cache;
-+ struct dtrace_action *act = cached->dte_action;
-+
-+ if (act != NULL) {
-+ ASSERT(act->dta_refcnt > 0);
-+
-+ act->dta_refcnt++;
-+ ecb->dte_action = act;
-+ ecb->dte_action_last = cached->dte_action_last;
-+ ecb->dte_needed = cached->dte_needed;
-+ ecb->dte_size = cached->dte_size;
-+ ecb->dte_alignment = cached->dte_alignment;
-+ }
-+
-+ return ecb;
-+ }
-+
-+ for (act = desc->dted_action; act != NULL; act = act->dtad_next) {
-+ enab->dten_error = dtrace_ecb_action_add(ecb, act);
-+ if (enab->dten_error != 0) {
-+ dtrace_ecb_destroy(ecb);
-+ return NULL;
-+ }
-+ }
-+
-+ dtrace_ecb_resize(ecb);
-+
-+ return (dtrace_ecb_create_cache = ecb);
-+}
-+
-+int dtrace_ecb_create_enable(struct dtrace_probe *probe, void *arg)
-+{
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_enabling *enab = arg;
-+ struct dtrace_state *state = enab->dten_vstate->dtvs_state;
-+
-+ ASSERT(state != NULL);
-+
-+ if (probe != NULL && probe->dtpr_gen < enab->dten_probegen)
-+ return DTRACE_MATCH_NEXT;
-+
-+ ecb = dtrace_ecb_create(state, probe, enab);
-+ if (ecb == NULL)
-+ return DTRACE_MATCH_DONE;
-+
-+ if (dtrace_ecb_enable(ecb) < 0)
-+ return DTRACE_MATCH_FAIL;
-+
-+ return DTRACE_MATCH_NEXT;
-+}
-+
-+void dtrace_ecb_destroy(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_state *state = ecb->dte_state;
-+ struct dtrace_vstate *vstate = &state->dts_vstate;
-+ struct dtrace_predicate *pred;
-+ dtrace_epid_t epid = ecb->dte_epid;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(ecb->dte_next == NULL);
-+ ASSERT(ecb->dte_probe == NULL || ecb->dte_probe->dtpr_ecb != ecb);
-+
-+ pred = ecb->dte_predicate;
-+ if (pred != NULL)
-+ dtrace_predicate_release(pred, vstate);
-+
-+ dtrace_ecb_action_remove(ecb);
-+
-+ ASSERT(state->dts_ecbs[epid - 1] == ecb);
-+ state->dts_ecbs[epid - 1] = NULL;
-+
-+ kfree(ecb);
-+}
-+
-+void dtrace_ecb_resize(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_action *act;
-+ uint32_t maxalign = sizeof(dtrace_epid_t);
-+ uint32_t align = sizeof(uint8_t), offs, diff;
-+ int wastuple = 0;
-+ uint32_t aggbase = UINT32_MAX;
-+ struct dtrace_state *state = ecb->dte_state;
-+
-+ /*
-+ * If we record anything, we always record the epid. (And we always
-+ * record it first.)
-+ */
-+ offs = sizeof(dtrace_epid_t);
-+ ecb->dte_size = ecb->dte_needed = sizeof(dtrace_epid_t);
-+
-+ for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
-+ struct dtrace_recdesc *rec = &act->dta_rec;
-+
-+ align = rec->dtrd_alignment;
-+ if (align > maxalign)
-+ maxalign = align;
-+
-+ if (!wastuple && act->dta_intuple) {
-+ /*
-+ * This is the first record in a tuple. Align the
-+ * offset to be at offset 4 in an 8-byte aligned
-+ * block.
-+ */
-+ diff = offs + sizeof(dtrace_aggid_t);
-+
-+ diff &= sizeof(uint64_t) - 1;
-+ if (diff)
-+ offs += sizeof(uint64_t) - diff;
-+
-+ aggbase = offs - sizeof(dtrace_aggid_t);
-+ ASSERT(!(aggbase & (sizeof(uint64_t) - 1)));
-+ }
-+
-+ if (rec->dtrd_size != 0) {
-+ diff = offs & (align - 1);
-+ if (diff)
-+ /*
-+ * The current offset is not properly
-+ * aligned; align it.
-+ */
-+ offs += align - diff;
-+ }
-+
-+ rec->dtrd_offset = offs;
-+
-+ if (offs + rec->dtrd_size > ecb->dte_needed) {
-+ ecb->dte_needed = offs + rec->dtrd_size;
-+
-+ if (ecb->dte_needed > state->dts_needed)
-+ state->dts_needed = ecb->dte_needed;
-+ }
-+
-+ if (DTRACEACT_ISAGG(act->dta_kind)) {
-+ struct dtrace_aggregation *agg;
-+ struct dtrace_action *first, *prev;
-+
-+ agg = (struct dtrace_aggregation *)act;
-+ first = agg->dtag_first;
-+
-+ ASSERT(rec->dtrd_size != 0 && first != NULL);
-+ ASSERT(wastuple);
-+ ASSERT(aggbase != UINT32_MAX);
-+
-+ agg->dtag_base = aggbase;
-+
-+ while ((prev = first->dta_prev) != NULL &&
-+ DTRACEACT_ISAGG(prev->dta_kind)) {
-+ agg = (struct dtrace_aggregation *)prev;
-+ first = agg->dtag_first;
-+ }
-+
-+ if (prev != NULL) {
-+ offs = prev->dta_rec.dtrd_offset +
-+ prev->dta_rec.dtrd_size;
-+ } else
-+ offs = sizeof(dtrace_epid_t);
-+
-+ wastuple = 0;
-+ } else {
-+ if (!act->dta_intuple)
-+ ecb->dte_size = offs + rec->dtrd_size;
-+
-+ offs += rec->dtrd_size;
-+ }
-+
-+ wastuple = act->dta_intuple;
-+ }
-+
-+ act = ecb->dte_action;
-+ if (act != NULL &&
-+ !(act->dta_kind == DTRACEACT_SPECULATE && act->dta_next == NULL) &&
-+ ecb->dte_size == sizeof(dtrace_epid_t)) {
-+ /*
-+ * If the size is still sizeof(dtrace_epid_t), then all
-+ * actions store no data; set the size to 0.
-+ */
-+ ecb->dte_alignment = maxalign;
-+ ecb->dte_size = 0;
-+
-+ /*
-+ * If the needed space is still sizeof(dtrace_epid_t), then
-+ * all actions need no additional space; set the needed
-+ * size to 0.
-+ */
-+ if (ecb->dte_needed == sizeof(dtrace_epid_t))
-+ ecb->dte_needed = 0;
-+
-+ return;
-+ }
-+
-+ /*
-+ * Set our alignment, and make sure that the dte_size and dte_needed
-+ * are aligned to the size of an EPID.
-+ */
-+ ecb->dte_alignment = maxalign;
-+ ecb->dte_size = (ecb->dte_size + (sizeof(dtrace_epid_t) - 1)) &
-+ ~(sizeof(dtrace_epid_t) - 1);
-+ ecb->dte_needed = (ecb->dte_needed + (sizeof(dtrace_epid_t) - 1)) &
-+ ~(sizeof(dtrace_epid_t) - 1);
-+ ASSERT(ecb->dte_size <= ecb->dte_needed);
-+}
-+
-+int dtrace_ecb_enable(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_probe *probe = ecb->dte_probe;
-+
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(ecb->dte_next == NULL);
-+
-+ if (probe == NULL)
-+ return 0;
-+
-+ if (probe->dtpr_ecb == NULL) {
-+ struct dtrace_provider *prov = probe->dtpr_provider;
-+
-+ probe->dtpr_ecb = probe->dtpr_ecb_last = ecb;
-+
-+
-+ if (ecb->dte_predicate != NULL)
-+ probe->dtpr_predcache = ecb->dte_predicate->dtp_cacheid;
-+
-+ return prov->dtpv_pops.dtps_enable(prov->dtpv_arg,
-+ probe->dtpr_id,
-+ probe->dtpr_arg);
-+ } else {
-+ ASSERT(probe->dtpr_ecb_last != NULL);
-+
-+ probe->dtpr_ecb_last->dte_next = ecb;
-+ probe->dtpr_ecb_last = ecb;
-+ probe->dtpr_predcache = 0;
-+
-+ dtrace_sync();
-+
-+ return 0;
-+ }
-+}
-+
-+struct dtrace_ecb *dtrace_epid2ecb(struct dtrace_state *state,
-+ dtrace_epid_t id)
-+{
-+ struct dtrace_ecb *ecb;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (id == 0 || id > state->dts_necbs)
-+ return NULL;
-+
-+ ASSERT(state->dts_necbs > 0 && state->dts_ecbs != NULL);
-+ ecb = state->dts_ecbs[id - 1];
-+ ASSERT(ecb == NULL || ecb->dte_epid == id);
-+
-+ return ecb;
-+}
-+
-+struct dtrace_aggregation *dtrace_aggid2agg(struct dtrace_state *state,
-+ dtrace_aggid_t id)
-+{
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ return idr_find(&state->dts_agg_idr, id);
-+}
-diff --git a/dtrace/dtrace_enable.c b/dtrace/dtrace_enable.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..72f30149cb9c6c7bad2d1f38303399bafdc86170
---- /dev/null
-+++ b/dtrace/dtrace_enable.c
-@@ -0,0 +1,449 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_enable.c
-+ * DESCRIPTION: DTrace - probe enabling implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/mutex.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+size_t dtrace_retain_max = 1024;
-+struct dtrace_enabling *dtrace_retained;
-+dtrace_genid_t dtrace_retained_gen;
-+
-+struct dtrace_enabling *dtrace_enabling_create(struct dtrace_vstate *vstate)
-+{
-+ struct dtrace_enabling *enab;
-+
-+ enab = kzalloc(sizeof(struct dtrace_enabling), GFP_KERNEL);
-+ if (enab == NULL)
-+ return NULL;
-+
-+ enab->dten_vstate = vstate;
-+
-+ return enab;
-+}
-+
-+void dtrace_enabling_add(struct dtrace_enabling *enab,
-+ struct dtrace_ecbdesc *ecb)
-+{
-+ struct dtrace_ecbdesc **ndesc;
-+ size_t osize, nsize;
-+
-+ /*
-+ * We can't add to enablings after we've enabled them, or after we've
-+ * retained them.
-+ */
-+ ASSERT(enab->dten_probegen == 0);
-+ ASSERT(enab->dten_next == NULL && enab->dten_prev == NULL);
-+
-+ if (enab->dten_ndesc < enab->dten_maxdesc) {
-+ enab->dten_desc[enab->dten_ndesc++] = ecb;
-+ return;
-+ }
-+
-+ osize = enab->dten_maxdesc * sizeof(struct dtrace_enabling *);
-+
-+ if (enab->dten_maxdesc == 0)
-+ enab->dten_maxdesc = 1;
-+ else
-+ enab->dten_maxdesc <<= 1;
-+
-+ ASSERT(enab->dten_ndesc < enab->dten_maxdesc);
-+
-+ nsize = enab->dten_maxdesc * sizeof(struct dtrace_enabling *);
-+ ndesc = vzalloc(nsize);
-+ memcpy(ndesc, enab->dten_desc, osize);
-+ vfree(enab->dten_desc);
-+
-+ enab->dten_desc = ndesc;
-+ enab->dten_desc[enab->dten_ndesc++] = ecb;
-+}
-+
-+static void dtrace_enabling_addlike(struct dtrace_enabling *enab,
-+ struct dtrace_ecbdesc *ecb,
-+ struct dtrace_probedesc *pd)
-+{
-+ struct dtrace_ecbdesc *new;
-+ struct dtrace_predicate *pred;
-+ struct dtrace_actdesc *act;
-+
-+ /*
-+ * We're going to create a new ECB description that matches the
-+ * specified ECB in every way, but has the specified probe description.
-+ */
-+ new = kzalloc(sizeof(struct dtrace_ecbdesc), GFP_KERNEL);
-+
-+ pred = ecb->dted_pred.dtpdd_predicate;
-+ if (pred != NULL)
-+ dtrace_predicate_hold(pred);
-+
-+ for (act = ecb->dted_action; act != NULL; act = act->dtad_next)
-+ dtrace_actdesc_hold(act);
-+
-+ new->dted_action = ecb->dted_action;
-+ new->dted_pred = ecb->dted_pred;
-+ new->dted_probe = *pd;
-+ new->dted_uarg = ecb->dted_uarg;
-+
-+ dtrace_enabling_add(enab, new);
-+}
-+
-+void dtrace_enabling_dump(struct dtrace_enabling *enab)
-+{
-+ int i;
-+
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_probedesc *desc =
-+ &enab->dten_desc[i]->dted_probe;
-+
-+ pr_info("enabling probe %d (%s:%s:%s:%s)",
-+ i, desc->dtpd_provider, desc->dtpd_mod,
-+ desc->dtpd_func, desc->dtpd_name);
-+ }
-+}
-+
-+void dtrace_enabling_destroy(struct dtrace_enabling *enab)
-+{
-+ int i;
-+ struct dtrace_ecbdesc *ep;
-+ struct dtrace_vstate *vstate = enab->dten_vstate;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_actdesc *act, *next;
-+ struct dtrace_predicate *pred;
-+
-+ ep = enab->dten_desc[i];
-+
-+ pred = ep->dted_pred.dtpdd_predicate;
-+ if (pred != NULL)
-+ dtrace_predicate_release(pred, vstate);
-+
-+ for (act = ep->dted_action; act != NULL; act = next) {
-+ next = act->dtad_next;
-+ dtrace_actdesc_release(act, vstate);
-+ }
-+
-+ kfree(ep);
-+ }
-+
-+ vfree(enab->dten_desc);
-+
-+ /*
-+ * If this was a retained enabling, decrement the dts_nretained count
-+ * and remove it from the dtrace_retained list.
-+ */
-+ if (enab->dten_prev != NULL || enab->dten_next != NULL ||
-+ dtrace_retained == enab) {
-+ ASSERT(enab->dten_vstate->dtvs_state != NULL);
-+ ASSERT(enab->dten_vstate->dtvs_state->dts_nretained > 0);
-+ enab->dten_vstate->dtvs_state->dts_nretained--;
-+ dtrace_retained_gen++;
-+ }
-+
-+ if (enab->dten_prev == NULL) {
-+ if (dtrace_retained == enab) {
-+ dtrace_retained = enab->dten_next;
-+
-+ if (dtrace_retained != NULL)
-+ dtrace_retained->dten_prev = NULL;
-+ }
-+ } else {
-+ ASSERT(enab != dtrace_retained);
-+ ASSERT(dtrace_retained != NULL);
-+ enab->dten_prev->dten_next = enab->dten_next;
-+ }
-+
-+ if (enab->dten_next != NULL) {
-+ ASSERT(dtrace_retained != NULL);
-+ enab->dten_next->dten_prev = enab->dten_prev;
-+ }
-+
-+ kfree(enab);
-+}
-+
-+int dtrace_enabling_retain(struct dtrace_enabling *enab)
-+{
-+ struct dtrace_state *state;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(enab->dten_next == NULL && enab->dten_prev == NULL);
-+ ASSERT(enab->dten_vstate != NULL);
-+
-+ state = enab->dten_vstate->dtvs_state;
-+ ASSERT(state != NULL);
-+
-+ /*
-+ * We only allow each state to retain dtrace_retain_max enablings.
-+ */
-+ if (state->dts_nretained >= dtrace_retain_max)
-+ return -ENOSPC;
-+
-+ state->dts_nretained++;
-+ dtrace_retained_gen++;
-+
-+ if (dtrace_retained == NULL) {
-+ dtrace_retained = enab;
-+ return 0;
-+ }
-+
-+ enab->dten_next = dtrace_retained;
-+ dtrace_retained->dten_prev = enab;
-+ dtrace_retained = enab;
-+
-+ return 0;
-+}
-+
-+int dtrace_enabling_replicate(struct dtrace_state *state,
-+ struct dtrace_probedesc *match,
-+ struct dtrace_probedesc *create)
-+{
-+ struct dtrace_enabling *new, *enab;
-+ int found = 0, err = -ENOENT;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(strlen(match->dtpd_provider) < DTRACE_PROVNAMELEN);
-+ ASSERT(strlen(match->dtpd_mod) < DTRACE_MODNAMELEN);
-+ ASSERT(strlen(match->dtpd_func) < DTRACE_FUNCNAMELEN);
-+ ASSERT(strlen(match->dtpd_name) < DTRACE_NAMELEN);
-+
-+ new = dtrace_enabling_create(&state->dts_vstate);
-+ if (new == NULL)
-+ return -ENOMEM;
-+
-+ /*
-+ * Iterate over all retained enablings, looking for enablings that
-+ * match the specified state.
-+ */
-+ for (enab = dtrace_retained; enab != NULL; enab = enab->dten_next) {
-+ int i;
-+
-+ /*
-+ * dtvs_state can only be NULL for helper enablings -- and
-+ * helper enablings can't be retained.
-+ */
-+ ASSERT(enab->dten_vstate->dtvs_state != NULL);
-+
-+ if (enab->dten_vstate->dtvs_state != state)
-+ continue;
-+
-+ /*
-+ * Now iterate over each probe description; we're looking for
-+ * an exact match to the specified probe description.
-+ */
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_ecbdesc *ep = enab->dten_desc[i];
-+ struct dtrace_probedesc *pd = &ep->dted_probe;
-+
-+ if (strcmp(pd->dtpd_provider, match->dtpd_provider))
-+ continue;
-+
-+ if (strcmp(pd->dtpd_mod, match->dtpd_mod))
-+ continue;
-+
-+ if (strcmp(pd->dtpd_func, match->dtpd_func))
-+ continue;
-+
-+ if (strcmp(pd->dtpd_name, match->dtpd_name))
-+ continue;
-+
-+ /*
-+ * We have a winning probe! Add it to our growing
-+ * enabling.
-+ */
-+ found = 1;
-+ dtrace_enabling_addlike(new, ep, create);
-+ }
-+ }
-+
-+ if (!found || (err = dtrace_enabling_retain(new)) != 0) {
-+ dtrace_enabling_destroy(new);
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+void dtrace_enabling_retract(struct dtrace_state *state)
-+{
-+ struct dtrace_enabling *enab, *next;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ /*
-+ * Iterate over all retained enablings, destroy the enablings retained
-+ * for the specified state.
-+ */
-+ for (enab = dtrace_retained; enab != NULL; enab = next) {
-+ next = enab->dten_next;
-+
-+ /*
-+ * dtvs_state can only be NULL for helper enablings, and helper
-+ * enablings can't be retained.
-+ */
-+ ASSERT(enab->dten_vstate->dtvs_state != NULL);
-+
-+ if (enab->dten_vstate->dtvs_state == state) {
-+ ASSERT(state->dts_nretained > 0);
-+ dtrace_enabling_destroy(enab);
-+ }
-+ }
-+
-+ ASSERT(state->dts_nretained == 0);
-+}
-+
-+int dtrace_enabling_match(struct dtrace_enabling *enab, int *nmatched)
-+{
-+ int i;
-+ int total_matched = 0, matched = 0;
-+
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_ecbdesc *ep = enab->dten_desc[i];
-+
-+ enab->dten_current = ep;
-+ enab->dten_error = 0;
-+
-+ dt_dbg_enable(" Matching enabling %p[%d] for %s:%s:%s:%s\n",
-+ enab, i, ep->dted_probe.dtpd_provider,
-+ ep->dted_probe.dtpd_mod,
-+ ep->dted_probe.dtpd_func,
-+ ep->dted_probe.dtpd_name);
-+
-+ matched = dtrace_probe_enable(&ep->dted_probe, enab);
-+ if (matched < 0) {
-+ dt_dbg_enable(" Matching enabling %p[%d] failed: "
-+ "busy\n", enab, i);
-+ return -EBUSY;
-+ }
-+
-+ dt_dbg_enable(" Matching enabling %p[%d] found %d matches.\n",
-+ enab, i, matched);
-+
-+ total_matched += matched;
-+
-+ if (enab->dten_error != 0) {
-+ if (nmatched == NULL)
-+ pr_warn("%s error on %p: %d\n", __func__,
-+ (void *)ep, enab->dten_error);
-+
-+ return enab->dten_error;
-+ }
-+ }
-+
-+ enab->dten_probegen = dtrace_probegen;
-+ if (nmatched != NULL)
-+ *nmatched = total_matched;
-+
-+ return 0;
-+}
-+
-+void dtrace_enabling_matchall(void)
-+{
-+ struct dtrace_enabling *enab;
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ for (enab = dtrace_retained; enab != NULL; enab = enab->dten_next)
-+ (void) dtrace_enabling_match(enab, NULL);
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+}
-+
-+/*
-+ * If an enabling is to be enabled without having matched probes (that is, if
-+ * dtrace_state_go() is to be called on the underlying dtrace_state_t), the
-+ * enabling must be _primed_ by creating an ECB for every ECB description.
-+ * This must be done to assure that we know the number of speculations, the
-+ * number of aggregations, the minimum buffer size needed, etc. before we
-+ * transition out of DTRACE_ACTIVITY_INACTIVE. To do this without actually
-+ * enabling any probes, we create ECBs for every ECB description, but with a
-+ * NULL probe -- which is exactly what this function does.
-+ */
-+void dtrace_enabling_prime(struct dtrace_state *state)
-+{
-+ struct dtrace_enabling *enab;
-+ int i;
-+
-+ for (enab = dtrace_retained; enab != NULL; enab = enab->dten_next) {
-+ ASSERT(enab->dten_vstate->dtvs_state != NULL);
-+
-+ if (enab->dten_vstate->dtvs_state != state)
-+ continue;
-+
-+ /*
-+ * We don't want to prime an enabling more than once, lest
-+ * we allow a malicious user to induce resource exhaustion.
-+ * (The ECBs that result from priming an enabling aren't
-+ * leaked -- but they also aren't deallocated until the
-+ * consumer state is destroyed.)
-+ */
-+ if (enab->dten_primed)
-+ continue;
-+
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ enab->dten_current = enab->dten_desc[i];
-+ dtrace_probe_enable(NULL, enab);
-+ }
-+
-+ enab->dten_primed = 1;
-+ }
-+}
-+
-+void dtrace_enabling_provide(struct dtrace_provider *prv)
-+{
-+ int all = 0;
-+ dtrace_genid_t gen;
-+
-+ if (prv == NULL) {
-+ all = 1;
-+ prv = dtrace_provider;
-+ }
-+
-+ do {
-+ struct dtrace_enabling *enab;
-+ void *parg = prv->dtpv_arg;
-+
-+retry:
-+ gen = dtrace_retained_gen;
-+ for (enab = dtrace_retained; enab != NULL;
-+ enab = enab->dten_next) {
-+ int i;
-+
-+ for (i = 0; i < enab->dten_ndesc; i++) {
-+ struct dtrace_probedesc desc;
-+
-+ desc = enab->dten_desc[i]->dted_probe;
-+ mutex_unlock(&dtrace_lock);
-+ prv->dtpv_pops.dtps_provide(parg, &desc);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (gen != dtrace_retained_gen)
-+ goto retry;
-+ }
-+ }
-+ } while (all && (prv = prv->dtpv_next) != NULL);
-+
-+ mutex_unlock(&dtrace_lock);
-+ dtrace_probe_provide(NULL, all ? NULL : prv);
-+ mutex_lock(&dtrace_lock);
-+}
-diff --git a/dtrace/dtrace_fmt.c b/dtrace/dtrace_fmt.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..78fcc8e6efb88cc156945e5d66182b1c455152e4
---- /dev/null
-+++ b/dtrace/dtrace_fmt.c
-@@ -0,0 +1,104 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_fmt.c
-+ * DESCRIPTION: DTrace - format string implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+uint16_t dtrace_format_add(struct dtrace_state *state, char *str)
-+{
-+ char *fmt, **new;
-+ uint16_t ndx;
-+
-+ fmt = dtrace_strdup(str);
-+ if (fmt == NULL)
-+ return 0;
-+
-+ for (ndx = 0; ndx < state->dts_nformats; ndx++) {
-+ if (state->dts_formats[ndx] == NULL) {
-+ state->dts_formats[ndx] = fmt;
-+
-+ return ndx + 1;
-+ }
-+ }
-+
-+ if (state->dts_nformats == UINT16_MAX) {
-+ kfree(fmt);
-+
-+ return 0;
-+ }
-+
-+ ndx = state->dts_nformats;
-+ new = vmalloc((ndx + 1) * sizeof(char *));
-+ if (new == NULL) {
-+ kfree(fmt);
-+ return 0;
-+ }
-+
-+ state->dts_nformats++;
-+
-+ if (state->dts_formats != NULL) {
-+ ASSERT(ndx != 0);
-+ memcpy(new, state->dts_formats, ndx * sizeof(char *));
-+ vfree(state->dts_formats);
-+ }
-+
-+ state->dts_formats = new;
-+ state->dts_formats[ndx] = fmt;
-+
-+ return ndx + 1;
-+}
-+
-+void dtrace_format_remove(struct dtrace_state *state, uint16_t format)
-+{
-+ char *fmt;
-+
-+ ASSERT(state->dts_formats != NULL);
-+ ASSERT(format <= state->dts_nformats);
-+ ASSERT(state->dts_formats[format - 1] != NULL);
-+
-+ fmt = state->dts_formats[format - 1];
-+ kfree(fmt);
-+ state->dts_formats[format - 1] = NULL;
-+}
-+
-+void dtrace_format_destroy(struct dtrace_state *state)
-+{
-+ int i;
-+
-+ if (state->dts_nformats == 0) {
-+ ASSERT(state->dts_formats == NULL);
-+ return;
-+ }
-+
-+ ASSERT(state->dts_formats != NULL);
-+
-+ for (i = 0; i < state->dts_nformats; i++) {
-+ char *fmt = state->dts_formats[i];
-+
-+ if (fmt == NULL)
-+ continue;
-+
-+ kfree(fmt);
-+ }
-+
-+ vfree(state->dts_formats);
-+ state->dts_nformats = 0;
-+ state->dts_formats = NULL;
-+}
-diff --git a/dtrace/dtrace_hash.c b/dtrace/dtrace_hash.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..0773c60e7897ce9cbc8efaa25f54f7181d86be02
---- /dev/null
-+++ b/dtrace/dtrace_hash.c
-@@ -0,0 +1,266 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_hash.c
-+ * DESCRIPTION: DTrace - hash table implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+
-+#define DTRACE_HASHSTR(hash, probe) \
-+ dtrace_hash_str(*((char **)((uintptr_t)(probe) + (hash)->dth_stroffs)))
-+#define DTRACE_HASHEQ(hash, lhs, rhs) \
-+ (strcmp(*((char **)((uintptr_t)(lhs) + (hash)->dth_stroffs)), \
-+ *((char **)((uintptr_t)(rhs) + (hash)->dth_stroffs))) == 0)
-+
-+static uint_t dtrace_hash_str(char *p)
-+{
-+ uint_t g;
-+ uint_t hval = 0;
-+
-+ while (*p) {
-+ hval = (hval << 4) + *p++;
-+ g = hval & 0xf0000000;
-+ if (g != 0)
-+ hval ^= g >> 24;
-+
-+ hval &= ~g;
-+ }
-+
-+ return hval;
-+}
-+
-+struct dtrace_hash *dtrace_hash_create(uintptr_t stroffs, uintptr_t nextoffs,
-+ uintptr_t prevoffs)
-+{
-+ struct dtrace_hash *hash;
-+
-+ hash = kzalloc(sizeof(struct dtrace_hash), GFP_KERNEL);
-+ if (hash == NULL)
-+ return NULL;
-+
-+ hash->dth_stroffs = stroffs;
-+ hash->dth_nextoffs = nextoffs;
-+ hash->dth_prevoffs = prevoffs;
-+
-+ hash->dth_size = 1;
-+ hash->dth_mask = hash->dth_size - 1;
-+
-+ hash->dth_tab = vzalloc(hash->dth_size *
-+ sizeof(struct dtrace_hashbucket *));
-+
-+ if (hash->dth_tab == NULL) {
-+ kfree(hash);
-+ return NULL;
-+ }
-+
-+ return hash;
-+}
-+
-+void dtrace_hash_destroy(struct dtrace_hash *hash)
-+{
-+#ifdef DEBUG
-+ int i;
-+
-+ for (i = 0; i < hash->dth_size; i++)
-+ ASSERT(hash->dth_tab[i] == NULL);
-+#endif
-+
-+ if (hash == NULL)
-+ return;
-+
-+ vfree(hash->dth_tab);
-+ kfree(hash);
-+}
-+
-+static int dtrace_hash_resize(struct dtrace_hash *hash)
-+{
-+ int size = hash->dth_size, i, ndx;
-+ int new_size = hash->dth_size << 1;
-+ int new_mask = new_size - 1;
-+ struct dtrace_hashbucket **new_tab, *bucket, *next;
-+
-+ ASSERT((new_size & new_mask) == 0);
-+
-+ new_tab = vzalloc(new_size * sizeof(void *));
-+ if (new_tab == NULL)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < size; i++) {
-+ for (bucket = hash->dth_tab[i]; bucket != NULL;
-+ bucket = next) {
-+ struct dtrace_probe *probe = bucket->dthb_chain;
-+
-+ ASSERT(probe != NULL);
-+ ndx = DTRACE_HASHSTR(hash, probe) & new_mask;
-+
-+ next = bucket->dthb_next;
-+ bucket->dthb_next = new_tab[ndx];
-+ new_tab[ndx] = bucket;
-+ }
-+ }
-+
-+ vfree(hash->dth_tab);
-+ hash->dth_tab = new_tab;
-+ hash->dth_size = new_size;
-+ hash->dth_mask = new_mask;
-+
-+ return 0;
-+}
-+
-+int dtrace_hash_add(struct dtrace_hash *hash, struct dtrace_probe *new)
-+{
-+ int hashval = DTRACE_HASHSTR(hash, new);
-+ int ndx = hashval & hash->dth_mask;
-+ struct dtrace_hashbucket *bucket = hash->dth_tab[ndx];
-+ struct dtrace_probe **nextp, **prevp;
-+
-+ for (; bucket != NULL; bucket = bucket->dthb_next) {
-+ if (DTRACE_HASHEQ(hash, bucket->dthb_chain, new))
-+ goto add;
-+ }
-+
-+ if ((hash->dth_nbuckets >> 1) > hash->dth_size) {
-+ int err = 0;
-+
-+ err = dtrace_hash_resize(hash);
-+ if (err != 0)
-+ return err;
-+
-+ dtrace_hash_add(hash, new);
-+ return 0;
-+ }
-+
-+ bucket = kzalloc(sizeof(struct dtrace_hashbucket), GFP_KERNEL);
-+ if (bucket == NULL)
-+ return -ENOMEM;
-+
-+ bucket->dthb_next = hash->dth_tab[ndx];
-+ hash->dth_tab[ndx] = bucket;
-+ hash->dth_nbuckets++;
-+
-+add:
-+ nextp = DTRACE_HASHNEXT(hash, new);
-+
-+ ASSERT(*nextp == NULL && *(DTRACE_HASHPREV(hash, new)) == NULL);
-+
-+ *nextp = bucket->dthb_chain;
-+
-+ if (bucket->dthb_chain != NULL) {
-+ prevp = DTRACE_HASHPREV(hash, bucket->dthb_chain);
-+
-+ ASSERT(*prevp == NULL);
-+
-+ *prevp = new;
-+ }
-+
-+ bucket->dthb_chain = new;
-+ bucket->dthb_len++;
-+
-+ return 0;
-+}
-+
-+struct dtrace_probe *dtrace_hash_lookup(struct dtrace_hash *hash,
-+ struct dtrace_probe *template)
-+{
-+ int hashval = DTRACE_HASHSTR(hash, template);
-+ int ndx = hashval & hash->dth_mask;
-+
-+ struct dtrace_hashbucket *bucket = hash->dth_tab[ndx];
-+
-+ for (; bucket != NULL; bucket = bucket->dthb_next) {
-+ if (DTRACE_HASHEQ(hash, bucket->dthb_chain, template))
-+ return bucket->dthb_chain;
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * FIXME:
-+ * It would be more accurate to calculate a lookup cost based on the number
-+ * of buckets in the hash table slot, the length of the chain, and the length
-+ * of the string being looked up.
-+ * The hash tables can also be optimized by storing the hashval in each element
-+ * rather than always performing string comparisons.
-+ */
-+int dtrace_hash_collisions(struct dtrace_hash *hash,
-+ struct dtrace_probe *template)
-+{
-+ int hashval = DTRACE_HASHSTR(hash, template);
-+ int ndx = hashval & hash->dth_mask;
-+
-+ struct dtrace_hashbucket *bucket = hash->dth_tab[ndx];
-+
-+ for (; bucket != NULL; bucket = bucket->dthb_next) {
-+ if (DTRACE_HASHEQ(hash, bucket->dthb_chain, template))
-+ return bucket->dthb_len;
-+ }
-+
-+ return 0;
-+}
-+
-+void dtrace_hash_remove(struct dtrace_hash *hash, struct dtrace_probe *probe)
-+{
-+ int ndx = DTRACE_HASHSTR(hash, probe) & hash->dth_mask;
-+
-+ struct dtrace_hashbucket *bucket = hash->dth_tab[ndx];
-+ struct dtrace_probe **prevp = DTRACE_HASHPREV(hash, probe);
-+ struct dtrace_probe **nextp = DTRACE_HASHNEXT(hash, probe);
-+
-+ for (; bucket != NULL; bucket = bucket->dthb_next) {
-+ if (DTRACE_HASHEQ(hash, bucket->dthb_chain, probe))
-+ break;
-+ }
-+
-+ ASSERT(bucket != NULL);
-+
-+ if (*prevp == NULL) {
-+ if (*nextp == NULL) {
-+ /*
-+ * This is the last probe in the bucket; we can remove
-+ * the bucket.
-+ */
-+ struct dtrace_hashbucket *b = hash->dth_tab[ndx];
-+
-+ ASSERT(bucket->dthb_chain == probe);
-+ ASSERT(b != NULL);
-+
-+ if (b == bucket)
-+ hash->dth_tab[ndx] = bucket->dthb_next;
-+ else {
-+ while (b->dthb_next != bucket)
-+ b = b->dthb_next;
-+
-+ b->dthb_next = bucket->dthb_next;
-+ }
-+
-+ ASSERT(hash->dth_nbuckets > 0);
-+
-+ hash->dth_nbuckets--;
-+ kfree(bucket);
-+
-+ return;
-+ }
-+
-+ bucket->dthb_chain = *nextp;
-+ } else
-+ *(DTRACE_HASHNEXT(hash, *prevp)) = *nextp;
-+
-+ if (*nextp != NULL)
-+ *(DTRACE_HASHPREV(hash, *nextp)) = *prevp;
-+}
-diff --git a/dtrace/dtrace_isa.c b/dtrace/dtrace_isa.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..f84ce1cd52cc82e6af9e6048c870865c7ec312ff
---- /dev/null
-+++ b/dtrace/dtrace_isa.c
-@@ -0,0 +1,361 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_isa.c
-+ * DESCRIPTION: DTrace - architecture specific code
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/hardirq.h>
-+#include <linux/mm.h>
-+#include <linux/smp.h>
-+#include <linux/uaccess.h>
-+#include <linux/cpumask.h>
-+#include <asm/cacheflush.h>
-+#include <asm/ptrace.h>
-+#include <asm/stacktrace.h>
-+
-+#include "dtrace.h"
-+
-+DEFINE_MUTEX(cpu_lock);
-+EXPORT_SYMBOL(cpu_lock);
-+
-+int dtrace_getipl(void)
-+{
-+ return in_interrupt();
-+}
-+
-+void dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg)
-+{
-+ if (cpu == DTRACE_CPUALL)
-+ smp_call_function(func, arg, 1);
-+ else
-+ smp_call_function_single(cpu, func, arg, 1);
-+}
-+
-+void dtrace_toxic_ranges(void (*func)(uintptr_t, uintptr_t))
-+{
-+ /* FIXME */
-+}
-+
-+/*
-+ * Note: not called from probe context. This function is called
-+ * asynchronously (and at a regular interval) from outside of probe context
-+ * by the DTrace framework to sync shared data which DTrace probe context
-+ * may access without locks.
-+ *
-+ * Whenever the framework updates data which can be accessed from probe context,
-+ * the framework then calls dtrace_sync(). dtrace_sync() guarantees all probes
-+ * are using the new data before returning.
-+ *
-+ * See the comment in dtrace_impl.h which describes this algorithm.
-+ * The cpuc_in_probe_ctxt flag is an increasing 16-bit count. It is odd when
-+ * in DTrace probe context and even when not in DTrace probe context.
-+ * The upper 15 bits are a counter which are incremented when exiting DTrace
-+ * probe context. These upper 15 bits are used to detect "sample aliasing":
-+ * i.e. the target CPU is not in DTrace probe context between samples but
-+ * continually enters probe context just before being sampled.
-+ *
-+ * dtrace_sync() loops over NCPUs. CPUs which are not in DTrace probe context
-+ * (cpuc_in_probe_ctxt is even) are removed from the list. This is repeated
-+ * until there are no CPUs left in the sync list.
-+ *
-+ * In the rare cases where dtrace_sync() loops over all NCPUs more than
-+ * dtrace_sync_sample_count times, dtrace_sync() then spins on one CPU's
-+ * cpuc_in_probe_ctxt count until the count increments. This is intended to
-+ * avoid sample aliasing.
-+ */
-+void dtrace_sync(void)
-+{
-+ /*
-+ * sync_cpus is a bitmap of CPUs that need to be synced with.
-+ */
-+ cpumask_t sync_cpus;
-+ uint64_t sample_count = 0;
-+ int cpuid, sample_cpuid = 0;
-+ int outstanding;
-+
-+ /*
-+ * Create bitmap of CPUs that need to be synced with.
-+ */
-+ cpumask_copy(&sync_cpus, cpu_online_mask);
-+ outstanding = 0;
-+ for_each_cpu(cpuid, &sync_cpus) {
-+ ++outstanding;
-+
-+ /*
-+ * Set a flag to let the CPU know we are syncing with it.
-+ */
-+ DTRACE_SYNC_START(cpuid);
-+ }
-+
-+ /*
-+ * The preceding stores by DTRACE_SYNC_START() must complete before
-+ * subsequent loads or stores. No membar is needed because the
-+ * atomic-add operation in DTRACE_SYNC_START is a memory barrier on
-+ * SPARC and X86.
-+ */
-+
-+ while (outstanding > 0) {
-+ /*
-+ * Loop over the map of CPUs that need to be synced with.
-+ */
-+ for_each_cpu(cpuid, &sync_cpus) {
-+ if (!DTRACE_SYNC_IN_CRITICAL(cpuid)) {
-+
-+ /* Clear the CPU's sync request flag */
-+ DTRACE_SYNC_END(cpuid);
-+
-+ /*
-+ * remove cpuid from list of CPUs that
-+ * still need to be synced with.
-+ */
-+ DTRACE_SYNC_DONE(cpuid, &sync_cpus);
-+ --outstanding;
-+ } else {
-+ /*
-+ * Remember one of the outstanding CPUs to spin
-+ * on once we reach the sampling limit.
-+ */
-+ sample_cpuid = cpuid;
-+ }
-+ }
-+
-+ /*
-+ * dtrace_probe may be running in sibling threads in this core.
-+ */
-+ if (outstanding > 0) {
-+ dtrace_safe_smt_pause();
-+
-+ /*
-+ * After sample_count loops, spin on one CPU's count
-+ * instead of just checking for odd/even.
-+ */
-+ if (++sample_count > dtrace_sync_sample_count) {
-+ uint64_t count =
-+ DTRACE_SYNC_CRITICAL_COUNT(sample_cpuid);
-+
-+ /*
-+ * Spin until critical section count increments.
-+ */
-+ if (DTRACE_SYNC_IN_CRITICAL(sample_cpuid)) {
-+ while (count ==
-+ DTRACE_SYNC_CRITICAL_COUNT(
-+ sample_cpuid)) {
-+
-+ dtrace_safe_smt_pause();
-+ }
-+ }
-+
-+ DTRACE_SYNC_END(sample_cpuid);
-+ DTRACE_SYNC_DONE(sample_cpuid, &sync_cpus);
-+ --outstanding;
-+ }
-+ }
-+ }
-+
-+/*
-+ * All preceding loads by DTRACE_SYNC_IN_CRITICAL() and
-+ * DTRACE_SYNC_CRITICAL_COUNT() must complete before subsequent loads
-+ * or stores. No membar is needed because the atomic-add operation in
-+ * DTRACE_SYNC_END() is a memory barrier on SPARC and X86.
-+ */
-+}
-+
-+/*
-+ * Handle a few special cases where we store information in kernel memory that
-+ * in other systems is typically found in userspace.
-+ */
-+static int dtrace_fake_copyin(intptr_t addr, size_t size)
-+{
-+ struct dtrace_psinfo *psinfo;
-+ uintptr_t argv;
-+ unsigned long argc;
-+ uintptr_t envp;
-+ unsigned long envc;
-+
-+ if (current->dt_task == NULL)
-+ return 0;
-+
-+ psinfo = current->dt_task->dt_psinfo;
-+ if (psinfo == NULL)
-+ return 0;
-+
-+ argv = (uintptr_t)psinfo->dtps_argv;
-+ argc = psinfo->dtps_argc;
-+ envp = (uintptr_t)psinfo->dtps_envp;
-+ envc = psinfo->dtps_envc;
-+
-+ /*
-+ * Ensure addr is within the argv array (or the envp array):
-+ * addr in [argv..argv + argc * sizeof(psinfo->argv[0])[
-+ * Ensure that addr + size is within the same array
-+ * addr + size in [argv..argv * sizeof(psinfo->argv[0])]
-+ *
-+ * To guard against overflows on (addr + size) we rewrite this basic
-+ * equation:
-+ * addr + size <= argv + argc * sizeof(psinfo->argv[0])
-+ * into:
-+ * addr - argv <= argc * sizeof(psinfo->argv[0]) - size
-+ */
-+ return (addr >= argv &&
-+ addr - argv < argc * sizeof(psinfo->dtps_argv[0]) &&
-+ addr - argv <= argc * sizeof(psinfo->dtps_argv[0]) - size) ||
-+ (addr >= envp &&
-+ addr - envp < envc * sizeof(psinfo->dtps_envp[0]) &&
-+ addr - envp <= envc * sizeof(psinfo->dtps_envp[0]) - size);
-+}
-+
-+void dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_fake_copyin(uaddr, size)) {
-+ memcpy((char *)kaddr, (char *)uaddr, size);
-+ return;
-+ }
-+
-+ dtrace_copyin_arch(uaddr, kaddr, size, flags);
-+}
-+
-+void dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+ if (dtrace_fake_copyin(uaddr, size)) {
-+ strncpy((char *)kaddr, (char *)uaddr,
-+ min(size, (size_t)PR_PSARGS_SZ));
-+ return;
-+ }
-+
-+ dtrace_copyinstr_arch(uaddr, kaddr, size, flags);
-+}
-+
-+/*
-+ * FIXME: aframes + 3 should really be aframes + 1, dtrace_stacktrace() in the
-+ * kernel should do its own aframes + 2
-+ */
-+void dtrace_getpcstack(uint64_t *pcstack, int pcstack_limit, int aframes,
-+ uint32_t *intrpc)
-+{
-+ struct stacktrace_state st = {
-+ pcstack,
-+ NULL,
-+ pcstack_limit,
-+ aframes + 3,
-+ STACKTRACE_KERNEL
-+ };
-+
-+ dtrace_stacktrace(&st);
-+
-+ while (st.depth < st.limit)
-+ pcstack[st.depth++] = 0;
-+}
-+EXPORT_SYMBOL(dtrace_getpcstack);
-+
-+/*
-+ * Get user stack entries up to the pcstack_limit; return the number of entries
-+ * acquired. If pcstack is NULL, return the number of entries potentially
-+ * acquirable.
-+ */
-+unsigned long dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack,
-+ int pcstack_limit)
-+{
-+ struct task_struct *p = current;
-+ struct stacktrace_state st;
-+ unsigned long depth;
-+
-+ if (pcstack) {
-+ if (unlikely(pcstack_limit < 2)) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return 0;
-+ }
-+ *pcstack++ = (uint64_t)p->pid;
-+ *pcstack++ = (uint64_t)p->tgid;
-+ pcstack_limit -= 2;
-+ }
-+
-+ st.pcs = pcstack;
-+ st.fps = fpstack;
-+ st.limit = pcstack_limit;
-+ st.depth = 0;
-+ st.flags = STACKTRACE_USER;
-+
-+ dtrace_stacktrace(&st);
-+
-+ depth = st.depth;
-+ if (pcstack) {
-+ while (st.depth < st.limit) {
-+ pcstack[st.depth++] = 0;
-+ if (fpstack)
-+ fpstack[st.depth++] = 0;
-+ }
-+ }
-+
-+ return depth;
-+}
-+
-+void dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
-+{
-+ dtrace_getufpstack(pcstack, NULL, pcstack_limit);
-+}
-+
-+/*
-+ * FIXME: aframes + 3 should really be aframes + 1, dtrace_stacktrace() in the
-+ * kernel should do its own aframes + 2
-+ */
-+int dtrace_getstackdepth(struct dtrace_mstate *mstate, int aframes)
-+{
-+ uintptr_t old = mstate->dtms_scratch_ptr;
-+ struct stacktrace_state st = {
-+ NULL,
-+ NULL,
-+ 0,
-+ aframes + 3,
-+ STACKTRACE_KERNEL
-+ };
-+
-+ st.pcs = (uint64_t *)ALIGN(old, 8);
-+ if ((uintptr_t)st.pcs >
-+ mstate->dtms_scratch_base + mstate->dtms_scratch_size) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ return 0;
-+ }
-+
-+ /*
-+ * Calculate how many (64-bit) PCs we can fit in the remaining scratch
-+ * memory.
-+ */
-+ st.limit = (mstate->dtms_scratch_base + mstate->dtms_scratch_size -
-+ (uintptr_t)st.pcs) >> 3;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ dtrace_stacktrace(&st);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ mstate->dtms_scratch_ptr = old;
-+
-+ return st.depth;
-+}
-+
-+int dtrace_getustackdepth(void)
-+{
-+ return dtrace_getufpstack(NULL, NULL, INT_MAX);
-+}
-+
-+void dtrace_probe_error(struct dtrace_state *state, dtrace_epid_t epid,
-+ int act, int fltoffs, int flags, uintptr_t addr)
-+{
-+ dtrace_probe(dtrace_probeid_error, (uintptr_t)state, epid, act,
-+ fltoffs, flags, addr, 0);
-+}
-diff --git a/dtrace/dtrace_match.c b/dtrace/dtrace_match.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..a63e3f8be1cde0114bfc7f78e6df6f278ed81a40
---- /dev/null
-+++ b/dtrace/dtrace_match.c
-@@ -0,0 +1,364 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_match.c
-+ * DESCRIPTION: DTrace - probe match implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include "dtrace.h"
-+
-+struct dtrace_hash *dtrace_bymod;
-+struct dtrace_hash *dtrace_byfunc;
-+struct dtrace_hash *dtrace_byname;
-+
-+int dtrace_match_priv(const struct dtrace_probe *prp, uint32_t priv,
-+ kuid_t uid)
-+{
-+ if (priv != DTRACE_PRIV_ALL) {
-+ uint32_t ppriv =
-+ prp->dtpr_provider->dtpv_priv.dtpp_flags;
-+ uint32_t match = priv & ppriv;
-+
-+ if ((priv & (DTRACE_PRIV_PROC | DTRACE_PRIV_USER |
-+ DTRACE_PRIV_KERNEL)) == 0)
-+ return 0;
-+
-+ if (match == 0 && ppriv != 0)
-+ return 0;
-+
-+ if (((ppriv & ~match) & DTRACE_PRIV_OWNER) != 0 &&
-+ !uid_eq(uid, make_kuid(init_user_namespace,
-+ prp->dtpr_provider->dtpv_priv.dtpp_uid)))
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+int dtrace_match_probe(const struct dtrace_probe *prp,
-+ const struct dtrace_probekey *pkp,
-+ uint32_t priv, kuid_t uid)
-+{
-+ struct dtrace_provider *pvp = prp->dtpr_provider;
-+ int rv;
-+
-+ if (pvp->dtpv_defunct)
-+ return 0;
-+
-+ rv = pkp->dtpk_pmatch(pvp->dtpv_name, pkp->dtpk_prov, 0);
-+ if (rv <= 0)
-+ return rv;
-+
-+ rv = pkp->dtpk_mmatch(prp->dtpr_mod, pkp->dtpk_mod, 0);
-+ if (rv <= 0)
-+ return rv;
-+
-+ rv = pkp->dtpk_fmatch(prp->dtpr_func, pkp->dtpk_func, 0);
-+ if (rv <= 0)
-+ return rv;
-+
-+ rv = pkp->dtpk_nmatch(prp->dtpr_name, pkp->dtpk_name, 0);
-+ if (rv <= 0)
-+ return rv;
-+
-+ if (dtrace_match_priv(prp, priv, uid) == 0)
-+ return 0;
-+
-+ return rv;
-+}
-+
-+int dtrace_match_glob(const char *s, const char *p, int depth)
-+{
-+ const char *olds;
-+ char s1, c;
-+ int gs;
-+
-+ if (depth > DTRACE_PROBEKEY_MAXDEPTH)
-+ return -1;
-+
-+ if (s == NULL)
-+ s = "";
-+
-+top:
-+ olds = s;
-+ s1 = *s++;
-+
-+ if (p == NULL)
-+ return 0;
-+
-+ c = *p++;
-+ if (c == '\0')
-+ return s1 == '\0';
-+
-+ switch (c) {
-+ case '[':
-+ {
-+ int ok = 0, notflag = 0;
-+ char lc = '\0';
-+
-+ if (s1 == '\0')
-+ return 0;
-+
-+ if (*p == '!') {
-+ notflag = 1;
-+ p++;
-+ }
-+
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+
-+ do {
-+ if (c == '-' && lc != '\0' && *p != ']') {
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+ if (c == '\\') {
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+ }
-+ if (notflag) {
-+ if (s1 < lc || s1 > c)
-+ ok++;
-+ else
-+ return 0;
-+ } else if (lc <= s1 && s1 <= c)
-+ ok++;
-+ } else if (c == '\\') {
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+ }
-+ lc = c;
-+
-+ if (notflag) {
-+ if (s1 != c)
-+ ok++;
-+ else
-+ return 0;
-+ } else if (s1 == c)
-+ ok++;
-+
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+ } while (c != ']');
-+
-+ if (ok)
-+ goto top;
-+
-+ return 0;
-+ }
-+
-+ case '\\':
-+ c = *p++;
-+ if (c == '\0')
-+ return 0;
-+ /* fallthru */
-+ default:
-+ if (c != s1)
-+ return 0;
-+ /* fallthru */
-+
-+ case '?':
-+ if (s1 != '\0')
-+ goto top;
-+
-+ return 0;
-+
-+ case '*':
-+ while (*p == '*')
-+ p++;
-+
-+ if (*p == '\0')
-+ return 1;
-+
-+ for (s = olds; *s != '\0'; s++) {
-+ gs = dtrace_match_glob(s, p, depth + 1);
-+ if (gs != 0)
-+ return gs;
-+ }
-+
-+ return 0;
-+ }
-+}
-+
-+int dtrace_match_string(const char *s, const char *p, int depth)
-+{
-+ return s != NULL && strcmp(s, p) == 0;
-+}
-+
-+int dtrace_match_nul(const char *s, const char *p, int depth)
-+{
-+ return 1;
-+}
-+
-+int dtrace_match_nonzero(const char *s, const char *p, int depth)
-+{
-+ return s != NULL && s[0] != '\0';
-+}
-+
-+struct probe_match {
-+ const struct dtrace_probekey *pkp;
-+ uint32_t priv;
-+ kuid_t uid;
-+ int (*matched)(struct dtrace_probe *, void *);
-+ void *arg;
-+ int nmatched;
-+};
-+
-+static int dtrace_match_one(int id, void *p, void *data)
-+{
-+ struct probe_match *pbm = (struct probe_match *)data;
-+ struct dtrace_probe *probe = (struct dtrace_probe *)p;
-+ int rc;
-+
-+ if (dtrace_match_probe(probe, pbm->pkp, pbm->priv, pbm->uid) <= 0)
-+ return 0;
-+
-+ pbm->nmatched++;
-+
-+ rc = (pbm->matched)(probe, pbm->arg);
-+ if (rc != DTRACE_MATCH_NEXT) {
-+ if (rc == DTRACE_MATCH_FAIL)
-+ return DTRACE_MATCH_FAIL;
-+ }
-+
-+ return 0;
-+}
-+
-+int dtrace_match(const struct dtrace_probekey *pkp, uint32_t priv, kuid_t uid,
-+ int (*matched)(struct dtrace_probe *, void *), void *arg)
-+{
-+ struct dtrace_probe template, *probe;
-+ struct dtrace_hash *hash = NULL;
-+ int len, rc, best = INT_MAX, nmatched = 0;
-+
-+ if (pkp->dtpk_id != DTRACE_IDNONE) {
-+ probe = dtrace_probe_lookup_id(pkp->dtpk_id);
-+ if (probe != NULL &&
-+ dtrace_match_probe(probe, pkp, priv, uid) > 0) {
-+ if ((*matched)(probe, arg) == DTRACE_MATCH_FAIL)
-+ return DTRACE_MATCH_FAIL;
-+
-+ nmatched++;
-+ }
-+
-+ return nmatched;
-+ }
-+
-+ template.dtpr_mod = (char *)pkp->dtpk_mod;
-+ template.dtpr_func = (char *)pkp->dtpk_func;
-+ template.dtpr_name = (char *)pkp->dtpk_name;
-+
-+ if (pkp->dtpk_mmatch == &dtrace_match_string) {
-+ len = dtrace_hash_collisions(dtrace_bymod, &template);
-+ if (len < best) {
-+ best = len;
-+ hash = dtrace_bymod;
-+ }
-+ }
-+
-+ if (pkp->dtpk_fmatch == &dtrace_match_string) {
-+ len = dtrace_hash_collisions(dtrace_byfunc, &template);
-+ if (len < best) {
-+ best = len;
-+ hash = dtrace_byfunc;
-+ }
-+ }
-+
-+ if (pkp->dtpk_nmatch == &dtrace_match_string) {
-+ len = dtrace_hash_collisions(dtrace_byname, &template);
-+ if (len < best) {
-+ best = len;
-+ hash = dtrace_byname;
-+ }
-+ }
-+
-+ if (hash == NULL) {
-+ struct probe_match pbm;
-+
-+ pbm.pkp = pkp;
-+ pbm.priv = priv;
-+ pbm.uid = uid;
-+ pbm.matched = matched;
-+ pbm.arg = arg;
-+ pbm.nmatched = 0;
-+
-+ rc = dtrace_probe_for_each(dtrace_match_one, &pbm);
-+ if (rc == DTRACE_MATCH_FAIL)
-+ return DTRACE_MATCH_FAIL;
-+
-+ return pbm.nmatched;
-+ }
-+
-+ for (probe = dtrace_hash_lookup(hash, &template); probe != NULL;
-+ probe = *(DTRACE_HASHNEXT(hash, probe))) {
-+ if (dtrace_match_probe(probe, pkp, priv, uid) <= 0)
-+ continue;
-+
-+ nmatched++;
-+
-+ rc = (*matched)(probe, arg);
-+ if (rc != DTRACE_MATCH_NEXT) {
-+ if (rc == DTRACE_MATCH_FAIL)
-+ return DTRACE_MATCH_FAIL;
-+
-+ break;
-+ }
-+ }
-+
-+ return nmatched;
-+}
-+
-+static dtrace_probekey_f *dtrace_probekey_func(const char *p)
-+{
-+ char c;
-+
-+ if (p == NULL || *p == '\0')
-+ return &dtrace_match_nul;
-+
-+ while ((c = *p++) != '\0') {
-+ if (c == '[' || c == '?' || c == '*' || c == '\\')
-+ return &dtrace_match_glob;
-+ }
-+
-+ return &dtrace_match_string;
-+}
-+
-+void dtrace_probekey(const struct dtrace_probedesc *pdp,
-+ struct dtrace_probekey *pkp)
-+{
-+ pkp->dtpk_prov = pdp->dtpd_provider;
-+ pkp->dtpk_pmatch = dtrace_probekey_func(pdp->dtpd_provider);
-+
-+ pkp->dtpk_mod = pdp->dtpd_mod;
-+ pkp->dtpk_mmatch = dtrace_probekey_func(pdp->dtpd_mod);
-+
-+ pkp->dtpk_func = pdp->dtpd_func;
-+ pkp->dtpk_fmatch = dtrace_probekey_func(pdp->dtpd_func);
-+
-+ pkp->dtpk_name = pdp->dtpd_name;
-+ pkp->dtpk_nmatch = dtrace_probekey_func(pdp->dtpd_name);
-+
-+ pkp->dtpk_id = pdp->dtpd_id;
-+
-+ if (pkp->dtpk_id == DTRACE_IDNONE &&
-+ pkp->dtpk_pmatch == &dtrace_match_nul &&
-+ pkp->dtpk_mmatch == &dtrace_match_nul &&
-+ pkp->dtpk_fmatch == &dtrace_match_nul &&
-+ pkp->dtpk_nmatch == &dtrace_match_nul)
-+ pkp->dtpk_fmatch = &dtrace_match_nonzero;
-+}
-diff --git a/dtrace/dtrace_mod.c b/dtrace/dtrace_mod.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..4da08c3cd816b751242765e8f680480b84ea29e7
---- /dev/null
-+++ b/dtrace/dtrace_mod.c
-@@ -0,0 +1,45 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_mod.c
-+ * DESCRIPTION: DTrace - framework kernel module
-+ *
-+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace_dev.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("Dynamic Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+/*
-+ * Initialize the module.
-+ */
-+static int __init dtrace_init(void)
-+{
-+ return dtrace_dev_init();
-+}
-+
-+/*
-+ * Perform cleanup before the module is removed.
-+ */
-+static void __exit dtrace_exit(void)
-+{
-+ dtrace_dev_exit();
-+}
-+
-+module_init(dtrace_init);
-+module_exit(dtrace_exit);
-diff --git a/dtrace/dtrace_predicate.c b/dtrace/dtrace_predicate.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..004a1c542c760f16631b54cbf105b3f37acc13e1
---- /dev/null
-+++ b/dtrace/dtrace_predicate.c
-@@ -0,0 +1,80 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_predicate.c
-+ * DESCRIPTION: DTrace - predicate cache implementation
-+ *
-+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/slab.h>
-+
-+#include "dtrace.h"
-+
-+static dtrace_cacheid_t dtrace_predcache_id = DTRACE_CACHEIDNONE + 1;
-+
-+struct dtrace_predicate *dtrace_predicate_create(struct dtrace_difo *dp)
-+{
-+ struct dtrace_predicate *pred;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dp->dtdo_refcnt != 0);
-+
-+ pred = kzalloc(sizeof(struct dtrace_predicate), GFP_KERNEL);
-+ if (pred == NULL)
-+ return NULL;
-+
-+ pred->dtp_difo = dp;
-+ pred->dtp_refcnt = 1;
-+
-+ if (!dtrace_difo_cacheable(dp))
-+ return pred;
-+
-+ /*
-+ * This is only theoretically possible -- we have had 2^32 cacheable
-+ * predicates on this machine. We cannot allow any more predicates to
-+ * become cacheable: as unlikely as it is, there may be a thread
-+ * caching a (now stale) predicate cache ID. (N.B.: the temptation is
-+ * being successfully resisted to have this cmn_err() "Holy shit -- we
-+ * executed this code!")
-+ */
-+ if (dtrace_predcache_id == DTRACE_CACHEIDNONE)
-+ return pred;
-+
-+ pred->dtp_cacheid = dtrace_predcache_id++;
-+
-+ return pred;
-+}
-+
-+void dtrace_predicate_hold(struct dtrace_predicate *pred)
-+{
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(pred->dtp_difo != NULL && pred->dtp_difo->dtdo_refcnt != 0);
-+ ASSERT(pred->dtp_refcnt > 0);
-+
-+ pred->dtp_refcnt++;
-+}
-+
-+void dtrace_predicate_release(struct dtrace_predicate *pred,
-+ struct dtrace_vstate *vstate)
-+{
-+ struct dtrace_difo *dp = pred->dtp_difo;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dp != NULL && dp->dtdo_refcnt != 0);
-+ ASSERT(pred->dtp_refcnt > 0);
-+
-+ if (--pred->dtp_refcnt == 0) {
-+ dtrace_difo_release(dp, vstate);
-+ kfree(pred);
-+ }
-+}
-diff --git a/dtrace/dtrace_priv.c b/dtrace/dtrace_priv.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..f50133de572df2be7c34b162124cfc05ac0b39d5
---- /dev/null
-+++ b/dtrace/dtrace_priv.c
-@@ -0,0 +1,120 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_priv.c
-+ * DESCRIPTION: DTrace - privilege support implementation
-+ *
-+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+
-+#include "dtrace.h"
-+
-+/*
-+ * This privilege check should be used by actions and subroutines to
-+ * verify that the user credentials of the process that enabled the
-+ * invoking ECB match the target credentials
-+ */
-+int dtrace_priv_proc_common_user(struct dtrace_state *state)
-+{
-+ const struct cred *cr, *s_cr = state->dts_cred.dcr_cred;
-+
-+ /*
-+ * We should always have a non-NULL state cred here, since if cred
-+ * is null (anonymous tracing), we fast-path bypass this routine.
-+ */
-+ ASSERT(s_cr != NULL);
-+
-+ cr = current_cred();
-+ if (cr != NULL &&
-+ uid_eq(s_cr->euid, cr->euid) &&
-+ uid_eq(s_cr->euid, cr->uid) &&
-+ uid_eq(s_cr->euid, cr->suid) &&
-+ gid_eq(s_cr->egid, cr->egid) &&
-+ gid_eq(s_cr->egid, cr->gid) &&
-+ gid_eq(s_cr->egid, cr->sgid))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/*
-+ * This privilege check should be used by actions and subroutines to
-+ * verify that the process has not setuid or changed credentials.
-+ */
-+int dtrace_priv_proc_common_nocd(void)
-+{
-+#ifdef FIXME
-+ proc_t *proc;
-+
-+ proc = ttoproc(curthread);
-+ if (proc != NULL && !(proc->p_flag & SNOCD))
-+ return 1;
-+#endif
-+
-+ return 0;
-+}
-+
-+int dtrace_priv_proc_destructive(struct dtrace_state *state)
-+{
-+ int action = state->dts_cred.dcr_action;
-+
-+ if (((action & DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER) == 0) &&
-+ dtrace_priv_proc_common_user(state) == 0)
-+ goto bad;
-+
-+ if (((action & DTRACE_CRA_PROC_DESTRUCTIVE_CREDCHG) == 0) &&
-+ dtrace_priv_proc_common_nocd() == 0)
-+ goto bad;
-+
-+ return 1;
-+
-+bad:
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_UPRIV);
-+
-+ return 0;
-+}
-+
-+int dtrace_priv_proc_control(struct dtrace_state *state)
-+{
-+ if (state->dts_cred.dcr_action & DTRACE_CRA_PROC_CONTROL)
-+ return 1;
-+
-+ if (dtrace_priv_proc_common_user(state) &&
-+ dtrace_priv_proc_common_nocd())
-+ return 1;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_UPRIV);
-+
-+ return 0;
-+}
-+
-+int dtrace_priv_proc(struct dtrace_state *state)
-+{
-+ if (state->dts_cred.dcr_action & DTRACE_CRA_PROC)
-+ return 1;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_UPRIV);
-+
-+ return 0;
-+}
-+
-+int dtrace_priv_kernel(struct dtrace_state *state)
-+{
-+ if (state->dts_cred.dcr_action & DTRACE_CRA_KERNEL)
-+ return 1;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
-+
-+ return 0;
-+}
-diff --git a/dtrace/dtrace_probe.c b/dtrace/dtrace_probe.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..8e2e04cb9c1358edc46cd70b6855967b663868f5
---- /dev/null
-+++ b/dtrace/dtrace_probe.c
-@@ -0,0 +1,1542 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_probe.c
-+ * DESCRIPTION: DTrace - probe implementation
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/hardirq.h>
-+#include <linux/highmem.h>
-+#include <linux/idr.h>
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <asm/pgtable.h>
-+#include <asm/cmpxchg.h>
-+#include <linux/sched/signal.h>
-+
-+#include "dtrace.h"
-+
-+ktime_t dtrace_chill_interval =
-+ KTIME_INIT(1, 0);
-+ktime_t dtrace_chill_max =
-+ KTIME_INIT(0,
-+ 500 * (NANOSEC / MILLISEC));
-+
-+dtrace_genid_t dtrace_probegen;
-+struct kmem_cache *dtrace_probe_cachep;
-+
-+static struct idr dtrace_probe_idr;
-+
-+static struct task_struct *dtrace_panicked;
-+
-+/*
-+ * Free probe structure (including partially filled in ones).
-+ */
-+void dtrace_probe_free(struct dtrace_probe *probe)
-+{
-+ if (probe == NULL)
-+ return;
-+
-+ dtrace_probe_remove_id(probe->dtpr_id);
-+
-+ kfree(probe->dtpr_mod);
-+ kfree(probe->dtpr_func);
-+ kfree(probe->dtpr_name);
-+
-+ kmem_cache_free(dtrace_probe_cachep, probe);
-+}
-+
-+/*
-+ * Create a new probe.
-+ */
-+dtrace_id_t dtrace_probe_create(dtrace_provider_id_t prov, const char *mod,
-+ const char *func, const char *name,
-+ int aframes, void *arg)
-+{
-+ struct dtrace_probe *probe;
-+ struct dtrace_provider *provider = (struct dtrace_provider *)prov;
-+ dtrace_id_t id;
-+
-+ probe = kmem_cache_alloc(dtrace_probe_cachep, GFP_KERNEL);
-+ if (probe == NULL)
-+ goto err_probe;
-+
-+ /*
-+ * The idr_preload() should be called without holding locks as it may
-+ * block. At the same time it is required to protect DTrace structures.
-+ * We can't drop it before idr_preload() and acquire after it because
-+ * we can't sleep in atomic context (until we reach idr_preload_end()).
-+ *
-+ * It is better to delay DTrace framework than traced host so the lock
-+ * is being held for the duration of idr allocation.
-+ *
-+ * When the provider is the DTrace core itself, dtrace_lock will be
-+ * held when we enter this function.
-+ */
-+ if (provider == dtrace_provider)
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ else
-+ mutex_lock(&dtrace_lock);
-+
-+ idr_preload(GFP_KERNEL);
-+ id = idr_alloc_cyclic(&dtrace_probe_idr, probe, 0, 0, GFP_NOWAIT);
-+ idr_preload_end();
-+ if (id < 0)
-+ goto err_probe;
-+
-+ probe->dtpr_id = id;
-+ probe->dtpr_ecb = NULL;
-+ probe->dtpr_ecb_last = NULL;
-+ probe->dtpr_arg = arg;
-+ probe->dtpr_predcache = DTRACE_CACHEIDNONE;
-+ probe->dtpr_aframes = aframes;
-+ probe->dtpr_provider = provider;
-+
-+ probe->dtpr_mod = dtrace_strdup(mod);
-+ if (probe->dtpr_mod == NULL)
-+ goto err_probe;
-+
-+ probe->dtpr_func = dtrace_strdup(func);
-+ if (probe->dtpr_func == NULL)
-+ goto err_probe;
-+
-+ probe->dtpr_name = dtrace_strdup(name);
-+ if (probe->dtpr_name == NULL)
-+ goto err_probe;
-+
-+ probe->dtpr_nextmod = probe->dtpr_prevmod = NULL;
-+ probe->dtpr_nextfunc = probe->dtpr_prevfunc = NULL;
-+ probe->dtpr_nextname = probe->dtpr_prevname = NULL;
-+ probe->dtpr_gen = dtrace_probegen++;
-+
-+ if (dtrace_hash_add(dtrace_bymod, probe) != 0)
-+ goto err_probe;
-+
-+ if (dtrace_hash_add(dtrace_byfunc, probe) != 0)
-+ goto err_hash_byfunc;
-+
-+ if (dtrace_hash_add(dtrace_byname, probe) != 0)
-+ goto err_hash_byname;
-+
-+ if (provider != dtrace_provider)
-+ mutex_unlock(&dtrace_lock);
-+
-+ return id;
-+
-+err_hash_byname:
-+ dtrace_hash_remove(dtrace_byfunc, probe);
-+err_hash_byfunc:
-+ dtrace_hash_remove(dtrace_bymod, probe);
-+err_probe:
-+ dtrace_probe_free(probe);
-+ if (provider != dtrace_provider)
-+ mutex_unlock(&dtrace_lock);
-+ return DTRACE_IDNONE;
-+}
-+EXPORT_SYMBOL(dtrace_probe_create);
-+
-+int dtrace_probe_enable(const struct dtrace_probedesc *desc,
-+ struct dtrace_enabling *enab)
-+{
-+ struct dtrace_probekey pkey;
-+ uint32_t priv;
-+ kuid_t uid;
-+
-+ dtrace_ecb_create_cache = NULL;
-+
-+ if (desc == NULL) {
-+ (void) dtrace_ecb_create_enable(NULL, enab);
-+
-+ return 0;
-+ }
-+
-+ dtrace_probekey(desc, &pkey);
-+ dtrace_cred2priv(enab->dten_vstate->dtvs_state->dts_cred.dcr_cred,
-+ &priv, &uid);
-+
-+ return dtrace_match(&pkey, priv, uid, dtrace_ecb_create_enable, enab);
-+}
-+
-+/*
-+ * Return the probe argument associated with the specified probe.
-+ */
-+void *dtrace_probe_arg(dtrace_provider_id_t id, dtrace_id_t pid)
-+{
-+ struct dtrace_probe *probe;
-+ void *rval = NULL;
-+
-+ mutex_lock(&dtrace_lock);
-+
-+ probe = dtrace_probe_lookup_id(pid);
-+ if (probe != NULL &&
-+ probe->dtpr_provider == (struct dtrace_provider *)id)
-+ rval = probe->dtpr_arg;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ return rval;
-+}
-+EXPORT_SYMBOL(dtrace_probe_arg);
-+
-+/*
-+ * Copy a probe into a probe description.
-+ */
-+void dtrace_probe_description(const struct dtrace_probe *prp,
-+ struct dtrace_probedesc *pdp)
-+{
-+ memset(pdp, 0, sizeof(struct dtrace_probedesc));
-+ pdp->dtpd_id = prp->dtpr_id;
-+
-+ strncpy(pdp->dtpd_provider, prp->dtpr_provider->dtpv_name,
-+ DTRACE_PROVNAMELEN - 1);
-+
-+ strncpy(pdp->dtpd_mod, prp->dtpr_mod, DTRACE_MODNAMELEN - 1);
-+ strncpy(pdp->dtpd_func, prp->dtpr_func, DTRACE_FUNCNAMELEN - 1);
-+ strncpy(pdp->dtpd_name, prp->dtpr_name, DTRACE_NAMELEN - 1);
-+}
-+
-+void dtrace_probe_provide(struct dtrace_probedesc *desc,
-+ struct dtrace_provider *prv)
-+{
-+ int all = 0;
-+
-+ if (prv == NULL) {
-+ all = 1;
-+ prv = dtrace_provider;
-+ }
-+
-+ do {
-+ prv->dtpv_pops.dtps_provide(prv->dtpv_arg, desc);
-+ dtrace_for_each_module(prv->dtpv_pops.dtps_provide_module,
-+ prv->dtpv_arg);
-+ } while (all && (prv = prv->dtpv_next) != NULL);
-+}
-+
-+/*
-+ * Atomically increment a specified error counter from probe context.
-+ */
-+static void dtrace_error(uint32_t *counter)
-+{
-+ /*
-+ * Most counters stored to in probe context are per-CPU counters.
-+ * However, there are some error conditions that are sufficiently
-+ * arcane that they don't merit per-CPU storage. If these counters
-+ * are incremented concurrently on different CPUs, scalability will be
-+ * adversely affected -- but we don't expect them to be white-hot in a
-+ * correctly constructed enabling...
-+ */
-+ uint32_t oval, nval;
-+
-+ do {
-+ oval = *counter;
-+
-+ nval = oval + 1;
-+ if (nval == 0) {
-+ /*
-+ * If the counter would wrap, set it to 1 -- assuring
-+ * that the counter is never zero when we have seen
-+ * errors. (The counter must be 32-bits because we
-+ * aren't guaranteed a 64-bit compare&swap operation.)
-+ * To save this code both the infamy of being fingered
-+ * by a priggish news story and the indignity of being
-+ * the target of a neo-puritan witch trial, we're
-+ * carefully avoiding any colorful description of the
-+ * likelihood of this condition -- but suffice it to
-+ * say that it is only slightly more likely than the
-+ * overflow of predicate cache IDs, as discussed in
-+ * dtrace_predicate_create().
-+ */
-+ nval = 1;
-+ }
-+ } while (cmpxchg(counter, oval, nval) != oval);
-+}
-+
-+static int dtrace_priv_kernel_destructive(struct dtrace_state *state)
-+{
-+ if (state->dts_cred.dcr_action & DTRACE_CRA_KERNEL_DESTRUCTIVE)
-+ return 1;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
-+
-+ return 0;
-+}
-+
-+static void dtrace_action_breakpoint(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_probe *probe = ecb->dte_probe;
-+ struct dtrace_provider *prov = probe->dtpr_provider;
-+ char c[DTRACE_FULLNAMELEN + 80], *str;
-+ char *msg = "dtrace: breakpoint action at probe ";
-+ char *ecbmsg = " (ecb ";
-+ uintptr_t mask = (0xf << (sizeof(uintptr_t) * NBBY / 4));
-+ uintptr_t val = (uintptr_t)ecb;
-+ int shift = (sizeof(uintptr_t) * NBBY) - 4, i = 0;
-+
-+ if (dtrace_destructive_disallow)
-+ return;
-+
-+ /*
-+ * It's impossible to be taking action on the NULL probe.
-+ */
-+ ASSERT(probe != NULL);
-+
-+ /*
-+ * This is a poor man's (destitute man's?) sprintf(): we want to
-+ * print the provider name, module name, function name and name of
-+ * the probe, along with the hex address of the ECB with the breakpoint
-+ * action -- all of which we must place in the character buffer by
-+ * hand.
-+ */
-+ while (*msg != '\0')
-+ c[i++] = *msg++;
-+
-+ for (str = prov->dtpv_name; *str != '\0'; str++)
-+ c[i++] = *str;
-+ c[i++] = ':';
-+
-+ for (str = probe->dtpr_mod; *str != '\0'; str++)
-+ c[i++] = *str;
-+ c[i++] = ':';
-+
-+ for (str = probe->dtpr_func; *str != '\0'; str++)
-+ c[i++] = *str;
-+ c[i++] = ':';
-+
-+ for (str = probe->dtpr_name; *str != '\0'; str++)
-+ c[i++] = *str;
-+
-+ while (*ecbmsg != '\0')
-+ c[i++] = *ecbmsg++;
-+
-+ while (shift >= 0) {
-+ mask = (uintptr_t)0xf << shift;
-+
-+ if (val >= ((uintptr_t)1 << shift))
-+ c[i++] = "0123456789abcdef"[(val & mask) >> shift];
-+
-+ shift -= 4;
-+ }
-+
-+ c[i++] = ')';
-+ c[i] = '\0';
-+
-+// debug_enter(c); /* FIXME */
-+}
-+
-+static void dtrace_action_panic(struct dtrace_ecb *ecb)
-+{
-+ struct dtrace_probe *probe = ecb->dte_probe;
-+
-+ /*
-+ * It's impossible to be taking action on the NULL probe.
-+ */
-+ ASSERT(probe != NULL);
-+
-+ if (dtrace_destructive_disallow)
-+ return;
-+
-+ if (dtrace_panicked != NULL)
-+ return;
-+
-+ if (cmpxchg(&dtrace_panicked, NULL, current) != NULL)
-+ return;
-+
-+ /*
-+ * We won the right to panic. (We want to be sure that only one
-+ * thread calls panic() from dtrace_probe(), and that panic() is
-+ * called exactly once.)
-+ */
-+ dtrace_panic(KERN_EMERG
-+ "dtrace: panic action at probe %s:%s:%s:%s (ecb %p)",
-+ probe->dtpr_provider->dtpv_name, probe->dtpr_mod,
-+ probe->dtpr_func, probe->dtpr_name, (void *)ecb);
-+}
-+
-+static void dtrace_action_raise(uint64_t sig)
-+{
-+ if (current->dt_task == NULL)
-+ return;
-+
-+ if (dtrace_destructive_disallow)
-+ return;
-+
-+ if (sig >= _NSIG) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return;
-+ }
-+
-+ /*
-+ * raise() has a queue depth of 1 -- we ignore all subsequent
-+ * invocations of the raise() action.
-+ */
-+ if (current->dt_task->dt_sig == 0)
-+ current->dt_task->dt_sig = (uint8_t)sig;
-+}
-+
-+static void dtrace_action_stop(void)
-+{
-+ if (current->dt_task == NULL)
-+ return;
-+
-+ if (dtrace_destructive_disallow)
-+ return;
-+
-+ if (!current->dt_task->dt_stop) {
-+ current->dt_task->dt_stop = 1;
-+// current->sig_check = 1; /* FIXME */
-+// aston(current); /* FIXME */
-+ }
-+}
-+
-+static void dtrace_action_chill(struct dtrace_mstate *mstate, ktime_t val)
-+{
-+ ktime_t now;
-+ volatile uint16_t *flags;
-+ struct cpu_core *cpu = this_cpu_core;
-+
-+ if (dtrace_destructive_disallow)
-+ return;
-+
-+ flags = (volatile uint16_t *)&cpu->cpuc_dtrace_flags;
-+
-+ now = dtrace_gethrtime();
-+
-+ if (ktime_gt(ktime_sub(now, cpu->cpu_dtrace_chillmark),
-+ dtrace_chill_interval)) {
-+ /*
-+ * We need to advance the mark to current time.
-+ */
-+ cpu->cpu_dtrace_chillmark = now;
-+ cpu->cpu_dtrace_chilled = ktime_set(0, 0);
-+ }
-+
-+ /*
-+ * Now check to see if the requested chill time would take us over
-+ * the maximum amount of time allowed in the chill interval. (Or
-+ * worse, if the calculation itself induces overflow.)
-+ */
-+ if (ktime_gt(ktime_add(cpu->cpu_dtrace_chilled, val),
-+ dtrace_chill_max) ||
-+ ktime_lt(ktime_add(cpu->cpu_dtrace_chilled, val),
-+ cpu->cpu_dtrace_chilled)) {
-+ *flags |= CPU_DTRACE_ILLOP;
-+ return;
-+ }
-+
-+ while (ktime_lt(ktime_sub(dtrace_gethrtime(), now), val))
-+ continue;
-+
-+ /*
-+ * Normally, we assure that the value of the variable "timestamp" does
-+ * not change within an ECB. The presence of chill() represents an
-+ * exception from this rule, however.
-+ */
-+ mstate->dtms_present &= ~DTRACE_MSTATE_TIMESTAMP;
-+ cpu->cpu_dtrace_chilled = ktime_add(cpu->cpu_dtrace_chilled, val);
-+}
-+
-+static void dtrace_action_ustack(struct dtrace_mstate *mstate,
-+ struct dtrace_state *state, uint64_t *buf,
-+ uint64_t arg)
-+{
-+ int nframes = DTRACE_USTACK_NFRAMES(arg);
-+ int strsize = DTRACE_USTACK_STRSIZE(arg);
-+ uint64_t *pcs = &buf[2], *fps;
-+ char *str = (char *)&pcs[nframes];
-+ int size, offs = 0, i, j;
-+ uintptr_t old = mstate->dtms_scratch_ptr, saved;
-+ uint16_t *flags = &this_cpu_core->cpuc_dtrace_flags;
-+ char *sym;
-+
-+ /*
-+ * Should be taking a faster path if string space has not been
-+ * allocated.
-+ */
-+ ASSERT(strsize != 0);
-+
-+ /*
-+ * We will first allocate some temporary space for the frame pointers.
-+ */
-+ fps = (uint64_t *)P2ROUNDUP(mstate->dtms_scratch_ptr, 8);
-+ size = (uintptr_t)fps - mstate->dtms_scratch_ptr +
-+ (nframes * sizeof(uint64_t));
-+
-+ if (!DTRACE_INSCRATCH(mstate, size)) {
-+ /*
-+ * Not enough room for our frame pointers -- need to indicate
-+ * that we ran out of scratch space.
-+ */
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
-+ return;
-+ }
-+
-+ mstate->dtms_scratch_ptr += size;
-+ saved = mstate->dtms_scratch_ptr;
-+
-+ /*
-+ * Now get a stack with both program counters and frame pointers.
-+ */
-+ dtrace_getufpstack(buf, fps, nframes + 2);
-+
-+ /*
-+ * If that faulted, we're cooked.
-+ */
-+ if (*flags & CPU_DTRACE_FAULT)
-+ goto out;
-+
-+ /*
-+ * Now we want to walk up the stack, calling the USTACK helper. For
-+ * each iteration, we restore the scratch pointer.
-+ */
-+ for (i = 0; i < nframes; i++) {
-+ mstate->dtms_scratch_ptr = saved;
-+
-+ if (offs >= strsize)
-+ break;
-+
-+ sym = (char *)(uintptr_t)dtrace_helper(
-+ DTRACE_HELPER_ACTION_USTACK,
-+ mstate, state, pcs[i], fps[i]);
-+
-+ /*
-+ * If we faulted while running the helper, we're going to
-+ * clear the fault and null out the corresponding string.
-+ */
-+ if (*flags & CPU_DTRACE_FAULT) {
-+ *flags &= ~CPU_DTRACE_FAULT;
-+ str[offs++] = '\0';
-+ continue;
-+ }
-+
-+ if (sym == NULL) {
-+ str[offs++] = '\0';
-+ continue;
-+ }
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+
-+ /*
-+ * Now copy in the string that the helper returned to us.
-+ */
-+ for (j = 0; offs + j < strsize; j++) {
-+ str[offs + j] = sym[j];
-+ if (str[offs + j] == '\0')
-+ break;
-+ }
-+
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ offs += j + 1;
-+ }
-+
-+ /*
-+ * If we didn't have room for all of the strings, we don't abort
-+ * processing -- this needn't be a fatal error -- but we still want
-+ * to increment a counter (dts_stkstroverflows) to allow this condition
-+ * to be warned about. (If this is from a jstack() action, it is
-+ * easily tuned via jstackstrsize.)
-+ */
-+ if (offs >= strsize)
-+ dtrace_error(&state->dts_stkstroverflows);
-+
-+ while (offs < strsize)
-+ str[offs++] = '\0';
-+
-+out:
-+ mstate->dtms_scratch_ptr = old;
-+}
-+
-+/*
-+ * This macro is used by dtrace_probe_pcap() below. See linux/skbuff.h for the
-+ * original. Only change is we pass in an already dereferenced page.p as
-+ * the fragment f.
-+ */
-+#define dtrace_skb_frag_foreach_page(f, f_off, f_len, p, p_off, p_len, copied) \
-+ for (p = f + ((f_off) >> PAGE_SHIFT), \
-+ p_off = (f_off) & (PAGE_SIZE - 1), \
-+ p_len = skb_frag_must_loop(p) ? \
-+ min_t(u32, f_len, PAGE_SIZE - p_off) : f_len, \
-+ copied = 0; \
-+ copied < f_len; \
-+ copied += p_len, p++, p_off = 0, \
-+ p_len = min_t(u32, f_len - copied, PAGE_SIZE)) \
-+
-+
-+/*
-+ * Capture skb data in linear and non-linear portions. Returns 0 on success,
-+ * -1 if an error is encountered.
-+ */
-+static __always_inline int dtrace_probe_pcap(uint64_t val, size_t *valoffs,
-+ size_t size, caddr_t tomax,
-+ ktime_t now,
-+ struct dtrace_mstate *mstate,
-+ struct dtrace_vstate *vstate,
-+ volatile uint16_t *flags)
-+
-+{
-+ uintptr_t start = *valoffs, end = *valoffs + size;
-+ uintptr_t skb_head, skb_data, skb_tail, shinfo;
-+ uint32_t skb_end, tail, skb_len = 0;
-+ uintptr_t baddr = val;
-+ uint8_t nr_frags, f;
-+ uint32_t data_len;
-+
-+ DTRACE_STORE(uint64_t, tomax, start, ktime_to_ns(now));
-+
-+ *valoffs += (2 * sizeof(uint64_t));
-+
-+ /*
-+ * Skip capture of NULL skbs.
-+ */
-+ if ((void *)baddr == NULL)
-+ goto pcap_done;
-+
-+ if (!dtrace_canload(baddr, sizeof(struct sk_buff), mstate, vstate))
-+ return -1;
-+
-+ skb_data = dtrace_loadptr(baddr + offsetof(struct sk_buff, data));
-+ skb_head = dtrace_loadptr(baddr + offsetof(struct sk_buff, head));
-+ skb_len = dtrace_load32(baddr + offsetof(struct sk_buff, len));
-+ tail = dtrace_load32(baddr + offsetof(struct sk_buff, tail));
-+ skb_tail = skb_head + tail;
-+
-+ if (skb_tail < skb_data) {
-+ *flags |= CPU_DTRACE_BADADDR;
-+ return -1;
-+ }
-+ while (*valoffs < end && skb_data < skb_tail) {
-+ DTRACE_STORE(uint8_t, tomax, (*valoffs)++,
-+ dtrace_load8(skb_data++));
-+ }
-+
-+ data_len = dtrace_load32(baddr + offsetof(struct sk_buff, data_len));
-+
-+ /*
-+ * If skb is linear, no need to explore fragments.
-+ */
-+ if (data_len == 0)
-+ goto pcap_done;
-+
-+ skb_end = dtrace_load32(baddr + offsetof(struct sk_buff, end));
-+ shinfo = skb_head + skb_end;
-+
-+ if (!dtrace_canload(shinfo, sizeof(struct skb_shared_info),
-+ mstate, vstate))
-+ return -1;
-+
-+ nr_frags = dtrace_load8(shinfo + offsetof(struct skb_shared_info,
-+ nr_frags));
-+
-+ /*
-+ * See skb_frag_foreach_page() macro usage elsewhere to understand the
-+ * manipulations here; the reason we need this complexity is to support
-+ * compound pages.
-+ */
-+ for (f = 0; f < nr_frags; f++) {
-+ uint32_t poff, plen, copied, flen;
-+ struct page *p, *frag;
-+ uintptr_t foff, v;
-+ void *vaddr;
-+
-+ flen = dtrace_load32(shinfo + offsetof(struct skb_shared_info,
-+ frags[f].bv_len));
-+ foff = dtrace_load32(shinfo + offsetof(struct skb_shared_info,
-+ frags[f].bv_offset));
-+ frag = (struct page *)dtrace_loadptr(shinfo + offsetof(
-+ struct skb_shared_info,
-+ frags[f].bv_page));
-+
-+ dtrace_skb_frag_foreach_page(frag, foff, flen,
-+ p, poff, plen, copied) {
-+ if (data_len == 0)
-+ break;
-+
-+ vaddr = kmap_atomic(p);
-+ v = (uintptr_t)vaddr + poff;
-+ if (!dtrace_canload(v, plen, mstate, vstate)) {
-+ kunmap_atomic(vaddr);
-+ return -1;
-+ }
-+ while (*valoffs < end && data_len-- > 0) {
-+ DTRACE_STORE(uint8_t, tomax, (*valoffs)++,
-+ dtrace_load8(v++));
-+ }
-+ kunmap_atomic(vaddr);
-+ }
-+ }
-+
-+pcap_done:
-+ /*
-+ * Note that we store the skb len here rather than the portion of it we
-+ * capture; we can determine the latter when collecting data by using
-+ * the "pcapsize" option. Packet capture headers specify a packet size
-+ * and a capture size, so we want to be able to provide both. Since
-+ * the capture size can be determined from the packet length when
-+ * consuming records, we don't need to store it.
-+ */
-+ DTRACE_STORE(uint64_t, tomax, start + sizeof(uint64_t),
-+ (uint64_t)skb_len);
-+
-+ return 0;
-+}
-+void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
-+ uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
-+ uintptr_t arg5, uintptr_t arg6)
-+{
-+ processorid_t cpuid;
-+ dtrace_icookie_t cookie;
-+ struct dtrace_probe *probe;
-+ struct dtrace_mstate mstate;
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_action *act;
-+ intptr_t offs;
-+ size_t size;
-+ int onintr;
-+ int vtime;
-+ volatile uint16_t *flags;
-+ ktime_t now;
-+ uint32_t re_entry;
-+ struct dtrace_task *dtsk = current->dt_task;
-+ dtrace_id_t old_id;
-+
-+#ifdef FIXME
-+ /*
-+ * Kick out immediately if this CPU is still being born (in which case
-+ * curthread will be set to -1) or the current thread can't allow
-+ * probes in its current context.
-+ */
-+ if (((uintptr_t)curthread & 1) || (curthread->t_flag & T_DONTDTRACE))
-+ return;
-+#endif
-+
-+ DTRACE_SYNC_ENTER_CRITICAL(cookie, re_entry);
-+
-+ /*
-+ * Probe context is not re-entrant, unless we're getting called to
-+ * process an ERROR probe.
-+ */
-+ flags = (volatile uint16_t *)&this_cpu_core->cpuc_dtrace_flags;
-+ cpuid = smp_processor_id();
-+ if (re_entry && id != dtrace_probeid_error) {
-+ dt_dbg_probe("Attempt to fire probe from within a probe " \
-+ "(ID %d, oID %d, CPU %d)\n", id,
-+ (int)this_cpu_core->cpuc_current_probe, cpuid);
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+ return;
-+ }
-+
-+ probe = dtrace_probe_lookup_id(id);
-+ onintr = in_interrupt();
-+
-+ if (!onintr && probe->dtpr_predcache != DTRACE_CACHEIDNONE &&
-+ dtsk != NULL && probe->dtpr_predcache == dtsk->dt_predcache) {
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+ return;
-+ }
-+
-+ if (oops_in_progress) {
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+ return;
-+ }
-+
-+ old_id = this_cpu_core->cpuc_current_probe;
-+ this_cpu_core->cpuc_current_probe = id;
-+
-+ now = dtrace_gethrtime();
-+ vtime = (dtrace_vtime_references > 0);
-+
-+ if (vtime && dtsk != NULL && ktime_nz(dtsk->dt_start))
-+ dtsk->dt_vtime = ktime_add(dtsk->dt_vtime,
-+ ktime_sub(now, dtsk->dt_start));
-+
-+ mstate.dtms_difo = NULL;
-+ mstate.dtms_probe = probe;
-+ mstate.dtms_strtok = (uintptr_t)NULL;
-+ mstate.dtms_arg[0] = arg0;
-+ mstate.dtms_arg[1] = arg1;
-+ mstate.dtms_arg[2] = arg2;
-+ mstate.dtms_arg[3] = arg3;
-+ mstate.dtms_arg[4] = arg4;
-+ mstate.dtms_arg[5] = arg5;
-+ mstate.dtms_arg[6] = arg6;
-+
-+ for (ecb = probe->dtpr_ecb; ecb != NULL; ecb = ecb->dte_next) {
-+ struct dtrace_predicate *pred = ecb->dte_predicate;
-+ struct dtrace_state *state = ecb->dte_state;
-+ struct dtrace_buffer *buf = &state->dts_buffer[cpuid];
-+ struct dtrace_buffer *aggbuf = &state->dts_aggbuffer[cpuid];
-+ struct dtrace_vstate *vstate = &state->dts_vstate;
-+ struct dtrace_provider *prov = probe->dtpr_provider;
-+ int committed = 0;
-+ caddr_t tomax;
-+
-+ /*
-+ * A little subtlety with the following (seemingly innocuous)
-+ * declaration of the automatic 'val': by looking at the
-+ * code, you might think that it could be declared in the
-+ * action processing loop, below. (That is, it's only used in
-+ * the action processing loop.) However, it must be declared
-+ * out of that scope because in the case of DIF expression
-+ * arguments to aggregating actions, one iteration of the
-+ * action loop will use the last iteration's value.
-+ */
-+ uint64_t val = 0;
-+
-+ mstate.dtms_present = DTRACE_MSTATE_ARGS | DTRACE_MSTATE_PROBE;
-+ *flags &= ~CPU_DTRACE_ERROR;
-+
-+ if (prov == dtrace_provider) {
-+ /*
-+ * If dtrace itself is the provider of this probe,
-+ * we're only going to continue processing the ECB if
-+ * arg0 (the dtrace_state_t) is equal to the ECB's
-+ * creating state. (This prevents disjoint consumers
-+ * from seeing one another's metaprobes.)
-+ */
-+ if (arg0 != (uint64_t)(uintptr_t)state)
-+ continue;
-+ }
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_ACTIVE) {
-+ /*
-+ * We're not currently active. If our provider isn't
-+ * the dtrace pseudo provider, we're not interested.
-+ */
-+ if (prov != dtrace_provider)
-+ continue;
-+
-+ /*
-+ * Now we must further check if we are in the BEGIN
-+ * probe. If we are, we will only continue orocessing
-+ * if we're still in WARMUP -- if one BEGIN enabling
-+ * has invoked the exit() action, we don't want to
-+ * evaluate subsequent BEGIN enablings.
-+ */
-+ if (probe->dtpr_id == dtrace_probeid_begin &&
-+ state->dts_activity != DTRACE_ACTIVITY_WARMUP) {
-+ ASSERT(state->dts_activity ==
-+ DTRACE_ACTIVITY_DRAINING);
-+ continue;
-+ }
-+ }
-+
-+ dt_dbg_probe("Probe (ID %d EPID %d) on CPU %d...\n",
-+ id, ecb->dte_epid, cpuid);
-+ if (ecb->dte_cond) {
-+ /*
-+ * If the dte_cond bits indicate that this
-+ * consumer is only allowed to see user-mode firings
-+ * of this probe, call the provider's dtps_usermode()
-+ * entry point to check that the probe was fired
-+ * while in a user context. Skip this ECB if that's
-+ * not the case.
-+ */
-+ if ((ecb->dte_cond & DTRACE_COND_USERMODE) &&
-+ prov->dtpv_pops.dtps_usermode(
-+ prov->dtpv_arg, probe->dtpr_id, probe->dtpr_arg
-+ ) == 0) {
-+ dt_dbg_probe("Probe (ID %d EPID %d) Skipped\n",
-+ id, ecb->dte_epid);
-+ continue;
-+ }
-+
-+ /*
-+ * This is more subtle than it looks. We have to be
-+ * absolutely certain that current_cred() isn't going
-+ * to change out from under us so it's only legit to
-+ * examine that structure if we're in constrained
-+ * situations. Currently, the only times we'll use this
-+ * check is if a non-super-user has enabled the
-+ * profile or syscall providers -- providers that
-+ * allow visibility of all processes. For the
-+ * profile case, the check above will ensure that
-+ * we're examining a user context.
-+ */
-+ if (ecb->dte_cond & DTRACE_COND_OWNER) {
-+ const struct cred *cr;
-+ const struct cred *s_cr =
-+ ecb->dte_state->dts_cred.dcr_cred;
-+
-+ ASSERT(s_cr != NULL);
-+
-+ cr = current_cred();
-+ if (cr == NULL ||
-+ !uid_eq(s_cr->euid, cr->euid) ||
-+ !uid_eq(s_cr->euid, cr->uid) ||
-+ !uid_eq(s_cr->euid, cr->suid) ||
-+ !gid_eq(s_cr->egid, cr->egid) ||
-+ !gid_eq(s_cr->egid, cr->gid) ||
-+ !gid_eq(s_cr->egid, cr->sgid)) {
-+ dt_dbg_probe("Probe (ID %d EPID %d) "
-+ "Skipped\n",
-+ id, ecb->dte_epid);
-+ continue;
-+ }
-+ }
-+ }
-+
-+ if (ktime_gt(ktime_sub(now, state->dts_alive),
-+ dtrace_deadman_timeout)) {
-+ /*
-+ * We seem to be dead. Unless we (a) have kernel
-+ * destructive permissions (b) have expicitly enabled
-+ * destructive actions and (c) destructive actions have
-+ * not been disabled, we're going to transition into
-+ * the KILLED state, from which no further processing
-+ * on this state will be performed.
-+ */
-+ if (!dtrace_priv_kernel_destructive(state) ||
-+ !state->dts_cred.dcr_destructive ||
-+ dtrace_destructive_disallow) {
-+ enum dtrace_activity *activity =
-+ &state->dts_activity;
-+ enum dtrace_activity curr;
-+
-+ do {
-+ curr = state->dts_activity;
-+ } while (cmpxchg(activity, curr,
-+ DTRACE_ACTIVITY_KILLED) != curr);
-+
-+ dt_dbg_probe("Probe (ID %d EPID %d) Skipped\n",
-+ id, ecb->dte_epid);
-+ continue;
-+ }
-+ }
-+
-+ offs = dtrace_buffer_reserve(buf, ecb->dte_needed,
-+ ecb->dte_alignment, state,
-+ &mstate);
-+ if (offs < 0) {
-+ dt_dbg_probe("Probe (ID %d EPID %d) Skipped\n",
-+ id, ecb->dte_epid);
-+ continue;
-+ }
-+
-+ tomax = buf->dtb_tomax;
-+ ASSERT(tomax != NULL);
-+
-+ if (ecb->dte_size != 0) {
-+ DTRACE_STORE(uint32_t, tomax, offs, ecb->dte_epid);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- %d [EPID] "
-+ "(from %s::%d)\n",
-+ buf, offs, offs + sizeof(uint32_t) - 1,
-+ ecb->dte_epid, __func__, __LINE__);
-+ }
-+
-+ mstate.dtms_epid = ecb->dte_epid;
-+ mstate.dtms_present |= DTRACE_MSTATE_EPID;
-+
-+ if (state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL)
-+ mstate.dtms_access = DTRACE_ACCESS_KERNEL;
-+ else
-+ mstate.dtms_access = 0;
-+
-+ if (pred != NULL) {
-+ struct dtrace_difo *dp = pred->dtp_difo;
-+ int rval;
-+
-+ dt_dbg_probe(" Evaluating predicate...\n");
-+
-+ rval = dtrace_dif_emulate(dp, &mstate, vstate, state);
-+
-+ if (!(*flags & CPU_DTRACE_ERROR) && !rval) {
-+ dtrace_cacheid_t cid =
-+ probe->dtpr_predcache;
-+
-+ if (cid != DTRACE_CACHEIDNONE && !onintr) {
-+ /*
-+ * Update the predicate cache...
-+ */
-+ ASSERT(cid == pred->dtp_cacheid);
-+ if (dtsk != NULL)
-+ dtsk->dt_predcache = cid;
-+ }
-+
-+ dt_dbg_probe(" Predicate not met (%d)\n",
-+ rval);
-+ dt_dbg_probe("Probe (ID %d EPID %d) Done\n",
-+ id, ecb->dte_epid);
-+ continue;
-+ }
-+
-+ dt_dbg_probe(" Predicate met (%d)\n", rval);
-+ }
-+
-+ for (act = ecb->dte_action;
-+ !(*flags & CPU_DTRACE_ERROR) && act != NULL;
-+ act = act->dta_next) {
-+ size_t valoffs;
-+ struct dtrace_difo *dp;
-+ struct dtrace_recdesc *rec = &act->dta_rec;
-+
-+ dt_dbg_probe(" Evaluating action %p (kind %d)...\n",
-+ act, act->dta_kind);
-+
-+ size = rec->dtrd_size;
-+ valoffs = offs + rec->dtrd_offset;
-+
-+ if (DTRACEACT_ISAGG(act->dta_kind)) {
-+ uint64_t v = 0xbad;
-+ struct dtrace_aggregation *agg;
-+
-+ agg = (struct dtrace_aggregation *)act;
-+
-+ dp = act->dta_difo;
-+ if (dp != NULL)
-+ v = dtrace_dif_emulate(dp, &mstate,
-+ vstate, state);
-+
-+ if (*flags & CPU_DTRACE_ERROR)
-+ continue;
-+
-+ /*
-+ * Note that we always pass the expression
-+ * value from the previous iteration of the
-+ * action loop. This value will only be used
-+ * if there is an expression argument to the
-+ * aggregating action, denoted by the
-+ * dtag_hasarg field.
-+ */
-+ dtrace_aggregate(agg, buf, offs, aggbuf, v,
-+ val);
-+ continue;
-+ }
-+
-+ switch (act->dta_kind) {
-+ case DTRACEACT_STOP:
-+ if (dtrace_priv_proc_destructive(state))
-+ dtrace_action_stop();
-+ continue;
-+
-+ case DTRACEACT_BREAKPOINT:
-+ if (dtrace_priv_kernel_destructive(state))
-+ dtrace_action_breakpoint(ecb);
-+ continue;
-+
-+ case DTRACEACT_PANIC:
-+ if (dtrace_priv_kernel_destructive(state))
-+ dtrace_action_panic(ecb);
-+ continue;
-+
-+ case DTRACEACT_STACK:
-+ if (!dtrace_priv_kernel(state))
-+ continue;
-+
-+ dtrace_getpcstack(
-+ (uint64_t *)(tomax + valoffs),
-+ size / sizeof(pc_t),
-+ probe->dtpr_aframes + 1,
-+ DTRACE_ANCHORED(probe)
-+ ? NULL
-+ : (uint32_t *)arg0);
-+
-+ continue;
-+
-+ case DTRACEACT_JSTACK:
-+ case DTRACEACT_USTACK:
-+ if (!dtrace_priv_proc(state))
-+ continue;
-+
-+ /*
-+ * See comment in DIF_VAR_PID.
-+ */
-+ if (DTRACE_ANCHORED(mstate.dtms_probe) &&
-+ in_interrupt()) {
-+ int depth = DTRACE_USTACK_NFRAMES(
-+ rec->dtrd_arg) + 2;
-+
-+ dtrace_bzero((void *)(tomax + valoffs),
-+ DTRACE_USTACK_STRSIZE(
-+ rec->dtrd_arg) +
-+ depth * sizeof(uint64_t));
-+
-+ continue;
-+ }
-+
-+ if (DTRACE_USTACK_STRSIZE(rec->dtrd_arg) != 0 &&
-+ dtsk != NULL && dtsk->dt_helpers != NULL) {
-+ /*
-+ * This is the slow path -- we have
-+ * allocated string space, and we're
-+ * getting the stack of a process that
-+ * has helpers. Call into a separate
-+ * routine to perform this processing.
-+ */
-+ dtrace_action_ustack(
-+ &mstate, state,
-+ (uint64_t *)(tomax + valoffs),
-+ rec->dtrd_arg);
-+ continue;
-+ }
-+
-+ dtrace_getupcstack(
-+ (uint64_t *)(tomax + valoffs),
-+ DTRACE_USTACK_NFRAMES(rec->dtrd_arg) +
-+ 2);
-+ continue;
-+
-+ default:
-+ break;
-+ }
-+
-+ dp = act->dta_difo;
-+ ASSERT(dp != NULL);
-+
-+ val = dtrace_dif_emulate(dp, &mstate, vstate, state);
-+
-+ if (*flags & CPU_DTRACE_ERROR)
-+ continue;
-+
-+ switch (act->dta_kind) {
-+ case DTRACEACT_SPECULATE:
-+ ASSERT(buf == &state->dts_buffer[cpuid]);
-+ buf = dtrace_speculation_buffer(state, cpuid,
-+ val);
-+
-+ if (buf == NULL) {
-+ *flags |= CPU_DTRACE_DROP;
-+ continue;
-+ }
-+
-+ offs = dtrace_buffer_reserve(buf,
-+ ecb->dte_needed,
-+ ecb->dte_alignment,
-+ state, NULL);
-+
-+ if (offs < 0) {
-+ *flags |= CPU_DTRACE_DROP;
-+ continue;
-+ }
-+
-+ tomax = buf->dtb_tomax;
-+ ASSERT(tomax != NULL);
-+
-+ if (ecb->dte_size != 0) {
-+ DTRACE_STORE(uint32_t, tomax, offs,
-+ ecb->dte_epid);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] "
-+ "<- %d [EPID] "
-+ "(from %s::%d)\n",
-+ buf, offs,
-+ offs + sizeof(uint32_t) - 1,
-+ ecb->dte_epid,
-+ __FUNCTION__, __LINE__);
-+ }
-+
-+ continue;
-+
-+ case DTRACEACT_CHILL:
-+ if (dtrace_priv_kernel_destructive(state))
-+ dtrace_action_chill(&mstate,
-+ ns_to_ktime(val));
-+
-+ continue;
-+
-+ case DTRACEACT_RAISE:
-+ if (dtrace_priv_proc_destructive(state))
-+ dtrace_action_raise(val);
-+
-+ continue;
-+
-+ case DTRACEACT_COMMIT:
-+ ASSERT(!committed);
-+
-+ /*
-+ * We need to commit our buffer state.
-+ */
-+ if (ecb->dte_size) {
-+ buf->dtb_offset = offs + ecb->dte_size;
-+ dt_dbg_buf(" Consume: %p[%ld .. "
-+ "%lld]\n",
-+ buf, offs,
-+ buf->dtb_offset - 1);
-+ }
-+
-+ buf = &state->dts_buffer[cpuid];
-+ dtrace_speculation_commit(state, cpuid, val);
-+ committed = 1;
-+ continue;
-+
-+ case DTRACEACT_DISCARD:
-+ dtrace_speculation_discard(state, cpuid, val);
-+ continue;
-+
-+ case DTRACEACT_DIFEXPR:
-+ case DTRACEACT_LIBACT:
-+ case DTRACEACT_PRINTF:
-+ case DTRACEACT_PRINTA:
-+ case DTRACEACT_SYSTEM:
-+ case DTRACEACT_FREOPEN:
-+ case DTRACEACT_TRACEMEM:
-+ case DTRACEACT_PCAP:
-+ break;
-+
-+ case DTRACEACT_SYM:
-+ case DTRACEACT_MOD:
-+ if (!dtrace_priv_kernel(state))
-+ continue;
-+ break;
-+
-+ case DTRACEACT_USYM:
-+ case DTRACEACT_UMOD:
-+ case DTRACEACT_UADDR: {
-+ pid_t pid = current->pid;
-+ pid_t tgid = current->tgid;
-+
-+ if (!dtrace_priv_proc(state))
-+ continue;
-+
-+ DTRACE_STORE(uint64_t, tomax, valoffs,
-+ (uint64_t)pid);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- %lld "
-+ "[PID] (from %s::%d)\n",
-+ buf, valoffs,
-+ valoffs + sizeof(uint64_t) - 1,
-+ (uint64_t)pid,
-+ __FUNCTION__, __LINE__);
-+ DTRACE_STORE(uint64_t, tomax,
-+ valoffs + sizeof(uint64_t),
-+ (uint64_t)tgid);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- %lld "
-+ "[TGID] (from %s::%d)\n",
-+ buf, valoffs + sizeof(uint64_t),
-+ valoffs + 2 * sizeof(uint64_t) - 1,
-+ (uint64_t)tgid,
-+ __FUNCTION__, __LINE__);
-+ DTRACE_STORE(uint64_t, tomax,
-+ valoffs + 2 * sizeof(uint64_t),
-+ val);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- %lld "
-+ "(from %s::%d)\n",
-+ buf, valoffs + 2 * sizeof(uint64_t),
-+ valoffs + 3 * sizeof(uint64_t) - 1,
-+ val, __FUNCTION__, __LINE__);
-+
-+ continue;
-+ }
-+
-+ case DTRACEACT_EXIT: {
-+ /*
-+ * For the exit action, we are going to attempt
-+ * to atomically set our activity to be
-+ * draining. If this fails (either because
-+ * another CPU has beat us to the exit action,
-+ * or because our current activity is something
-+ * other than ACTIVE or WARMUP), we will
-+ * continue. This assures that the exit action
-+ * can be successfully recorded at most once
-+ * when we're in the ACTIVE state. If we're
-+ * encountering the exit() action while in
-+ * COOLDOWN, however, we want to honor the new
-+ * status code. (We know that we're the only
-+ * thread in COOLDOWN, so there is no race.)
-+ */
-+ enum dtrace_activity *activity =
-+ &state->dts_activity;
-+ enum dtrace_activity curr =
-+ state->dts_activity;
-+
-+ if (curr == DTRACE_ACTIVITY_COOLDOWN)
-+ break;
-+
-+ if (curr != DTRACE_ACTIVITY_WARMUP)
-+ curr = DTRACE_ACTIVITY_ACTIVE;
-+
-+ if (cmpxchg(activity, curr,
-+ DTRACE_ACTIVITY_DRAINING) != curr) {
-+ *flags |= CPU_DTRACE_DROP;
-+ continue;
-+ }
-+
-+ break;
-+ }
-+
-+ default:
-+ ASSERT(0);
-+ }
-+
-+ if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF) {
-+ uintptr_t end = valoffs + size;
-+
-+ if (!dtrace_vcanload((void *)(uintptr_t)val,
-+ &dp->dtdo_rtype, &mstate,
-+ vstate))
-+ continue;
-+
-+ if (act->dta_kind == DTRACEACT_PCAP) {
-+ if (dtrace_probe_pcap(val, &valoffs,
-+ size, tomax, now,
-+ &mstate, vstate,
-+ flags) == -1)
-+ break;
-+ continue;
-+ }
-+
-+ /*
-+ * If this is a string, we're going to only
-+ * load until we find the zero byte -- after
-+ * which we'll store zero bytes.
-+ */
-+ if (dp->dtdo_rtype.dtdt_kind ==
-+ DIF_TYPE_STRING) {
-+ char c = '\0' + 1;
-+ int intuple = act->dta_intuple;
-+ size_t s;
-+
-+ for (s = 0; s < size; s++) {
-+ if (c != '\0')
-+ c = dtrace_load8(val++);
-+
-+ DTRACE_STORE(uint8_t, tomax,
-+ valoffs++, c);
-+ dt_dbg_buf(" Store: %p[%ld]"
-+ " <- %d (from "
-+ "%s::%d)\n",
-+ buf, valoffs, c,
-+ __FUNCTION__,
-+ __LINE__);
-+
-+ if (c == '\0' && intuple)
-+ break;
-+ }
-+
-+ continue;
-+ }
-+
-+ while (valoffs < end) {
-+ DTRACE_STORE(uint8_t, tomax, valoffs++,
-+ dtrace_load8(val++));
-+ dt_dbg_buf(" Store: %p[%ld] <- ??? "
-+ "(from %s::%d)\n",
-+ buf, valoffs,
-+ __FUNCTION__, __LINE__);
-+ }
-+
-+ continue;
-+ }
-+
-+ switch (size) {
-+ case 0:
-+ break;
-+ case sizeof(uint8_t):
-+ DTRACE_STORE(uint8_t, tomax, valoffs, val);
-+ dt_dbg_buf(" Store: %p[%ld] <- %d "
-+ "(from %s::%d)\n",
-+ buf, valoffs, (uint8_t)val,
-+ __FUNCTION__, __LINE__);
-+ break;
-+ case sizeof(uint16_t):
-+ DTRACE_STORE(uint16_t, tomax, valoffs, val);
-+ dt_dbg_buf(" Store: %p[%ld .. %ld] <- %d "
-+ "(from %s::%d)\n",
-+ buf, valoffs,
-+ valoffs + sizeof(uint16_t) - 1,
-+ (uint16_t)val,
-+ __FUNCTION__, __LINE__);
-+ break;
-+ case sizeof(uint32_t):
-+ DTRACE_STORE(uint32_t, tomax, valoffs, val);
-+ dt_dbg_buf(" Store: %p[%ld] <- %d "
-+ "(from %s::%d)\n",
-+ buf, valoffs,
-+ (uint32_t)val,
-+ __FUNCTION__, __LINE__);
-+ break;
-+ case sizeof(uint64_t):
-+ DTRACE_STORE(uint64_t, tomax, valoffs, val);
-+ dt_dbg_buf(" Store: %p[%ld] <- %lld "
-+ "(from %s::%d)\n",
-+ buf, valoffs,
-+ val,
-+ __FUNCTION__, __LINE__);
-+ break;
-+ default:
-+ /*
-+ * Any other size should have been returned by
-+ * reference, not by value.
-+ */
-+ ASSERT(0);
-+ break;
-+ }
-+ }
-+
-+ if (*flags & CPU_DTRACE_DROP) {
-+ dt_dbg_probe(" -> Dropped\n");
-+ continue;
-+ }
-+
-+ if (*flags & CPU_DTRACE_FAULT) {
-+ int ndx;
-+ struct dtrace_action *err;
-+
-+ dt_dbg_probe(" -> Failed (%x)\n", *flags);
-+
-+ buf->dtb_errors++;
-+
-+ if (probe->dtpr_id == dtrace_probeid_error) {
-+ /*
-+ * There's nothing we can do -- we had an
-+ * error on the error probe. We bump an
-+ * error counter to at least indicate that
-+ * this condition happened.
-+ */
-+ dtrace_error(&state->dts_dblerrors);
-+ continue;
-+ }
-+
-+ if (vtime && dtsk != NULL)
-+ /*
-+ * Before recursing on dtrace_probe(), we
-+ * need to explicitly clear out our start
-+ * time to prevent it from being accumulated
-+ * into the dtrace_vtime.
-+ */
-+ dtsk->dt_start = ktime_set(0, 0);
-+
-+ /*
-+ * Iterate over the actions to figure out which action
-+ * we were processing when we experienced the error.
-+ * Note that act points _past_ the faulting action; if
-+ * act is ecb->dte_action, the fault was in the
-+ * predicate, if it's ecb->dte_action->dta_next it's
-+ * in action #1, and so on.
-+ */
-+ for (err = ecb->dte_action, ndx = 0;
-+ err != act; err = err->dta_next, ndx++)
-+ continue;
-+
-+ dtrace_probe_error(
-+ state, ecb->dte_epid, ndx,
-+ (mstate.dtms_present & DTRACE_MSTATE_FLTOFFS)
-+ ? mstate.dtms_fltoffs
-+ : -1,
-+ DTRACE_FLAGS2FLT(*flags),
-+ this_cpu_core->cpuc_dtrace_illval);
-+
-+ continue;
-+ }
-+
-+ if (!committed) {
-+ buf->dtb_offset = offs + ecb->dte_size;
-+ dt_dbg_buf(" Consume: %p[%ld .. %lld]\n",
-+ buf, offs, buf->dtb_offset);
-+ }
-+
-+ dt_dbg_probe("Probe (ID %d EPID %d) Done\n",
-+ id, ecb->dte_epid);
-+ }
-+
-+ if (vtime && dtsk != NULL)
-+ dtsk->dt_start = dtrace_gethrtime();
-+
-+ this_cpu_core->cpuc_current_probe = old_id;
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+
-+ if (dtsk != NULL && dtsk->dt_sig != 0) {
-+ int sig = dtsk->dt_sig;
-+
-+ dtsk->dt_sig = 0;
-+
-+ send_sig(sig, current, 0);
-+ }
-+}
-+EXPORT_SYMBOL(dtrace_probe);
-+
-+int dtrace_probe_init(void)
-+{
-+ dtrace_id_t id;
-+
-+ dtrace_probe_cachep = KMEM_CACHE(dtrace_probe, SLAB_HWCACHE_ALIGN);
-+ if (dtrace_probe_cachep == NULL)
-+ return -ENOMEM;
-+
-+ idr_init(&dtrace_probe_idr);
-+
-+ /*
-+ * We create a ID 0 entry as a sentinel, so we can always depend on it
-+ * being the very first entry. This is used in functionality that runs
-+ * through the list of probes.
-+ */
-+ idr_preload(GFP_KERNEL);
-+ id = idr_alloc_cyclic(&dtrace_probe_idr, NULL, 0, 0, GFP_NOWAIT);
-+ idr_preload_end();
-+
-+ return id == 0 ? 0 : -EAGAIN;
-+}
-+
-+void dtrace_probe_exit(void)
-+{
-+ idr_destroy(&dtrace_probe_idr);
-+ kmem_cache_destroy(dtrace_probe_cachep);
-+}
-+
-+void dtrace_probe_remove_id(dtrace_id_t id)
-+{
-+ idr_remove(&dtrace_probe_idr, id);
-+}
-+
-+struct dtrace_probe *dtrace_probe_lookup_id(dtrace_id_t id)
-+{
-+ return idr_find(&dtrace_probe_idr, id);
-+}
-+
-+static int dtrace_probe_lookup_match(struct dtrace_probe *probe, void *arg)
-+{
-+ *((dtrace_id_t *)arg) = probe->dtpr_id;
-+
-+ return DTRACE_MATCH_DONE;
-+}
-+
-+dtrace_id_t dtrace_probe_lookup(dtrace_provider_id_t prid, const char *mod,
-+ const char *func, const char *name)
-+{
-+ struct dtrace_probekey pkey;
-+ dtrace_id_t id;
-+ int match;
-+
-+ pkey.dtpk_prov = ((struct dtrace_provider *)prid)->dtpv_name;
-+ pkey.dtpk_pmatch = &dtrace_match_string;
-+ pkey.dtpk_mod = mod;
-+ pkey.dtpk_mmatch = mod ? &dtrace_match_string : &dtrace_match_nul;
-+ pkey.dtpk_func = func;
-+ pkey.dtpk_fmatch = func ? &dtrace_match_string : &dtrace_match_nul;
-+ pkey.dtpk_name = name;
-+ pkey.dtpk_nmatch = name ? &dtrace_match_string : &dtrace_match_nul;
-+ pkey.dtpk_id = DTRACE_IDNONE;
-+
-+ mutex_lock(&dtrace_lock);
-+ match = dtrace_match(&pkey, DTRACE_PRIV_ALL,
-+ make_kuid(init_user_namespace, 0),
-+ dtrace_probe_lookup_match, &id);
-+ mutex_unlock(&dtrace_lock);
-+
-+ ASSERT(match == 1 || match == 0);
-+
-+ return match ? id : 0;
-+}
-+EXPORT_SYMBOL(dtrace_probe_lookup);
-+
-+struct dtrace_probe *dtrace_probe_get_next(dtrace_id_t *idp)
-+{
-+ return idr_get_next(&dtrace_probe_idr, idp);
-+}
-+
-+int dtrace_probe_for_each(int (*fn)(int id, void *p, void *data), void *data)
-+{
-+ return idr_for_each(&dtrace_probe_idr, fn, data);
-+}
-diff --git a/dtrace/dtrace_probe_ctx.c b/dtrace/dtrace_probe_ctx.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..f04b5b26922291955285a8aba7a3f6cb6ca6c512
---- /dev/null
-+++ b/dtrace/dtrace_probe_ctx.c
-@@ -0,0 +1,659 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_probe_ctx.c
-+ * DESCRIPTION: DTrace - probe context safe functions
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+
-+#include "dtrace.h"
-+
-+void dtrace_panic(const char *fmt, ...)
-+{
-+ va_list alist;
-+
-+ va_start(alist, fmt);
-+ vprintk(fmt, alist);
-+ va_end(alist);
-+
-+ BUG();
-+}
-+EXPORT_SYMBOL(dtrace_panic);
-+
-+int dtrace_assfail(const char *a, const char *f, int l)
-+{
-+ dtrace_panic(KERN_EMERG "assertion failed: %s, file: %s, line: %d",
-+ a, f, l);
-+
-+ /*
-+ * FIXME: We can do better than this. The OpenSolaris DTrace source
-+ * states that this cannot be optimized away.
-+ */
-+ return a[(uintptr_t)f];
-+}
-+EXPORT_SYMBOL(dtrace_assfail);
-+
-+#define DT_MASK_LO 0x00000000FFFFFFFFULL
-+
-+static void dtrace_add_128(uint64_t *addend1, uint64_t *addend2, uint64_t *sum)
-+{
-+ uint64_t result[2];
-+
-+ result[0] = addend1[0] + addend2[0];
-+ result[1] = addend1[1] + addend2[1] +
-+ (result[0] < addend1[0] || result[0] < addend2[0] ? 1 : 0);
-+
-+ sum[0] = result[0];
-+ sum[1] = result[1];
-+}
-+
-+static void dtrace_shift_128(uint64_t *a, int b)
-+{
-+ uint64_t mask;
-+
-+ if (b == 0)
-+ return;
-+
-+ if (b < 0) {
-+ b = -b;
-+
-+ if (b >= 64) {
-+ a[0] = a[1] >> (b - 64);
-+ a[1] = 0;
-+ } else {
-+ a[0] >>= b;
-+ mask = 1LL << (64 - b);
-+ mask -= 1;
-+ a[0] |= ((a[1] & mask) << (64 - b));
-+ a[1] >>= b;
-+ }
-+ } else {
-+ if (b >= 64) {
-+ a[1] = a[0] << (b - 64);
-+ a[0] = 0;
-+ } else {
-+ a[1] <<= b;
-+ mask = a[0] >> (64 - b);
-+ a[1] |= mask;
-+ a[0] <<= b;
-+ }
-+ }
-+}
-+
-+static void dtrace_multiply_128(uint64_t factor1, uint64_t factor2,
-+ uint64_t *product)
-+{
-+ uint64_t hi1, hi2, lo1, lo2;
-+ uint64_t tmp[2];
-+
-+ hi1 = factor1 >> 32;
-+ hi2 = factor2 >> 32;
-+
-+ lo1 = factor1 & DT_MASK_LO;
-+ lo2 = factor2 & DT_MASK_LO;
-+
-+ product[0] = lo1 * lo2;
-+ product[1] = hi1 * hi2;
-+
-+ tmp[0] = hi1 * lo2;
-+ tmp[1] = 0;
-+ dtrace_shift_128(tmp, 32);
-+ dtrace_add_128(product, tmp, product);
-+
-+ tmp[0] = hi2 * lo1;
-+ tmp[1] = 0;
-+ dtrace_shift_128(tmp, 32);
-+ dtrace_add_128(product, tmp, product);
-+}
-+
-+void dtrace_aggregate_min(uint64_t *oval, uint64_t nval, uint64_t arg)
-+{
-+ if ((int64_t)nval < (int64_t)*oval)
-+ *oval = nval;
-+}
-+
-+void dtrace_aggregate_max(uint64_t *oval, uint64_t nval, uint64_t arg)
-+{
-+ if ((int64_t)nval > (int64_t)*oval)
-+ *oval = nval;
-+}
-+
-+void dtrace_aggregate_quantize(uint64_t *quanta, uint64_t nval, uint64_t incr)
-+{
-+ int i, zero = DTRACE_QUANTIZE_ZEROBUCKET;
-+ int64_t val = (int64_t)nval;
-+
-+ if (val < 0) {
-+ for (i = 0; i < zero; i++) {
-+ if (val <= DTRACE_QUANTIZE_BUCKETVAL(i)) {
-+ quanta[i] += incr;
-+
-+ return;
-+ }
-+ }
-+ } else {
-+ for (i = zero + 1; i < DTRACE_QUANTIZE_NBUCKETS; i++) {
-+ if (val < DTRACE_QUANTIZE_BUCKETVAL(i)) {
-+ quanta[i - 1] += incr;
-+
-+ return;
-+ }
-+ }
-+
-+ quanta[DTRACE_QUANTIZE_NBUCKETS - 1] += incr;
-+
-+ return;
-+ }
-+
-+ ASSERT(0);
-+}
-+
-+void dtrace_aggregate_lquantize(uint64_t *lquanta, uint64_t nval,
-+ uint64_t incr)
-+{
-+ uint64_t arg = *lquanta++;
-+ int32_t base = DTRACE_LQUANTIZE_BASE(arg);
-+ uint16_t step = DTRACE_LQUANTIZE_STEP(arg);
-+ uint16_t levels = DTRACE_LQUANTIZE_LEVELS(arg);
-+ int64_t val = (int64_t)nval, level;
-+
-+ ASSERT(step != 0);
-+ ASSERT(levels != 0);
-+
-+ if (val < base) {
-+ lquanta[0] += incr;
-+
-+ return;
-+ }
-+
-+ level = (val - base) / step;
-+
-+ if (level < levels) {
-+ lquanta[level + 1] += incr;
-+
-+ return;
-+ }
-+
-+ lquanta[levels + 1] += incr;
-+}
-+
-+static uint64_t dtrace_pow(uint64_t base, uint64_t exp)
-+{
-+ uint64_t p, r;
-+
-+ p = base;
-+ r = 1;
-+ while (exp > 0) {
-+ if (exp & 1)
-+ r *= p;
-+
-+ p *= p;
-+ exp >>= 1;
-+ }
-+
-+ return (r);
-+}
-+
-+void dtrace_aggregate_llquantize(uint64_t *llquanta, uint64_t nval,
-+ uint64_t incr)
-+{
-+ uint64_t arg = *llquanta++;
-+ int factor = DTRACE_LLQUANTIZE_FACTOR(arg);
-+ int lmag = DTRACE_LLQUANTIZE_LMAG(arg);
-+ int hmag = DTRACE_LLQUANTIZE_HMAG(arg);
-+ int steps = DTRACE_LLQUANTIZE_STEPS(arg);
-+ int i, signbit, steps_factor, mag, underflow_bin;
-+ uint64_t val, bucket_max;
-+
-+ ASSERT(steps != 0);
-+ ASSERT(factor > 1);
-+
-+ if (nval >> (64 - 1)) {
-+ signbit = -1;
-+ val = 1 + ~nval;
-+ } else {
-+ signbit = +1;
-+ val = nval;
-+ }
-+
-+ /*
-+ * Compute steps/factor.
-+ * Notice that while we say there are "steps" bins per logarithmic
-+ * range, steps/factor of them actually overlap with lower ranges.
-+ * E.g., if factor=10 and steps=20, for mag=2 we have the 20 bins
-+ * 0 50 100 150 200 250 300 350 ... 800 850 900 950
-+ * but the first two actually belong to lower ranges.
-+ */
-+ steps_factor = steps/factor;
-+
-+ /* the underflow bin is in the middle */
-+ underflow_bin = 1 + (hmag-lmag+1) * (steps-steps_factor);
-+
-+ bucket_max = dtrace_pow(factor, lmag);
-+
-+ /* check for "underflow" (smaller than the smallest bin) */
-+ if (val < bucket_max) {
-+ llquanta[underflow_bin] += incr;
-+ return;
-+ }
-+
-+ /* loop over the logarithmic ranges */
-+ i = 0;
-+ for (mag = lmag; mag <= hmag; mag++) {
-+ bucket_max *= factor;
-+ if (val >= bucket_max)
-+ continue;
-+
-+ /*
-+ * We want
-+ * i = val * steps / bucket_max;
-+ * but val*steps could overflow. An alternative is
-+ * i = val / ( bucket_max/steps )
-+ * but bucket_max/steps might not divide evenly.
-+ * (Plus, we end up with an extra divide.)
-+ *
-+ * From Solaris, we inherit constraints on factor and steps
-+ * that mean bucket_max/steps divides evenly when mag>0.
-+ * Meanwhile, if mag==0, val*steps cannot overflow.
-+ * So between our two expressions for i, at least one
-+ * will work and we just have to pick which one to use.
-+ */
-+ if (mag == 0)
-+ i = val * steps / bucket_max;
-+ else
-+ i = val / (bucket_max/steps);
-+
-+ // shift for low indices that can never happen
-+ i -= steps_factor;
-+ break;
-+ }
-+ i = underflow_bin+signbit*((steps-steps_factor)*(mag-lmag)+i+1);
-+ llquanta[i] += incr;
-+}
-+
-+void dtrace_aggregate_avg(uint64_t *data, uint64_t nval, uint64_t arg)
-+{
-+ data[0]++;
-+ data[1] += nval;
-+}
-+
-+void dtrace_aggregate_stddev(uint64_t *data, uint64_t nval, uint64_t arg)
-+{
-+ int64_t snval = (int64_t)nval;
-+ uint64_t tmp[2];
-+
-+ data[0]++;
-+ data[1] += nval;
-+
-+ if (snval < 0)
-+ snval = -snval;
-+
-+ dtrace_multiply_128((uint64_t)snval, (uint64_t)snval, tmp);
-+ dtrace_add_128(data + 2, tmp, data + 2);
-+}
-+
-+void dtrace_aggregate_count(uint64_t *oval, uint64_t nval, uint64_t arg)
-+{
-+ *oval = *oval + 1;
-+}
-+
-+void dtrace_aggregate_sum(uint64_t *oval, uint64_t nval, uint64_t arg)
-+{
-+ *oval += nval;
-+}
-+
-+/*
-+ * DTrace Aggregation Buffers
-+ *
-+ * Aggregation buffers use much of the same mechanism as described above
-+ * ("DTrace Buffers"). However, because an aggregation is fundamentally a
-+ * hash, there exists dynamic metadata associated with an aggregation buffer
-+ * that is not associated with other kinds of buffers. This aggregation
-+ * metadata is _only_ relevant for the in-kernel implementation of
-+ * aggregations; it is not actually relevant to user-level consumers. To do
-+ * this, we allocate dynamic aggregation data (hash keys and hash buckets)
-+ * starting below the _limit_ of the buffer, and we allocate data from the
-+ * _base_ of the buffer. When the aggregation buffer is copied out, _only_ the
-+ * data is copied out; the metadata is simply discarded. Schematically,
-+ * aggregation buffers look like:
-+ *
-+ * base of data buffer ---> +-------+------+-----------+-------+
-+ * | aggid | key | value | aggid |
-+ * +-------+------+-----------+-------+
-+ * | key |
-+ * +-------+-------+-----+------------+
-+ * | value | aggid | key | value |
-+ * +-------+------++-----+------+-----+
-+ * | aggid | key | value | |
-+ * +-------+------+-------------+ |
-+ * | || |
-+ * | || |
-+ * | \/ |
-+ * : :
-+ * . .
-+ * . .
-+ * . .
-+ * : :
-+ * | /\ |
-+ * | || +------------+
-+ * | || | |
-+ * +---------------------+ |
-+ * | hash keys |
-+ * | (dtrace_aggkey structures) |
-+ * | |
-+ * +----------------------------------+
-+ * | hash buckets |
-+ * | (dtrace_aggbuffer structure) |
-+ * | |
-+ * limit of data buffer ---> +----------------------------------+
-+ *
-+ * As implied above, just as we assure that ECBs always store a constant
-+ * amount of data, we assure that a given aggregation -- identified by its
-+ * aggregation ID -- always stores data of a constant quantity and type.
-+ * As with EPIDs, this allows the aggregation ID to serve as the metadata for a
-+ * given record.
-+ *
-+ * Note that the size of the dtrace_aggkey structure must be sizeof (uintptr_t)
-+ * aligned. (If this the structure changes such that this becomes false, an
-+ * assertion will fail in dtrace_aggregate().)
-+ */
-+#define DTRACE_AGGHASHSIZE_SLEW 17
-+
-+struct dtrace_aggkey {
-+ uint32_t dtak_hashval; /* hash value */
-+ uint32_t dtak_action:4; /* action -- 4 bits */
-+ uint32_t dtak_size:28; /* size -- 28 bits */
-+ caddr_t dtak_data; /* data pointer */
-+ struct dtrace_aggkey *dtak_next; /* next in hash chain */
-+};
-+
-+struct dtrace_aggbuffer {
-+ uintptr_t dtagb_hashsize; /* number of buckets */
-+ uintptr_t dtagb_free; /* free list of keys */
-+ struct dtrace_aggkey **dtagb_hash; /* hash table */
-+};
-+
-+#define DTRACEACT_ISSTRING(act) \
-+ ((act)->dta_kind == DTRACEACT_DIFEXPR && \
-+ (act)->dta_difo->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING)
-+
-+/*
-+ * Aggregate given the tuple in the principal data buffer, and the aggregating
-+ * action denoted by the specified dtrace_aggregation_t. The aggregation
-+ * buffer is specified as the buf parameter. This routine does not return
-+ * failure; if there is no space in the aggregation buffer, the data will be
-+ * dropped, and a corresponding counter incremented.
-+ */
-+void dtrace_aggregate(struct dtrace_aggregation *agg,
-+ struct dtrace_buffer *dbuf,
-+ intptr_t offset, struct dtrace_buffer *buf,
-+ uint64_t expr, uint64_t arg)
-+{
-+ struct dtrace_recdesc *rec = &agg->dtag_action.dta_rec;
-+ uint32_t i, ndx, size, fsize;
-+ uint32_t align = sizeof(uint64_t) - 1;
-+ struct dtrace_aggbuffer *agb;
-+ struct dtrace_aggkey *key;
-+ uint32_t hashval = 0, limit, isstr;
-+ caddr_t tomax, data, kdata;
-+ dtrace_actkind_t action;
-+ struct dtrace_action *act;
-+ uintptr_t offs;
-+
-+ if (buf == NULL)
-+ return;
-+
-+ if (!agg->dtag_hasarg)
-+ /*
-+ * Currently, only quantize(), lquantize() and llquantize()
-+ * take additional arguments, and they have the same semantics:
-+ * an increment value that defaults to 1 when not present. If
-+ * additional aggregating actions take arguments, the setting
-+ * of the default argument value will presumably have to
-+ * become more sophisticated...
-+ */
-+ arg = 1;
-+
-+ action = agg->dtag_action.dta_kind - DTRACEACT_AGGREGATION;
-+ size = rec->dtrd_offset - agg->dtag_base;
-+ fsize = size + rec->dtrd_size;
-+
-+ ASSERT(dbuf->dtb_tomax != NULL);
-+ data = dbuf->dtb_tomax + offset + agg->dtag_base;
-+
-+ tomax = buf->dtb_tomax;
-+ if (tomax == NULL) {
-+ dtrace_buffer_drop(buf);
-+ return;
-+ }
-+
-+ /*
-+ * The metastructure is always at the bottom of the buffer.
-+ */
-+ agb = (struct dtrace_aggbuffer *)(tomax + buf->dtb_size -
-+ sizeof(struct dtrace_aggbuffer));
-+
-+ if (buf->dtb_offset == 0) {
-+ /*
-+ * We just kludge up approximately 1/8th of the size to be
-+ * buckets. If this guess ends up being routinely
-+ * off-the-mark, we may need to dynamically readjust this
-+ * based on past performance.
-+ */
-+ uintptr_t hashsize = (buf->dtb_size >> 3) /
-+ sizeof(uintptr_t);
-+
-+ if ((uintptr_t)agb - hashsize * sizeof(struct dtrace_aggkey *) <
-+ (uintptr_t)tomax || hashsize == 0) {
-+ /*
-+ * We've been given a ludicrously small buffer;
-+ * increment our drop count and leave.
-+ */
-+ dtrace_buffer_drop(buf);
-+ return;
-+ }
-+
-+ /*
-+ * And now, a pathetic attempt to try to get a an odd (or
-+ * perchance, a prime) hash size for better hash distribution.
-+ */
-+ if (hashsize > (DTRACE_AGGHASHSIZE_SLEW << 3))
-+ hashsize -= DTRACE_AGGHASHSIZE_SLEW;
-+
-+ agb->dtagb_hashsize = hashsize;
-+ agb->dtagb_hash = (struct dtrace_aggkey **)((uintptr_t)agb -
-+ agb->dtagb_hashsize * sizeof(struct dtrace_aggkey *));
-+ agb->dtagb_free = (uintptr_t)agb->dtagb_hash;
-+
-+ for (i = 0; i < agb->dtagb_hashsize; i++)
-+ agb->dtagb_hash[i] = NULL;
-+ }
-+
-+ ASSERT(agg->dtag_first != NULL);
-+ ASSERT(agg->dtag_first->dta_intuple);
-+
-+ /*
-+ * Calculate the hash value based on the key. Note that we _don't_
-+ * include the aggid in the hashing (but we will store it as part of
-+ * the key). The hashing algorithm is Bob Jenkins' "One-at-a-time"
-+ * algorithm: a simple, quick algorithm that has no known funnels, and
-+ * gets good distribution in practice. The efficacy of the hashing
-+ * algorithm (and a comparison with other algorithms) may be found by
-+ * running the ::dtrace_aggstat MDB dcmd.
-+ */
-+ for (act = agg->dtag_first; act->dta_intuple; act = act->dta_next) {
-+ i = act->dta_rec.dtrd_offset - agg->dtag_base;
-+ limit = i + act->dta_rec.dtrd_size;
-+ ASSERT(limit <= size);
-+ isstr = DTRACEACT_ISSTRING(act);
-+
-+ for (; i < limit; i++) {
-+ hashval += data[i];
-+ hashval += (hashval << 10);
-+ hashval ^= (hashval >> 6);
-+
-+ if (isstr && data[i] == '\0')
-+ break;
-+ }
-+ }
-+
-+ hashval += (hashval << 3);
-+ hashval ^= (hashval >> 11);
-+ hashval += (hashval << 15);
-+
-+ /*
-+ * Yes, the divide here is expensive -- but it's generally the least
-+ * of the performance issues given the amount of data that we iterate
-+ * over to compute hash values, compare data, etc.
-+ */
-+ ndx = hashval % agb->dtagb_hashsize;
-+
-+ for (key = agb->dtagb_hash[ndx]; key != NULL; key = key->dtak_next) {
-+ ASSERT((caddr_t)key >= tomax);
-+ ASSERT((caddr_t)key < tomax + buf->dtb_size);
-+
-+ if (hashval != key->dtak_hashval || key->dtak_size != size)
-+ continue;
-+
-+ kdata = key->dtak_data;
-+ ASSERT(kdata >= tomax && kdata < tomax + buf->dtb_size);
-+
-+ for (act = agg->dtag_first; act->dta_intuple;
-+ act = act->dta_next) {
-+ i = act->dta_rec.dtrd_offset - agg->dtag_base;
-+ limit = i + act->dta_rec.dtrd_size;
-+ ASSERT(limit <= size);
-+ isstr = DTRACEACT_ISSTRING(act);
-+
-+ for (; i < limit; i++) {
-+ if (kdata[i] != data[i])
-+ goto next;
-+
-+ if (isstr && data[i] == '\0')
-+ break;
-+ }
-+ }
-+
-+ if (action != key->dtak_action) {
-+ /*
-+ * We are aggregating on the same value in the same
-+ * aggregation with two different aggregating actions.
-+ * (This should have been picked up in the compiler,
-+ * so we may be dealing with errant or devious DIF.)
-+ * This is an error condition; we indicate as much,
-+ * and return.
-+ */
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-+ return;
-+ }
-+
-+ /*
-+ * This is a hit: we need to apply the aggregator to
-+ * the value at this key.
-+ */
-+ dt_dbg_agg(" Aggregate [accum]: Buf %p, offs %d, act %d, "
-+ "%lld (%lld, %lld)\n",
-+ buf, size,
-+ agg->dtag_action.dta_kind - DTRACEACT_AGGREGATION,
-+ *(uint64_t *)(kdata + size), expr, arg);
-+ agg->dtag_aggregate((uint64_t *)(kdata + size), expr, arg);
-+ return;
-+next:
-+ continue;
-+ }
-+
-+ /*
-+ * We didn't find it. We need to allocate some zero-filled space,
-+ * link it into the hash table appropriately, and apply the aggregator
-+ * to the (zero-filled) value.
-+ */
-+ offs = buf->dtb_offset;
-+ while (offs & (align - 1))
-+ offs += sizeof(uint32_t);
-+
-+ /*
-+ * If we don't have enough room to both allocate a new key _and_
-+ * its associated data, increment the drop count and return.
-+ */
-+ if ((uintptr_t)tomax + offs + fsize >
-+ agb->dtagb_free - sizeof(struct dtrace_aggkey)) {
-+ dtrace_buffer_drop(buf);
-+ return;
-+ }
-+
-+ ASSERT(!(sizeof(struct dtrace_aggkey) & (sizeof(uintptr_t) - 1)));
-+ key = (struct dtrace_aggkey *)
-+ (agb->dtagb_free - sizeof(struct dtrace_aggkey));
-+ agb->dtagb_free -= sizeof(struct dtrace_aggkey);
-+
-+ key->dtak_data = kdata = tomax + offs;
-+ buf->dtb_offset = offs + fsize;
-+
-+ /*
-+ * Now copy the data across.
-+ */
-+ *((dtrace_aggid_t *)kdata) = agg->dtag_id;
-+
-+ for (i = sizeof(dtrace_aggid_t); i < size; i++)
-+ kdata[i] = data[i];
-+
-+ /*
-+ * Because strings are not zeroed out by default, we need to iterate
-+ * looking for actions that store strings, and we need to explicitly
-+ * pad these strings out with zeroes.
-+ */
-+ for (act = agg->dtag_first; act->dta_intuple; act = act->dta_next) {
-+ int nul;
-+
-+ if (!DTRACEACT_ISSTRING(act))
-+ continue;
-+
-+ i = act->dta_rec.dtrd_offset - agg->dtag_base;
-+ limit = i + act->dta_rec.dtrd_size;
-+ ASSERT(limit <= size);
-+
-+ for (nul = 0; i < limit; i++) {
-+ if (nul) {
-+ kdata[i] = '\0';
-+ continue;
-+ }
-+
-+ if (data[i] != '\0')
-+ continue;
-+
-+ nul = 1;
-+ }
-+ }
-+
-+ for (i = size; i < fsize; i++)
-+ kdata[i] = 0;
-+
-+ key->dtak_hashval = hashval;
-+ key->dtak_size = size;
-+ key->dtak_action = action;
-+ key->dtak_next = agb->dtagb_hash[ndx];
-+ agb->dtagb_hash[ndx] = key;
-+
-+ /*
-+ * Finally, apply the aggregator.
-+ */
-+ *((uint64_t *)(key->dtak_data + size)) = agg->dtag_initial;
-+ dt_dbg_agg(" Aggregate [initial]: Buf %p, offs %d, act %d, "
-+ "%lld (%lld, %lld)\n",
-+ buf, size,
-+ agg->dtag_action.dta_kind - DTRACEACT_AGGREGATION,
-+ *(uint64_t *)(key->dtak_data + size), expr, arg);
-+ agg->dtag_aggregate((uint64_t *)(key->dtak_data + size), expr, arg);
-+}
-diff --git a/dtrace/dtrace_ptofapi.c b/dtrace/dtrace_ptofapi.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..c42a8471879cc0ea532ad19adf9ea66b20c9183e
---- /dev/null
-+++ b/dtrace/dtrace_ptofapi.c
-@@ -0,0 +1,649 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_ptofapi.c
-+ * DESCRIPTION: DTrace - (meta) provider-to-framework API
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/idr.h>
-+#include <linux/list.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+
-+#include "dtrace.h"
-+
-+struct dtrace_provider *dtrace_provider;
-+struct dtrace_meta *dtrace_meta_pid;
-+struct dtrace_helpers *dtrace_deferred_pid;
-+
-+DEFINE_MUTEX(dtrace_provider_lock);
-+DEFINE_MUTEX(dtrace_meta_lock);
-+
-+/*
-+ * Register the calling provider with the DTrace core. This should generally
-+ * be called by providers during module initialization.
-+ */
-+int dtrace_register(const char *name, const struct dtrace_pattr *pap,
-+ uint32_t priv, const struct cred *cr,
-+ const struct dtrace_pops *pops, void *arg,
-+ dtrace_provider_id_t *idp)
-+{
-+ struct dtrace_provider *provider;
-+
-+ if (name == NULL || pap == NULL || pops == NULL || idp == NULL) {
-+ pr_warn("Failed to register provider %s: invalid args\n",
-+ name ? name : "<NULL>");
-+ return -EINVAL;
-+ }
-+
-+ if (name[0] == '\0' || dtrace_badname(name)) {
-+ pr_warn("Failed to register provider %s: invalid name\n",
-+ name);
-+ return -EINVAL;
-+ }
-+
-+ if ((pops->dtps_provide == NULL && pops->dtps_provide_module == NULL) ||
-+ pops->dtps_enable == NULL || pops->dtps_disable == NULL ||
-+ pops->dtps_destroy == NULL ||
-+ ((pops->dtps_resume == NULL) != (pops->dtps_suspend == NULL))) {
-+ pr_warn("Failed to register provider %s: invalid ops\n",
-+ name);
-+ return -EINVAL;
-+ }
-+
-+ if (dtrace_badattr(&pap->dtpa_provider) ||
-+ dtrace_badattr(&pap->dtpa_mod) ||
-+ dtrace_badattr(&pap->dtpa_func) ||
-+ dtrace_badattr(&pap->dtpa_name) ||
-+ dtrace_badattr(&pap->dtpa_args)) {
-+ pr_warn("Failed to register provider %s: invalid attributes\n",
-+ name);
-+ return -EINVAL;
-+ }
-+
-+ if (priv & ~DTRACE_PRIV_ALL) {
-+ pr_warn("Failed to register provider %s: invalid privilege "
-+ "attributes\n", name);
-+ return -EINVAL;
-+ }
-+
-+ if ((priv & DTRACE_PRIV_KERNEL) &&
-+ (priv & (DTRACE_PRIV_USER | DTRACE_PRIV_OWNER)) &&
-+ pops->dtps_usermode == NULL) {
-+ pr_warn("Failed to register provider %s: need "
-+ "dtps_usermode() op for given privilege "
-+ "attributes\n", name);
-+ return -EINVAL;
-+ }
-+
-+ dt_dbg_prov("Registering provider '%s'...\n", name);
-+ provider = kzalloc(sizeof(struct dtrace_provider), GFP_KERNEL);
-+ if (provider == NULL) {
-+ dt_dbg_prov(" Failed to allocate provider struct\n");
-+ return -ENOMEM;
-+ }
-+ provider->dtpv_name = dtrace_strdup(name);
-+ if (provider->dtpv_name == NULL) {
-+ kfree(provider);
-+ dt_dbg_prov(" Failed to allocate provider name\n");
-+ return -ENOMEM;
-+ }
-+ provider->dtpv_attr = *pap;
-+ provider->dtpv_priv.dtpp_flags = priv;
-+
-+ if (cr != NULL) {
-+ provider->dtpv_priv.dtpp_uid =
-+ from_kuid(init_user_namespace, get_cred(cr)->uid);
-+ put_cred(cr);
-+ }
-+
-+ provider->dtpv_pops = *pops;
-+
-+ if (pops->dtps_provide == NULL) {
-+ ASSERT(pops->dtps_provide_module != NULL);
-+ provider->dtpv_pops.dtps_provide =
-+ (void (*)(void *, const struct dtrace_probedesc *))
-+ dtrace_nullop;
-+ }
-+
-+ if (pops->dtps_provide_module == NULL) {
-+ ASSERT(pops->dtps_provide != NULL);
-+ provider->dtpv_pops.dtps_provide_module =
-+ (void (*)(void *, struct module *))dtrace_nullop;
-+ }
-+
-+ if (pops->dtps_destroy_module == NULL) {
-+ provider->dtpv_pops.dtps_destroy_module =
-+ (void (*)(void *, struct module *))dtrace_nullop;
-+ }
-+
-+ if (pops->dtps_suspend == NULL) {
-+ ASSERT(pops->dtps_resume == NULL);
-+ provider->dtpv_pops.dtps_suspend =
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop;
-+ provider->dtpv_pops.dtps_resume =
-+ (void (*)(void *, dtrace_id_t, void *))dtrace_nullop;
-+ }
-+
-+ provider->dtpv_arg = arg;
-+ *idp = (dtrace_provider_id_t)provider;
-+
-+ if (pops == &dtrace_provider_ops) {
-+ ASSERT(MUTEX_HELD(&dtrace_provider_lock));
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dtrace_anon.dta_enabling == NULL);
-+
-+ /*
-+ * The DTrace provider must be at the head of the provider
-+ * chain.
-+ */
-+ provider->dtpv_next = dtrace_provider;
-+ dtrace_provider = provider;
-+
-+ dt_dbg_prov(" Done registering %s\n", name);
-+
-+ return 0;
-+ }
-+
-+ mutex_lock(&module_mutex);
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ /*
-+ * If there is at least one provider registered, we'll add this new one
-+ * after the first provider.
-+ */
-+ if (dtrace_provider != NULL) {
-+ provider->dtpv_next = dtrace_provider->dtpv_next;
-+ dtrace_provider->dtpv_next = provider;
-+ } else
-+ dtrace_provider = provider;
-+
-+ if (dtrace_retained != NULL) {
-+ dt_dbg_prov(" Processing retained enablings for %s\n", name);
-+ dtrace_enabling_provide(provider);
-+
-+ /*
-+ * We must now call dtrace_enabling_matchall() which needs to
-+ * acquire cpu_lock and dtrace_lock. We therefore need to drop
-+ * our locks before calling it.
-+ */
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+ dtrace_enabling_matchall();
-+
-+ dt_dbg_prov(" Done registering %s\n", name);
-+
-+ return 0;
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ mutex_unlock(&module_mutex);
-+
-+ dt_dbg_prov(" Done registering %s\n", name);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_register);
-+
-+struct unreg_state {
-+ struct dtrace_provider *prov;
-+ struct dtrace_probe *first;
-+};
-+
-+/*
-+ * Check whether the given probe is still enabled for the given provider.
-+ */
-+static int dtrace_unregister_check(int id, void *p, void *data)
-+{
-+ struct dtrace_probe *probe = (struct dtrace_probe *)p;
-+ struct unreg_state *st = (struct unreg_state *)data;
-+
-+ if (probe->dtpr_provider != st->prov)
-+ return 0;
-+
-+ if (probe->dtpr_ecb == NULL)
-+ return 0;
-+
-+ return -EBUSY;
-+}
-+
-+/*
-+ * Remove the given probe from the hash tables and the probe IDR, if it is
-+ * associated with the given provider. The probes are chained for further
-+ * processing.
-+ */
-+static int dtrace_unregister_probe(int id, void *p, void *data)
-+{
-+ struct dtrace_probe *probe = (struct dtrace_probe *)p;
-+ struct unreg_state *st = (struct unreg_state *)data;
-+
-+ if (probe->dtpr_provider != st->prov)
-+ return 0;
-+
-+ dtrace_hash_remove(dtrace_bymod, probe);
-+ dtrace_hash_remove(dtrace_byfunc, probe);
-+ dtrace_hash_remove(dtrace_byname, probe);
-+
-+ if (st->first == NULL) {
-+ st->first = probe;
-+ probe->dtpr_nextmod = NULL;
-+ } else {
-+ probe->dtpr_nextmod = st->first;
-+ st->first = probe;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Remove the given probe from the hash tables and the probe IDR, if it is
-+ * associated with the given provider and if it does not have any enablings.
-+ * The probes are chained for further processing.
-+ */
-+static int dtrace_condense_probe(int id, void *p, void *data)
-+{
-+ struct dtrace_probe *probe = (struct dtrace_probe *)p;
-+ struct unreg_state *st = (struct unreg_state *)data;
-+
-+ if (probe->dtpr_provider != st->prov)
-+ return 0;
-+
-+ if (probe->dtpr_ecb == NULL)
-+ return 0;
-+
-+ dtrace_hash_remove(dtrace_bymod, probe);
-+ dtrace_hash_remove(dtrace_byfunc, probe);
-+ dtrace_hash_remove(dtrace_byname, probe);
-+
-+ if (st->first == NULL) {
-+ st->first = probe;
-+ probe->dtpr_nextmod = NULL;
-+ } else {
-+ probe->dtpr_nextmod = st->first;
-+ st->first = probe;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Unregister the specified provider from the DTrace core. This should be
-+ * called by provider during module cleanup.
-+ *
-+ * The mutex_lock is already held during this call.
-+ */
-+int dtrace_unregister(dtrace_provider_id_t id)
-+{
-+ struct dtrace_provider *old = (struct dtrace_provider *)id;
-+ struct dtrace_provider *prev = NULL;
-+ int err, self = 0;
-+ struct dtrace_probe *probe;
-+ struct unreg_state st = { old, NULL };
-+
-+ ASSERT(MUTEX_HELD(&module_mutex));
-+
-+ dt_dbg_prov("Unregistering provider '%s'...\n", old->dtpv_name);
-+
-+ if (old->dtpv_pops.dtps_enable ==
-+ (int (*)(void *, dtrace_id_t, void *))dtrace_enable_nullop) {
-+ /*
-+ * When the provider is the DTrace core itself, we're called
-+ * with locks already held.
-+ */
-+ ASSERT(old == dtrace_provider);
-+ ASSERT(MUTEX_HELD(&dtrace_provider_lock));
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ self = 1;
-+
-+ if (dtrace_provider->dtpv_next != NULL) {
-+ /*
-+ * We cannot and should not remove the DTrace provider
-+ * if there is any other provider left.
-+ */
-+ dt_dbg_prov(" Failed to unregister %s - not last\n",
-+ old->dtpv_name);
-+
-+ return -EBUSY;
-+ }
-+ } else {
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+ }
-+
-+ /*
-+ * If /dev/dtrace/dtrace is still held open by a process, or if there
-+ * are anonymous probes that are still enabled, we refuse to deregister
-+ * providers, unless the provider has been invalidated explicitly.
-+ */
-+ if (!old->dtpv_defunct &&
-+ (dtrace_opens || (dtrace_anon.dta_state != NULL &&
-+ dtrace_anon.dta_state->dts_necbs > 0))) {
-+ if (!self) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ }
-+
-+ dt_dbg_prov(" Failed to unregister %s - dtrace in use\n",
-+ old->dtpv_name);
-+
-+ return -EBUSY;
-+ }
-+
-+ /*
-+ * Check whether any of the probes associated with this provider are
-+ * still enabled (having at least one ECB). If any are found, we
-+ * cannot remove this provider.
-+ */
-+ st.prov = old;
-+ err = dtrace_probe_for_each(dtrace_unregister_check, &st);
-+ if (err < 0) {
-+ if (!self) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ }
-+
-+ dt_dbg_prov(" Failed to unregister %s - provider in use\n",
-+ old->dtpv_name);
-+
-+ return err;
-+ }
-+
-+ /*
-+ * All the probes associated with this provider are disabled. We can
-+ * safely remove these probes from the hashtables and the probe array.
-+ * We chain all the probes together for further processing.
-+ */
-+ dtrace_probe_for_each(dtrace_unregister_probe, &st);
-+
-+ /*
-+ * The probes associated with the provider have been removed. Ensure
-+ * synchronization on probe IDR processing.
-+ */
-+ dtrace_sync();
-+
-+ /*
-+ * Now get rid of the actual probes.
-+ */
-+ for (probe = st.first; probe != NULL; probe = st.first) {
-+ int probe_id = probe->dtpr_id;
-+
-+ st.first = probe->dtpr_nextmod;
-+
-+ old->dtpv_pops.dtps_destroy(old->dtpv_arg, probe_id,
-+ probe->dtpr_arg);
-+
-+ kfree(probe->dtpr_mod);
-+ kfree(probe->dtpr_func);
-+ kfree(probe->dtpr_name);
-+ kmem_cache_free(dtrace_probe_cachep, probe);
-+
-+ dtrace_probe_remove_id(probe_id);
-+ }
-+
-+ prev = dtrace_provider;
-+ if (prev == old) {
-+ /*
-+ * We are removing the provider at the head of the chain.
-+ */
-+ ASSERT(self);
-+ ASSERT(old->dtpv_next == NULL);
-+
-+ dtrace_provider = old->dtpv_next;
-+ } else {
-+ while (prev != NULL && prev->dtpv_next != old)
-+ prev = prev->dtpv_next;
-+
-+ if (prev == NULL) {
-+ pr_err("Attempt to unregister non-existent DTrace "
-+ "provider %p\n", (void *)id);
-+ BUG();
-+ }
-+
-+ prev->dtpv_next = old->dtpv_next;
-+ }
-+
-+ if (!self) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+ }
-+
-+ kfree(old->dtpv_name);
-+ kfree(old);
-+
-+ dt_dbg_prov(" Done unregistering\n");
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_unregister);
-+
-+/*
-+ * Invalidate the specified provider. All subsequent probe lookups for the
-+ * specified provider will fail, but the probes will not be removed.
-+ */
-+void dtrace_invalidate(dtrace_provider_id_t id)
-+{
-+ struct dtrace_provider *pvp = (struct dtrace_provider *)id;
-+
-+ ASSERT(pvp->dtpv_pops.dtps_enable !=
-+ (int (*)(void *, dtrace_id_t, void *))dtrace_enable_nullop);
-+
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ pvp->dtpv_defunct = 1;
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+}
-+EXPORT_SYMBOL(dtrace_invalidate);
-+
-+/*
-+ * Indicate whether or not DTrace has attached.
-+ */
-+int dtrace_attached(void)
-+{
-+ /*
-+ * dtrace_provider will be non-NULL iff the DTrace driver has
-+ * attached. (It's non-NULL because DTrace is always itself a
-+ * provider.)
-+ */
-+ return dtrace_provider != NULL;
-+}
-+EXPORT_SYMBOL(dtrace_attached);
-+
-+/*
-+ * Remove all the unenabled probes for the given provider. This function is
-+ * not unlike dtrace_unregister(), except that it doesn't remove the provider
-+ * -- just as many of its associated probes as it can.
-+ */
-+int dtrace_condense(dtrace_provider_id_t id)
-+{
-+ struct dtrace_provider *prov = (struct dtrace_provider *)id;
-+ struct dtrace_probe *probe;
-+ struct unreg_state st = { prov, NULL };
-+
-+ /*
-+ * Make sure this isn't the DTrace provider itself.
-+ */
-+ ASSERT(prov->dtpv_pops.dtps_enable !=
-+ (int (*)(void *, dtrace_id_t, void *))dtrace_enable_nullop);
-+
-+ mutex_lock(&dtrace_provider_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ /*
-+ * Attempt to destroy the probes associated with this provider.
-+ */
-+ dtrace_probe_for_each(dtrace_condense_probe, &st);
-+
-+ /*
-+ * The probes associated with the provider have been removed. Ensure
-+ * synchronization on probe IDR processing.
-+ */
-+ dtrace_sync();
-+
-+ /*
-+ * Now get rid of the actual probes.
-+ */
-+ for (probe = st.first; probe != NULL; probe = st.first) {
-+ int probe_id = probe->dtpr_id;
-+
-+ st.first = probe->dtpr_nextmod;
-+
-+ prov->dtpv_pops.dtps_destroy(prov->dtpv_arg, probe_id,
-+ probe->dtpr_arg);
-+
-+ kfree(probe->dtpr_mod);
-+ kfree(probe->dtpr_func);
-+ kfree(probe->dtpr_name);
-+ kfree(probe);
-+
-+ dtrace_probe_remove_id(probe_id);
-+ }
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_provider_lock);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_condense);
-+
-+int dtrace_meta_register(const char *name, const struct dtrace_mops *mops,
-+ void *arg, dtrace_meta_provider_id_t *idp)
-+{
-+ struct dtrace_meta *meta;
-+ struct dtrace_helpers *help, *next;
-+ int i;
-+
-+ *idp = DTRACE_METAPROVNONE;
-+
-+ /*
-+ * We strictly don't need the name, but we hold onto it for
-+ * debuggability. All hail error queues!
-+ */
-+ if (name == NULL) {
-+ pr_warn("failed to register meta-provider: invalid name\n");
-+ return -EINVAL;
-+ }
-+
-+ if (mops == NULL ||
-+ mops->dtms_create_probe == NULL ||
-+ mops->dtms_provide_pid == NULL ||
-+ mops->dtms_remove_pid == NULL) {
-+ pr_warn("failed to register meta-register %s: invalid ops\n",
-+ name);
-+ return -EINVAL;
-+ }
-+
-+ dt_dbg_prov("Registering provider '%s'...\n", name);
-+ meta = kzalloc(sizeof(struct dtrace_meta), GFP_KERNEL);
-+ if (meta == NULL) {
-+ dt_dbg_prov(" Failed to allocate meta provider struct\n");
-+ return -ENOMEM;
-+ }
-+ meta->dtm_mops = *mops;
-+ meta->dtm_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
-+ if (meta->dtm_name == NULL) {
-+ kfree(meta);
-+ dt_dbg_prov(" Failed to allocate meta provider name\n");
-+ return -ENOMEM;
-+ }
-+ strcpy(meta->dtm_name, name);
-+ meta->dtm_arg = arg;
-+
-+ mutex_lock(&dtrace_meta_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (dtrace_meta_pid != NULL) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_meta_lock);
-+ pr_warn("failed to register meta-register %s: user-land "
-+ "meta-provider exists", name);
-+ kfree(meta->dtm_name);
-+ kfree(meta);
-+ return -EINVAL;
-+ }
-+
-+ dtrace_meta_pid = meta;
-+ *idp = (dtrace_meta_provider_id_t)meta;
-+
-+ /*
-+ * If there are providers and probes ready to go, pass them
-+ * off to the new meta provider now.
-+ */
-+ help = dtrace_deferred_pid;
-+ dtrace_deferred_pid = NULL;
-+
-+ mutex_unlock(&dtrace_lock);
-+
-+ while (help != NULL) {
-+ for (i = 0; i < help->dthps_nprovs; i++) {
-+ dtrace_helper_provide(&help->dthps_provs[i]->dthp_prov,
-+ help->dthps_pid);
-+ }
-+
-+ next = help->dthps_next;
-+ help->dthps_next = NULL;
-+ help->dthps_prev = NULL;
-+ help->dthps_deferred = 0;
-+ help = next;
-+ }
-+
-+ mutex_unlock(&dtrace_meta_lock);
-+
-+ dt_dbg_prov(" Done registering %s\n", name);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_meta_register);
-+
-+int dtrace_meta_unregister(dtrace_meta_provider_id_t id)
-+{
-+ struct dtrace_meta **pp, *old = (struct dtrace_meta *)id;
-+
-+ dt_dbg_prov("Unregistering meta provider '%s'...\n", old->dtm_name);
-+ mutex_lock(&dtrace_meta_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (old == dtrace_meta_pid) {
-+ pp = &dtrace_meta_pid;
-+ } else {
-+ pr_err("Attempt to unregister non-existent DTrace meta-"
-+ "provider %p\n", (void *)old);
-+ BUG();
-+ }
-+
-+ if (old->dtm_count != 0) {
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_meta_lock);
-+ return -EBUSY;
-+ }
-+
-+ *pp = NULL;
-+
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&dtrace_meta_lock);
-+
-+ kfree(old->dtm_name);
-+ kfree(old);
-+
-+ dt_dbg_prov(" Done unregistering\n");
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_meta_unregister);
-diff --git a/dtrace/dtrace_spec.c b/dtrace/dtrace_spec.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..4ca9bb7a6427468d8a1fcf5d5b3aec00107200ac
---- /dev/null
-+++ b/dtrace/dtrace_spec.c
-@@ -0,0 +1,434 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_spec.c
-+ * DESCRIPTION: DTrace - speculation implementation
-+ *
-+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/smp.h>
-+#include <asm/cmpxchg.h>
-+
-+#include "dtrace.h"
-+
-+/*
-+ * Given consumer state, this routine finds a speculation in the INACTIVE
-+ * state and transitions it into the ACTIVE state. If there is no speculation
-+ * in the INACTIVE state, 0 is returned. In this case, no error counter is
-+ * incremented -- it is up to the caller to take appropriate action.
-+ */
-+int dtrace_speculation(struct dtrace_state *state)
-+{
-+ int i = 0;
-+ uint32_t count, *stat = &state->dts_speculations_unavail;
-+ enum dtrace_speculation_state curr;
-+
-+ while (i < state->dts_nspeculations) {
-+ struct dtrace_speculation *spec = &state->dts_speculations[i];
-+
-+ curr = spec->dtsp_state;
-+
-+ if (curr != DTRACESPEC_INACTIVE) {
-+ if (curr == DTRACESPEC_COMMITTINGMANY ||
-+ curr == DTRACESPEC_COMMITTING ||
-+ curr == DTRACESPEC_DISCARDING)
-+ stat = &state->dts_speculations_busy;
-+
-+ i++;
-+ continue;
-+ }
-+
-+ if (cmpxchg((uint32_t *)&spec->dtsp_state, curr,
-+ DTRACESPEC_ACTIVE) == curr)
-+ return i + 1;
-+ }
-+
-+ /*
-+ * We couldn't find a speculation. If we found as much as a single
-+ * busy speculation buffer, we'll attribute this failure as "busy"
-+ * instead of "unavail".
-+ */
-+ do {
-+ count = *stat;
-+ } while (cmpxchg(stat, count, count + 1) != count);
-+
-+ return 0;
-+}
-+
-+/*
-+ * This routine commits an active speculation. If the specified speculation
-+ * is not in a valid state to perform a commit(), this routine will silently do
-+ * nothing. The state of the specified speculation is transitioned according
-+ * to the state transition diagram outlined in <sys/dtrace_impl.h>
-+ */
-+void dtrace_speculation_commit(struct dtrace_state *state, processorid_t cpu,
-+ dtrace_specid_t which)
-+{
-+ struct dtrace_speculation *spec;
-+ struct dtrace_buffer *src, *dest;
-+ uintptr_t daddr, saddr, dlimit;
-+ enum dtrace_speculation_state curr, new = 0;
-+ intptr_t offs;
-+
-+ if (which == 0)
-+ return;
-+
-+ if (which > state->dts_nspeculations) {
-+ per_cpu_core(cpu)->cpuc_dtrace_flags |= CPU_DTRACE_ILLOP;
-+ return;
-+ }
-+
-+ spec = &state->dts_speculations[which - 1];
-+ src = &spec->dtsp_buffer[cpu];
-+ dest = &state->dts_buffer[cpu];
-+
-+ do {
-+ curr = spec->dtsp_state;
-+
-+ if (curr == DTRACESPEC_COMMITTINGMANY)
-+ break;
-+
-+ switch (curr) {
-+ case DTRACESPEC_INACTIVE:
-+ case DTRACESPEC_DISCARDING:
-+ return;
-+
-+ case DTRACESPEC_COMMITTING:
-+ /*
-+ * This is only possible if we are (a) commit()'ing
-+ * without having done a prior speculate() on this CPU
-+ * and (b) racing with another commit() on a different
-+ * CPU. There's nothing to do -- we just assert that
-+ * our offset is 0.
-+ */
-+ ASSERT(src->dtb_offset == 0);
-+ return;
-+
-+ case DTRACESPEC_ACTIVE:
-+ new = DTRACESPEC_COMMITTING;
-+ break;
-+
-+ case DTRACESPEC_ACTIVEONE:
-+ /*
-+ * This speculation is active on one CPU. If our
-+ * buffer offset is non-zero, we know that the one CPU
-+ * must be us. Otherwise, we are committing on a
-+ * different CPU from the speculate(), and we must
-+ * rely on being asynchronously cleaned.
-+ */
-+ if (src->dtb_offset != 0) {
-+ new = DTRACESPEC_COMMITTING;
-+ break;
-+ }
-+ /*FALLTHROUGH*/
-+
-+ case DTRACESPEC_ACTIVEMANY:
-+ new = DTRACESPEC_COMMITTINGMANY;
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ }
-+ } while (cmpxchg((uint32_t *)&spec->dtsp_state, curr, new) !=
-+ curr);
-+
-+ /*
-+ * We have set the state to indicate that we are committing this
-+ * speculation. Now reserve the necessary space in the destination
-+ * buffer.
-+ */
-+ offs = dtrace_buffer_reserve(dest, src->dtb_offset, sizeof(uint64_t),
-+ state, NULL);
-+ if (offs < 0) {
-+ dtrace_buffer_drop(dest);
-+ goto out;
-+ }
-+
-+ /*
-+ * We have the space; copy the buffer across. (Note that this is a
-+ * highly subobtimal bcopy(); in the unlikely event that this becomes
-+ * a serious performance issue, a high-performance DTrace-specific
-+ * bcopy() should obviously be invented.)
-+ */
-+ daddr = (uintptr_t)dest->dtb_tomax + offs;
-+ dlimit = daddr + src->dtb_offset;
-+ saddr = (uintptr_t)src->dtb_tomax;
-+
-+ /*
-+ * First, the aligned portion.
-+ */
-+ while (dlimit - daddr >= sizeof(uint64_t)) {
-+ *((uint64_t *)daddr) = *((uint64_t *)saddr);
-+ *((uint64_t *)daddr) = *((uint64_t *)saddr);
-+
-+ daddr += sizeof(uint64_t);
-+ saddr += sizeof(uint64_t);
-+ }
-+
-+ /*
-+ * Now any left-over bit...
-+ */
-+ while (dlimit - daddr)
-+ *((uint8_t *)daddr++) = *((uint8_t *)saddr++);
-+
-+ /*
-+ * Finally, commit the reserved space in the destination buffer.
-+ */
-+ dest->dtb_offset = offs + src->dtb_offset;
-+
-+out:
-+ /*
-+ * If we're lucky enough to be the only active CPU on this speculation
-+ * buffer, we can just set the state back to DTRACESPEC_INACTIVE.
-+ */
-+ if (curr == DTRACESPEC_ACTIVE ||
-+ (curr == DTRACESPEC_ACTIVEONE && new == DTRACESPEC_COMMITTING)) {
-+ /*
-+ * Will cause unused warning if DEBUG is not defined.
-+ */
-+ uint32_t rval =
-+ cmpxchg((uint32_t *)&spec->dtsp_state,
-+ DTRACESPEC_COMMITTING,
-+ DTRACESPEC_INACTIVE);
-+
-+ ASSERT(rval == DTRACESPEC_COMMITTING);
-+ rval = 0; /* Avoid warning about unused variable if !DEBUG */
-+ }
-+
-+ src->dtb_offset = 0;
-+ src->dtb_xamot_drops += src->dtb_drops;
-+ src->dtb_drops = 0;
-+}
-+
-+/*
-+ * This routine discards an active speculation. If the specified speculation
-+ * is not in a valid state to perform a discard(), this routine will silently
-+ * do nothing. The state of the specified speculation is transitioned
-+ * according to the state transition diagram outlined in <sys/dtrace_impl.h>
-+ */
-+void dtrace_speculation_discard(struct dtrace_state *state, processorid_t cpu,
-+ dtrace_specid_t which)
-+{
-+ struct dtrace_speculation *spec;
-+ enum dtrace_speculation_state curr, new = 0;
-+ struct dtrace_buffer *buf;
-+
-+ if (which == 0)
-+ return;
-+
-+ if (which > state->dts_nspeculations) {
-+ per_cpu_core(cpu)->cpuc_dtrace_flags |= CPU_DTRACE_ILLOP;
-+ return;
-+ }
-+
-+ spec = &state->dts_speculations[which - 1];
-+ buf = &spec->dtsp_buffer[cpu];
-+
-+ do {
-+ curr = spec->dtsp_state;
-+
-+ switch (curr) {
-+ case DTRACESPEC_INACTIVE:
-+ case DTRACESPEC_COMMITTINGMANY:
-+ case DTRACESPEC_COMMITTING:
-+ case DTRACESPEC_DISCARDING:
-+ return;
-+
-+ case DTRACESPEC_ACTIVE:
-+ case DTRACESPEC_ACTIVEMANY:
-+ new = DTRACESPEC_DISCARDING;
-+ break;
-+
-+ case DTRACESPEC_ACTIVEONE:
-+ if (buf->dtb_offset != 0)
-+ new = DTRACESPEC_INACTIVE;
-+ else
-+ new = DTRACESPEC_DISCARDING;
-+
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ }
-+ } while (cmpxchg((uint32_t *)&spec->dtsp_state, curr, new) != curr);
-+
-+ buf->dtb_offset = 0;
-+ buf->dtb_drops = 0;
-+}
-+
-+/*
-+ * Note: not called from probe context. This function is called
-+ * asynchronously from cross call context to clean any speculations that are
-+ * in the COMMITTINGMANY or DISCARDING states. These speculations may not be
-+ * transitioned back to the INACTIVE state until all CPUs have cleaned the
-+ * speculation.
-+ */
-+void dtrace_speculation_clean_here(struct dtrace_state *state)
-+{
-+ dtrace_icookie_t cookie;
-+ processorid_t cpu = smp_processor_id();
-+ struct dtrace_buffer *dest = &state->dts_buffer[cpu];
-+ dtrace_specid_t i;
-+ uint32_t re_entry;
-+
-+ DTRACE_SYNC_ENTER_CRITICAL(cookie, re_entry);
-+
-+ if (dest->dtb_tomax == NULL) {
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+ return;
-+ }
-+
-+ for (i = 0; i < state->dts_nspeculations; i++) {
-+ struct dtrace_speculation *spec = &state->dts_speculations[i];
-+ struct dtrace_buffer *src = &spec->dtsp_buffer[cpu];
-+
-+ if (src->dtb_tomax == NULL)
-+ continue;
-+
-+ if (spec->dtsp_state == DTRACESPEC_DISCARDING) {
-+ src->dtb_offset = 0;
-+ continue;
-+ }
-+
-+ if (spec->dtsp_state != DTRACESPEC_COMMITTINGMANY)
-+ continue;
-+
-+ if (src->dtb_offset == 0)
-+ continue;
-+
-+ dtrace_speculation_commit(state, cpu, i + 1);
-+ }
-+
-+ DTRACE_SYNC_EXIT_CRITICAL(cookie, re_entry);
-+}
-+
-+void dtrace_speculation_clean(struct dtrace_state *state)
-+{
-+ int work = 0, rv;
-+ dtrace_specid_t i;
-+
-+ for (i = 0; i < state->dts_nspeculations; i++) {
-+ struct dtrace_speculation *spec = &state->dts_speculations[i];
-+
-+ ASSERT(!spec->dtsp_cleaning);
-+
-+ if (spec->dtsp_state != DTRACESPEC_DISCARDING &&
-+ spec->dtsp_state != DTRACESPEC_COMMITTINGMANY)
-+ continue;
-+
-+ work++;
-+ spec->dtsp_cleaning = 1;
-+ }
-+
-+ if (!work)
-+ return;
-+
-+ dtrace_xcall(DTRACE_CPUALL,
-+ (dtrace_xcall_t)dtrace_speculation_clean_here, state);
-+
-+ /*
-+ * We now know that all CPUs have committed or discarded their
-+ * speculation buffers, as appropriate. We can now set the state
-+ * to inactive.
-+ */
-+ for (i = 0; i < state->dts_nspeculations; i++) {
-+ struct dtrace_speculation *spec =
-+ &state->dts_speculations[i];
-+ enum dtrace_speculation_state curr, new;
-+
-+ if (!spec->dtsp_cleaning)
-+ continue;
-+
-+ curr = spec->dtsp_state;
-+ ASSERT(curr == DTRACESPEC_DISCARDING ||
-+ curr == DTRACESPEC_COMMITTINGMANY);
-+
-+ new = DTRACESPEC_INACTIVE;
-+
-+ rv = cmpxchg((uint32_t *)&spec->dtsp_state, curr, new);
-+ ASSERT(rv == curr);
-+ spec->dtsp_cleaning = 0;
-+ }
-+}
-+
-+/*
-+ * Called as part of a speculate() to get the speculative buffer associated
-+ * with a given speculation. Returns NULL if the specified speculation is not
-+ * in an ACTIVE state. If the speculation is in the ACTIVEONE state -- and
-+ * the active CPU is not the specified CPU -- the speculation will be
-+ * atomically transitioned into the ACTIVEMANY state.
-+ */
-+struct dtrace_buffer *dtrace_speculation_buffer(struct dtrace_state *state,
-+ processorid_t cpu,
-+ dtrace_specid_t which)
-+{
-+ struct dtrace_speculation *spec;
-+ enum dtrace_speculation_state curr, new = 0;
-+ struct dtrace_buffer *buf;
-+
-+ if (which == 0)
-+ return NULL;
-+
-+ if (which > state->dts_nspeculations) {
-+ per_cpu_core(cpu)->cpuc_dtrace_flags |= CPU_DTRACE_ILLOP;
-+ return NULL;
-+ }
-+
-+ spec = &state->dts_speculations[which - 1];
-+ buf = &spec->dtsp_buffer[cpu];
-+
-+ do {
-+ curr = spec->dtsp_state;
-+
-+ switch (curr) {
-+ case DTRACESPEC_INACTIVE:
-+ case DTRACESPEC_COMMITTINGMANY:
-+ case DTRACESPEC_DISCARDING:
-+ return NULL;
-+
-+ case DTRACESPEC_COMMITTING:
-+ ASSERT(buf->dtb_offset == 0);
-+ return NULL;
-+
-+ case DTRACESPEC_ACTIVEONE:
-+ /*
-+ * This speculation is currently active on one CPU.
-+ * Check the offset in the buffer; if it's non-zero,
-+ * that CPU must be us (and we leave the state alone).
-+ * If it's zero, assume that we're starting on a new
-+ * CPU -- and change the state to indicate that the
-+ * speculation is active on more than one CPU.
-+ */
-+ if (buf->dtb_offset != 0)
-+ return buf;
-+
-+ new = DTRACESPEC_ACTIVEMANY;
-+ break;
-+
-+ case DTRACESPEC_ACTIVEMANY:
-+ return buf;
-+
-+ case DTRACESPEC_ACTIVE:
-+ new = DTRACESPEC_ACTIVEONE;
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ }
-+ } while (cmpxchg((uint32_t *)&spec->dtsp_state, curr, new) != curr);
-+
-+ ASSERT(new == DTRACESPEC_ACTIVEONE || new == DTRACESPEC_ACTIVEMANY);
-+
-+ return buf;
-+}
-diff --git a/dtrace/dtrace_state.c b/dtrace/dtrace_state.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..7fb696e8f1a9d80fe98643c183018a1b4633911e
---- /dev/null
-+++ b/dtrace/dtrace_state.c
-@@ -0,0 +1,1108 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_state.c
-+ * DESCRIPTION: DTrace - consumer state implementation
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/cyclic.h>
-+#include <linux/fs.h>
-+#include <linux/idr.h>
-+#include <linux/slab.h>
-+#include <linux/smp.h>
-+#include <linux/vmalloc.h>
-+#include <asm/cmpxchg.h>
-+
-+#include "dtrace.h"
-+
-+int dtrace_destructive_disallow = 0;
-+dtrace_optval_t dtrace_nspec_default = 1;
-+dtrace_optval_t dtrace_specsize_default = 32 * 1024;
-+dtrace_optval_t dtrace_dstate_defsize = 1 * 1024 * 1024;
-+size_t dtrace_strsize_default = 256;
-+dtrace_optval_t dtrace_stackframes_default = 20;
-+dtrace_optval_t dtrace_ustackframes_default = 100;
-+dtrace_optval_t dtrace_cleanrate_default = 9900990;
-+dtrace_optval_t dtrace_cleanrate_min = 20000;
-+dtrace_optval_t dtrace_cleanrate_max = (uint64_t)60 * NANOSEC;
-+dtrace_optval_t dtrace_aggrate_default = NANOSEC;
-+dtrace_optval_t dtrace_switchrate_default = NANOSEC;
-+dtrace_optval_t dtrace_statusrate_default = NANOSEC;
-+dtrace_optval_t dtrace_statusrate_max = (uint64_t)10 * NANOSEC;
-+dtrace_optval_t dtrace_jstackframes_default = 50;
-+dtrace_optval_t dtrace_jstackstrsize_default = 512;
-+ktime_t dtrace_deadman_interval = KTIME_INIT(1, 0);
-+ktime_t dtrace_deadman_timeout = KTIME_INIT(10, 0);
-+ktime_t dtrace_deadman_user = KTIME_INIT(30, 0);
-+
-+ /* Sampling before counting */
-+uint64_t dtrace_sync_sample_count = 100;
-+
-+dtrace_id_t dtrace_probeid_begin;
-+dtrace_id_t dtrace_probeid_end;
-+dtrace_id_t dtrace_probeid_error;
-+
-+struct dtrace_dynvar dtrace_dynhash_sink;
-+
-+#define DTRACE_DYNHASH_FREE 0
-+#define DTRACE_DYNHASH_SINK 1
-+#define DTRACE_DYNHASH_VALID 2
-+
-+#define DTRACE_DYNVAR_CHUNKSIZE 256
-+
-+static void dtrace_dynvar_clean(struct dtrace_dstate *dstate)
-+{
-+ struct dtrace_dynvar *dirty;
-+ struct dtrace_dstate_percpu *dcpu;
-+ int i, work = 0;
-+
-+ for (i = 0; i < NR_CPUS; i++) {
-+ dcpu = &dstate->dtds_percpu[i];
-+
-+ ASSERT(dcpu->dtdsc_rinsing == NULL);
-+
-+ /*
-+ * If the dirty list is NULL, there is no dirty work to do.
-+ */
-+ if (dcpu->dtdsc_dirty == NULL)
-+ continue;
-+
-+ /*
-+ * If the clean list is non-NULL, then we're not going to do
-+ * any work for this CPU -- it means that there has not been
-+ * a dtrace_dynvar() allocation on this CPU (or from this CPU)
-+ * since the last time we cleaned house.
-+ */
-+ if (dcpu->dtdsc_clean != NULL)
-+ continue;
-+
-+ work = 1;
-+
-+ /*
-+ * Atomically move the dirty list aside.
-+ */
-+ do {
-+ dirty = dcpu->dtdsc_dirty;
-+
-+ /*
-+ * Before we zap the dirty list, set the rinsing list.
-+ * (This allows for a potential assertion in
-+ * dtrace_dynvar(): if a free dynamic variable appears
-+ * on a hash chain, either the dirty list or the
-+ * rinsing list for some CPU must be non-NULL.)
-+ */
-+ dcpu->dtdsc_rinsing = dirty;
-+ dtrace_membar_producer();
-+ } while (cmpxchg(&dcpu->dtdsc_dirty, dirty, NULL) != dirty);
-+ }
-+
-+ /*
-+ * No work to do; return.
-+ */
-+ if (!work)
-+ return;
-+
-+ dtrace_sync();
-+
-+ for (i = 0; i < NR_CPUS; i++) {
-+ dcpu = &dstate->dtds_percpu[i];
-+
-+ if (dcpu->dtdsc_rinsing == NULL)
-+ continue;
-+
-+ /*
-+ * We are now guaranteed that no hash chain contains a pointer
-+ * into this dirty list; we can make it clean.
-+ */
-+ ASSERT(dcpu->dtdsc_clean == NULL);
-+ dcpu->dtdsc_clean = dcpu->dtdsc_rinsing;
-+ dcpu->dtdsc_rinsing = NULL;
-+ }
-+
-+ /*
-+ * Before we actually set the state to be DTRACE_DSTATE_CLEAN, make
-+ * sure that all CPUs have seen all of the dtdsc_clean pointers.
-+ * This prevents a race whereby a CPU incorrectly decides that
-+ * the state should be something other than DTRACE_DSTATE_CLEAN
-+ * after dtrace_dynvar_clean() has completed.
-+ */
-+ dtrace_sync();
-+
-+ dstate->dtds_state = DTRACE_DSTATE_CLEAN;
-+}
-+
-+int dtrace_dstate_init(struct dtrace_dstate *dstate, size_t size)
-+{
-+ size_t hashsize, maxper, min,
-+ chunksize = dstate->dtds_chunksize;
-+ void *base, *percpu;
-+ uintptr_t limit;
-+ struct dtrace_dynvar *dvar, *next, *start;
-+ int i;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(dstate->dtds_base == NULL && dstate->dtds_percpu == NULL);
-+
-+ memset(dstate, 0, sizeof(struct dtrace_dstate));
-+
-+ dstate->dtds_chunksize = chunksize;
-+ if (dstate->dtds_chunksize == 0)
-+ dstate->dtds_chunksize = DTRACE_DYNVAR_CHUNKSIZE;
-+
-+ min = dstate->dtds_chunksize + sizeof(struct dtrace_dynhash);
-+ if (size < min)
-+ size = min;
-+
-+ base = dtrace_vzalloc_try(size);
-+ if (base == NULL)
-+ return -ENOMEM;
-+ percpu = kmem_cache_alloc(dtrace_state_cachep, GFP_KERNEL);
-+ if (percpu == NULL) {
-+ vfree(base);
-+ return -ENOMEM;
-+ }
-+
-+ dstate->dtds_size = size;
-+ dstate->dtds_base = base;
-+ dstate->dtds_percpu = percpu;
-+ memset(dstate->dtds_percpu, 0,
-+ NR_CPUS * sizeof(struct dtrace_dstate_percpu));
-+
-+ hashsize = size /
-+ (dstate->dtds_chunksize + sizeof(struct dtrace_dynhash));
-+
-+ if (hashsize != 1 && (hashsize & 1))
-+ hashsize--;
-+
-+ dstate->dtds_hashsize = hashsize;
-+ dstate->dtds_hash = dstate->dtds_base;
-+
-+ /*
-+ * Set all of our hash buckets to point to the single sink, and (if
-+ * it hasn't already been set), set the sink's hash value to be the
-+ * sink sentinel value. The sink is needed for dynamic variable
-+ * lookups to know that they have iterated over an entire, valid hash
-+ * chain.
-+ */
-+ for (i = 0; i < hashsize; i++)
-+ dstate->dtds_hash[i].dtdh_chain = &dtrace_dynhash_sink;
-+
-+ if (dtrace_dynhash_sink.dtdv_hashval != DTRACE_DYNHASH_SINK)
-+ dtrace_dynhash_sink.dtdv_hashval = DTRACE_DYNHASH_SINK;
-+
-+ /*
-+ * Determine number of active CPUs. Divide free list evenly among
-+ * active CPUs.
-+ */
-+ start = (struct dtrace_dynvar *)((uintptr_t)base +
-+ hashsize * sizeof(struct dtrace_dynhash));
-+ limit = (uintptr_t)base + size;
-+
-+ maxper = (limit - (uintptr_t)start) / NR_CPUS;
-+ maxper = (maxper / dstate->dtds_chunksize) * dstate->dtds_chunksize;
-+
-+ for (i = 0; i < NR_CPUS; i++) {
-+ dstate->dtds_percpu[i].dtdsc_free = dvar = start;
-+
-+ /*
-+ * If we don't even have enough chunks to make it once through
-+ * NCPUs, we're just going to allocate everything to the first
-+ * CPU. And if we're on the last CPU, we're going to allocate
-+ * whatever is left over. In either case, we set the limit to
-+ * be the limit of the dynamic variable space.
-+ */
-+ if (maxper == 0 || i == NR_CPUS - 1) {
-+ limit = (uintptr_t)base + size;
-+ start = NULL;
-+ } else {
-+ limit = (uintptr_t)start + maxper;
-+ start = (struct dtrace_dynvar *)limit;
-+ }
-+
-+ ASSERT(limit <= (uintptr_t)base + size);
-+
-+ for (;;) {
-+ next = (struct dtrace_dynvar *)((uintptr_t)dvar +
-+ dstate->dtds_chunksize);
-+
-+ if ((uintptr_t)next + dstate->dtds_chunksize >= limit)
-+ break;
-+
-+ dvar->dtdv_next = next;
-+ dvar = next;
-+ }
-+
-+ if (maxper == 0)
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+void dtrace_dstate_fini(struct dtrace_dstate *dstate)
-+{
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+ if (dstate->dtds_base == NULL)
-+ return;
-+
-+ vfree(dstate->dtds_base);
-+ kmem_cache_free(dtrace_state_cachep, dstate->dtds_percpu);
-+}
-+
-+void dtrace_vstate_fini(struct dtrace_vstate *vstate)
-+{
-+ /*
-+ * If only there was a logical XOR operator...
-+ */
-+ ASSERT((vstate->dtvs_nglobals == 0) ^ (vstate->dtvs_globals != NULL));
-+
-+ if (vstate->dtvs_nglobals > 0)
-+ vfree(vstate->dtvs_globals);
-+
-+ if (vstate->dtvs_ntlocals > 0)
-+ vfree(vstate->dtvs_tlocals);
-+
-+ ASSERT((vstate->dtvs_nlocals == 0) ^ (vstate->dtvs_locals != NULL));
-+
-+ if (vstate->dtvs_nlocals > 0)
-+ vfree(vstate->dtvs_locals);
-+}
-+
-+static void dtrace_state_clean(struct dtrace_state *state)
-+{
-+ dtrace_optval_t *opt = state->dts_options;
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_ACTIVE &&
-+ state->dts_activity != DTRACE_ACTIVITY_DRAINING)
-+ return;
-+
-+ dtrace_dynvar_clean(&state->dts_vstate.dtvs_dynvars);
-+ dtrace_speculation_clean(state);
-+
-+ cyclic_reprogram(state->dts_cleaner, ns_to_ktime(
-+ opt[DTRACEOPT_CLEANRATE]));
-+}
-+
-+static void dtrace_state_deadman(struct dtrace_state *state)
-+{
-+ ktime_t now;
-+
-+ dtrace_sync();
-+
-+ now = dtrace_gethrtime();
-+ if (state != dtrace_anon.dta_state &&
-+ ktime_ge(ktime_sub(now, state->dts_laststatus),
-+ dtrace_deadman_user))
-+ return;
-+
-+ /*
-+ * We must be sure that dts_alive never appears to be less than the
-+ * value upon entry to dtrace_state_deadman(), and because we lack a
-+ * dtrace_cas64(), we cannot store to it atomically. We thus instead
-+ * store KTIME_MAX to it, followed by a memory barrier, followed by
-+ * the new value. This assures that dts_alive never appears to be
-+ * less than its true value, regardless of the order in which the
-+ * stores to the underlying storage are issued.
-+ */
-+ state->dts_alive = ktime_set(KTIME_SEC_MAX, 0);
-+ dtrace_membar_producer();
-+ state->dts_alive = now;
-+}
-+
-+struct dtrace_state *dtrace_state_create(struct file *file)
-+{
-+ struct dtrace_state *state;
-+ dtrace_optval_t *opt;
-+ int bufsize = NR_CPUS * sizeof(struct dtrace_buffer), i;
-+#ifdef FIXME
-+ const struct cred *cr = file->f_cred;
-+#endif
-+ dtrace_aggid_t aggid;
-+
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ state = kzalloc(sizeof(struct dtrace_state), GFP_KERNEL);
-+ if (state == NULL)
-+ return NULL;
-+
-+ state->dts_epid = DTRACE_EPIDNONE + 1;
-+ state->dts_buffer = vzalloc(bufsize);
-+ if (state->dts_buffer == NULL) {
-+ kfree(state);
-+ return NULL;
-+ }
-+
-+ state->dts_aggbuffer = vzalloc(bufsize);
-+ if (state->dts_aggbuffer == NULL) {
-+ vfree(state->dts_buffer);
-+ kfree(state);
-+ return NULL;
-+ }
-+
-+ idr_init(&state->dts_agg_idr);
-+ state->dts_naggs = 0;
-+ state->dts_cleaner = 0;
-+ state->dts_deadman = 0;
-+ state->dts_vstate.dtvs_state = state;
-+
-+ /*
-+ * Create a first entry in the aggregation IDR, so that ID 0 is used as
-+ * that gets used as meaning 'none'.
-+ */
-+ idr_preload(GFP_KERNEL);
-+ aggid = idr_alloc_cyclic(&state->dts_agg_idr, NULL, 0, 0, GFP_NOWAIT);
-+ idr_preload_end();
-+
-+ ASSERT(aggid == 0);
-+
-+ for (i = 0; i < DTRACEOPT_MAX; i++)
-+ state->dts_options[i] = DTRACEOPT_UNSET;
-+
-+ /*
-+ * Set the default options.
-+ */
-+ opt = state->dts_options;
-+ opt[DTRACEOPT_BUFPOLICY] = DTRACEOPT_BUFPOLICY_SWITCH;
-+ opt[DTRACEOPT_BUFRESIZE] = DTRACEOPT_BUFRESIZE_AUTO;
-+ opt[DTRACEOPT_NSPEC] = dtrace_nspec_default;
-+ opt[DTRACEOPT_SPECSIZE] = dtrace_specsize_default;
-+ opt[DTRACEOPT_CPU] = (dtrace_optval_t)DTRACE_CPUALL;
-+ opt[DTRACEOPT_STRSIZE] = dtrace_strsize_default;
-+ opt[DTRACEOPT_STACKFRAMES] = dtrace_stackframes_default;
-+ opt[DTRACEOPT_USTACKFRAMES] = dtrace_ustackframes_default;
-+ opt[DTRACEOPT_CLEANRATE] = dtrace_cleanrate_default;
-+ opt[DTRACEOPT_AGGRATE] = dtrace_aggrate_default;
-+ opt[DTRACEOPT_SWITCHRATE] = dtrace_switchrate_default;
-+ opt[DTRACEOPT_STATUSRATE] = dtrace_statusrate_default;
-+ opt[DTRACEOPT_JSTACKFRAMES] = dtrace_jstackframes_default;
-+ opt[DTRACEOPT_JSTACKSTRSIZE] = dtrace_jstackstrsize_default;
-+
-+ state->dts_activity = DTRACE_ACTIVITY_INACTIVE;
-+
-+#ifdef FIXME
-+ /*
-+ * Set probe visibility and destructiveness based on user credential
-+ * information. For actual anonymous tracing or if all privileges are
-+ * set, checks are bypassed.
-+ */
-+ if (cr == NULL ||
-+ PRIV_POLICY_ONLY(cr, PRIV_ALL, FALSE)) {
-+ state->dts_cred.dcr_visible = DTRACE_CRV_ALL;
-+ state->dts_cred.dcr_action = DTRACE_CRA_ALL;
-+ } else {
-+ state->dts_cred.dcr_cred = get_cred(cr);
-+
-+ /*
-+ * CRA_PROC means "we have *some* privilege for dtrace" and
-+ * it unlocks the use of variables like pid, etc.
-+ */
-+ if (PRIV_POLICY_ONLY(cr, PRIV_DTRACE_USER, FALSE) ||
-+ PRIV_POLICY_ONLY(cr, PRIV_DTRACE_PROC, FALSE))
-+ state->dts_cred.dcr_action |= DTRACE_CRA_PROC;
-+
-+ /*
-+ * The DTRACE_USER privilege allows the use of syscall and
-+ * profile providers. If the user also has PROC_OWNER, we
-+ * extend the scope to include additional visibility and
-+ * destructive power.
-+ */
-+ if (PRIV_POLICY_ONLY(cr, PRIV_DTRACE_USER, FALSE)) {
-+ if (PRIV_POLICY_ONLY(cr, PRIV_PROC_OWNER, FALSE))
-+ state->dts_cred.dcr_visible |=
-+ DTRACE_CRV_ALLPROC;
-+
-+ state->dts_cred.dcr_action |=
-+ DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER;
-+ }
-+
-+ /*
-+ * Holding the DTRACE_KERNEL privilege also implies that
-+ * the user has the DTRACE_USER privilege from a visibility
-+ * perspective. But without further privileges, some
-+ * destructive actions are not available.
-+ */
-+ if (PRIV_POLICY_ONLY(cr, PRIV_DTRACE_KERNEL, FALSE)) {
-+ /*
-+ * Make all probes in all zones visible. However,
-+ * this doesn't mean that all actions become available
-+ * to all zones.
-+ */
-+ state->dts_cred.dcr_visible |= DTRACE_CRV_KERNEL |
-+ DTRACE_CRV_ALLPROC;
-+ state->dts_cred.dcr_action |= DTRACE_CRA_KERNEL |
-+ DTRACE_CRA_PROC;
-+
-+ /*
-+ * Holding PROC_OWNER means that destructive actions
-+ * are allowed.
-+ */
-+ if (PRIV_POLICY_ONLY(cr, PRIV_PROC_OWNER, FALSE))
-+ state->dts_cred.dcr_action |=
-+ DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER;
-+ }
-+
-+ /*
-+ * Holding the DTRACE_PROC privilege gives control over the
-+ * fasttrap and pid providers. We need to grant wider
-+ * destructive privileges in the event that the user has
-+ * PROC_OWNER .
-+ */
-+ if (PRIV_POLICY_ONLY(cr, PRIV_DTRACE_PROC, FALSE)) {
-+ if (PRIV_POLICY_ONLY(cr, PRIV_PROC_OWNER, FALSE))
-+ state->dts_cred.dcr_action |=
-+ DTRACE_CRA_PROC_DESTRUCTIVE_ALLUSER;
-+ }
-+ }
-+#else
-+ state->dts_cred.dcr_visible = DTRACE_CRV_ALLPROC | DTRACE_CRV_KERNEL;
-+ state->dts_cred.dcr_action = DTRACE_CRA_ALL;
-+#endif
-+
-+ return state;
-+}
-+
-+static int dtrace_state_buffer(struct dtrace_state *state,
-+ struct dtrace_buffer *buf, int which)
-+{
-+ dtrace_optval_t *opt = state->dts_options, size;
-+ processorid_t cpu = DTRACE_CPUALL;
-+ int flags = 0, rval;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+ ASSERT(which < DTRACEOPT_MAX);
-+ ASSERT(state->dts_activity == DTRACE_ACTIVITY_INACTIVE ||
-+ (state == dtrace_anon.dta_state &&
-+ state->dts_activity == DTRACE_ACTIVITY_ACTIVE));
-+
-+ if (opt[which] == DTRACEOPT_UNSET || opt[which] == 0)
-+ return 0;
-+
-+ if (opt[DTRACEOPT_CPU] != DTRACEOPT_UNSET)
-+ cpu = opt[DTRACEOPT_CPU];
-+
-+ if (which == DTRACEOPT_SPECSIZE)
-+ flags |= DTRACEBUF_NOSWITCH;
-+
-+ if (which == DTRACEOPT_BUFSIZE) {
-+ if (opt[DTRACEOPT_BUFPOLICY] == DTRACEOPT_BUFPOLICY_RING)
-+ flags |= DTRACEBUF_RING;
-+
-+ if (opt[DTRACEOPT_BUFPOLICY] == DTRACEOPT_BUFPOLICY_FILL)
-+ flags |= DTRACEBUF_FILL;
-+
-+ if (state != dtrace_anon.dta_state ||
-+ state->dts_activity != DTRACE_ACTIVITY_ACTIVE)
-+ flags |= DTRACEBUF_INACTIVE;
-+ }
-+
-+ for (size = opt[which]; size >= sizeof(uint64_t); size >>= 1) {
-+ /*
-+ * The size must be 8-byte aligned. If the size is not 8-byte
-+ * aligned, drop it down by the difference.
-+ */
-+ if (size & (sizeof(uint64_t) - 1))
-+ size -= size & (sizeof(uint64_t) - 1);
-+
-+ if (size < state->dts_reserve) {
-+ /*
-+ * Buffers always must be large enough to accommodate
-+ * their prereserved space. We return -E2BIG instead
-+ * of ENOMEM in this case to allow for user-level
-+ * software to differentiate the cases.
-+ */
-+ return -E2BIG;
-+ }
-+
-+ rval = dtrace_buffer_alloc(buf, size, flags, cpu);
-+ if (rval != -ENOMEM) {
-+ opt[which] = size;
-+ return rval;
-+ }
-+
-+ if (opt[DTRACEOPT_BUFRESIZE] == DTRACEOPT_BUFRESIZE_MANUAL)
-+ return rval;
-+ }
-+
-+ return -ENOMEM;
-+}
-+
-+static int dtrace_state_buffers(struct dtrace_state *state)
-+{
-+ struct dtrace_speculation *spec = state->dts_speculations;
-+ int rval, i;
-+
-+ rval = dtrace_state_buffer(state, state->dts_buffer, DTRACEOPT_BUFSIZE);
-+ if (rval != 0)
-+ return rval;
-+
-+ rval = dtrace_state_buffer(state, state->dts_aggbuffer,
-+ DTRACEOPT_AGGSIZE);
-+ if (rval != 0)
-+ return rval;
-+
-+ for (i = 0; i < state->dts_nspeculations; i++) {
-+ rval = dtrace_state_buffer(state, spec[i].dtsp_buffer,
-+ DTRACEOPT_SPECSIZE);
-+ if (rval != 0)
-+ return rval;
-+ }
-+
-+ return 0;
-+}
-+
-+static void dtrace_begin_probe(struct dtrace_state *state)
-+{
-+ processorid_t cpuid = smp_processor_id();
-+
-+ ASSERT(state->dts_buffer[cpuid].dtb_flags & DTRACEBUF_INACTIVE);
-+ state->dts_buffer[cpuid].dtb_flags &= ~DTRACEBUF_INACTIVE;
-+
-+ dtrace_probe(dtrace_probeid_begin, (uint64_t)(uintptr_t)state, 0, 0, 0,
-+ 0, 0, 0);
-+
-+ /*
-+ * We may have had an exit action from a BEGIN probe; only change our
-+ * state to ACTIVE if we're still in WARMUP.
-+ */
-+ ASSERT(state->dts_activity == DTRACE_ACTIVITY_WARMUP ||
-+ state->dts_activity == DTRACE_ACTIVITY_DRAINING);
-+
-+ if (state->dts_activity == DTRACE_ACTIVITY_WARMUP)
-+ state->dts_activity = DTRACE_ACTIVITY_ACTIVE;
-+
-+ dtrace_membar_enter();
-+}
-+
-+static void dtrace_state_prereserve(struct dtrace_state *state)
-+{
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_probe *probe;
-+
-+ state->dts_reserve = 0;
-+
-+ if (state->dts_options[DTRACEOPT_BUFPOLICY] != DTRACEOPT_BUFPOLICY_FILL)
-+ return;
-+
-+ /*
-+ * If our buffer policy is a "fill" buffer policy, we need to set the
-+ * prereserved space to be the space required by the END probes.
-+ */
-+ probe = dtrace_probe_lookup_id(dtrace_probeid_end);
-+ ASSERT(probe != NULL);
-+
-+ for (ecb = probe->dtpr_ecb; ecb != NULL; ecb = ecb->dte_next) {
-+ if (ecb->dte_state != state)
-+ continue;
-+
-+ state->dts_reserve += ecb->dte_needed + ecb->dte_alignment;
-+ }
-+}
-+
-+int dtrace_state_go(struct dtrace_state *state, processorid_t *cpu)
-+{
-+ dtrace_optval_t *opt = state->dts_options, sz, nspec;
-+ struct dtrace_speculation *spec;
-+ struct dtrace_buffer *buf;
-+ struct cyc_handler hdlr;
-+ struct cyc_time when;
-+ processorid_t cpuid;
-+ int rval = 0, i, bufsize = NR_CPUS * sizeof(struct dtrace_buffer);
-+
-+ mutex_lock(&cpu_lock);
-+ mutex_lock(&dtrace_lock);
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE) {
-+ rval = -EBUSY;
-+ goto out;
-+ }
-+
-+ /*
-+ * Before we can perform any checks, we must prime all of the
-+ * retained enablings that correspond to this state.
-+ */
-+ dtrace_enabling_prime(state);
-+
-+ if (state->dts_destructive && !state->dts_cred.dcr_destructive) {
-+ rval = -EACCES;
-+ goto out;
-+ }
-+
-+ dtrace_state_prereserve(state);
-+
-+ /*
-+ * If a cpu has been selected check if its value is valid and
-+ * the cpu is online.
-+ */
-+ cpuid = opt[DTRACEOPT_CPU];
-+ if (cpuid != DTRACE_CPUALL &&
-+ (cpuid < 0 || cpuid >= NR_CPUS || !cpu_online(cpuid))) {
-+ rval = -ENXIO;
-+ goto out;
-+ }
-+
-+ /*
-+ * Now we want to do is try to allocate our speculations.
-+ * We do not automatically resize the number of speculations; if
-+ * this fails, we will fail the operation.
-+ */
-+ nspec = opt[DTRACEOPT_NSPEC];
-+ ASSERT(nspec != DTRACEOPT_UNSET);
-+
-+ if (nspec > INT_MAX) {
-+ rval = -ENOMEM;
-+ goto out;
-+ }
-+
-+ spec = vzalloc(nspec * sizeof(struct dtrace_speculation));
-+ if (spec == NULL) {
-+ rval = -ENOMEM;
-+ goto out;
-+ }
-+
-+ state->dts_speculations = spec;
-+ state->dts_nspeculations = (int)nspec;
-+
-+ for (i = 0; i < nspec; i++) {
-+ buf = vzalloc(bufsize);
-+ if (buf == NULL) {
-+ rval = -ENOMEM;
-+ goto err;
-+ }
-+
-+ spec[i].dtsp_buffer = buf;
-+ }
-+
-+ if (opt[DTRACEOPT_GRABANON] != DTRACEOPT_UNSET) {
-+ if (dtrace_anon.dta_state == NULL) {
-+ rval = -ENOENT;
-+ goto out;
-+ }
-+
-+ if (state->dts_necbs != 0) {
-+ rval = -EALREADY;
-+ goto out;
-+ }
-+
-+ state->dts_anon = dtrace_anon_grab();
-+ ASSERT(state->dts_anon != NULL);
-+ state = state->dts_anon;
-+
-+ /*
-+ * We want "grabanon" to be set in the grabbed state, so we'll
-+ * copy that option value from the grabbing state into the
-+ * grabbed state.
-+ */
-+ state->dts_options[DTRACEOPT_GRABANON] =
-+ opt[DTRACEOPT_GRABANON];
-+
-+ *cpu = dtrace_anon.dta_beganon;
-+
-+ /*
-+ * If the anonymous state is active (as it almost certainly
-+ * is if the anonymous enabling ultimately matched anything),
-+ * we don't allow any further option processing -- but we
-+ * don't return failure.
-+ */
-+ if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE)
-+ goto out;
-+ }
-+
-+ if (opt[DTRACEOPT_AGGSIZE] != DTRACEOPT_UNSET &&
-+ opt[DTRACEOPT_AGGSIZE] != 0) {
-+ if (state->dts_naggs == 0) {
-+ /*
-+ * We're not going to create an aggregation buffer
-+ * because we don't have any ECBs that contain
-+ * aggregations -- set this option to 0.
-+ */
-+ opt[DTRACEOPT_AGGSIZE] = 0;
-+ } else {
-+ /*
-+ * If we have an aggregation buffer, we must also have
-+ * a buffer to use as scratch.
-+ */
-+ if (opt[DTRACEOPT_BUFSIZE] == DTRACEOPT_UNSET ||
-+ opt[DTRACEOPT_BUFSIZE] < state->dts_needed)
-+ opt[DTRACEOPT_BUFSIZE] = state->dts_needed;
-+ }
-+ }
-+
-+ if (opt[DTRACEOPT_SPECSIZE] != DTRACEOPT_UNSET &&
-+ opt[DTRACEOPT_SPECSIZE] != 0) {
-+ /*
-+ * We are not going to create speculation buffers if we do not
-+ * have any ECBs that actually speculate.
-+ */
-+ if (!state->dts_speculates)
-+ opt[DTRACEOPT_SPECSIZE] = 0;
-+ }
-+
-+ /*
-+ * The bare minimum size for any buffer that we're actually going to
-+ * do anything to is sizeof (uint64_t).
-+ */
-+ sz = sizeof(uint64_t);
-+
-+ if ((state->dts_needed != 0 && opt[DTRACEOPT_BUFSIZE] < sz) ||
-+ (state->dts_speculates && opt[DTRACEOPT_SPECSIZE] < sz) ||
-+ (state->dts_naggs != 0 && opt[DTRACEOPT_AGGSIZE] < sz)) {
-+ /*
-+ * A buffer size has been explicitly set to 0 (or to a size
-+ * that will be adjusted to 0) and we need the space -- we
-+ * need to return failure. We return -ENOSPC to differentiate
-+ * it from failing to allocate a buffer due to failure to meet
-+ * the reserve (for which we return -E2BIG).
-+ */
-+ rval = -ENOSPC;
-+ goto out;
-+ }
-+
-+ rval = dtrace_state_buffers(state);
-+ if (rval != 0)
-+ goto err;
-+
-+ sz = opt[DTRACEOPT_DYNVARSIZE];
-+ if (sz == DTRACEOPT_UNSET)
-+ sz = dtrace_dstate_defsize;
-+
-+ do {
-+ rval = dtrace_dstate_init(&state->dts_vstate.dtvs_dynvars, sz);
-+
-+ if (rval == 0)
-+ break;
-+
-+ if (opt[DTRACEOPT_BUFRESIZE] == DTRACEOPT_BUFRESIZE_MANUAL)
-+ goto err;
-+ } while (sz >>= 1);
-+
-+ opt[DTRACEOPT_DYNVARSIZE] = sz;
-+
-+ if (rval != 0)
-+ goto err;
-+
-+ if (opt[DTRACEOPT_STATUSRATE] > dtrace_statusrate_max)
-+ opt[DTRACEOPT_STATUSRATE] = dtrace_statusrate_max;
-+
-+ if (opt[DTRACEOPT_CLEANRATE] == 0)
-+ opt[DTRACEOPT_CLEANRATE] = dtrace_cleanrate_max;
-+
-+ if (opt[DTRACEOPT_CLEANRATE] < dtrace_cleanrate_min)
-+ opt[DTRACEOPT_CLEANRATE] = dtrace_cleanrate_min;
-+
-+ if (opt[DTRACEOPT_CLEANRATE] > dtrace_cleanrate_max)
-+ opt[DTRACEOPT_CLEANRATE] = dtrace_cleanrate_max;
-+
-+ hdlr.cyh_func = (cyc_func_t)dtrace_state_clean;
-+ hdlr.cyh_arg = (uintptr_t)state;
-+ hdlr.cyh_level = CY_LOW_LEVEL;
-+
-+ when.cyt_when = ktime_set(0, 0);
-+ when.cyt_interval = CY_INTERVAL_INF;
-+
-+ state->dts_cleaner = cyclic_add(&hdlr, &when);
-+ cyclic_reprogram(state->dts_cleaner, ns_to_ktime(
-+ opt[DTRACEOPT_CLEANRATE]));
-+
-+ hdlr.cyh_func = (cyc_func_t)dtrace_state_deadman;
-+ hdlr.cyh_arg = (uintptr_t)state;
-+ hdlr.cyh_level = CY_LOW_LEVEL;
-+
-+ when.cyt_when = ktime_set(0, 0);
-+ when.cyt_interval = dtrace_deadman_interval;
-+
-+ state->dts_alive = state->dts_laststatus = dtrace_gethrtime();
-+ state->dts_deadman = cyclic_add(&hdlr, &when);
-+
-+ state->dts_activity = DTRACE_ACTIVITY_WARMUP;
-+
-+ /*
-+ * Issue xcall even when the BEGIN probe fires on current CPU. The
-+ * underlying implementation of SMP will turn it into direct function
-+ * call. It is not allowed to turn off interrupts so we need to pick
-+ * a cpu first and then xcall it. This way a begin probe will always
-+ * fire on the expected cpu.
-+ */
-+ *cpu = (cpuid == DTRACE_CPUALL) ? smp_processor_id() : cpuid;
-+ dtrace_xcall(*cpu, (dtrace_xcall_t)dtrace_begin_probe, state);
-+
-+ /*
-+ * Regardless of whether or not now we're in ACTIVE or DRAINING, we
-+ * want each CPU to transition its principal buffer out of the
-+ * INACTIVE state. Doing this assures that no CPU will suddenly begin
-+ * processing an ECB halfway down a probe's ECB chain; all CPUs will
-+ * atomically transition from processing none of a state's ECBs to
-+ * processing all of them.
-+ */
-+ dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_buffer_activate,
-+ state);
-+ goto out;
-+
-+err:
-+ dtrace_buffer_free(state->dts_buffer);
-+ dtrace_buffer_free(state->dts_aggbuffer);
-+
-+ nspec = state->dts_nspeculations;
-+ if (nspec == 0) {
-+ ASSERT(state->dts_speculations == NULL);
-+ goto out;
-+ }
-+
-+ spec = state->dts_speculations;
-+ ASSERT(spec != NULL);
-+
-+ for (i = 0; i < state->dts_nspeculations; i++) {
-+ buf = spec[i].dtsp_buffer;
-+ if (buf == NULL)
-+ break;
-+
-+ dtrace_buffer_free(buf);
-+ vfree(buf);
-+ }
-+
-+ vfree(spec);
-+ state->dts_nspeculations = 0;
-+ state->dts_speculations = NULL;
-+
-+out:
-+ mutex_unlock(&dtrace_lock);
-+ mutex_unlock(&cpu_lock);
-+
-+ return rval;
-+}
-+
-+static void dtrace_end_probe(struct dtrace_state *state)
-+{
-+ dtrace_probe(dtrace_probeid_end, (uint64_t)(uintptr_t)state, 0, 0, 0,
-+ 0, 0, 0);
-+
-+ state->dts_activity = DTRACE_ACTIVITY_STOPPED;
-+
-+ dtrace_membar_enter();
-+}
-+
-+int dtrace_state_stop(struct dtrace_state *state, processorid_t *cpu)
-+{
-+ processorid_t cpuid = state->dts_options[DTRACEOPT_CPU];
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_ACTIVE &&
-+ state->dts_activity != DTRACE_ACTIVITY_DRAINING)
-+ return -EINVAL;
-+
-+ /*
-+ * We'll set the activity to DTRACE_ACTIVITY_DRAINING, and issue a sync
-+ * to be sure that every CPU has seen it. See below for the details
-+ * on why this is done.
-+ */
-+ state->dts_activity = DTRACE_ACTIVITY_DRAINING;
-+ dtrace_sync();
-+
-+ /*
-+ * By this point, it is impossible for any CPU to be still processing
-+ * with DTRACE_ACTIVITY_ACTIVE. We can thus set our activity to
-+ * DTRACE_ACTIVITY_COOLDOWN and know that we're not racing with any
-+ * other CPU in dtrace_buffer_reserve(). This allows dtrace_probe()
-+ * and callees to know that the activity is DTRACE_ACTIVITY_COOLDOWN
-+ * iff we're in the END probe.
-+ */
-+ state->dts_activity = DTRACE_ACTIVITY_COOLDOWN;
-+ dtrace_sync();
-+ ASSERT(state->dts_activity == DTRACE_ACTIVITY_COOLDOWN);
-+
-+ /*
-+ * Finally, we can release the reserve and call the END probe. We
-+ * disable interrupts across calling the END probe to allow us to
-+ * return the CPU on which we actually called the END probe. This
-+ * allows user-land to be sure that this CPU's principal buffer is
-+ * processed last.
-+ */
-+ state->dts_reserve = 0;
-+
-+ /*
-+ * Same as for BEGIN probe in dtrace_state_go(). The END probe must
-+ * also fire on the enabled cpu.
-+ */
-+ *cpu = (cpuid == DTRACE_CPUALL) ? smp_processor_id() : cpuid;
-+ dtrace_xcall(*cpu, (dtrace_xcall_t)dtrace_end_probe, state);
-+
-+ dtrace_sync();
-+ return 0;
-+}
-+
-+int dtrace_state_option(struct dtrace_state *state, dtrace_optid_t option,
-+ dtrace_optval_t val)
-+{
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+
-+ if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE)
-+ return -EBUSY;
-+
-+ if (option >= DTRACEOPT_MAX)
-+ return -EINVAL;
-+
-+ if (option != DTRACEOPT_CPU && val < 0)
-+ return -EINVAL;
-+
-+ switch (option) {
-+ case DTRACEOPT_DESTRUCTIVE:
-+ if (dtrace_destructive_disallow)
-+ return -EACCES;
-+
-+ state->dts_cred.dcr_destructive = 1;
-+ break;
-+
-+ case DTRACEOPT_BUFSIZE:
-+ case DTRACEOPT_DYNVARSIZE:
-+ case DTRACEOPT_AGGSIZE:
-+ case DTRACEOPT_SPECSIZE:
-+ case DTRACEOPT_STRSIZE:
-+ if (val < 0)
-+ return -EINVAL;
-+
-+ /*
-+ * If this is an otherwise negative value, set it to the
-+ * highest multiple of 128m less than LONG_MAX. Technically,
-+ * we're adjusting the size without regard to the buffer
-+ * resizing policy, but in fact, this has no effect -- if we
-+ * set the buffer size to ~LONG_MAX and the buffer policy is
-+ * ultimately set to be "manual", the buffer allocation is
-+ * guaranteed to fail, if only because the allocation requires
-+ * two buffers. (We set the the size to the highest multiple
-+ * of 128m because it ensures that the size will remain a
-+ * multiple of a megabyte when repeatedly halved -- all the
-+ * way down to 15m.)
-+ */
-+ if (val >= LONG_MAX)
-+ val = LONG_MAX - (1 << 27) + 1;
-+ }
-+
-+ state->dts_options[option] = val;
-+
-+ return 0;
-+}
-+
-+void dtrace_state_destroy(struct dtrace_state *state)
-+{
-+ struct dtrace_ecb *ecb;
-+ struct dtrace_vstate *vstate = &state->dts_vstate;
-+ int i;
-+ struct dtrace_speculation *spec = state->dts_speculations;
-+ int nspec = state->dts_nspeculations;
-+ uint32_t match;
-+
-+ ASSERT(MUTEX_HELD(&dtrace_lock));
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+ /*
-+ * First, retract any retained enablings for this state.
-+ */
-+ dtrace_enabling_retract(state);
-+ ASSERT(state->dts_nretained == 0);
-+
-+ if (state->dts_activity == DTRACE_ACTIVITY_ACTIVE ||
-+ state->dts_activity == DTRACE_ACTIVITY_DRAINING) {
-+ /*
-+ * We have managed to come into dtrace_state_destroy() on a
-+ * hot enabling -- almost certainly because of a disorderly
-+ * shutdown of a consumer. (That is, a consumer that is
-+ * exiting without having called dtrace_stop().) In this case,
-+ * we're going to set our activity to be KILLED, and then
-+ * issue a sync to be sure that everyone is out of probe
-+ * context before we start blowing away ECBs.
-+ */
-+ state->dts_activity = DTRACE_ACTIVITY_KILLED;
-+ dtrace_sync();
-+ }
-+
-+ /*
-+ * Release the credential hold we took in dtrace_state_create().
-+ */
-+ if (state->dts_cred.dcr_cred != NULL)
-+ put_cred(state->dts_cred.dcr_cred);
-+
-+ /*
-+ * Now we can safely disable and destroy any enabled probes. Because
-+ * any DTRACE_PRIV_KERNEL probes may actually be slowing our progress
-+ * (especially if they're all enabled), we take two passes through the
-+ * ECBs: in the first, we disable just DTRACE_PRIV_KERNEL probes, and
-+ * in the second we disable whatever is left over.
-+ */
-+ for (match = DTRACE_PRIV_KERNEL; ; match = 0) {
-+ for (i = 0; i < state->dts_necbs; i++) {
-+ ecb = state->dts_ecbs[i];
-+ if (ecb == NULL)
-+ continue;
-+
-+ if (match && ecb->dte_probe != NULL) {
-+ struct dtrace_probe *probe =
-+ ecb->dte_probe;
-+ struct dtrace_provider *prov =
-+ probe->dtpr_provider;
-+
-+ if (!(prov->dtpv_priv.dtpp_flags & match))
-+ continue;
-+ }
-+
-+ dtrace_ecb_disable(ecb);
-+ dtrace_ecb_destroy(ecb);
-+ }
-+
-+ if (!match)
-+ break;
-+ }
-+
-+ /*
-+ * Before we free the buffers, perform one more sync to assure that
-+ * every CPU is out of probe context.
-+ */
-+ dtrace_sync();
-+
-+ dtrace_buffer_free(state->dts_buffer);
-+ dtrace_buffer_free(state->dts_aggbuffer);
-+
-+ for (i = 0; i < nspec; i++)
-+ dtrace_buffer_free(spec[i].dtsp_buffer);
-+
-+ if (state->dts_cleaner != CYCLIC_NONE)
-+ cyclic_remove(state->dts_cleaner);
-+
-+ if (state->dts_deadman != CYCLIC_NONE)
-+ cyclic_remove(state->dts_deadman);
-+
-+ dtrace_dstate_fini(&vstate->dtvs_dynvars);
-+ dtrace_vstate_fini(vstate);
-+ vfree(state->dts_ecbs);
-+
-+ /*
-+ * If there were aggregations allocated, they should have been cleaned
-+ * up by now, so we can get rid of the idr.
-+ */
-+ idr_destroy(&state->dts_agg_idr);
-+
-+ vfree(state->dts_buffer);
-+ vfree(state->dts_aggbuffer);
-+
-+ for (i = 0; i < nspec; i++)
-+ vfree(spec[i].dtsp_buffer);
-+
-+ vfree(spec);
-+
-+ dtrace_format_destroy(state);
-+
-+ kfree(state);
-+}
-diff --git a/dtrace/dtrace_util.c b/dtrace/dtrace_util.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..76fdf2bd8b41d069de795b655ce1ea475aad81a2
---- /dev/null
-+++ b/dtrace/dtrace_util.c
-@@ -0,0 +1,282 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_util.c
-+ * DESCRIPTION: DTrace - utility functions
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/module.h>
-+#include <linux/vmalloc.h>
-+#include <asm/pgtable.h>
-+
-+#include "dtrace.h"
-+
-+int dtrace_isglob(const char *s)
-+{
-+ char c;
-+
-+ while ((c = *s++) != '\0') {
-+ if (c == '[' || c == '?' || c == '*' || c == '\\')
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_isglob);
-+
-+int dtrace_gmatch(const char *s, const char *p)
-+{
-+ const char *olds = s;
-+ char sc;
-+ char pc;
-+
-+ sc = *s++;
-+ pc = *p++;
-+
-+ if (!pc)
-+ return !sc;
-+
-+ switch (pc) {
-+ case '[': {
-+ int ok = 0;
-+ char lc = '\0';
-+ int inv = 0;
-+
-+ if (!sc)
-+ return 0;
-+
-+ if (*p == '!') {
-+ inv = 1;
-+ p++;
-+ }
-+
-+ pc = *p++;
-+ do {
-+ if (pc == '-' && lc && *p != ']') {
-+ pc = *p++;
-+ if (pc == '\\')
-+ pc = *p++;
-+
-+ if (inv) {
-+ if (sc < lc || sc > pc)
-+ ok++;
-+ else
-+ return 0;
-+ } else {
-+ if (lc <= sc && sc <= pc)
-+ ok++;
-+ }
-+ } else if (pc == '\\') {
-+ pc = *p++;
-+ }
-+
-+ lc = sc;
-+
-+ if (inv) {
-+ if (sc != lc)
-+ ok++;
-+ else
-+ return 0;
-+ } else {
-+ if (sc == lc)
-+ ok++;
-+ }
-+
-+ pc = *p++;
-+ } while (pc != ']');
-+
-+ return ok ? dtrace_gmatch(s, p) : 0;
-+ }
-+ case '\\':
-+ pc = *p++;
-+ if (!pc)
-+ return 0;
-+
-+ /* fall-through */
-+ default:
-+ if (pc != sc)
-+ return 0;
-+
-+ /* fall-through */
-+ case '?':
-+ return sc ? dtrace_gmatch(s, p) : 0;
-+ case '*':
-+ while (*p == '*')
-+ p++;
-+
-+ if (!*p)
-+ return 1;
-+
-+ s = olds;
-+ while (*s) {
-+ if (dtrace_gmatch(s, p))
-+ return 1;
-+
-+ s++;
-+ }
-+
-+ return 0;
-+ }
-+}
-+EXPORT_SYMBOL(dtrace_gmatch);
-+
-+int dtrace_badattr(const struct dtrace_attribute *a)
-+{
-+ return a->dtat_name > DTRACE_STABILITY_MAX ||
-+ a->dtat_data > DTRACE_STABILITY_MAX ||
-+ a->dtat_class > DTRACE_CLASS_MAX;
-+}
-+
-+/*
-+ * Allocate a chunk of virtual memory in kernel space, and zero it out. This
-+ * allocation might fail (which will report a backtrace in the kernel log, yet
-+ * it is harmless).
-+ */
-+void *dtrace_vzalloc_try(unsigned long size)
-+{
-+ return __vmalloc(size,
-+ GFP_NOWAIT | __GFP_FS | __GFP_IO | __GFP_NOMEMALLOC |
-+ __GFP_NORETRY | __GFP_NOWARN | __GFP_ZERO);
-+}
-+EXPORT_SYMBOL(dtrace_vzalloc_try);
-+
-+/*
-+ * Return a duplicate copy of a string. If the specified string is NULL, this
-+ * function returs a zero-length string.
-+ */
-+char *dtrace_strdup(const char *str)
-+{
-+ return kstrdup(str ? str : "", GFP_KERNEL);
-+}
-+
-+/*
-+ * Compare two strings using safe loads.
-+ */
-+int dtrace_strncmp(char *s1, char *s2, size_t limit)
-+{
-+ uint8_t c1, c2;
-+ volatile uint16_t *flags;
-+
-+ if (s1 == s2 || limit == 0)
-+ return 0;
-+
-+ flags = (volatile uint16_t *)&this_cpu_core->cpuc_dtrace_flags;
-+
-+ do {
-+ if (s1 == NULL)
-+ c1 = '\0';
-+ else
-+ c1 = dtrace_load8((uintptr_t)s1++);
-+
-+ if (s2 == NULL)
-+ c2 = '\0';
-+ else
-+ c2 = dtrace_load8((uintptr_t)s2++);
-+
-+ if (c1 != c2)
-+ return (c1 - c2);
-+ } while (--limit && c1 != '\0' && !(*flags & CPU_DTRACE_FAULT));
-+
-+ return 0;
-+}
-+
-+/*
-+ * Compute strlen(s) for a string using safe memory accesses. The additional
-+ * len parameter is used to specify a maximum length to ensure completion.
-+ */
-+size_t dtrace_strlen(const char *s, size_t lim)
-+{
-+ uint_t len;
-+
-+ for (len = 0; len != lim; len++) {
-+ if (dtrace_load8((uintptr_t)s++) == '\0')
-+ break;
-+ }
-+
-+ return len;
-+}
-+
-+#define DTRACE_ISALPHA(c) (((c) >= 'a' && (c) <= 'z') || \
-+ ((c) >= 'A' && (c) <= 'Z'))
-+int dtrace_badname(const char *s)
-+{
-+ char c;
-+
-+ if (s == NULL)
-+ return 0;
-+
-+ c = *s++;
-+ if (c == '\0')
-+ return 0;
-+
-+ if (!DTRACE_ISALPHA(c) && c != '-' && c != '_' && c != '.')
-+ return 1;
-+
-+ while ((c = *s++) != '\0') {
-+ if (!DTRACE_ISALPHA(c) && (c < '0' || c > '9') &&
-+ c != '-' && c != '_' && c != '.' && c != '`')
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+void dtrace_cred2priv(const struct cred *cr, uint32_t *privp, kuid_t *uidp)
-+{
-+#ifdef FIXME
-+/*
-+ * This should probably be rewritten based on capabilities in the struct cred.
-+ */
-+ uint32_t priv;
-+
-+ if (cr == NULL)
-+ priv = DTRACE_PRIV_ALL;
-+ else {
-+ const struct cred *lcr = get_cred(cr);
-+
-+ if (PRIV_POLICY_ONLY(lcr, PRIV_ALL, FALSE))
-+ priv = DTRACE_PRIV_ALL;
-+ else {
-+ *uidp = lcr->uid;
-+ priv = 0;
-+
-+ if (PRIV_POLICY_ONLY(lcr, PRIV_DTRACE_KERNEL, FALSE))
-+ priv |= DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER;
-+ else if (PRIV_POLICY_ONLY(lcr, PRIV_DTRACE_USER,
-+ FALSE))
-+ priv |= DTRACE_PRIV_USER;
-+
-+ if (PRIV_POLICY_ONLY(lcr, PRIV_DTRACE_PROC, FALSE))
-+ priv |= DTRACE_PRIV_PROC;
-+ if (PRIV_POLICY_ONLY(lcr, PRIV_PROC_OWNER, FALSE))
-+ priv |= DTRACE_PRIV_OWNER;
-+ }
-+
-+ put_cred(cr);
-+ }
-+
-+ *privp = priv;
-+#else
-+ *privp = DTRACE_PRIV_ALL;
-+
-+ if (cr != NULL) {
-+ const struct cred *lcr = get_cred(cr);
-+
-+ *uidp = lcr->uid;
-+ put_cred(cr);
-+ }
-+#endif
-+}
-+
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0006-dtrace-systrace-provider-core-components.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0006-dtrace-systrace-provider-core-components.patch
deleted file mode 100644
index 82a4f079a525..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0006-dtrace-systrace-provider-core-components.patch
+++ /dev/null
@@ -1,326 +0,0 @@
-From a71a23031f2c3ae2e9b4a560bf5ed11e6d237003 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 16:55:11 +0000
-Subject: [PATCH 06/19] dtrace: systrace provider core components
-
-This implements the core (linked-in) components of the DTrace systrace
-provider, which intercepts system call invocations. As previously,
-the arch-dependent pieces needed for x86 are also provided.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/entry/syscall_32.c | 4 +
- arch/x86/entry/syscall_64.c | 4 +
- arch/x86/include/asm/dtrace_syscall.h | 3 +
- arch/x86/include/asm/dtrace_syscall_types.h | 11 +++
- arch/x86/include/asm/syscall.h | 8 ++
- arch/x86/kernel/dtrace_syscall.c | 97 +++++++++++++++++++++
- arch/x86/kernel/dtrace_syscall_stubs.S | 0
- include/linux/dtrace_syscall.h | 60 +++++++++++++
- kernel/dtrace/Kconfig | 9 ++
- kernel/dtrace/Makefile | 1 +
- 10 files changed, 197 insertions(+)
- create mode 100644 arch/x86/include/asm/dtrace_syscall.h
- create mode 100644 arch/x86/include/asm/dtrace_syscall_types.h
- create mode 100644 arch/x86/kernel/dtrace_syscall.c
- create mode 100644 arch/x86/kernel/dtrace_syscall_stubs.S
- create mode 100644 include/linux/dtrace_syscall.h
-
-diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c
-index 86eb0d89d46fa5244b766272bc5d0fd6411588a3..66381ebd6a9f4628416dd40be15ccfa230b1c15a 100644
---- a/arch/x86/entry/syscall_32.c
-+++ b/arch/x86/entry/syscall_32.c
-@@ -15,7 +15,11 @@
-
- #define __SYSCALL_I386(nr, sym) [nr] = __ia32_##sym,
-
-+#if IS_ENABLED(CONFIG_DT_SYSTRACE)
-+__visible sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = {
-+#else
- __visible const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = {
-+#endif /* CONFIG_DT_SYSTRACE || CONFIG_DT_SYSTRACE_MODULE */
- /*
- * Smells like a compiler bug -- it doesn't work
- * when the & below is removed.
-diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
-index 1594ec72bcbb7183512f087acd29160443802683..42587831ef04e801399cf58e1068212d2d15e53e 100644
---- a/arch/x86/entry/syscall_64.c
-+++ b/arch/x86/entry/syscall_64.c
-@@ -17,7 +17,11 @@
-
- #define __SYSCALL_64(nr, sym) [nr] = __x64_##sym,
-
-+#if IS_ENABLED(CONFIG_DT_SYSTRACE)
-+asmlinkage sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
-+#else
- asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
-+#endif /* CONFIG_DT_SYSTRACE || CONFIG_DT_SYSTRACE_MODULE */
- /*
- * Smells like a compiler bug -- it doesn't work
- * when the & below is removed.
-diff --git a/arch/x86/include/asm/dtrace_syscall.h b/arch/x86/include/asm/dtrace_syscall.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..402826562478213976f122510d4082af23028fd3
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_syscall.h
-@@ -0,0 +1,3 @@
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-diff --git a/arch/x86/include/asm/dtrace_syscall_types.h b/arch/x86/include/asm/dtrace_syscall_types.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..2b3ee563ad143daab95cc6256e02e12ce15a4436
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_syscall_types.h
-@@ -0,0 +1,11 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/dtrace_types.h>
-+
-+typedef asmlinkage long (*dt_sys_call_t)(const struct pt_regs *regs);
-+
-+#define DTRACE_SYSCALL_WRAP_PREFIX "__x64_"
-diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
-index 7cbf733d11afd9fe150cbd8676065821a928d9ad..3d1bce850b7494381a2127bf526eab11ff7e5029 100644
---- a/arch/x86/include/asm/syscall.h
-+++ b/arch/x86/include/asm/syscall.h
-@@ -17,15 +17,23 @@
- #include <asm/unistd.h>
-
- typedef long (*sys_call_ptr_t)(const struct pt_regs *);
-+#if IS_ENABLED(CONFIG_DT_SYSTRACE)
-+extern sys_call_ptr_t sys_call_table[];
-+#else
- extern const sys_call_ptr_t sys_call_table[];
-+#endif
-
- #if defined(CONFIG_X86_32)
- #define ia32_sys_call_table sys_call_table
- #endif
-
- #if defined(CONFIG_IA32_EMULATION)
-+#if IS_ENABLED(CONFIG_DT_SYSTRACE)
-+extern sys_call_ptr_t ia32_sys_call_table[];
-+#else
- extern const sys_call_ptr_t ia32_sys_call_table[];
- #endif
-+#endif
-
- #ifdef CONFIG_X86_X32_ABI
- extern const sys_call_ptr_t x32_sys_call_table[];
-diff --git a/arch/x86/kernel/dtrace_syscall.c b/arch/x86/kernel/dtrace_syscall.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..3328710e7050714930851dc2bf3e5b1a2de32f5b
---- /dev/null
-+++ b/arch/x86/kernel/dtrace_syscall.c
-@@ -0,0 +1,97 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_syscall.c
-+ * DESCRIPTION: Dynamic Tracing: system call tracing support (arch-specific)
-+ *
-+ * Copyright (C) 2010-2018 Oracle Corporation
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_syscall.h>
-+#include <linux/fs.h>
-+#include <linux/module.h>
-+#include <linux/namei.h>
-+#include <linux/sched.h>
-+#include <asm/insn.h>
-+#include <asm/stacktrace.h>
-+#include <asm/syscalls.h>
-+
-+/*
-+ * SYSTEM CALL TRACING SUPPORT
-+ */
-+void (*systrace_probe)(dtrace_id_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t);
-+
-+void systrace_stub(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
-+ uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
-+ uintptr_t arg5, uintptr_t arg6)
-+{
-+}
-+
-+asmlinkage long systrace_syscall(const struct pt_regs *regs);
-+
-+asmlinkage long dtrace_stub_ptregs(uintptr_t, uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t);
-+
-+static struct systrace_info systrace_info =
-+{
-+ &systrace_probe,
-+ systrace_stub,
-+ systrace_syscall,
-+ {},
-+ {
-+#define __SYSCALL_64(nr, sym) [nr] { __stringify(sym), },
-+#define __SYSCALL_COMMON(nr, sym) __SYSCALL_64(nr, sym)
-+#define __SYSCALL_X32(nt, sym)
-+#include <asm/syscalls_64.h>
-+ }
-+};
-+
-+asmlinkage long systrace_syscall(const struct pt_regs *regs)
-+{
-+ long rc = 0;
-+ unsigned long sysnum;
-+ dtrace_id_t id;
-+ struct dtrace_syscalls *sc;
-+
-+ sysnum = syscall_get_nr(current, (struct pt_regs *) regs);
-+ sc = &systrace_info.sysent[sysnum];
-+
-+ /*
-+ * Note: 64-bit syscall-specific.
-+ */
-+ id = sc->stsy_entry;
-+ if (id != DTRACE_IDNONE)
-+ (*systrace_probe)(id, regs->di, regs->si, regs->dx,
-+ regs->r10, regs->r8, regs->r9, 0);
-+
-+ /*
-+ * FIXME: Add stop functionality for DTrace.
-+ */
-+
-+ if (sc->stsy_underlying != NULL)
-+ rc = (*sc->stsy_underlying)(regs);
-+
-+ id = sc->stsy_return;
-+ if (id != DTRACE_IDNONE)
-+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
-+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0, 0);
-+
-+ return rc;
-+}
-+
-+struct systrace_info *dtrace_syscalls_init(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < NR_syscalls; i++) {
-+ systrace_info.sysent[i].stsy_tblent =
-+ (dt_sys_call_t *)&sys_call_table[i];
-+ systrace_info.sysent[i].stsy_underlying =
-+ (dt_sys_call_t)sys_call_table[i];
-+ }
-+
-+ return &systrace_info;
-+}
-+EXPORT_SYMBOL(dtrace_syscalls_init);
-diff --git a/arch/x86/kernel/dtrace_syscall_stubs.S b/arch/x86/kernel/dtrace_syscall_stubs.S
-new file mode 100644
-index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
-diff --git a/include/linux/dtrace_syscall.h b/include/linux/dtrace_syscall.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..7f9e351f3783ec92d36c6984233723f95cdbcaa7
---- /dev/null
-+++ b/include/linux/dtrace_syscall.h
-@@ -0,0 +1,60 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_SYSCALL_H_
-+#define _LINUX_DTRACE_SYSCALL_H_
-+
-+#include <linux/types.h>
-+#include <linux/dtrace_os.h>
-+#include <asm/syscall.h>
-+
-+#define DTRACE_SYSCALL_STUB(t, n) SCE_##t,
-+enum dtrace_sce_id {
-+ SCE_NONE = 0,
-+#include <asm/dtrace_syscall.h>
-+ SCE_nr_stubs
-+};
-+#undef DTRACE_SYSCALL_STUB
-+
-+#define DTRACE_SYSCALL_STUB(t, n) \
-+ asmlinkage long dtrace_stub_##n(uintptr_t, uintptr_t, uintptr_t, \
-+ uintptr_t, uintptr_t, uintptr_t, \
-+ uintptr_t);
-+#include <asm/dtrace_syscall.h>
-+#undef DTRACE_SYSCALL_STUB
-+
-+#ifndef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
-+typedef asmlinkage long (*dt_sys_call_t)(uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t);
-+
-+#define DTRACE_SYSCALL_WRAP_PREFIX ""
-+#else
-+#include <asm/dtrace_syscall_types.h>
-+#endif
-+
-+struct dtrace_syscalls {
-+ const char *name;
-+ dtrace_id_t stsy_entry;
-+ dtrace_id_t stsy_return;
-+ dt_sys_call_t stsy_underlying;
-+ dt_sys_call_t *stsy_tblent;
-+};
-+
-+typedef void (*dtrace_systrace_probe_t)(dtrace_id_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t);
-+
-+struct systrace_info {
-+ dtrace_systrace_probe_t *probep;
-+ dtrace_systrace_probe_t stub;
-+ dt_sys_call_t syscall;
-+ dt_sys_call_t stubs[SCE_nr_stubs];
-+ struct dtrace_syscalls sysent[NR_syscalls];
-+};
-+
-+extern struct systrace_info *dtrace_syscalls_init(void);
-+
-+#endif /* _LINUX_DTRACE_SYSCALL_H_ */
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-index 854e4411343f9f7c773bf7fd54349fa46e6de5cb..d04ca0ab7ac9c14f4450927423b30784311a3cbd 100644
---- a/kernel/dtrace/Kconfig
-+++ b/kernel/dtrace/Kconfig
-@@ -23,6 +23,15 @@ config DT_CORE
-
- if DT_CORE
-
-+config DT_SYSTRACE
-+ tristate "System Call Tracing"
-+ default m
-+ select FTRACE
-+ select FTRACE_SYSCALLS
-+ help
-+ Provides DTrace probes at the entry and exit of all system calls,
-+ in the syscall provider.
-+
- config DT_DT_TEST
- tristate "DTrace Test Probe"
- default m
-diff --git a/kernel/dtrace/Makefile b/kernel/dtrace/Makefile
-index 872785327c3d8d9f1ec0e5555b86fd470e9d1fc2..68fc3861e5d1175006494f12758ff1f0304d10fa 100644
---- a/kernel/dtrace/Makefile
-+++ b/kernel/dtrace/Makefile
-@@ -3,6 +3,7 @@
- #
-
- DT_CORE_ARCH_OBJS = $(addprefix ../../arch/$(SRCARCH)/kernel/, \
-+ dtrace_syscall.o dtrace_syscall_stubs.o \
- dtrace_util.o)
-
- ifdef CONFIG_DT_CORE
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0007-dtrace-systrace-provider.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0007-dtrace-systrace-provider.patch
deleted file mode 100644
index 77058c80bbe1..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0007-dtrace-systrace-provider.patch
+++ /dev/null
@@ -1,374 +0,0 @@
-From 5d684eeadb4a16c417cfc365180a4b6a9364866f Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 17:58:09 +0000
-Subject: [PATCH 07/19] dtrace: systrace provider
-
-This implements the DTrace systrace provider, which intercepts system
-call invocations.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- dtrace/Makefile | 2 +
- dtrace/systrace.h | 33 +++++++
- dtrace/systrace_dev.c | 224 ++++++++++++++++++++++++++++++++++++++++++
- dtrace/systrace_mod.c | 52 ++++++++++
- 4 files changed, 311 insertions(+)
- create mode 100644 dtrace/systrace.h
- create mode 100644 dtrace/systrace_dev.c
- create mode 100644 dtrace/systrace_mod.c
-
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-index 36a4b97b922c4d2baecb0679e41b2d384f56a5b5..b91bc69d38020d8c872483f894349f02a8eb58e6 100644
---- a/dtrace/Makefile
-+++ b/dtrace/Makefile
-@@ -3,6 +3,7 @@
- #
-
- obj-$(CONFIG_DT_CORE) += dtrace.o
-+obj-$(CONFIG_DT_SYSTRACE) += systrace.o
- obj-$(CONFIG_DT_DT_TEST) += dt_test.o
-
- dtrace-y := dtrace_mod.o dtrace_dev.o \
-@@ -14,6 +15,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \
- dtrace_probe.o dtrace_probe_ctx.o \
- dtrace_ptofapi.o dtrace_predicate.o \
- dtrace_spec.o dtrace_state.o dtrace_util.o
-+systrace-y := systrace_mod.o systrace_dev.o
- dt_test-y := dt_test_mod.o dt_test_dev.o
-
- -include arch/$(SRCARCH)/dtrace/Makefile.arch
-diff --git a/dtrace/systrace.h b/dtrace/systrace.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..832bc613b966c5ecaf53f8c4b602306ccc955d73
---- /dev/null
-+++ b/dtrace/systrace.h
-@@ -0,0 +1,33 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - syscall tracing provider
-+ *
-+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _SYSTRACE_H_
-+#define _SYSTRACE_H_
-+
-+#include "dtrace.h"
-+
-+extern void systrace_provide(void *, const struct dtrace_probedesc *);
-+extern int systrace_enable(void *arg, dtrace_id_t, void *);
-+extern void systrace_disable(void *arg, dtrace_id_t, void *);
-+extern void systrace_destroy(void *, dtrace_id_t, void *);
-+
-+extern dtrace_provider_id_t syscall_id;
-+
-+extern int syscall_dev_init(void);
-+extern void syscall_dev_exit(void);
-+
-+#endif /* _SYSTRACE_H_ */
-diff --git a/dtrace/systrace_dev.c b/dtrace/systrace_dev.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..2ff3ba4329a524ba9ad2687da2e83260475b37da
---- /dev/null
-+++ b/dtrace/systrace_dev.c
-@@ -0,0 +1,224 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: systrace_dev.c
-+ * DESCRIPTION: DTrace - systrace provider device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_syscall.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <asm/unistd.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "systrace.h"
-+
-+#define SYSTRACE_ARTIFICIAL_FRAMES 1
-+
-+#define SYSTRACE_SHIFT 16
-+#define SYSTRACE_ENTRY(id) ((1 << SYSTRACE_SHIFT) | (id))
-+#define SYSTRACE_RETURN(id) (id)
-+#define SYSTRACE_SYSNUM(x) ((int)(x) & ((1 << SYSTRACE_SHIFT) - 1))
-+#define SYSTRACE_ISENTRY(x) ((int)(x) >> SYSTRACE_SHIFT)
-+
-+#if ((1 << SYSTRACE_SHIFT) <= NR_syscalls)
-+# error 1 << SYSTRACE_SHIFT must exceed number of system calls
-+#endif
-+
-+static struct systrace_info *systrace_info;
-+
-+void systrace_provide(void *arg, const struct dtrace_probedesc *desc)
-+{
-+ int failed_count = 0;
-+ int i;
-+
-+ ASSERT(systrace_info != NULL);
-+
-+ if (desc != NULL)
-+ return;
-+
-+ for (i = 0; i < NR_syscalls; i++) {
-+ const char *nm = systrace_info->sysent[i].name;
-+ dtrace_id_t id;
-+ int sz;
-+ size_t wrap_len;
-+
-+ if (nm == NULL)
-+ continue;
-+
-+ if (systrace_info->sysent[i].stsy_underlying == NULL)
-+ continue;
-+
-+ wrap_len = strlen(DTRACE_SYSCALL_WRAP_PREFIX);
-+ sz = strlen(nm);
-+ if (sz > wrap_len &&
-+ memcmp(nm, DTRACE_SYSCALL_WRAP_PREFIX, wrap_len) == 0) {
-+ nm += wrap_len;
-+ sz -= wrap_len;
-+ }
-+ if (sz > 4 && memcmp(nm, "sys_", 4) == 0)
-+ nm += 4;
-+ else if (sz > 5 && memcmp(nm, "stub_", 5) == 0)
-+ nm += 5;
-+
-+ id = dtrace_probe_lookup(syscall_id, dtrace_kmod->name, nm,
-+ "entry");
-+ if (id == DTRACE_IDNONE) {
-+ id = dtrace_probe_create(syscall_id, dtrace_kmod->name,
-+ nm, "entry",
-+ SYSTRACE_ARTIFICIAL_FRAMES,
-+ (void *)((uintptr_t)SYSTRACE_ENTRY(i)));
-+ if (id == DTRACE_IDNONE)
-+ failed_count++;
-+
-+ systrace_info->sysent[i].stsy_entry = DTRACE_IDNONE;
-+ }
-+
-+ id = dtrace_probe_lookup(syscall_id, dtrace_kmod->name, nm,
-+ "return");
-+ if (id == DTRACE_IDNONE) {
-+ id = dtrace_probe_create(syscall_id, dtrace_kmod->name,
-+ nm, "return",
-+ SYSTRACE_ARTIFICIAL_FRAMES,
-+ (void *)((uintptr_t)SYSTRACE_RETURN(i)));
-+ if (id == DTRACE_IDNONE)
-+ failed_count++;
-+
-+ systrace_info->sysent[i].stsy_return = DTRACE_IDNONE;
-+ }
-+ }
-+
-+ if (failed_count > 0)
-+ pr_warn("systrace: Failed to provide %d probes (out of memory)\n", failed_count);
-+}
-+
-+static dt_sys_call_t get_intercept(int sysnum)
-+{
-+ switch (sysnum) {
-+ default:
-+ return systrace_info->syscall;
-+#define DTRACE_SYSCALL_STUB(t, n) \
-+ case __NR_##n: \
-+ return systrace_info->stubs[SCE_##t];
-+#include <asm/dtrace_syscall.h>
-+#undef DTRACE_SYSCALL_STUB
-+ }
-+}
-+
-+int systrace_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
-+ struct dtrace_syscalls *sc = &systrace_info->sysent[sysnum];
-+ int enabled = sc->stsy_entry != DTRACE_IDNONE ||
-+ sc->stsy_return != DTRACE_IDNONE;
-+ dt_sys_call_t intercept = get_intercept(sysnum);
-+
-+ if (!enabled) {
-+ if (cmpxchg(sc->stsy_tblent, sc->stsy_underlying,
-+ intercept) != sc->stsy_underlying)
-+ return 1;
-+ } else
-+ ASSERT(*sc->stsy_tblent == intercept);
-+
-+ if (SYSTRACE_ISENTRY((uintptr_t)parg))
-+ sc->stsy_entry = id;
-+ else
-+ sc->stsy_return = id;
-+
-+ return 0;
-+}
-+
-+void systrace_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
-+ struct dtrace_syscalls *sc = &systrace_info->sysent[sysnum];
-+ int enabled =
-+ (sc->stsy_entry != DTRACE_IDNONE ? 1 : 0) +
-+ (sc->stsy_return != DTRACE_IDNONE ? 1 : 0);
-+ dt_sys_call_t intercept = get_intercept(sysnum);
-+
-+ /*
-+ * Every syscall can have 2 probes associated with it. We need to keep
-+ * the interceptor in place until the last probe is getting disabled.
-+ */
-+ if (enabled == 1)
-+ (void)cmpxchg(sc->stsy_tblent, intercept, sc->stsy_underlying);
-+
-+ if (SYSTRACE_ISENTRY((uintptr_t)parg))
-+ sc->stsy_entry = DTRACE_IDNONE;
-+ else
-+ sc->stsy_return = DTRACE_IDNONE;
-+}
-+
-+void systrace_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+ int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
-+
-+ /*
-+ * Nothing to be done here - just ensure our probe has been disabled.
-+ */
-+ if (SYSTRACE_ISENTRY((uintptr_t)parg))
-+ ASSERT(systrace_info->sysent[sysnum].stsy_entry ==
-+ DTRACE_IDNONE);
-+ else
-+ ASSERT(systrace_info->sysent[sysnum].stsy_return ==
-+ DTRACE_IDNONE);
-+}
-+
-+static int systrace_open(struct inode *inode, struct file *file)
-+{
-+ return -EAGAIN;
-+}
-+
-+static int systrace_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations systrace_fops = {
-+ .owner = THIS_MODULE,
-+ .open = systrace_open,
-+ .release = systrace_close,
-+};
-+
-+static struct miscdevice systrace_dev = {
-+ .minor = DT_DEV_SYSTRACE_MINOR,
-+ .name = "systrace",
-+ .nodename = "dtrace/provider/systrace",
-+ .fops = &systrace_fops,
-+};
-+
-+int syscall_dev_init(void)
-+{
-+ int ret = 0;
-+
-+ systrace_info = dtrace_syscalls_init();
-+
-+ ret = misc_register(&systrace_dev);
-+ if (ret)
-+ pr_err("%s: Can't register misc device %d\n",
-+ systrace_dev.name, systrace_dev.minor);
-+
-+ *(systrace_info->probep) = (dtrace_systrace_probe_t)dtrace_probe;
-+
-+ return ret;
-+}
-+
-+void syscall_dev_exit(void)
-+{
-+ *(systrace_info->probep) = systrace_info->stub;
-+
-+ misc_deregister(&systrace_dev);
-+}
-diff --git a/dtrace/systrace_mod.c b/dtrace/systrace_mod.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..d286f7d9d47aba259de63da3b0391a4f0075906c
---- /dev/null
-+++ b/dtrace/systrace_mod.c
-@@ -0,0 +1,52 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: systrace_mod.c
-+ * DESCRIPTION: DTrace - systrace provider kernel module
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "systrace.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("System Call Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+static const struct dtrace_pattr syscall_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pops syscall_pops = {
-+ .dtps_provide = systrace_provide,
-+ .dtps_provide_module = NULL,
-+ .dtps_destroy_module = NULL,
-+ .dtps_enable = systrace_enable,
-+ .dtps_disable = systrace_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = NULL,
-+ .dtps_getargval = NULL,
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = systrace_destroy
-+};
-+
-+DT_PROVIDER_MODULE(syscall, DTRACE_PRIV_USER)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0008-dtrace-sdt-provider-core-components.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0008-dtrace-sdt-provider-core-components.patch
deleted file mode 100644
index f2045b15e4d8..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0008-dtrace-sdt-provider-core-components.patch
+++ /dev/null
@@ -1,3112 +0,0 @@
-From 0bf2a2a85df13740247a26e7b217f39eda237b0c Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 22:03:10 +0000
-Subject: [PATCH 08/19] dtrace: sdt provider core components
-
-This implements the core (linked-in) machinery needed for SDT
-tracepoints:
-
- - generate empty stub function calls __dtrace_probe_* for each probe
- point and perf-event probe point, and record their section-relative
- offset in tables in special symbols in the output; calls to
- is-enabling probes (conditionals of the form
- if (DTRACE_FOO_ENABLED(probe-name))) are translated as well
- - similarly record the names and types of arguments to probes in
- special sections
- - parse both of these at load time, and substitute in nops over the top
- of the stub functions, remembering their locations: is-enabled probes
- get 0-returns patched over the top
- - on probe enabling, patch invalid-operation traps over the top of
- those stub functions; handle these by calling the probe, then return
- as if the trap had never happened
-
-The provider module itself is added in the next commit.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- .gitignore | 6 +
- Makefile | 1 +
- arch/x86/dtrace/include/dtrace/sdt_arch.h | 28 ++
- arch/x86/include/asm/dtrace_arch.h | 8 +-
- arch/x86/include/asm/dtrace_sdt_arch.h | 11 +
- arch/x86/include/asm/dtrace_util.h | 13 +
- arch/x86/include/asm/spinlock.h | 1 +
- arch/x86/include/asm/text-patching.h | 1 +
- arch/x86/kernel/alternative.c | 2 +-
- arch/x86/kernel/dtrace_sdt.c | 76 +++
- arch/x86/kernel/dtrace_util.c | 214 +++++++-
- arch/x86/kernel/vmlinux.lds.S | 3 +-
- include/asm-generic/vmlinux.lds.h | 16 +
- include/linux/dtrace_os.h | 3 +
- include/linux/dtrace_sdt.h | 32 ++
- include/linux/module.h | 5 +
- include/linux/sdt.h | 191 +++++++
- include/linux/sdt_internal.h | 276 ++++++++++
- include/linux/tracepoint.h | 8 +-
- kernel/dtrace/Kconfig | 16 +
- kernel/dtrace/Makefile | 3 +-
- kernel/dtrace/dtrace_os.c | 83 +++
- kernel/dtrace/dtrace_sdt_core.c | 364 ++++++++++++++
- kernel/module.c | 14 +
- scripts/.gitignore | 1 +
- scripts/Makefile | 6 +
- scripts/Makefile.modfinal | 52 +-
- scripts/dtrace_sdt.sh | 588 ++++++++++++++++++++++
- scripts/kmodsdt.c | 410 +++++++++++++++
- scripts/link-vmlinux.sh | 69 ++-
- scripts/mod/modpost.c | 19 +-
- 31 files changed, 2500 insertions(+), 20 deletions(-)
- create mode 100644 arch/x86/dtrace/include/dtrace/sdt_arch.h
- create mode 100644 arch/x86/include/asm/dtrace_sdt_arch.h
- create mode 100644 arch/x86/kernel/dtrace_sdt.c
- create mode 100644 include/linux/dtrace_sdt.h
- create mode 100644 include/linux/sdt.h
- create mode 100644 include/linux/sdt_internal.h
- create mode 100644 kernel/dtrace/dtrace_sdt_core.c
- create mode 100755 scripts/dtrace_sdt.sh
- create mode 100644 scripts/kmodsdt.c
-
-diff --git a/.gitignore b/.gitignore
-index 1c10cd7ce03399a97367d56dbefd66dea1823859..13954b4624a9009197acbd538f654dbdf54affde 100644
---- a/.gitignore
-+++ b/.gitignore
-@@ -158,3 +158,9 @@ x509.genkey
-
- # Documentation toolchain
- sphinx_*/
-+#
-+# Generated DTrace SDT files
-+#
-+*.sdtinfo.c
-+*.sdtinfo.h
-+*.sdtstub.S
-diff --git a/Makefile b/Makefile
-index 4b25be692ac15ae9f6eb52c4a5f135da70598b05..e3f113b646818a2250cb6a14203b12e3b38ce26c 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1883,6 +1883,7 @@ clean: $(clean-dirs)
- -o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \
- -o -name '*.dwo' -o -name '*.lst' \
- -o -name '*.su' -o -name '*.mod' \
-+ -o -name '*.sdtinfo.c' -o -name '*.sdtinfo.h' -o -name '*.sdtstub.S' \
- -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
- -o -name '*.lex.c' -o -name '*.tab.[ch]' \
- -o -name '*.asn1.[ch]' \
-diff --git a/arch/x86/dtrace/include/dtrace/sdt_arch.h b/arch/x86/dtrace/include/dtrace/sdt_arch.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..d8616b44079b57f41466cea603ecc7b9be0d13e6
---- /dev/null
-+++ b/arch/x86/dtrace/include/dtrace/sdt_arch.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - SDT Implementation defines
-+ *
-+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _X86_64_SDT_ARCH_H
-+#define _X86_64_SDT_ARCH_H
-+
-+#define SDT_AFRAMES 4
-+
-+#endif /* _X86_64_SDT_ARCH_H */
-diff --git a/arch/x86/include/asm/dtrace_arch.h b/arch/x86/include/asm/dtrace_arch.h
-index 74e27f08a873c9cd3ed329d911e8e18505ae5b62..88beb8e4db0b545085974560a9383a703bb5a790 100644
---- a/arch/x86/include/asm/dtrace_arch.h
-+++ b/arch/x86/include/asm/dtrace_arch.h
-@@ -12,16 +12,22 @@
-
- typedef uint8_t asm_instr_t;
-
-+#define ASM_CALL_SIZE 5
-+
- typedef int (*prov_exit_f)(void);
-
- /*
- * Structure to hold DTrace specific information about modules (including the
- * core kernel module). Note that each module (and the main kernel) already
-- * has one field that relates to probing:
-+ * has three fields that relate to probing:
-+ * - sdt_probes: description of SDT probes in the module
-+ * - sdt_probec: number of SDT probes in the module
- * - pdata: pointer to a dtrace_module struct (for DTrace)
- */
- struct dtrace_module {
- int enabled_cnt;
-+ size_t sdt_probe_cnt;
-+ size_t fbt_probe_cnt;
- prov_exit_f prov_exit; /* Called with module_mutex held */
- };
-
-diff --git a/arch/x86/include/asm/dtrace_sdt_arch.h b/arch/x86/include/asm/dtrace_sdt_arch.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..59f57cb489abd5499bdf3a1ab5961181623aa789
---- /dev/null
-+++ b/arch/x86/include/asm/dtrace_sdt_arch.h
-@@ -0,0 +1,11 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/* Copyright (C) 2016 Oracle, Inc. */
-+
-+#ifndef _X86_DTRACE_SDT_ARCH_H
-+#define _X86_DTRACE_SDT_ARCH_H
-+
-+#define __DTRACE_SDT_ISENABLED_PROTO void
-+#define __DTRACE_SDT_ISENABLED_ARGS
-+
-+#endif /* _X86_DTRACE_SDT_ARCH_H */
-diff --git a/arch/x86/include/asm/dtrace_util.h b/arch/x86/include/asm/dtrace_util.h
-index 4d9843bbc95b92dcc3c20d4aa1d2b762b7376d91..ce28bf42a59daeeb9070a42c37e98cb5519ad814 100644
---- a/arch/x86/include/asm/dtrace_util.h
-+++ b/arch/x86/include/asm/dtrace_util.h
-@@ -6,11 +6,24 @@
- #ifndef _X86_DTRACE_UTIL_H
- #define _X86_DTRACE_UTIL_H
-
-+#define DTRACE_INVOP_NOPS 0x0f /* 5-byte NOP sequence */
-+#define DTRACE_INVOP_MOV_RSP_RBP 0x48 /* mov %rsp, %rbp = 48 89 e5 */
-+#define DTRACE_INVOP_PUSH_BP 0x55 /* push %rbp = 55 */
-+#define DTRACE_INVOP_NOP 0x90 /* nop = 90 */
-+#define DTRACE_INVOP_LEAVE 0xc9 /* leave = c9 */
-+#define DTRACE_INVOP_RET 0xc3 /* ret = c3 */
-+
- #ifndef __ASSEMBLY__
-
- #include <asm/dtrace_arch.h>
- #include <asm/ptrace.h>
-
-+extern int dtrace_invop_add(uint8_t (*func)(struct pt_regs *));
-+extern void dtrace_invop_remove(uint8_t (*func)(struct pt_regs *));
-+
-+extern void dtrace_invop_enable(asm_instr_t *, asm_instr_t);
-+extern void dtrace_invop_disable(asm_instr_t *, asm_instr_t);
-+
- #endif
-
- #endif /* _X86_DTRACE_UTIL_H */
-diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
-index 5b6bc7016c223e7496fc2645ae8b3434ef83b96b..79e017f90c6040c6927ab0f2485ba45b0401b1bd 100644
---- a/arch/x86/include/asm/spinlock.h
-+++ b/arch/x86/include/asm/spinlock.h
-@@ -9,6 +9,7 @@
- #include <linux/compiler.h>
- #include <asm/paravirt.h>
- #include <asm/bitops.h>
-+#include <linux/sdt.h>
-
- /*
- * Your basic SMP spinlocks, allowing only a single CPU anywhere
-diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
-index b7421780e4e92959689646cb425485c9deeabfc3..127a59c41e6d51f4bea3297403e9481e923955e4 100644
---- a/arch/x86/include/asm/text-patching.h
-+++ b/arch/x86/include/asm/text-patching.h
-@@ -25,6 +25,7 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
- */
- #define POKE_MAX_OPCODE_SIZE 5
-
-+extern void add_nops(void *insns, unsigned int len);
- extern void text_poke_early(void *addr, const void *opcode, size_t len);
-
- /*
-diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
-index 2400ad62f330b9f518b3bcfa3462f5fd2e659e78..389c3870ce48534b92c76d3b9fce606394755160 100644
---- a/arch/x86/kernel/alternative.c
-+++ b/arch/x86/kernel/alternative.c
-@@ -256,7 +256,7 @@ void __init arch_init_ideal_nops(void)
- }
-
- /* Use this to add nops to a buffer, then text_poke the whole buffer. */
--static void __init_or_module add_nops(void *insns, unsigned int len)
-+void __init_or_module add_nops(void *insns, unsigned int len)
- {
- while (len > 0) {
- unsigned int noplen = len;
-diff --git a/arch/x86/kernel/dtrace_sdt.c b/arch/x86/kernel/dtrace_sdt.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..31bb962573fb15443a2e5d4a7fbb0516cad29262
---- /dev/null
-+++ b/arch/x86/kernel/dtrace_sdt.c
-@@ -0,0 +1,76 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_sdt.c
-+ * DESCRIPTION: Dynamic Tracing: SDT registration code (arch-specific)
-+ *
-+ * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/memory.h>
-+#include <linux/module.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/sdt.h>
-+#include <linux/slab.h>
-+#include <linux/sync_core.h>
-+#include <linux/vmalloc.h>
-+#include <asm/nmi.h>
-+#include <asm/nops.h>
-+#include <asm/dtrace_arch.h>
-+#include <asm/text-patching.h>
-+
-+static uint8_t nops[ASM_CALL_SIZE];
-+static uint8_t movs[ASM_CALL_SIZE];
-+
-+#define DT_OP_REX_RAX 0x48
-+#define DT_OP_XOR_EAX_0 0x33
-+#define DT_OP_XOR_EAX_1 0xc0
-+
-+/* This code is based on apply_alternatives and text_poke_early. It needs to
-+ * run before SMP is initialized in order to avoid SMP problems with patching
-+ * code that might be accessed on another CPU.
-+ */
-+void __init_or_module dtrace_sdt_nop_multi(asm_instr_t **addrs,
-+ int *is_enabled, int cnt)
-+{
-+ int i;
-+ asm_instr_t *addr;
-+ unsigned long flags;
-+
-+ stop_nmi();
-+ local_irq_save(flags);
-+
-+ for (i = 0; i < cnt; i++) {
-+ addr = addrs[i];
-+ if (likely(!is_enabled[i]))
-+ memcpy(addr, nops, sizeof(nops));
-+ else
-+ memcpy(addr, movs, sizeof(movs));
-+ }
-+
-+ sync_core();
-+ local_irq_restore(flags);
-+ restart_nmi();
-+}
-+
-+void __init dtrace_sdt_init_arch(void)
-+{
-+ /*
-+ * A little unusual, but potentially necessary. While we could use a
-+ * single NOP sequence of length ASM_CALL_SIZE, we need to consider the
-+ * fact that when a SDT probe point is enabled, a single invalid opcode
-+ * is written on the first byte of this NOP sequence. By using a
-+ * sequence of a 1-byte NOP, followed by a (ASM_CALL_SIZE - 1) byte NOP
-+ * sequence, we play it pretty safe.
-+ */
-+ add_nops(nops, 1);
-+ add_nops(nops + 1, ASM_CALL_SIZE - 1);
-+
-+ /*
-+ * Is-enabled probe points contain an "xor %rax, %rax" when disabled.
-+ */
-+ movs[0] = DT_OP_REX_RAX;
-+ movs[1] = DT_OP_XOR_EAX_0;
-+ movs[2] = DT_OP_XOR_EAX_1;
-+ add_nops(movs + 3, ASM_CALL_SIZE - 3);
-+}
-diff --git a/arch/x86/kernel/dtrace_util.c b/arch/x86/kernel/dtrace_util.c
-index d3d552c062f7ea425567cdb867b31f65d0242cac..f138fd62f555c8d6b3599287b18846fe8017db53 100644
---- a/arch/x86/kernel/dtrace_util.c
-+++ b/arch/x86/kernel/dtrace_util.c
-@@ -61,6 +61,13 @@ void dtrace_handle_badaddr(struct pt_regs *regs)
- dtrace_skip_instruction(regs);
- }
-
-+struct dtrace_invop_hdlr {
-+ uint8_t (*dtih_func)(struct pt_regs *);
-+ struct dtrace_invop_hdlr *dtih_next;
-+};
-+
-+static struct dtrace_invop_hdlr *dtrace_invop_hdlrs;
-+
- /*
- * Trap notification handler.
- */
-@@ -68,6 +75,7 @@ int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
- void *args)
- {
- struct die_args *dargs = args;
-+ int orig_trapnr = 0;
-
- switch (val) {
- case DIE_PAGE_FAULT: {
-@@ -79,12 +87,141 @@ int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
- return NOTIFY_OK | NOTIFY_STOP_MASK;
- }
- case DIE_GPF: {
-- if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
-+ /*
-+ * This gets messy... For one, some versions of Xen deliver
-+ * the invalid opcode generated by the LOCK prefix (0xf0) as a
-+ * GP fault rather than a UD fault. So, we need to figure out
-+ * whether the GP we're processing here is one of those
-+ * misreported faults.
-+ *
-+ * But, it is possible that the instruction that caused the
-+ * fault (0xf0) gets overwritten by a different CPU with the
-+ * original valid opcode before we get to look at it here,
-+ * which makes it kind of hard to recognize.
-+ *
-+ * So... we're going to assume that a GP fault that gets
-+ * triggered for the LOCK prefix opcode (0xf0) *or* for an
-+ * opcode that can get overwritten with the LOCK prefix for
-+ * probing is actually a UD fault.
-+ *
-+ * If we are wrong, the handlers will simply see a fault that
-+ * isn't theirs, and return without consuming it. And in that
-+ * case, the kernel will report a UD fault that may have been
-+ * a real GP fault... Sorry.
-+ */
-+ asm_instr_t opc = *(asm_instr_t *)dargs->regs->ip;
-+
-+ if (opc != 0xf0 && opc != 0x55 && opc != 0xc3) {
-+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
-+ return NOTIFY_DONE;
-+
-+ dtrace_handle_badaddr(dargs->regs);
-+
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ }
-+
-+ /*
-+ * ... and instead treat them as the SDT probe point traps that
-+ * they are.
-+ */
-+ orig_trapnr = dargs->trapnr;
-+ dargs->trapnr = 6;
-+ }
-+ /* fallthrough */
-+ case DIE_TRAP: {
-+ struct dtrace_invop_hdlr *hdlr;
-+ int rval = 0;
-+
-+ if (dargs->trapnr != 6)
- return NOTIFY_DONE;
-
-- dtrace_handle_badaddr(dargs->regs);
-+ for (hdlr = dtrace_invop_hdlrs; hdlr != NULL;
-+ hdlr = hdlr->dtih_next) {
-+ rval = hdlr->dtih_func(dargs->regs);
-+ if (rval != 0)
-+ break;
-+ }
-
-- return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ switch (rval) {
-+ case DTRACE_INVOP_NOPS:
-+ /*
-+ * SDT probe points are encoded as either:
-+ * - a 1-byte NOP followed by a multi-byte NOP
-+ * - a multi-byte code sequence (to set AX to 0),
-+ * followed by a multi-byte NOP
-+ * In both cases, the total length of the probe point
-+ * instruction is ASM_CALL_SITE bytes, so we can safely
-+ * skip that number of bytes here.
-+ */
-+ dargs->regs->ip += ASM_CALL_SIZE;
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ case DTRACE_INVOP_MOV_RSP_RBP:
-+ case DTRACE_INVOP_NOP:
-+ case DTRACE_INVOP_PUSH_BP:
-+ case DTRACE_INVOP_RET:
-+ return notifier_from_errno(-rval);
-+ default:
-+ /*
-+ * This must not have been a trap triggered from a
-+ * probe point. Let someone else deal with it...
-+ *
-+ * If we got here because of a GPF that we thought
-+ * was a UD (due to a bug in some versions of Xen),
-+ * undo our change to dargs->trapnr.
-+ */
-+ if (unlikely(orig_trapnr))
-+ dargs->trapnr = orig_trapnr;
-+
-+ return NOTIFY_DONE;
-+ }
-+ }
-+ case DIE_INT3: {
-+ struct dtrace_invop_hdlr *hdlr;
-+ int rval = 0;
-+
-+ /*
-+ * Let's assume that this is a DTrace probe firing, so we need
-+ * to adjust the IP (to be consistent with #UD processing) so
-+ * that it reflects the address of the #BP rather than the
-+ * following intruction.
-+ *
-+ * If it turns out that this was not DTrace related, we'll have
-+ * to reverse this adjustment.
-+ */
-+ dargs->regs->ip--;
-+ for (hdlr = dtrace_invop_hdlrs; hdlr != NULL;
-+ hdlr = hdlr->dtih_next) {
-+ rval = hdlr->dtih_func(dargs->regs);
-+ if (rval != 0)
-+ break;
-+ }
-+
-+ switch (rval) {
-+ case DTRACE_INVOP_NOPS:
-+ /*
-+ * SDT probe points are encoded as either:
-+ * - a 1-byte NOP followed by a multi-byte NOP
-+ * - a multi-byte code sequence (to set AX to 0),
-+ * followed by a multi-byte NOP
-+ * In both cases, the total length of the probe point
-+ * instruction is ASM_CALL_SITE bytes, so we can safely
-+ * skip that number of bytes here.
-+ */
-+ dargs->regs->ip += ASM_CALL_SIZE;
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ case DTRACE_INVOP_MOV_RSP_RBP:
-+ case DTRACE_INVOP_NOP:
-+ case DTRACE_INVOP_PUSH_BP:
-+ case DTRACE_INVOP_RET:
-+ return notifier_from_errno(-rval);
-+ default:
-+ /*
-+ * This must not have been a trap triggered from a
-+ * probe point. Re-adjust the instruction pointer
-+ * and let someone else deal with it...
-+ */
-+ dargs->regs->ip++;
-+ }
- }
- /* fallthrough */
- default:
-@@ -92,6 +229,77 @@ int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
- }
- }
-
-+/*
-+ * Add an INVOP trap handler.
-+ */
-+int dtrace_invop_add(uint8_t (*func)(struct pt_regs *))
-+{
-+ struct dtrace_invop_hdlr *hdlr;
-+
-+ hdlr = kmalloc(sizeof(struct dtrace_invop_hdlr), GFP_KERNEL);
-+ if (hdlr == NULL) {
-+ pr_warn("Failed to add invop handler: out of memory\n");
-+ return -ENOMEM;
-+ }
-+
-+ hdlr->dtih_func = func;
-+ hdlr->dtih_next = dtrace_invop_hdlrs;
-+ dtrace_invop_hdlrs = hdlr;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_invop_add);
-+
-+/*
-+ * Remove an INVOP trap handler.
-+ */
-+void dtrace_invop_remove(uint8_t (*func)(struct pt_regs *))
-+{
-+ struct dtrace_invop_hdlr *hdlr = dtrace_invop_hdlrs, *prev = NULL;
-+
-+ for (;;) {
-+ if (hdlr == NULL)
-+ return;
-+
-+ if (hdlr->dtih_func == func)
-+ break;
-+
-+ prev = hdlr;
-+ hdlr = hdlr->dtih_next;
-+ }
-+
-+ if (prev == NULL)
-+ dtrace_invop_hdlrs = hdlr->dtih_next;
-+ else
-+ prev->dtih_next = hdlr->dtih_next;
-+
-+ kfree(hdlr);
-+}
-+EXPORT_SYMBOL(dtrace_invop_remove);
-+
-+/*
-+ * Enable an INVOP-based probe, i.e. ensure that an INVOP trap is triggered at
-+ * the specified address.
-+ */
-+void dtrace_invop_enable(asm_instr_t *addr, asm_instr_t opcode)
-+{
-+ mutex_lock(&text_mutex);
-+ text_poke(addr, ((unsigned char []){opcode}), 1);
-+ mutex_unlock(&text_mutex);
-+}
-+EXPORT_SYMBOL(dtrace_invop_enable);
-+
-+/*
-+ * Disable an INVOP-based probe.
-+ */
-+void dtrace_invop_disable(asm_instr_t *addr, asm_instr_t opcode)
-+{
-+ mutex_lock(&text_mutex);
-+ text_poke(addr, ((unsigned char []){opcode}), 1);
-+ mutex_unlock(&text_mutex);
-+}
-+EXPORT_SYMBOL(dtrace_invop_disable);
-+
- static inline int dtrace_bad_address(void *addr)
- {
- unsigned long dummy;
-diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
-index bf9e0adb5b7ec25fd078fcf85f4c2c38f409175d..970b6cd011f69e33dcefeb4e5efa4214ab32467f 100644
---- a/arch/x86/kernel/vmlinux.lds.S
-+++ b/arch/x86/kernel/vmlinux.lds.S
-@@ -473,7 +473,8 @@ INIT_PER_CPU(irq_stack_backing_store);
- /*
- * Build-time check on the image size:
- */
--. = ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
-+. = ASSERT(((_end < _text) ? (_end < KERNEL_IMAGE_SIZE)
-+ : (_end - _text <= KERNEL_IMAGE_SIZE)),
- "kernel image bigger than KERNEL_IMAGE_SIZE");
-
- #ifdef CONFIG_SMP
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index b2b3d81b1535a5abbf6803f3dfbb29058a979bc4..7d1517f97db21f0821d5dedc866a40dc71865453 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -214,6 +214,20 @@
- #define ERROR_INJECT_WHITELIST()
- #endif
-
-+#ifdef CONFIG_DTRACE
-+#define DTRACE_SDT_NAMES() . = ALIGN(8); \
-+ __start_dtrace_sdt_names = .; \
-+ KEEP(*(_dtrace_sdt_names)) \
-+ __stop_dtrace_sdt_names = .;
-+#define DTRACE_SDT_ARGS() . = ALIGN(8); \
-+ __start_dtrace_sdt_args = .; \
-+ KEEP(*(_dtrace_sdt_args)) \
-+ __stop_dtrace_sdt_args = .;
-+#else
-+#define DTRACE_SDT_NAMES()
-+#define DTRACE_SDT_ARGS()
-+#endif
-+
- #ifdef CONFIG_EVENT_TRACING
- #define FTRACE_EVENTS() . = ALIGN(8); \
- __start_ftrace_events = .; \
-@@ -721,6 +735,8 @@
- FTRACE_EVENTS() \
- TRACE_SYSCALLS() \
- KPROBE_BLACKLIST() \
-+ DTRACE_SDT_NAMES() \
-+ DTRACE_SDT_ARGS() \
- ERROR_INJECT_WHITELIST() \
- MEM_DISCARD(init.rodata) \
- CLK_OF_TABLES() \
-diff --git a/include/linux/dtrace_os.h b/include/linux/dtrace_os.h
-index 5bcd77e08a14e8502cbadb53004dbbeb711dc953..f2921ce039a76dd29f93c8183073b8d750681fe6 100644
---- a/include/linux/dtrace_os.h
-+++ b/include/linux/dtrace_os.h
-@@ -25,6 +25,9 @@ extern void __init dtrace_os_init(void);
- extern void __init dtrace_psinfo_os_init(void);
- extern void __init dtrace_task_os_init(void);
-
-+extern void *dtrace_alloc_text(struct module *, unsigned long);
-+extern void dtrace_free_text(void *);
-+
- extern void dtrace_mod_pdata_alloc(struct module *);
- extern void dtrace_mod_pdata_free(struct module *);
- extern int dtrace_destroy_prov(struct module *);
-diff --git a/include/linux/dtrace_sdt.h b/include/linux/dtrace_sdt.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..3a4d608bc3fa3de46fded719352e12e9b2f9f2f0
---- /dev/null
-+++ b/include/linux/dtrace_sdt.h
-@@ -0,0 +1,32 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _DTRACE_SDT_H_
-+#define _DTRACE_SDT_H_
-+
-+#ifdef CONFIG_DTRACE
-+#include <linux/module.h>
-+#include <asm/dtrace_arch.h>
-+
-+extern void __init dtrace_sdt_init(void);
-+extern void __init dtrace_sdt_register(struct module *);
-+extern void dtrace_sdt_register_module(struct module *,
-+ void *sdt_names_addr, size_t,
-+ void *sdt_args_addr, size_t);
-+extern void dtrace_sdt_exit(void);
-+
-+/*
-+ * Functions to be defined in arch/<arch>/kernel/dtrace_sdt.c
-+ */
-+extern void __init_or_module dtrace_sdt_nop_multi(asm_instr_t **, int *, int);
-+
-+#ifdef CONFIG_X86_64
-+extern void __init dtrace_sdt_init_arch(void);
-+#else
-+#define dtrace_sdt_init_arch()
-+#endif /* CONFIG_X86_64 */
-+
-+#endif /* CONFIG_DTRACE */
-+#endif /* _DTRACE_SDT_H_ */
-diff --git a/include/linux/module.h b/include/linux/module.h
-index 44915ed85337f8ef9931afaee5b78f9961ac112e..7abbaeb5d659fa3711c0cd845219366894152ffc 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -30,6 +30,8 @@
- #include <linux/percpu.h>
- #include <asm/module.h>
-
-+#include <linux/sdt.h>
-+
- /* Not Yet Implemented */
- #define MODULE_SUPPORTED_DEVICE(name)
-
-@@ -513,8 +515,11 @@ struct module {
- #endif
-
- #ifdef CONFIG_DTRACE
-+ struct sdt_probedesc *sdt_probes;
-+ unsigned int sdt_probec;
- void *pdata;
- #endif
-+
- #ifdef CONFIG_MODULE_UNLOAD
- /* What modules depend on me? */
- struct list_head source_list;
-diff --git a/include/linux/sdt.h b/include/linux/sdt.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..8efb63cff1ac608f809fe8f4dc55409099d23543
---- /dev/null
-+++ b/include/linux/sdt.h
-@@ -0,0 +1,191 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_SDT_H_
-+#define _LINUX_SDT_H_
-+
-+#include <linux/sdt_internal.h>
-+
-+#if IS_ENABLED(CONFIG_DT_SDT)
-+
-+#include <asm/dtrace_sdt_arch.h>
-+#include <linux/stringify.h>
-+
-+#define DTRACE_PROBE(name, ...) { \
-+ extern int __dtrace_probe_##name(__DTRACE_TYPE_APPLY_DEFAULT(__DTRACE_UINTPTR_EACH, void, ## __VA_ARGS__)); \
-+ (void)__dtrace_probe_##name(__DTRACE_ARG_APPLY(__DTRACE_UINTCAST_EACH, ## __VA_ARGS__)); \
-+ asm volatile(".pushsection _dtrace_sdt_names, \"a\", @progbits\n" \
-+ ".ascii \"" __stringify(name) "\"\n" \
-+ ".byte 0\n" \
-+ ".popsection\n" \
-+ ".pushsection _dtrace_sdt_args, \"a\", @progbits\n" \
-+ __DTRACE_TYPE_APPLY_NOCOMMA(__DTRACE_TYPE_EACH, ## __VA_ARGS__) \
-+ ".byte 0\n" \
-+ ".popsection\n"); \
-+}
-+
-+#define DTRACE_PROBE_ENABLED(name) unlikely(({ \
-+ extern int __dtrace_isenabled_##name(__DTRACE_SDT_ISENABLED_PROTO); \
-+ __dtrace_isenabled_##name(__DTRACE_SDT_ISENABLED_ARGS); \
-+}))
-+
-+#ifdef CONFIG_DT_SDT_PERF
-+
-+#define __DTRACE_UINTPTR_CAST_EACH(x) ({ \
-+ union { \
-+ typeof((x)) __val; \
-+ unsigned char __c; \
-+ unsigned short __s; \
-+ unsigned int __i; \
-+ unsigned long __l; \
-+ unsigned long long __ll; } __u = { .__val = (x) }; \
-+ __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__c), __u.__c, \
-+ __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__s), __u.__s, \
-+ __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__i), __u.__i, \
-+ __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__l), __u.__l, \
-+ __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__ll), __u.__ll, \
-+ (uintptr_t)&(__u.__val)))))); })
-+
-+#define DTRACE_PROBE_TRACEPOINT(name, ...) { \
-+ extern void __dtrace_probe___perf_##name(__DTRACE_APPLY(__DTRACE_UINTPTR_EACH, ## __VA_ARGS__)); \
-+ __dtrace_probe___perf_##name(__DTRACE_APPLY(__DTRACE_UINTPTR_CAST_EACH, ## __VA_ARGS__)); \
-+}
-+
-+#define DTRACE_PROTO_TRACEPOINT(name, ...) { \
-+ asm volatile(".pushsection _dtrace_sdt_names, \"a\", @progbits\n"\
-+ ".ascii \"" __stringify(__perf_##name) "\"\n" \
-+ ".byte 0\n" \
-+ ".popsection\n" \
-+ ".pushsection _dtrace_sdt_args, \"a\", @progbits\n" \
-+ ".ascii \"" __stringify(__VA_ARGS__) "\"\n" \
-+ ".byte 0\n" \
-+ ".popsection\n"); \
-+}
-+#else
-+
-+#define DTRACE_PROBE_TRACEPOINT(name, ...)
-+#define DTRACE_PROTO_TRACEPOINT(name, ...)
-+
-+#endif
-+
-+#else /* ! IS_ENABLED(CONFIG_DT_SDT) */
-+
-+/*
-+ * This apparently redundant call serves to validate the DTRACE_PROBE has the
-+ * right number of args even when dtrace is turned off.
-+ */
-+#define DTRACE_PROBE(name, ...) \
-+ __DTRACE_DOUBLE_APPLY_NOCOMMA(__DTRACE_NONE, __DTRACE_NONE, ## __VA_ARGS__) \
-+ do { } while (0)
-+#define DTRACE_PROBE_ENABLED(name) 0
-+#define DTRACE_PROBE_TRACEPOINT(name, ...)
-+#define DTRACE_PROTO_TRACEPOINT(name, ...)
-+
-+#endif /* IS_ENABLED(CONFIG_DT_SDT) */
-+
-+#ifdef CONFIG_DTRACE
-+
-+struct sdt_probedesc {
-+ char *sdpd_name; /* probe name */
-+ char *sdpd_func; /* probe function */
-+#ifndef __GENKSYMS__
-+ const char *sdpd_args; /* arg string */
-+#endif
-+ unsigned long sdpd_offset; /* offset of call in text */
-+ struct sdt_probedesc *sdpd_next; /* next static probe */
-+};
-+
-+#endif /* CONFIG_DTRACE */
-+
-+#define DTRACE_SCHED(name, ...) \
-+ DTRACE_PROBE(__sched_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_PROC(name, ...) \
-+ DTRACE_PROBE(__proc_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_IO(name, ...) \
-+ DTRACE_PROBE(__io_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_IO_ENABLED(name) \
-+ DTRACE_PROBE_ENABLED(__io_##name)
-+
-+#define DTRACE_ISCSI(name, ...) \
-+ DTRACE_PROBE(__iscsi_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_NFSV3(name, ...) \
-+ DTRACE_PROBE(__nfsv3_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_NFSV4(name, ...) \
-+ DTRACE_PROBE(__nfsv4_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_SMB(name, ...) \
-+ DTRACE_PROBE(__smb_##name, ## __VA_ARGS__);
-+
-+/*
-+ * These definitions are used at probe points to specify the traffic direction;
-+ * this helps simplify argument translation.
-+ */
-+#define DTRACE_NET_PROBE_OUTBOUND 0x0
-+#define DTRACE_NET_PROBE_INBOUND 0x1
-+
-+#define DTRACE_IP(name, ...) \
-+ DTRACE_PROBE(__ip_##name, ## __VA_ARGS__);
-+
-+/*
-+ * Default DTRACE_TCP() and DTRACE_UDP() provider definitions specify the
-+ * probe point within an is-enabled predicate. This is to avoid the overhead
-+ * incurred during argument dereferencing (e.g. calls to ip_hdr(skb)), along
-+ * with any conditional evaluation (which would require branching) when the
-+ * probe is disabled.
-+ *
-+ * Because some TCP probe points require additional argument preparation,
-+ * we also define the is-enabled predicate directly as
-+ * DTRACE_TCP_ENABLED(probename) along with a probe point which does not
-+ * the probe in an is-enabled predicate; this allows us to handle cases such
-+ * as this:
-+ *
-+ * if (DTRACE_TCP_ENABLED(state__change)) {
-+ * ...argument preparation...
-+ * DTRACE_TCP_NOCHECK(state__change, ...);
-+ * }
-+ */
-+
-+#define DTRACE_TCP(name, ...) \
-+ if (DTRACE_PROBE_ENABLED(__tcp_##name)) \
-+ DTRACE_PROBE(__tcp_##name, ## __VA_ARGS__)
-+#define DTRACE_TCP_ENABLED(name) \
-+ DTRACE_PROBE_ENABLED(__tcp_##name)
-+#define DTRACE_TCP_NOCHECK(name, ...) \
-+ DTRACE_PROBE(__tcp_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_UDP(name, ...) \
-+ if (DTRACE_PROBE_ENABLED(__udp_##name)) \
-+ DTRACE_PROBE(__udp_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_SYSEVENT(name, ...) \
-+ DTRACE_PROBE(__sysevent_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_XPV(name, ...) \
-+ DTRACE_PROBE(__xpv_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_FC(name, ...) \
-+ DTRACE_PROBE(__fc_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_SRP(name, ...) \
-+ DTRACE_PROBE(__srp_##name, ## __VA_ARGS__);
-+
-+#define DTRACE_LOCKSTAT_ENABLED(name) \
-+ DTRACE_PROBE_ENABLED(__lockstat_##name)
-+
-+#define DTRACE_LOCKSTAT(name, ...) \
-+ DTRACE_PROBE(__lockstat_##name, ## __VA_ARGS__)
-+
-+#define DTRACE_LOCKSTAT_RW_WRITER 0
-+#define DTRACE_LOCKSTAT_RW_READER 1
-+
-+/* Needed for lockstat probes where we cannot include ktime.h */
-+extern u64 dtrace_gethrtime_ns(void);
-+
-+#endif /* _LINUX_SDT_H_ */
-diff --git a/include/linux/sdt_internal.h b/include/linux/sdt_internal.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..b544f8e619cff9052620af1ec4f1478032c98d66
---- /dev/null
-+++ b/include/linux/sdt_internal.h
-@@ -0,0 +1,276 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Hide away all the terrible macro magic.
-+ *
-+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_SDT_INTERNAL_H_
-+#define _LINUX_SDT_INTERNAL_H_
-+
-+#include <linux/types.h>
-+
-+/*
-+ * This counts the number of args.
-+ */
-+#define __DTRACE_NARGS_SEQ(dummy, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
-+ _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
-+ _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
-+ _31, _32, _33, _34, _35, _36, N, ...) N
-+#define __DTRACE_NARGS(...) \
-+ __DTRACE_NARGS_SEQ(dummy, ##__VA_ARGS__, 36, 35, 34, 33, 32, 31, \
-+ 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
-+ 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, \
-+ 8, 7, 6, 5, 4, 3, 2, 1, 0)
-+
-+/*
-+ * This will let macros expand before concatting them.
-+ */
-+#define __DTRACE_PRIMITIVE_CAT(x, y) x ## y
-+#define __DTRACE_CAT(x, y) __DTRACE_PRIMITIVE_CAT(x, y)
-+
-+#define __DTRACE_COMMA ,
-+#define __DTRACE_NO_COMMA
-+#define __DTRACE_NONE(x)
-+
-+/*
-+ * This will call two macros on each argument-pair passed in (the first two args
-+ * are the names of the macros to call). Its TYPE and NAME variants will throw
-+ * away the name and type arguments, respectively. __DTRACE_*_APPLY_NOCOMMA
-+ * are like DTRACE_*_APPLY, but also omit the comma between arguments in the
-+ * expansion of the macro. DTRACE_TYPE_APPLY_DEFAULT lets you specify a default
-+ * if no variadic args are provided.
-+ */
-+#define __DTRACE_DOUBLE_APPLY(type_macro, arg_macro, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(type_macro, \
-+ arg_macro, __DTRACE_COMMA, \
-+ __DTRACE_COMMA, , ## __VA_ARGS__)
-+#define __DTRACE_DOUBLE_APPLY_NOCOMMA(type_macro, arg_macro, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(type_macro, \
-+ arg_macro, __DTRACE_NO_COMMA, \
-+ __DTRACE_NO_COMMA, , ## __VA_ARGS__)
-+#define __DTRACE_TYPE_APPLY(type_macro, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(type_macro, \
-+ __DTRACE_NONE, __DTRACE_NO_COMMA, \
-+ __DTRACE_COMMA, , ## __VA_ARGS__)
-+#define __DTRACE_TYPE_APPLY_NOCOMMA(type_macro, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(type_macro, \
-+ __DTRACE_NONE, __DTRACE_NO_COMMA, \
-+ __DTRACE_NO_COMMA, , ## __VA_ARGS__)
-+#define __DTRACE_TYPE_APPLY_DEFAULT(type_macro, def, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(type_macro, \
-+ __DTRACE_NONE, __DTRACE_NO_COMMA, \
-+ __DTRACE_COMMA, def, ## __VA_ARGS__)
-+#define __DTRACE_ARG_APPLY(arg_macro, ...) \
-+ __DTRACE_CAT(__DTRACE_DOUBLE_APPLY_, \
-+ __DTRACE_NARGS(__VA_ARGS__))(__DTRACE_NONE, \
-+ arg_macro, __DTRACE_NO_COMMA, \
-+ __DTRACE_COMMA, , ## __VA_ARGS__)
-+#define __DTRACE_DOUBLE_APPLY_0(t, a, comma_t, comma_a, def) def
-+#define __DTRACE_DOUBLE_APPLY_2(t, a, comma_t, comma_a, def, type1, arg1) \
-+ t(type1) comma_t a(arg1)
-+#define __DTRACE_DOUBLE_APPLY_4(t, a, comma_t, comma_a, def, type1, arg1, \
-+ type2, arg2) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2)
-+#define __DTRACE_DOUBLE_APPLY_6(t, a, comma_t, comma_a, def, type1, \
-+ arg1, type2, arg2, type3, arg3) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3)
-+#define __DTRACE_DOUBLE_APPLY_8(t, a, comma_t, comma_a, def, type1, arg1, \
-+ type2, arg2, type3, arg3, type4, arg4) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4)
-+#define __DTRACE_DOUBLE_APPLY_10(t, a, comma_t, comma_a, def, type1, arg1,\
-+ type2, arg2, type3, arg3, type4, arg4, \
-+ type5, arg5) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5)
-+#define __DTRACE_DOUBLE_APPLY_12(t, a, comma_t, comma_a, def, type1, \
-+ arg1, type2, arg2, type3, arg3, type4, \
-+ arg4, type5, arg5, type6, arg6) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6)
-+#define __DTRACE_DOUBLE_APPLY_14(t, a, comma_t, comma_a, def, type1, \
-+ arg1, type2, arg2, type3, arg3, type4, \
-+ arg4, type5, arg5, type6, arg6, type7, \
-+ arg7) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7)
-+#define __DTRACE_DOUBLE_APPLY_16(t, a, comma_t, comma_a, def, type1, \
-+ arg1, type2, arg2, type3, arg3, type4, \
-+ arg4, type5, arg5, type6, arg6, type7, \
-+ arg7, type8, arg8) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8)
-+#define __DTRACE_DOUBLE_APPLY_18(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9)
-+#define __DTRACE_DOUBLE_APPLY_20(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga)
-+#define __DTRACE_DOUBLE_APPLY_22(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb)
-+#define __DTRACE_DOUBLE_APPLY_24(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc)
-+#define __DTRACE_DOUBLE_APPLY_26(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd)
-+#define __DTRACE_DOUBLE_APPLY_28(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd, typee, arge) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd) comma_a t(typee) comma_t a(arge)
-+#define __DTRACE_DOUBLE_APPLY_30(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd, typee, arge, typef, argf) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd) comma_a t(typee) comma_t a(arge) comma_a \
-+ t(typef) comma_t a(argf)
-+#define __DTRACE_DOUBLE_APPLY_32(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd, typee, arge, typef, argf, typeg, argg) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd) comma_a t(typee) comma_t a(arge) comma_a \
-+ t(typef) comma_t a(argf) comma_a t(typeg) comma_t a(argg)
-+#define __DTRACE_DOUBLE_APPLY_34(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd, typee, arge, typef, argf, typeg, argg, typeh, argh) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd) comma_a t(typee) comma_t a(arge) comma_a \
-+ t(typef) comma_t a(argf) comma_a t(typeg) comma_t a(argg) comma_a \
-+ t(typeh) comma_t a(argh)
-+#define __DTRACE_DOUBLE_APPLY_36(t, a, comma_t, comma_a, def, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8, type9, arg9, typea, arga, typeb, argb, typec, argc, typed, argd, typee, arge, typef, argf, typeg, argg, typeh, argh, typei, argi) \
-+ t(type1) comma_t a(arg1) comma_a t(type2) comma_t a(arg2) comma_a \
-+ t(type3) comma_t a(arg3) comma_a t(type4) comma_t a(arg4) comma_a \
-+ t(type5) comma_t a(arg5) comma_a t(type6) comma_t a(arg6) comma_a \
-+ t(type7) comma_t a(arg7) comma_a t(type8) comma_t a(arg8) comma_a \
-+ t(type9) comma_t a(arg9) comma_a t(typea) comma_t a(arga) comma_a \
-+ t(typeb) comma_t a(argb) comma_a t(typec) comma_t a(argc) comma_a \
-+ t(typed) comma_t a(argd) comma_a t(typee) comma_t a(arge) comma_a \
-+ t(typef) comma_t a(argf) comma_a t(typeg) comma_t a(argg) comma_a \
-+ t(typeh) comma_t a(argh) comma_a t(typei) comma_t a(argi)
-+
-+#define __DTRACE_DOUBLE_APPLY_ERROR Error: type specified without arg.
-+#define __DTRACE_DOUBLE_APPLY_1 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_3 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_5 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_7 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_9 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_11 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_13 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_15 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_17 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_19 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_21 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_23 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_25 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_27 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_29 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_31 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_33 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_35 __DTRACE_DOUBLE_APPLY_ERROR
-+#define __DTRACE_DOUBLE_APPLY_37 __DTRACE_DOUBLE_APPLY_ERROR
-+
-+#define __DTRACE_UINTPTR_EACH(x) uintptr_t
-+
-+#define __DTRACE_UINTCAST_EACH(x) (uintptr_t)(x)
-+#define __DTRACE_TYPE_EACH(x) ".ascii \"" __stringify(x) ",\"\n"
-+
-+/*
-+ * Convert everything to the appropriate integral type, unless too large to fit
-+ * into any of them, in which case its address is taken instead.
-+ */
-+
-+/*
-+ * This will call a macro on each argument passed in, with optional default for
-+ * zero args.
-+ */
-+#define __DTRACE_APPLY(macro, ...) __DTRACE_CAT(__DTRACE_APPLY_, __DTRACE_NARGS(__VA_ARGS__))(macro, , ## __VA_ARGS__)
-+#define __DTRACE_APPLY_DEFAULT(macro, def, ...) __DTRACE_CAT(__DTRACE_APPLY_, __DTRACE_NARGS(__VA_ARGS__))(macro, def, ## __VA_ARGS__)
-+#define __DTRACE_APPLY_0(m, def) def
-+#define __DTRACE_APPLY_1(m, def, x1) m(x1)
-+#define __DTRACE_APPLY_2(m, def, x1, x2) m(x1), m(x2)
-+#define __DTRACE_APPLY_3(m, def, x1, x2, x3) m(x1), m(x2), m(x3)
-+#define __DTRACE_APPLY_4(m, def, x1, x2, x3, x4) m(x1), m(x2), m(x3), m(x4)
-+#define __DTRACE_APPLY_5(m, def, x1, x2, x3, x4, x5) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5)
-+#define __DTRACE_APPLY_6(m, def, x1, x2, x3, x4, x5, x6) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6)
-+#define __DTRACE_APPLY_7(m, def, x1, x2, x3, x4, x5, x6, x7) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7)
-+#define __DTRACE_APPLY_8(m, def, x1, x2, x3, x4, x5, x6, x7, x8) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
-+#define __DTRACE_APPLY_9(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9)
-+#define __DTRACE_APPLY_10(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa)
-+#define __DTRACE_APPLY_11(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb)
-+#define __DTRACE_APPLY_12(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc)
-+#define __DTRACE_APPLY_13(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd)
-+#define __DTRACE_APPLY_14(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd), m(xe)
-+#define __DTRACE_APPLY_15(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd), m(xe), m(xf)
-+#define __DTRACE_APPLY_16(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, xg) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd), m(xe), m(xf), m(xg)
-+#define __DTRACE_APPLY_17(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, xg, xh) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd), m(xe), m(xf), m(xg), m(xh)
-+#define __DTRACE_APPLY_18(m, def, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, xg, xh, xi) \
-+ m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(xa), \
-+ m(xb), m(xc), m(xd), m(xe), m(xf), m(xg), m(xh), m(xi)
-+
-+#endif /* _LINUX_SDT_INTERNAL_H */
-diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
-index 0f21617f1a6689395d9caa86d8d2982ef9a3ea84..e847bbafd1234695a78008b77aa8d8740d21d0a0 100644
---- a/include/linux/tracepoint.h
-+++ b/include/linux/tracepoint.h
-@@ -20,6 +20,7 @@
- #include <linux/rcupdate.h>
- #include <linux/tracepoint-defs.h>
- #include <linux/static_call.h>
-+#include <linux/sdt.h>
-
- struct module;
- struct tracepoint;
-@@ -237,6 +238,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
- extern struct tracepoint __tracepoint_##name; \
- static inline void trace_##name(proto) \
- { \
-+ DTRACE_PROBE_TRACEPOINT(name, args); \
-+ DTRACE_PROTO_TRACEPOINT(name, proto); \
- if (static_key_false(&__tracepoint_##name.key)) \
- __DO_TRACE(name, \
- TP_PROTO(data_proto), \
-@@ -332,7 +335,10 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
- #else /* !TRACEPOINTS_ENABLED */
- #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
- static inline void trace_##name(proto) \
-- { } \
-+ { \
-+ DTRACE_PROBE_TRACEPOINT(name, args); \
-+ DTRACE_PROTO_TRACEPOINT(name, proto); \
-+ } \
- static inline void trace_##name##_rcuidle(proto) \
- { } \
- static inline int \
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-index d04ca0ab7ac9c14f4450927423b30784311a3cbd..c1ec55d8750edfbaf55ab9431b7c822b3dd2afae 100644
---- a/kernel/dtrace/Kconfig
-+++ b/kernel/dtrace/Kconfig
-@@ -23,6 +23,22 @@ config DT_CORE
-
- if DT_CORE
-
-+config DT_SDT
-+ tristate "Statically Defined Tracing"
-+ default m
-+ select KALLSYMS
-+ help
-+ Statically defined tracepoints in the kernel.
-+
-+config DT_SDT_PERF
-+ bool "DTrace perf-events Probes"
-+ default y
-+ depends on DT_SDT
-+ select TRACEPOINTS
-+ help
-+ Provides the perf provider, containing a DTrace probe for each
-+ perf-events tracepoint in the system.
-+
- config DT_SYSTRACE
- tristate "System Call Tracing"
- default m
-diff --git a/kernel/dtrace/Makefile b/kernel/dtrace/Makefile
-index 68fc3861e5d1175006494f12758ff1f0304d10fa..06329cbe52cbfbd96c23e6838fc99e53cc5ec5d6 100644
---- a/kernel/dtrace/Makefile
-+++ b/kernel/dtrace/Makefile
-@@ -4,10 +4,11 @@
-
- DT_CORE_ARCH_OBJS = $(addprefix ../../arch/$(SRCARCH)/kernel/, \
- dtrace_syscall.o dtrace_syscall_stubs.o \
-- dtrace_util.o)
-+ dtrace_sdt.o dtrace_util.o)
-
- ifdef CONFIG_DT_CORE
- obj-y += cyclic.o dtrace_os.o dtrace_cpu.o \
-+ dtrace_sdt_core.o \
- dtrace_task.o dtrace_psinfo.o \
- $(DT_CORE_ARCH_OBJS)
- endif
-diff --git a/kernel/dtrace/dtrace_os.c b/kernel/dtrace/dtrace_os.c
-index d023f3913323b42678aee5a7467a4b39c378c8cc..931cfd0d0fbfc05c7670f4c01f1cfef140dbf408 100644
---- a/kernel/dtrace/dtrace_os.c
-+++ b/kernel/dtrace/dtrace_os.c
-@@ -19,6 +19,7 @@
- #include <linux/binfmts.h>
- #include <linux/dtrace_cpu.h>
- #include <linux/dtrace_os.h>
-+#include <linux/dtrace_sdt.h>
- #include <linux/fs.h>
- #include <linux/hardirq.h>
- #include <linux/interrupt.h>
-@@ -66,6 +67,46 @@ void __init dtrace_os_init(void)
- if (dtrace_pdata_cachep == NULL)
- pr_debug("Can't allocate kmem cache for pdata\n");
-
-+ /*
-+ * A little bit of magic...
-+ * We create a dummy module to represent the core Linux kernel. The
-+ * only data we're interested in is the name, the SDT probe points data
-+ * (to be filled in by dtrace_sdt_register()), and the probe data.
-+ * DTrace uses an architecture-specific structure (hidden from us here)
-+ * to hold some data.
-+ */
-+ dtrace_kmod = kmalloc(sizeof(struct module), GFP_KERNEL | __GFP_ZERO);
-+ if (dtrace_kmod == NULL) {
-+ pr_warn("%s: cannot allocate kernel pseudo-module\n",
-+ __func__);
-+ return;
-+ }
-+
-+ strlcpy(dtrace_kmod->name, "vmlinux", MODULE_NAME_LEN);
-+
-+ /*
-+ * Some sizing info is required for kernel module. We are going to use
-+ * modules VA range for trampoline anyway so lets pretend a kernel has
-+ * no init section and VA range (0, MODULES_VADDR) is occupied by
-+ * kernel itself
-+ */
-+#ifdef CONFIG_X86_64
-+ dtrace_kmod->core_layout.base = (void *)__START_KERNEL_map;
-+ dtrace_kmod->core_layout.size = KERNEL_IMAGE_SIZE;
-+#elif defined(CONFIG_SPARC64)
-+ /* Hardcoded see pgtable_64.h */
-+ dtrace_kmod->core_layout.base = (void *)0x4000000;
-+ dtrace_kmod->core_layout.size = 0x2000000;
-+#endif
-+
-+ dtrace_kmod->state = MODULE_STATE_LIVE;
-+ atomic_inc(&dtrace_kmod->refcnt);
-+
-+ dtrace_mod_pdata_alloc(dtrace_kmod);
-+
-+ INIT_LIST_HEAD(&dtrace_kmod->source_list);
-+ INIT_LIST_HEAD(&dtrace_kmod->target_list);
-+
- /*
- * We need to set up a psinfo structure for PID 0 (swapper).
- */
-@@ -73,7 +114,49 @@ void __init dtrace_os_init(void)
- dtrace_psinfo_os_init();
- dtrace_task_init(&init_task);
- dtrace_psinfo_alloc(&init_task);
-+
-+ dtrace_sdt_init();
-+ dtrace_sdt_register(dtrace_kmod);
-+}
-+
-+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-+#define TRAMP_RANGE 0x80000000
-+
-+void *dtrace_alloc_text(struct module *mp, unsigned long size)
-+{
-+ unsigned long mp_start, mp_end;
-+ unsigned long va_start, va_end;
-+ void *trampoline;
-+
-+ /* module range */
-+ mp_start = (unsigned long) mp->core_layout.base;
-+ mp_end = mp_start + mp->core_layout.size;
-+
-+ if (mp->init_layout.size) {
-+ mp_start = MIN(mp_start, (unsigned long)mp->init_layout.base);
-+ mp_end = MAX(mp_end, (unsigned long)mp->init_layout.base +
-+ mp->init_layout.size);
-+ }
-+
-+ /* get trampoline range */
-+ va_end = MIN(mp_start + TRAMP_RANGE, MODULES_END);
-+ va_start = (mp_end < TRAMP_RANGE) ? 0 : mp_end - TRAMP_RANGE;
-+ va_start = MAX(va_start, MODULES_VADDR);
-+
-+ trampoline = __vmalloc_node_range(size, 1, va_start, va_end,
-+ GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
-+ __builtin_return_address(0));
-+
-+ return trampoline;
-+}
-+EXPORT_SYMBOL(dtrace_alloc_text);
-+
-+void dtrace_free_text(void *ptr)
-+{
-+ return vfree(ptr);
- }
-+EXPORT_SYMBOL(dtrace_free_text);
-
- /*
- * MODULE SUPPORT FUNCTIONS
-diff --git a/kernel/dtrace/dtrace_sdt_core.c b/kernel/dtrace/dtrace_sdt_core.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..90b86726f195ff4a917c8f73ebb4bfa99fd669c6
---- /dev/null
-+++ b/kernel/dtrace/dtrace_sdt_core.c
-@@ -0,0 +1,364 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_sdt_core.c
-+ * DESCRIPTION: DTrace - SDT probes
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/memory.h>
-+#include <linux/module.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_sdt.h>
-+#include <linux/jhash.h>
-+#include <linux/sdt.h>
-+#include <linux/slab.h>
-+#include <linux/string.h>
-+#include <linux/vmalloc.h>
-+#include <asm-generic/bitsperlong.h>
-+#include <asm-generic/sections.h>
-+
-+const char *sdt_prefix = "__dtrace_probe_";
-+int dtrace_nosdt;
-+
-+/*
-+ * Compiled-in SDT probe data.
-+ */
-+extern const unsigned long dtrace_sdt_probes[];
-+extern const char dtrace_sdt_strings[];
-+extern const unsigned long dtrace_sdt_nprobes;
-+
-+/*
-+ * Markers of core-kernel sdt_args and sdt_names sections.
-+ */
-+extern const char __start_dtrace_sdt_args[];
-+extern const char __stop_dtrace_sdt_args[];
-+extern const char __start_dtrace_sdt_names[];
-+extern const char __stop_dtrace_sdt_names[];
-+
-+static int sdt_probe_set(struct sdt_probedesc *sdp, const char *name,
-+ const char *func, uintptr_t addr, asm_instr_t **paddr,
-+ struct sdt_probedesc *prv)
-+{
-+ sdp->sdpd_name = kstrdup(name, GFP_KERNEL);
-+ if (sdp->sdpd_name == NULL) {
-+ kfree(sdp);
-+ return 1;
-+ }
-+
-+ sdp->sdpd_func = kstrdup(func, GFP_KERNEL);
-+ if (sdp->sdpd_func == NULL) {
-+ kfree(sdp->sdpd_name);
-+ kfree(sdp);
-+ return 1;
-+ }
-+
-+ sdp->sdpd_args = NULL;
-+ sdp->sdpd_offset = addr;
-+ sdp->sdpd_next = NULL;
-+
-+ *paddr = (asm_instr_t *)addr;
-+
-+ if (prv && strcmp(prv->sdpd_name, sdp->sdpd_name) == 0
-+ && strcmp(prv->sdpd_func, sdp->sdpd_func) == 0)
-+ prv->sdpd_next = sdp;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Transfer the SDT args section into the sdpd_args field left NULL above.
-+ *
-+ * The memory pointed to by args_start must have a lifetime at least as long as
-+ * that pointed to by sdpd.
-+ */
-+void dtrace_sdt_stash_args(const char *module_name,
-+ struct sdt_probedesc *sdpd, size_t nprobes,
-+ const char *names_start, size_t names_len,
-+ const char *args_start, size_t args_len)
-+{
-+ struct probe_name_hashent_t {
-+ const char *pnhe_name;
-+ const char *pnhe_args;
-+ } *args_by_name;
-+ int i;
-+ const char *namep, *argp;
-+ size_t hashsize;
-+
-+ /*
-+ * We need to find the probes (and there may be many) in the sdpd
-+ * corresponding to the probe with that name in the argtype section.
-+ *
-+ * Build a hashtable mapping from probe name -> args string, ignoring
-+ * duplicate probe names except to check (in debugging mode) that they
-+ * have the same args string as the first. Then cycle over the sdpd
-+ * looking up each probe in turn and pointing to the same place.
-+ *
-+ * We don't know how many entries there are in the table, but we do know
-+ * there cannot be more than nprobes (and are probably less).
-+ */
-+
-+ hashsize = nprobes * 4; /* arbitrary expansion factor */
-+ args_by_name = vzalloc(hashsize * sizeof(struct probe_name_hashent_t));
-+ if (args_by_name == NULL) {
-+ pr_warn("%s: cannot allocate hash for sdt args population\n",
-+ __func__);
-+ return;
-+ }
-+
-+ namep = names_start;
-+ argp = args_start;
-+ while ((namep < names_start + names_len) &&
-+ (argp < args_start + args_len)) {
-+
-+ size_t l = strlen(namep);
-+ u32 h = jhash(namep, l, 0) % hashsize;
-+
-+ while (args_by_name[h].pnhe_name != NULL &&
-+ strcmp(args_by_name[h].pnhe_name, namep) != 0) {
-+ h++;
-+ h %= hashsize;
-+ }
-+
-+ if (args_by_name[h].pnhe_name == NULL) {
-+ args_by_name[h].pnhe_name = namep;
-+ args_by_name[h].pnhe_args = argp;
-+ }
-+#if defined(CONFIG_DT_DEBUG)
-+ else if (strcmp(args_by_name[h].pnhe_name, namep) != 0)
-+ pr_warn("%s: multiple distinct arg strings for probe "
-+ "%s found: %s versus %s",
-+ module_name, namep,
-+ args_by_name[h].pnhe_args,
-+ argp);
-+#endif
-+ namep += l + 1;
-+ argp += strlen(argp) + 1;
-+ }
-+
-+#if defined(CONFIG_DT_DEBUG)
-+ if ((namep < names_start + names_len) || (argp < args_start + args_len))
-+ pr_warn("%s: Not all SDT names or args consumed: %zi "
-+ "bytes of names and %zi of args left over. "
-+ "Some arg types will be mis-assigned.\n", module_name,
-+ namep - (names_start + names_len),
-+ argp - (args_start + args_len));
-+#endif
-+
-+ for (i = 0; i < nprobes; i++) {
-+ size_t l = strlen(sdpd[i].sdpd_name);
-+ u32 h = jhash(sdpd[i].sdpd_name, l, 0) % hashsize;
-+
-+ /*
-+ * Is-enabled probes have no arg string.
-+ */
-+ if (sdpd[i].sdpd_name[0] == '?')
-+ continue;
-+
-+ while (args_by_name[h].pnhe_name != NULL &&
-+ strcmp(sdpd[i].sdpd_name,
-+ args_by_name[h].pnhe_name) != 0) {
-+ h++;
-+ h %= hashsize;
-+ }
-+
-+ if (args_by_name[h].pnhe_name == NULL) {
-+ /*
-+ * No arg string. Peculiar: report in debugging mode.
-+ */
-+#if defined(CONFIG_DT_DEBUG)
-+ pr_warn("%s: probe %s has no arg string.\n",
-+ module_name, sdpd[i].sdpd_name);
-+#endif
-+ continue;
-+ }
-+
-+ sdpd[i].sdpd_args = args_by_name[h].pnhe_args;
-+ }
-+ vfree(args_by_name);
-+}
-+
-+/*
-+ * Register the SDT probes for the core kernel, i.e. SDT probes that reside in
-+ * vmlinux. For SDT probes in kernel modules, we use dtrace_mod_notifier().
-+ */
-+void __init dtrace_sdt_register(struct module *mp)
-+{
-+ int i, cnt;
-+ struct sdt_probedesc *sdps;
-+ asm_instr_t **addrs;
-+ int *is_enabled;
-+ void *args;
-+ size_t args_len;
-+
-+ if (mp == NULL) {
-+ pr_warn("%s: no module provided - nothing registered\n",
-+ __func__);
-+ return;
-+ }
-+
-+ /*
-+ * Just in case we run into failures further on...
-+ */
-+ mp->sdt_probes = NULL;
-+ mp->sdt_probec = 0;
-+
-+ if (dtrace_sdt_nprobes == 0 || dtrace_nosdt)
-+ return;
-+
-+ /*
-+ * Allocate the array of SDT probe descriptions to be registered in the
-+ * vmlinux pseudo-module.
-+ */
-+ sdps = (struct sdt_probedesc *)vmalloc(dtrace_sdt_nprobes *
-+ sizeof(struct sdt_probedesc));
-+ if (sdps == NULL) {
-+ pr_warn("%s: cannot allocate SDT probe array\n", __func__);
-+ return;
-+ }
-+
-+ /*
-+ * Create a list of addresses (SDT probe locations) that need to be
-+ * patched with a NOP instruction (or instruction sequence), and another
-+ * array indicating whether each probe needs patching with an
-+ * arch-dependent false return instead.
-+ */
-+ addrs = (asm_instr_t **)vmalloc(dtrace_sdt_nprobes *
-+ sizeof(asm_instr_t *));
-+ is_enabled = (int *)vmalloc(dtrace_sdt_nprobes * sizeof(int));
-+ if ((addrs == NULL) || (is_enabled == NULL)) {
-+ pr_warn("%s: cannot allocate SDT probe address/is-enabled "
-+ "lists\n", __func__);
-+ vfree(sdps);
-+ vfree(addrs);
-+ vfree(is_enabled);
-+ return;
-+ }
-+
-+ for (i = cnt = 0; i < dtrace_sdt_nprobes; i++) {
-+ uintptr_t addr, poff, foff;
-+ const char *fname = &dtrace_sdt_strings[foff];
-+ const char *pname;
-+
-+ addr = dtrace_sdt_probes[i * 3]; /* address */
-+ poff = dtrace_sdt_probes[i * 3 + 1]; /* probe name offset */
-+ foff = dtrace_sdt_probes[i * 3 + 2]; /* func name offset */
-+ pname = &dtrace_sdt_strings[poff];
-+ fname = &dtrace_sdt_strings[foff];
-+
-+ is_enabled[cnt] = (pname[0] == '?');
-+
-+ if (sdt_probe_set(&sdps[cnt], pname, fname, addr, &addrs[cnt],
-+ cnt > 0 ? &sdps[cnt - 1] : NULL))
-+ pr_warn("%s: failed to add SDT probe %s for %s\n",
-+ __func__, pname, fname);
-+ else
-+ cnt++;
-+ }
-+
-+ mp->sdt_probes = sdps;
-+ mp->sdt_probec = cnt;
-+
-+ dtrace_sdt_nop_multi(addrs, is_enabled, cnt);
-+
-+ /*
-+ * Allocate space for the array of arg types, and copy it in from the
-+ * (discardable) kernel section. We will need to keep it. (The
-+ * identically-ordered array of probe names is not needed after
-+ * initialization.)
-+ */
-+ args_len = __stop_dtrace_sdt_args - __start_dtrace_sdt_args;
-+ args = vmalloc(args_len);
-+ if (args == NULL) {
-+ pr_warn("%s: cannot allocate table of SDT arg types\n",
-+ __func__);
-+ goto end;
-+ }
-+
-+ memcpy(args, __start_dtrace_sdt_args, args_len);
-+
-+ dtrace_sdt_stash_args("vmlinux", sdps, cnt,
-+ __start_dtrace_sdt_names,
-+ (__stop_dtrace_sdt_names - __start_dtrace_sdt_names),
-+ args, args_len);
-+
-+end:
-+ vfree(addrs);
-+ vfree(is_enabled);
-+}
-+
-+static int __init nosdt(char *str)
-+{
-+ dtrace_nosdt = 1;
-+
-+ return 0;
-+}
-+
-+early_param("nosdt", nosdt);
-+
-+void dtrace_sdt_register_module(struct module *mp,
-+ void *sdt_names_addr, size_t sdt_names_len,
-+ void *sdt_args_addr, size_t sdt_args_len)
-+{
-+ int i, cnt;
-+ struct sdt_probedesc *sdp;
-+ asm_instr_t **addrs;
-+ int *is_enabled;
-+
-+ if (mp->sdt_probec == 0 || mp->sdt_probes == NULL)
-+ return;
-+
-+ /*
-+ * Create a list of addresses (SDT probe locations) that need to be
-+ * patched with a NOP instruction (or instruction sequence).
-+ */
-+ addrs = (asm_instr_t **)vmalloc(mp->sdt_probec *
-+ sizeof(asm_instr_t *));
-+ is_enabled = (int *)vmalloc(mp->sdt_probec * sizeof(int));
-+ if ((addrs == NULL) || (is_enabled == NULL)) {
-+ pr_warn("%s: cannot allocate SDT probe address list (%s)\n",
-+ __func__, mp->name);
-+ vfree(addrs);
-+ vfree(is_enabled);
-+ return;
-+ }
-+
-+ for (i = cnt = 0, sdp = mp->sdt_probes; i < mp->sdt_probec;
-+ i++, sdp++) {
-+ addrs[cnt] = (asm_instr_t *)sdp->sdpd_offset;
-+ is_enabled[cnt++] = (sdp->sdpd_name[0] == '?');
-+ }
-+
-+ dtrace_sdt_nop_multi(addrs, is_enabled, cnt);
-+
-+ dtrace_sdt_stash_args(mp->name, mp->sdt_probes, mp->sdt_probec,
-+ sdt_names_addr, sdt_names_len,
-+ sdt_args_addr, sdt_args_len);
-+
-+ vfree(addrs);
-+ vfree(is_enabled);
-+}
-+
-+void __init dtrace_sdt_init(void)
-+{
-+ dtrace_sdt_init_arch();
-+}
-+
-+#if IS_ENABLED(CONFIG_DT_DT_PERF)
-+void dtrace_sdt_perf(void)
-+{
-+ DTRACE_PROBE(measure);
-+}
-+EXPORT_SYMBOL(dtrace_sdt_perf);
-+#endif
-diff --git a/kernel/module.c b/kernel/module.c
-index f4269dabc63837a9055eeed1bab211e30422413e..2f214881ae30de2bfc913db89e618e3446e89cb3 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -40,6 +40,7 @@
- #include <linux/string.h>
- #include <linux/mutex.h>
- #include <linux/rculist.h>
-+#include <linux/sdt.h>
- #include <linux/uaccess.h>
- #include <asm/cacheflush.h>
- #include <linux/set_memory.h>
-@@ -47,6 +48,7 @@
- #include <linux/license.h>
- #include <asm/sections.h>
- #include <linux/dtrace_os.h>
-+#include <linux/dtrace_sdt.h>
- #include <linux/tracepoint.h>
- #include <linux/ftrace.h>
- #include <linux/livepatch.h>
-@@ -3777,6 +3779,18 @@ static int complete_formation(struct module *mod, struct load_info *info)
- {
- int err;
-
-+#ifdef CONFIG_DTRACE
-+ void *sdt_args, *sdt_names;
-+ unsigned int sdt_args_len, sdt_names_len;
-+
-+ sdt_names = section_objs(info, "_dtrace_sdt_names", 1,
-+ &sdt_names_len);
-+ sdt_args = section_objs(info, "_dtrace_sdt_args", 1,
-+ &sdt_args_len);
-+ dtrace_sdt_register_module(mod, sdt_names, sdt_names_len,
-+ sdt_args, sdt_args_len);
-+#endif
-+
- mutex_lock(&module_mutex);
-
- /* Find duplicate symbols (must be called under lock). */
-diff --git a/scripts/.gitignore b/scripts/.gitignore
-index a6c11316c9696751b12e3f0b9157d58a8233f613..8458568004eb7b30b825bea7e6d8b9efd5eb3309 100644
---- a/scripts/.gitignore
-+++ b/scripts/.gitignore
-@@ -9,3 +9,4 @@ extract-cert
- sign-file
- insert-sys-cert
- /module.lds
-+kmodsdt
-diff --git a/scripts/Makefile b/scripts/Makefile
-index efa1ff4dff951222a8c98326c29f2146d7e4c587..509a73b6f2697e945c01cfb21785c7646a8f1142 100644
---- a/scripts/Makefile
-+++ b/scripts/Makefile
-@@ -11,6 +11,7 @@ hostprogs-always-$(CONFIG_ASN1) += asn1_compiler
- hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
- hostprogs-always-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
- hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
-+hostprogs-always-$(CONFIG_DTRACE) += kmodsdt
-
- kallsyms-objs := kallsyms.o
-
-@@ -36,6 +37,11 @@ HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
- HOSTLDLIBS_sorttable = -lpthread
- endif
-
-+ifeq ($(CONFIG_DTRACE),y)
-+HOSTCFLAGS_kmodsdt.o := -I$(srctree)/include/generated
-+HOSTLDLIBS_kmodsdt := -lelf
-+endif
-+
- # The following programs are only built on demand
- hostprogs += unifdef
-
-diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
-index 920545d75da9b3248ef47ff1cdc81c981d3637ba..50c464f248ef7318d089de8719d9766b5964e11a 100644
---- a/scripts/Makefile.modfinal
-+++ b/scripts/Makefile.modfinal
-@@ -2,7 +2,7 @@
- # ===========================================================================
- # Module final link and CTF generation
- # ===========================================================================
--# 1) compile all <module>.mod.c files
-+# 1) compute SDT offsets, generate SDT stubs, and compile all .mod.c files
- # 2) for external modules, generate CTF for the module (there is an extra,
- # externally-invoked target that does this for the entire kernel but does
- # not invoke the rst of the module-building process)
-@@ -32,11 +32,52 @@ modname = $(notdir $(@:.mod.o=))
- part-of-module = y
-
- quiet_cmd_cc_o_c = CC [M] $@
-- cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
-+ cmd_cc_o_c = $(CC) $(c_flags) -I$(dir $@) -c -o $@ $<
-+
-+quiet_cmd_as_o_S = AS $@
-+ cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
-+
-+ifdef CONFIG_DTRACE
-+
-+sdtgen = $(srctree)/scripts/dtrace_sdt.sh
-+
-+quiet_cmd_sdtinfo = SDTINF $@
-+ cmd_sdtinfo = $(sdtgen) sdtinfo $@ $< kmod $(@:.c=.h)
-+
-+quiet_cmd_sdtstub = SDTSTB $@
-+ cmd_sdtstub = $(sdtgen) sdtstub $@ $<
-+
-+# We depend on the .mod.c file to ensure that modpost runs before sdtinfo.
-+$(modules:.ko=.sdtinfo.c): %.sdtinfo.c: %.o %.mod.c
-+ $(call cmd,sdtinfo)
-+
-+# We depend on the sdtinfo file because info generation rewrites the .o,
-+# while sdtstubs reads it.
-+$(modules:.ko=.sdtstub.S) : %.sdtstub.S: %.o %.sdtinfo.c
-+ $(call cmd,sdtstub)
-+
-+%.sdtinfo.o : %.sdtinfo.c
-+ $(call if_changed_dep,cc_o_c)
-+
-+%.mod.o: %.mod.c %.sdtinfo.c FORCE
-+ $(call if_changed_dep,cc_o_c)
-+
-+$(modules:.ko=.sdtstub.o): %.sdtstub.o: %.sdtstub.S
-+ $(call if_changed,as_o_S)
-+
-+module-sdt-modular-prereq = %.sdtstub.o
-+sdtinfo-prereq = $(modules:.ko=.sdtinfo.c)
-+
-+else
-
- %.mod.o: %.mod.c FORCE
- $(call if_changed_dep,cc_o_c)
-
-+module-sdt-modular-prereq =
-+sdtinfo-prereq =
-+
-+endif
-+
- # Generate CTF for the entire kernel, or for the module alone if this is a
- # build of an external module.
-
-@@ -95,7 +136,7 @@ $(1) $(wordlist 1,1024,$(2))
- $(if $(word 1025,$(2)),$(call xargs,$(1),$(wordlist 1025,$(words $(2)),$(2))))
- endef
-
--$(ctf-filelist-raw): $(ctf-builtins-prereq) $(ctf-modules)
-+$(ctf-filelist-raw): $(ctf-builtins-prereq) $(ctf-modules) | $(sdtinfo-prereq)
- @rm -f $(ctf-filelist-raw);
- @if [ -n "$(ctf-dir-mk)" ]; then \
- mkdir -p "$(ctf-dir-mk)"; \
-@@ -123,7 +164,8 @@ vmlinux.ctfa: $(ctf-filelist)
- else
-
- # The CTF depends on the output CTF file list, and that depends
--# on the .o files for the modules
-+# on the .o files for the modules, and on the sdtinfo files, if any
-+# (for the same reason that the sdtstub does).
- $(ctf-stamp): $(ctf-filelist)
- $(call if_changed,ctf)
- @shopt -s nullglob; \
-@@ -170,7 +212,7 @@ quiet_cmd_ld_ko_o = LD [M] $@
- $(OBJCOPY) $(module-ctf-flags) $@.tmp $@ && rm -f $@.tmp ; \
- $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
-
--$(modules): %.ko: %.o %.mod.o scripts/module.lds $(module-ctfs-modular-prereq) FORCE
-+$(modules): %.ko: %.o %.mod.o %.sdtinfo.o scripts/module.lds $(module-sdt-modular-prereq) $(module-ctfs-modular-prereq) FORCE
- $(call cmd_touch_ctf)
- +$(call if_changed,ld_ko_o)
-
-diff --git a/scripts/dtrace_sdt.sh b/scripts/dtrace_sdt.sh
-new file mode 100755
-index 0000000000000000000000000000000000000000..2dd7ea1aebd8fed2d5632f438a4e406c91906520
---- /dev/null
-+++ b/scripts/dtrace_sdt.sh
-@@ -0,0 +1,588 @@
-+#!/bin/sh
-+# SPDX-License-Identifier: GPL-2.0
-+
-+LANG=C
-+
-+#
-+# Syntax:
-+# dtrace_sdt.sh sdtstub <S-file> <o-file>+
-+# This is used to generate DTrace SDT probe stubs based on one
-+# or more object file(s). The stubs are written to <S-file>.
-+# dtrace_sdt.sh sdtinfo <c-file> <o-file> kmod <h-file>
-+# This is used to generate DTrace SDT probe definitions for a
-+# kmod .o file. The output is written to <c-file> and <h-file>.
-+# dtrace_sdt.sh sdtinfo <S-file> <l-file>
-+# This is used to generate DTrace SDT probe definitions for a
-+# linked kernel image file <l-file>. The output is written to
-+# <S-file>.
-+#
-+
-+opr="$1"
-+shift
-+if [ -z "$opr" ]; then
-+ echo "ERROR: Missing operation" > /dev/stderr
-+ exit 1
-+fi
-+
-+tfn="$1"
-+shift
-+if [ -z "$tfn" ]; then
-+ echo "ERROR: Missing target filename" > /dev/stderr
-+ exit 1
-+fi
-+
-+ofn="$1"
-+tok="$2"
-+
-+if [ -z "$ofn" ]; then
-+ echo "ERROR: Missing object file argument" > /dev/stderr
-+ exit 1
-+fi
-+
-+if [ "$opr" = "sdtstub" ]; then
-+ ${NM} -u $* | grep -E '__dtrace_(probe|isenabled)_' | sort | uniq | \
-+ gawk -v arch=${ARCH} \
-+ '{
-+ printf("\t.globl %s\n\t.type %s,@function\n%s:\n",
-+ $2, $2, $2);
-+ count++;
-+ }
-+
-+ END {
-+ if (count) {
-+ if (arch == "x86" || arch == "x86_64") {
-+ print "\txor %eax,%eax";
-+ print "\tretq";
-+ } else if (arch == "sparc" || arch == "sparc64") {
-+ print "\tretl";
-+ print "\tnop";
-+ } else if (arch == "arm" || arch == "arm64") {
-+ print "\tmov w0, #0x0";
-+ print "\tret";
-+ }
-+ }
-+ }' > $tfn
-+ exit $?
-+fi
-+
-+if [ "$opr" != "sdtinfo" ]; then
-+ echo "ERROR: Invalid operation, should be sdtstub or sdtinfo" > /dev/stderr
-+ exit 1
-+fi
-+
-+if [ "$tok" = "kmod" ]; then
-+ hfile="$3"
-+
-+ # Pre-process the object file to handle any local functions that contain
-+ # SDT probes.
-+ scripts/kmodsdt ${ofn}
-+
-+ # Output all function symbols in the symbol table of the object file.
-+ # Subsequently, output all relocation records for DTrace SDT probes. The
-+ # probes are identified by either a __dtrace_probe_ or __dtrace_isenabled_
-+ # prefix.
-+ #
-+ # We sort the output primarily based on the section, using the value (or
-+ # offset) as secondary sort criterion The overall result is that the
-+ # output will be structured as a list of functions, and for any functions
-+ # that contain DTrace SDT probes, relocation records will follow the
-+ # function entry they are associated with.
-+ #
-+ # Relocations are reported by objdump per section, with a header line
-+ # documenting the specific section being reported:
-+ # RELOCATION RECORDS FOR [<section>]:
-+ # This is followed by a column header line, and a list of relocations.
-+ # The relocations are listed with 3 tokens per line:
-+ # <offset> <type> <value>
-+ #
-+ # Three different types can show up in the output (all with 4 tokens):
-+ # <section> <offset> F <value>
-+ # Function within a section at a specific offset.
-+ # (See STAGE 3a below.)
-+ # <section> <offset> G <value>
-+ # Global alias for a local function within a section at a specific
-+ # offset. A function can only have one alias, and there cannot be
-+ # an alias without its respective function.
-+ # (See STAGE 3a below.)
-+ # <section> <offset> R <value>
-+ # Relocation within a section at a specific offset.
-+ # (See STAGE 3b below.)
-+ #
-+ ${OBJDUMP} -tr ${ofn} | \
-+ gawk '/^RELOC/ {
-+ sect = substr($4, 2, length($4) - 3);
-+ if (sect ~ /^\.(exit|init|meminit)\.text/)
-+ sect = 0;
-+
-+ next;
-+ }
-+
-+ sect && /__dtrace_probe_/ {
-+ $3 = substr($3, 16);
-+ sub(/[\-+].*$/, "", $3);
-+ print sect " " $1 " R " $3;
-+ next;
-+ }
-+
-+ sect && /__dtrace_isenabled_/ {
-+ $3 = substr($3, 20);
-+ sub(/[\-+].*$/, "", $3);
-+ print sect " " $1 " R ?" $3;
-+ next;
-+ }
-+
-+ /file format/ {
-+ next;
-+ }
-+
-+ / F / {
-+ if ($4 ~ /^\.(exit|init|meminit)\.text/)
-+ next;
-+
-+ if ($6 == ".hidden")
-+ print $4 " " $1 " G " $7;
-+ else
-+ print $4 " " $1 " F " $6;
-+ }' | \
-+ sort -k1,2 | \
-+ gawk -v arch=${ARCH} -v hfile=${hfile} \
-+ 'function subl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ if (v0l >= v1l) {
-+ if (v0h >= v1h) {
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ if (v0h > v1h) {
-+ v0h--;
-+ v0l += 4294967296;
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 - v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ BEGIN {
-+ print "#include <linux/sdt.h>";
-+
-+ probec = 0;
-+ }
-+
-+ #
-+ # Process a symbol table definition for a function in the object
-+ # file ($ofn). As we pass through the symbol table, we record the
-+ # function name, address, and symbol table index or alias. This
-+ # information is needed for any potential DTrace probes that may exist
-+ # in the function. They will be listed in relocation records
-+ # subsequent to this function definition (and are processed in the
-+ # next action block).
-+ #
-+ NF == 4 && $3 == "F" {
-+ fname = $4;
-+ sub(/\..*$/, "", fname);
-+ alias = $4;
-+ faddr = $2;
-+ sub(/^0+/, "", faddr);
-+
-+ next;
-+ }
-+
-+ NF == 4 && $3 == "G" {
-+ alias = $4;
-+
-+ next;
-+ }
-+
-+ #
-+ # Process a relocation record associated with the preceding function.
-+ #
-+ # For kernel modules:
-+ # Convert the section offset into an offset in the function where the
-+ # DTrace probe is located, i.e. an offset from the start of the
-+ # function. This will be resolved in an absolute address at runtime
-+ # when the module is loaded.
-+ #
-+ NF == 4 && $3 == "R" {
-+ sub(/^0+/, "", $2);
-+
-+ addr = subl($2, faddr);
-+
-+ if (arch == "x86" || arch == "x86_64")
-+ addr = subl(addr, 1);
-+
-+ protom[alias] = 1;
-+ probev[probec] = sprintf(" {\042%s\042, \042%s\042 /* %s */, 0 /* sdt_args string */, (uintptr_t)%s+0x%s },", $4, fname, $1, alias, addr);
-+ probec++;
-+
-+ next;
-+ }
-+
-+ END {
-+ for (alias in protom)
-+ printf "extern void %s(void);\n", alias;
-+ print "\nstruct sdt_probedesc\t_sdt_probes[] = {";
-+ for (i = 0; i < probec; i++)
-+ print probev[i];
-+ print "};\n";
-+
-+ print "#define _sdt_probec\t" probec > hfile;
-+ print "extern struct sdt_probedesc _sdt_probes[];" >> hfile;
-+
-+ exit(errc == 0 ? 0 : 1);
-+ }' > $tfn
-+else
-+ # For a linked kernel (with relocation data), the scope of the DTrace SDT
-+ # probe discovery can be limited to CODE sections that are not included in
-+ # the init or exit code sections.
-+ #
-+ # First the sections records are parsed to order to determine the base
-+ # address for each relevant section.
-+ #
-+ # Subsequently, all function symbols that are located in the sections we
-+ # care about are read from the symbol table of the linked kernel object.
-+ # Each symbol is reported in the output stream with its section name,
-+ # address, a token identifying it as a function (or alias), and its name.
-+ #
-+ # Finally, each relocation record from relevant sections that relates to
-+ # SDT probes are written to the output stream with its section name,
-+ # address, a token # identifying it as a relocation, and its name. Probes
-+ # are identified in the relocation records as symbols with either a
-+ # __dtrace_probe_ or __dtrace_isenabled_ prefix.
-+ #
-+ # We sort the output based on the section name and address, ensuring that
-+ # the output will be a list of functions, and each function record will be
-+ # followed immediately by any DTrace SDT probe records that are used in
-+ # that function.
-+ #
-+ # Three different record types can show up in the output (4 tokens each):
-+ # <section> <address> F <name>
-+ # Named function at a specific address.
-+ # <section> <address> G <name>
-+ # Global alias for a local function at a specific offset. A
-+ # function can only have one alias, and there cannot be an alias
-+ # without its respective function.
-+ # <section> <address> R <value>
-+ # Relocation within a section at a specific address
-+ #
-+ ${OBJDUMP} -htr ${ofn} | \
-+ gawk 'function addl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8 || length(v1) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ v0l += v1l;
-+ v0h += v1h;
-+ d = sprintf("%x", v0l);
-+ if (length(d) > 8) {
-+ v0h++;
-+ v0l -= 4294967296;
-+ }
-+ d = sprintf("%x", v0h);
-+ if (length(d) <= 8) {
-+ d = sprintf("%08x%08x", v0h, v0l);
-+ } else {
-+ printf "#error Invalid addresses: %s + %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 + v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ function subl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ if (v0l >= v1l) {
-+ if (v0h >= v1h) {
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ if (v0h > v1h) {
-+ v0h--;
-+ v0l += 4294967296;
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 - v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ NF == 7 && $2 !~ /^\.(exit|init|meminit)\.text/ {
-+ snam = $2;
-+ addr = $4;
-+
-+ getline;
-+ if (/CODE/)
-+ base[snam] = addr;
-+
-+ next;
-+ }
-+
-+ NF == 5 && $2 == "g" && $NF == "_stext" {
-+ print ". " $1 " B _stext";
-+ next;
-+ }
-+
-+ /^RELOC/ {
-+ snam = substr($4, 2, length($4) - 3);
-+ if (snam in base)
-+ in_reloc = 1;
-+ else
-+ in_reloc = 0;
-+ next;
-+ }
-+
-+ in_reloc && /__dtrace_probe_/ {
-+ $3 = substr($3, 16);
-+ sub(/[\-+].*$/, "", $3);
-+ print snam " " addl(base[snam], $1) " R " $3;
-+ next;
-+ }
-+
-+ in_reloc && /__dtrace_isenabled_/ {
-+ $3 = substr($3, 20);
-+ sub(/[\-+].*$/, "", $3);
-+ print snam " " addl(base[snam], $1) " R ?" $3;
-+ next;
-+ }
-+
-+ / F / {
-+ if (!($4 in base))
-+ next;
-+
-+ if ($6 == ".hidden")
-+ print $4 " " $1 " G " $7;
-+ else
-+ print $4 " " $1 " F " $6;
-+ }' | \
-+ sort -k2 | \
-+ gawk -v arch=${ARCH} \
-+ 'function subl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ if (v0l >= v1l) {
-+ if (v0h >= v1h) {
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error Invalid addresses: %x vs %x", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ printf "#error Invalid addresses: %x vs %x", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 - v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ function map_string(str, off) {
-+ if (str in strmap)
-+ off = strmap[str];
-+ else {
-+ off = strsz;
-+ strmap[str] = strsz;
-+ strv[strc++] = str;
-+ strsz += length(str) + 1;
-+ }
-+
-+ return off;
-+ }
-+
-+ BEGIN {
-+ print "#include <asm/types.h>";
-+ print "#if BITS_PER_LONG == 64";
-+ print "# define PTR .quad";
-+ if (arch == "aarch64")
-+ print "# define ALGN .align 3";
-+ else
-+ print "# define ALGN .align 8";
-+ print "#else";
-+ print "# define PTR .long";
-+ if (arch == "aarch64")
-+ print "# define ALGN .align 2";
-+ else
-+ print "# define ALGN .align 4";
-+ print "#endif";
-+
-+ print "\t.section .rodata, \042a\042";
-+ print "";
-+
-+ print ".globl dtrace_sdt_probes";
-+ print "\tALGN";
-+ print "dtrace_sdt_probes:";
-+
-+ probec = 0;
-+ stroff = 0;
-+ strc = 0;
-+ }
-+
-+
-+ #
-+ # Record the _stext address so probe locations can be expressed
-+ # relative to that address.
-+ #
-+ NF == 4 && $1 == "." && $4 == "_stext" {
-+ stext = $2;
-+ next;
-+ }
-+
-+ #
-+ # Process a symbol table definition for a function in the .text
-+ # section of the kernel image. We record the function name and
-+ # the address, and pre-populate the alias name with the function
-+ # name.
-+ #
-+ # We also compare the address of the current symbol to the last
-+ # recorded address, and if they are the same, we do not increment
-+ # the function count.
-+ #
-+ NF == 4 && $3 == "F" {
-+ faddr = $2;
-+ fname = $4;
-+ sub(/\..*$/, "", fname);
-+ alias = $4;
-+
-+ if ($2 != prev)
-+ funcc++;
-+ prev = $2;
-+
-+ next;
-+ }
-+
-+ #
-+ # When we encounter an alias symbol, we record the name.
-+ #
-+ NF == 4 && $3 == "G" {
-+ alias = $4;
-+
-+ next;
-+ }
-+
-+ #
-+ # Process a relocation record associated with the preceding function.
-+ #
-+ # The address was resolved earlier, so we can simply generate the
-+ # numeric information for the SDT probe information record. The
-+ # text information (probe name and function name) are stored. This
-+ # allows us to weed out duplicates, and it is necessary because the
-+ # data blob with all the strings will be written to output later.
-+ #
-+ NF == 4 && $3 == "R" {
-+ sub(/^0+/, "", $2);
-+
-+ addr = subl($2, stext);
-+
-+ #
-+ # On x86, relocations point to the 2nd byte of a call instruction
-+ # so we need to adjust the address.
-+ #
-+ if (arch == "x86" || arch == "x86_64")
-+ addr = subl(addr, 1);
-+
-+ print "/*";
-+ print " * " $1 " " faddr " F " fname;
-+ print " * " $0;
-+ print " */";
-+ printf "\tPTR\t_stext + 0x%s\n", addr;
-+ printf "\tPTR\t%d\n", map_string($4);
-+ printf "\tPTR\t%d\n", map_string(fname);
-+
-+ probec++;
-+
-+ next;
-+ }
-+
-+ END {
-+ print "";
-+ print ".globl dtrace_sdt_strings";
-+ print "\tALGN";
-+ print "dtrace_sdt_strings:";
-+
-+
-+ for (i = 0; i < strc; i++)
-+ printf "\t.asciz\t\042%s\042\n", strv[i];
-+
-+ print "";
-+ print ".globl dtrace_sdt_nprobes";
-+ print ".globl dtrace_fbt_nfuncs";
-+ print "\tALGN";
-+ print "dtrace_sdt_nprobes:";
-+ printf "\tPTR\t%d\n", probec;
-+ print "dtrace_fbt_nfuncs:";
-+ printf "\tPTR\t%d\n", funcc;
-+
-+ exit(errc == 0 ? 0 : 1);
-+ }' > $tfn
-+fi
-+
-+exit $?
-diff --git a/scripts/kmodsdt.c b/scripts/kmodsdt.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..1e35794467d75ea0fd8e324eac97223fd3dc2ce5
---- /dev/null
-+++ b/scripts/kmodsdt.c
-@@ -0,0 +1,410 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright 2016 Oracle, Inc. All rights reserved.
-+ * Use is subject to license terms.
-+ */
-+
-+#include "../include/generated/autoconf.h"
-+
-+#define ELF_TARGET_ALL
-+#include <elf.h>
-+#include <gelf.h>
-+
-+#include <sys/types.h>
-+
-+#include <unistd.h>
-+#include <string.h>
-+#include <limits.h>
-+#include <stddef.h>
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <fcntl.h>
-+#include <errno.h>
-+#include <assert.h>
-+
-+typedef struct symtbl {
-+ struct symtbl *next;
-+ void *strtab;
-+ void *symtab;
-+} symtbl_t;
-+
-+static int
-+dt_elf_symtab_lookup(Elf_Data *data_sym, int nsym, uintptr_t addr, uint32_t shn,
-+ GElf_Sym *sym)
-+{
-+ int i, ret = -1;
-+ GElf_Sym s;
-+
-+ for (i = 0; i < nsym && gelf_getsym(data_sym, i, sym) != NULL; i++) {
-+ if (GELF_ST_TYPE(sym->st_info) == STT_FUNC &&
-+ shn == sym->st_shndx &&
-+ sym->st_value <= addr &&
-+ addr < sym->st_value + sym->st_size) {
-+ if (GELF_ST_BIND(sym->st_info) == STB_GLOBAL)
-+ return i;
-+
-+ ret = i;
-+ s = *sym;
-+ }
-+ }
-+
-+ if (ret >= 0)
-+ *sym = s;
-+ return ret;
-+}
-+
-+static int
-+process_obj(const char *obj)
-+{
-+ static const char dt_ppref[] = "__dtrace_probe_";
-+ static const char dt_spref[] = "__dta_";
-+ int fd, i, sidx, mod = 0;
-+ Elf *elf = NULL;
-+ GElf_Ehdr ehdr;
-+ Elf_Scn *scn_rel, *scn_sym, *scn_str;
-+ Elf_Data *data_rel, *data_sym, *data_str;
-+ GElf_Shdr shdr_rel, shdr_sym, shdr_str;
-+ GElf_Sym rsym, fsym, dsym;
-+ GElf_Rela rela;
-+ char *p, *r, *f, *a;
-+ uint32_t eclass, emachine1, emachine2;
-+ size_t symsize, nsym, nstr, isym, istr, osym, len;
-+ symtbl_t *pair, *bufs = NULL;
-+ char **alttab;
-+ const char *elferrstr = "no error";
-+
-+ fd = open(obj, O_RDWR);
-+ if (fd == -1) {
-+ fprintf(stderr, "failed to open %s: %s\n", obj,
-+ strerror(errno));
-+ return 1;
-+ }
-+
-+ if (elf_version(EV_CURRENT) == EV_NONE) {
-+ fprintf(stderr, "ELF library version too old\n");
-+ return 1;
-+ }
-+
-+ elf = elf_begin(fd, ELF_C_RDWR, NULL);
-+ if (elf == NULL) {
-+ fprintf(stderr, "failed to process %s: %s\n", obj,
-+ elf_errmsg(elf_errno()));
-+ return 1;
-+ }
-+
-+ switch (elf_kind(elf)) {
-+ case ELF_K_ELF:
-+ break;
-+ case ELF_K_AR:
-+ fprintf(stderr, "archives are not permitted; %s\n", obj);
-+ return 1;
-+ default:
-+ fprintf(stderr, "invalid file type: %s\n", obj);
-+ return 1;
-+ }
-+
-+ if (gelf_getehdr(elf, &ehdr) == NULL) {
-+ fprintf(stderr, "corrupt file: %s\n", obj);
-+ return 1;
-+ }
-+
-+#ifdef CONFIG_64BIT
-+ eclass = ELFCLASS64;
-+# if defined(__sparc)
-+ emachine1 = emachine2 = EM_SPARCV9;
-+# elif defined(__i386) || defined(__amd64)
-+ emachine1 = emachine2 = EM_X86_64;
-+# elif defined(__aarch64__)
-+ emachine1 = emachine2 = EM_AARCH64;
-+# endif
-+ symsize = sizeof(Elf64_Sym);
-+#else
-+ eclass = ELFCLASS32;
-+# if defined(__sparc)
-+ emachine1 = EM_SPARC;
-+ emachine2 = EM_SPARC32PLUS;
-+# elif defined(__i386) || defined(__amd64)
-+ emachine1 = emachine2 = EM_386;
-+# elif defined(__arm__)
-+ emachine1 = emachine2 = EM_ARM;
-+# endif
-+ symsize = sizeof(Elf32_Sym);
-+#endif
-+
-+ if (ehdr.e_ident[EI_CLASS] != eclass) {
-+ fprintf(stderr, "incorrect ELF class for %s: %d "
-+ "(expected %d)\n", obj, ehdr.e_ident[EI_CLASS],
-+ eclass);
-+ return 1;
-+ }
-+ if (ehdr.e_machine != emachine1 && ehdr.e_machine != emachine2) {
-+ fprintf(stderr, "incorrect ELF machine type for %s: %d "
-+ "(expected %d or %d)\n",
-+ obj, ehdr.e_machine, emachine1, emachine2);
-+ return 1;
-+ }
-+
-+ scn_rel = NULL;
-+ while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) {
-+ if (gelf_getshdr(scn_rel, &shdr_rel) == NULL) {
-+ elferrstr = "failed to get section header";
-+ goto elf_err;
-+ }
-+
-+ /*
-+ * Skip any non-relocation sections.
-+ */
-+ if (shdr_rel.sh_type != SHT_RELA && shdr_rel.sh_type != SHT_REL)
-+ continue;
-+
-+ data_rel = elf_getdata(scn_rel, NULL);
-+ if (data_rel == NULL) {
-+ elferrstr = "failed to get relocation data";
-+ goto elf_err;
-+ }
-+
-+ /*
-+ * Grab the section, section header and section data for the
-+ * symbol table that this relocation section references.
-+ */
-+ scn_sym = elf_getscn(elf, shdr_rel.sh_link);
-+ if (scn_sym == NULL ||
-+ gelf_getshdr(scn_sym, &shdr_sym) == NULL ||
-+ (data_sym = elf_getdata(scn_sym, NULL)) == NULL) {
-+ elferrstr = "failed to get symbol table";
-+ goto elf_err;
-+ }
-+
-+ /*
-+ * Ditto for that symbol table's string table.
-+ */
-+ scn_str = elf_getscn(elf, shdr_sym.sh_link);
-+ if (scn_str == NULL ||
-+ gelf_getshdr(scn_str, &shdr_str) == NULL ||
-+ (data_str = elf_getdata(scn_str, NULL)) == NULL) {
-+ elferrstr = "failed to get string table";
-+ goto elf_err;
-+ }
-+
-+ /*
-+ * We're looking for relocations to symbols matching this form:
-+ *
-+ * __dtrace_probe_<probe>
-+ *
-+ * If the function containing the probe is locally scoped
-+ * (static), we create an alias. The alias, a new symbol,
-+ * will be global (so that it can be referenced from sdtinfo
-+ * entries) and hidden (so that it is converted to a local
-+ * symbol at link time). Such aliases have this form:
-+ *
-+ * __dta_<function>_<symindex>
-+ *
-+ * The <symindex> is appended to ensure that aliases are unique
-+ * because they are referenced in global scope. Two local
-+ * functions with identical names need to be distrinct at the
-+ * level of the aliases.
-+ *
-+ * We take a first pass through all the relocations to
-+ * populate our string table and count the number of extra
-+ * symbols we'll require. Note that the <function> is
-+ * sanitized to ensure that it is a valid C identifier, i.e.
-+ * any periods in the name are converted to underscores.
-+ */
-+ isym = osym = data_sym->d_size / symsize;
-+ istr = data_str->d_size;
-+
-+ /*
-+ * Allocate the alias table to be the exact same size as the
-+ * symtab. If an alias is required for a specific symbol, its
-+ * corresponding entry in this alias table will contain the
-+ * alias name. Otherwise, the entry will be NULL.
-+ */
-+ alttab = (char **)calloc(isym, sizeof(char *));
-+
-+ nsym = 0;
-+ nstr = 0;
-+
-+ for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
-+ if (shdr_rel.sh_type == SHT_RELA) {
-+ if (gelf_getrela(data_rel, i, &rela) == NULL)
-+ continue;
-+ } else {
-+ GElf_Rel rel;
-+
-+ if (gelf_getrel(data_rel, i, &rel) == NULL)
-+ continue;
-+ rela.r_offset = rel.r_offset;
-+ rela.r_info = rel.r_info;
-+ rela.r_addend = 0;
-+ }
-+
-+ if (gelf_getsym(data_sym, GELF_R_SYM(rela.r_info),
-+ &rsym) == NULL) {
-+ elferrstr = "relocation symbol not found";
-+ goto elf_err;
-+ }
-+
-+ assert(rsym.st_name < data_str->d_size);
-+
-+ r = (char *)data_str->d_buf + rsym.st_name;
-+ if (strncmp(r, dt_ppref, sizeof(dt_ppref) - 1) != 0)
-+ continue;
-+
-+ sidx = dt_elf_symtab_lookup(data_sym, isym,
-+ rela.r_offset,
-+ shdr_rel.sh_info, &fsym);
-+ if (sidx < 0) {
-+ fprintf(stderr, "relocation %x not in "
-+ "function\n", i);
-+ goto err;
-+ }
-+
-+ assert(fsym.st_name < data_str->d_size);
-+ assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC);
-+
-+ if (GELF_ST_BIND(fsym.st_info) != STB_LOCAL)
-+ continue;
-+
-+ f = (char *)data_str->d_buf + fsym.st_name;
-+
-+ if (alttab[sidx] != NULL)
-+ continue;
-+
-+ len = snprintf(NULL, 0, "%s%s_%d", dt_spref, f, sidx)
-+ + 1;
-+ a = malloc(len);
-+ assert(a != NULL);
-+ nstr += snprintf(a, len, "%s%s_%d", dt_spref, f, sidx)
-+ + 1;
-+ for (p = a; *p != '\0'; p++) {
-+ if (*p == '.')
-+ *p = '_';
-+ }
-+ alttab[sidx] = a;
-+ nsym++;
-+ }
-+
-+ if (!nsym) {
-+ free(alttab);
-+ continue;
-+ }
-+
-+ pair = malloc(sizeof(symtbl_t));
-+ if (pair == NULL) {
-+ fprintf(stderr, "failed to alloc new symtbl\n");
-+ goto err;
-+ }
-+ pair->strtab = malloc(data_str->d_size + nstr);
-+ if (pair->strtab == NULL) {
-+ fprintf(stderr, "failed to alloc new symtbl->strtab\n");
-+ free(pair);
-+ goto err;
-+ }
-+ pair->symtab = malloc(data_sym->d_size + nsym * symsize);
-+ if (pair->symtab == NULL) {
-+ fprintf(stderr, "failed to alloc new symtbl->symtab\n");
-+ free(pair->strtab);
-+ free(pair);
-+ goto err;
-+ }
-+
-+ pair->next = bufs;
-+ bufs = pair;
-+
-+ memcpy(pair->strtab, data_str->d_buf, data_str->d_size);
-+ data_str->d_buf = pair->strtab;
-+ data_str->d_size += nstr;
-+ elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
-+ shdr_str.sh_size += nstr;
-+ gelf_update_shdr(scn_str, &shdr_str);
-+
-+ memcpy(pair->symtab, data_sym->d_buf, data_sym->d_size);
-+ data_sym->d_buf = pair->symtab;
-+ data_sym->d_size += nsym * symsize;
-+ elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
-+ shdr_sym.sh_size += nsym * symsize;
-+ gelf_update_shdr(scn_sym, &shdr_sym);
-+
-+ nsym += isym;
-+
-+ /*
-+ * Now that the tables have been allocated, add the aliases as
-+ * described above. Since we already know the symtab index of
-+ * the symbol that the alias refers to, we can simply run down
-+ * the alttab and add alias for any non-NULL entries.
-+ */
-+ for (i = 1; i < osym; i++) {
-+ if (alttab[i] == NULL)
-+ continue;
-+
-+ if (gelf_getsym(data_sym, i, &fsym) == NULL) {
-+ fprintf(stderr, "failed to get symbol %d: %s\n",
-+ i, elf_errmsg(elf_errno()));
-+ goto err;
-+ }
-+
-+ assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC);
-+ assert(GELF_ST_BIND(fsym.st_info) == STB_LOCAL);
-+ /*
-+ * Add the alias as a new symbol to the symtab.
-+ */
-+ dsym = fsym;
-+ dsym.st_name = istr;
-+ dsym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC);
-+ dsym.st_other = ELF64_ST_VISIBILITY(STV_HIDDEN);
-+
-+ len = strlen(alttab[i]) + 1;
-+ assert(istr + len <= data_str->d_size);
-+ a = (char *)data_str->d_buf + istr;
-+ memcpy(a, alttab[i], len);
-+
-+ gelf_update_sym(data_sym, isym, &dsym);
-+ istr += len;
-+ isym++;
-+
-+ assert(isym <= nsym);
-+
-+ mod = 1;
-+
-+ free(alttab[i]);
-+ }
-+
-+ free(alttab);
-+ }
-+
-+ if (mod && elf_update(elf, ELF_C_WRITE) == -1) {
-+ elferrstr = "Failed to update ELF object";
-+ goto elf_err;
-+ }
-+
-+ elf_end(elf);
-+ close(fd);
-+
-+ while ((pair = bufs) != NULL) {
-+ bufs = pair->next;
-+ free(pair->strtab);
-+ free(pair->symtab);
-+ free(pair);
-+ }
-+
-+ return 0;
-+
-+elf_err:
-+ fprintf(stderr, "%s: %s\n", elferrstr, elf_errmsg(elf_errno()));
-+err:
-+ fprintf(stderr, "an error was encountered while processing %s\n", obj);
-+ return 1;
-+}
-+
-+int
-+main(int argc, char *argv[])
-+{
-+ int i;
-+
-+ for (i = 1; i < argc; i++) {
-+ if (process_obj(argv[i]))
-+ exit(1);
-+ }
-+
-+ exit(0);
-+}
-diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
-index bc533252fa3c39482a870654036caf3897946123..0b2f3bb60936f81449de21f296bdaddd466c9569 100755
---- a/scripts/link-vmlinux.sh
-+++ b/scripts/link-vmlinux.sh
-@@ -43,6 +43,34 @@ info()
- fi
- }
-
-+# Generate the SDT probe point stubs object file
-+# ${1} output file
-+sdtstub()
-+{
-+ info SDTSTB ${1}
-+ ${srctree}/scripts/dtrace_sdt.sh sdtstub .tmp_sdtstub.S \
-+ ${KBUILD_VMLINUX_OBJS}
-+
-+ local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
-+ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
-+
-+ ${CC} ${aflags} -c -o ${1} .tmp_sdtstub.S
-+}
-+
-+# Generate the SDT probe info for kernel image ${1}
-+# ${2} output file
-+sdtinfo()
-+{
-+ info SDTINF ${2}
-+
-+ ${srctree}/scripts/dtrace_sdt.sh sdtinfo .tmp_sdtinfo.S ${1}
-+
-+ local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
-+ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
-+
-+ ${CC} ${aflags} -c -o ${2} .tmp_sdtinfo.S
-+}
-+
- # Link of vmlinux.o used for section mismatch analysis
- # ${1} output file
- modpost_link()
-@@ -84,17 +112,20 @@ objtool_link()
-
- # Link of vmlinux
- # ${1} - output file
--# ${2}, ${3}, ... - optional extra .o files
-+# ${2} - optional extra ld flag(s)
-+# ${3}, ${4}, ... - optional extra .o files
- vmlinux_link()
- {
- local lds="${objtree}/${KBUILD_LDS}"
- local output=${1}
-+ local flags="${2}"
- local objects
- local strip_debug
-
- info LD ${output}
-
-- # skip output file argument
-+ # skip output file and flags arguments
-+ shift
- shift
-
- # The kallsyms linking does not need debug symbols included.
-@@ -114,7 +145,7 @@ vmlinux_link()
-
- ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
- ${strip_debug#-Wl,} \
-- -o ${output} \
-+ ${flags} -o ${output} \
- -T ${lds} ${objects}
- else
- objects="-Wl,--whole-archive \
-@@ -128,7 +159,7 @@ vmlinux_link()
-
- ${CC} ${CFLAGS_vmlinux} \
- ${strip_debug} \
-- -o ${output} \
-+ ${flags} -o ${output} \
- -Wl,-T,${lds} \
- ${objects} \
- -lutil -lrt -lpthread
-@@ -219,7 +250,7 @@ kallsyms_step()
- kallsymso=${kallsyms_vmlinux}.o
- kallsyms_S=${kallsyms_vmlinux}.S
-
-- vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
-+ vmlinux_link ${kallsyms_vmlinux} "${2:-}" "${kallsymso_prev}" ${btf_vmlinux_bin_o} ${sdtstubo} ${sdtinfoo}
- kallsyms ${kallsyms_vmlinux} ${kallsyms_S}
-
- info AS ${kallsyms_S}
-@@ -245,6 +276,8 @@ cleanup()
- {
- rm -f .btf.*
- rm -f .tmp_System.map
-+ rm -f .tmp_sdtstub.*
-+ rm -f .tmp_sdtinfo.*
- rm -f .tmp_vmlinux*
- rm -f System.map
- rm -f vmlinux
-@@ -293,6 +326,14 @@ fi;
- # final build of init/
- ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
-
-+sdtstubo=""
-+sdtinfoo=""
-+if [ -n "${CONFIG_DTRACE}" ]; then
-+ sdtstubo=.tmp_sdtstub.o
-+ sdtinfoo=.tmp_sdtinfo.o
-+ sdtstub ${sdtstubo}
-+fi
-+
- #link vmlinux.o
- info LD vmlinux.o
- modpost_link vmlinux.o
-@@ -346,7 +387,23 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
- # a) Verify that the System.map from vmlinux matches the map from
- # ${kallsymso}.
-
-+ # step 1
-+ if [ -n "${CONFIG_DTRACE}" ]; then
-+ sdtinfo vmlinux.o ${sdtinfoo}
-+ fi
-+
- kallsyms_step 1
-+
-+ if [ -n "${CONFIG_DTRACE}" ]; then
-+ if [ -n "${CONFIG_ARM64}" ]; then
-+ kallsyms_step 1
-+ else
-+ kallsyms_step 1 -r
-+ fi
-+ sdtinfo ${kallsyms_vmlinux} ${sdtinfoo} vmlinux.o
-+ fi
-+
-+ # step 2
- kallsyms_step 2
-
- # step 3
-@@ -358,7 +415,7 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
- fi
- fi
-
--vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o}
-+vmlinux_link vmlinux "" "${kallsymso}" ${btf_vmlinux_bin_o} ${sdtstubo} ${sdtinfoo}
-
- # fill in BTF IDs
- if [ -n "${CONFIG_DEBUG_INFO_BTF}" -a -n "${CONFIG_BPF}" ]; then
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index f882ce0d9327f857049e914196b2e03c38dea9b1..ceeb69afc2091694194d42a93693ff081f7b87fe 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -2183,7 +2183,9 @@ static int check_exports(struct module *mod)
- const char *basename;
- exp = find_symbol(s->name);
- if (!exp || exp->module == mod) {
-- if (have_vmlinux && !s->weak) {
-+ if (have_vmlinux && !s->weak &&
-+ !strstarts(s->name, "__dtrace_probe_") &&
-+ !strstarts(s->name, "__dtrace_isenabled_")) {
- modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR,
- "\"%s\" [%s.ko] undefined!\n",
- s->name, mod->name);
-@@ -2238,6 +2240,13 @@ static int check_modname_len(struct module *mod)
- **/
- static void add_header(struct buffer *b, struct module *mod)
- {
-+ const char *modname;
-+
-+ modname = strrchr(mod->name, '/');
-+ if (modname != NULL)
-+ modname++;
-+ else
-+ modname = mod->name;
- buf_printf(b, "#include <linux/module.h>\n");
- /*
- * Include build-salt.h after module.h in order to
-@@ -2248,6 +2257,10 @@ static void add_header(struct buffer *b, struct module *mod)
- buf_printf(b, "#include <linux/vermagic.h>\n");
- buf_printf(b, "#include <linux/compiler.h>\n");
- buf_printf(b, "\n");
-+ buf_printf(b, "#ifdef CONFIG_DTRACE\n");
-+ buf_printf(b, "# include \"%s.sdtinfo.h\"\n", modname);
-+ buf_printf(b, "#endif\n");
-+ buf_printf(b, "\n");
- buf_printf(b, "BUILD_SALT;\n");
- buf_printf(b, "\n");
- buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
-@@ -2263,6 +2276,10 @@ static void add_header(struct buffer *b, struct module *mod)
- "\t.exit = cleanup_module,\n"
- "#endif\n");
- buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n");
-+ buf_printf(b, "#ifdef CONFIG_DTRACE\n");
-+ buf_printf(b, "\t.sdt_probes = _sdt_probes,\n");
-+ buf_printf(b, "\t.sdt_probec = _sdt_probec,\n");
-+ buf_printf(b, "#endif\n");
- buf_printf(b, "};\n");
- }
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0009-dtrace-sdt-provider-for-x86.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0009-dtrace-sdt-provider-for-x86.patch
deleted file mode 100644
index 9931c75853b5..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0009-dtrace-sdt-provider-for-x86.patch
+++ /dev/null
@@ -1,1076 +0,0 @@
-From 33bb9a2aab1f792110ebeebcc2a5a0b5e02cec6c Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 18:00:18 +0000
-Subject: [PATCH 09/19] dtrace: sdt provider for x86
-
-This implements the SDT provider itself. It is relatively
-straightforward except for the code needed to parse the argument strings
-ultimately derived from SDT DTRACE_PROBE invocations and perf-event
-prototype definitions.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/dtrace/Makefile.arch | 2 +
- arch/x86/dtrace/sdt_x86_64.c | 126 ++++++++
- dtrace/Makefile | 2 +
- dtrace/dt_test_dev.c | 33 ++
- dtrace/dt_test_mod.c | 5 +
- dtrace/sdt_dev.c | 562 ++++++++++++++++++++++++++++++++++
- dtrace/sdt_impl.h | 87 ++++++
- dtrace/sdt_mod.c | 154 ++++++++++
- 8 files changed, 971 insertions(+)
- create mode 100644 arch/x86/dtrace/sdt_x86_64.c
- create mode 100644 dtrace/sdt_dev.c
- create mode 100644 dtrace/sdt_impl.h
- create mode 100644 dtrace/sdt_mod.c
-
-diff --git a/arch/x86/dtrace/Makefile.arch b/arch/x86/dtrace/Makefile.arch
-index ffb9ef4d1722b673511418c5744067ac501d49c5..8492eaee426d1ba7a25769ff3c95d1dc828f69ae 100644
---- a/arch/x86/dtrace/Makefile.arch
-+++ b/arch/x86/dtrace/Makefile.arch
-@@ -7,5 +7,7 @@ DTARCHDIR = ../arch/x86/dtrace
- ccflags-y += -I$(srctree)/arch/x86/dtrace/include -Idtrace
-
- dtrace-obj += dtrace_asm_x86_64.o dtrace_isa_x86_64.o
-+sdt-obj += sdt_x86_64.o
-
- dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
-+sdt-y += $(addprefix $(DTARCHDIR)/, $(sdt-obj))
-diff --git a/arch/x86/dtrace/sdt_x86_64.c b/arch/x86/dtrace/sdt_x86_64.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..e686634ff410372a83d3dd63d5041b4943f0412d
---- /dev/null
-+++ b/arch/x86/dtrace/sdt_x86_64.c
-@@ -0,0 +1,126 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: sdt_dev.c
-+ * DESCRIPTION: DTrace - SDT provider implementation for x86
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/sdt.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <asm/dtrace_util.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "sdt_impl.h"
-+
-+#define SDT_PATCHVAL 0xf0
-+
-+static uint8_t sdt_invop(struct pt_regs *regs)
-+{
-+ struct sdt_probe *sdt = sdt_probetab[SDT_ADDR2NDX(regs->ip)];
-+
-+ for (; sdt != NULL; sdt = sdt->sdp_hashnext) {
-+ if ((uintptr_t)sdt->sdp_patchpoint == regs->ip) {
-+ if (sdt->sdp_ptype == SDTPT_IS_ENABLED)
-+ regs->ax = 1;
-+ else {
-+ struct pt_regs *old_regs =
-+ this_cpu_core->cpu_dtrace_regs;
-+
-+ this_cpu_core->cpu_dtrace_regs = regs;
-+
-+ dtrace_probe(sdt->sdp_id, regs->di, regs->si,
-+ regs->dx, regs->cx, regs->r8,
-+ regs->r9, 0);
-+
-+ this_cpu_core->cpu_dtrace_regs = old_regs;
-+ }
-+
-+ return DTRACE_INVOP_NOPS;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+void sdt_provide_probe_arch(struct sdt_probe *sdp, struct module *mp, int idx)
-+{
-+ sdp->sdp_patchval = SDT_PATCHVAL;
-+ sdp->sdp_savedval = *sdp->sdp_patchpoint;
-+}
-+
-+int sdt_provide_module_arch(void *arg, struct module *mp)
-+{
-+ return 1;
-+}
-+
-+void sdt_destroy_module(void *arg, struct module *mp)
-+{
-+}
-+
-+void sdt_enable_arch(struct sdt_probe *sdp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_invop_enable(sdp->sdp_patchpoint, sdp->sdp_patchval);
-+}
-+
-+void sdt_disable_arch(struct sdt_probe *sdp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_invop_disable(sdp->sdp_patchpoint, sdp->sdp_savedval);
-+}
-+
-+uint64_t sdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ return 0;
-+
-+ switch (argno) {
-+ case 0:
-+ return regs->di;
-+ case 1:
-+ return regs->si;
-+ case 2:
-+ return regs->dx;
-+ case 3:
-+ return regs->cx;
-+ case 4:
-+ return regs->r8;
-+ case 5:
-+ return regs->r9;
-+ }
-+
-+ ASSERT(argno > 5);
-+
-+ st = (uint64_t *)regs->sp;
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ val = st[argno - 6];
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return val;
-+}
-+
-+int sdt_dev_init_arch(void)
-+{
-+ return dtrace_invop_add(sdt_invop);
-+}
-+
-+void sdt_dev_exit_arch(void)
-+{
-+ dtrace_invop_remove(sdt_invop);
-+}
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-index b91bc69d38020d8c872483f894349f02a8eb58e6..126d4985967a2478ea2df97ab42eb384e6fe14d2 100644
---- a/dtrace/Makefile
-+++ b/dtrace/Makefile
-@@ -3,6 +3,7 @@
- #
-
- obj-$(CONFIG_DT_CORE) += dtrace.o
-+obj-$(CONFIG_DT_SDT) += sdt.o
- obj-$(CONFIG_DT_SYSTRACE) += systrace.o
- obj-$(CONFIG_DT_DT_TEST) += dt_test.o
-
-@@ -15,6 +16,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \
- dtrace_probe.o dtrace_probe_ctx.o \
- dtrace_ptofapi.o dtrace_predicate.o \
- dtrace_spec.o dtrace_state.o dtrace_util.o
-+sdt-y := sdt_mod.o sdt_dev.o
- systrace-y := systrace_mod.o systrace_dev.o
- dt_test-y := dt_test_mod.o dt_test_dev.o
-
-diff --git a/dtrace/dt_test_dev.c b/dtrace/dt_test_dev.c
-index 8e1f5bab8a128bdc29a345e422467e6e9d294cf0..b720d8091787df618cdff877b63da2cc80a52836 100644
---- a/dtrace/dt_test_dev.c
-+++ b/dtrace/dt_test_dev.c
-@@ -131,6 +131,39 @@ static long dt_test_ioctl(struct file *file,
- return 0;
- }
-
-+ if (DTRACE_PROBE_ENABLED(sdt__test))
-+ DTRACE_PROBE(sdt__test__is__enabled);
-+
-+ DTRACE_PROBE(sdt__test);
-+
-+ /*
-+ * Test translation-to-nothing.
-+ */
-+ DTRACE_PROBE(sdt__test__ioctl__file, int, cmd, int :, 666,
-+ char * : (), 0, struct file *, file, int, arg);
-+
-+ /*
-+ * Probes with every valid count of args.
-+ */
-+ DTRACE_PROBE(sdt__test__arg1, int, 1);
-+ DTRACE_PROBE(sdt__test__arg2, int, 1, int, 2);
-+ DTRACE_PROBE(sdt__test__arg3, int, 1, int, 2, int, 3);
-+ DTRACE_PROBE(sdt__test__arg4, int, 1, int, 2, int, 3, int, 4);
-+ DTRACE_PROBE(sdt__test__arg5, int, 1, int, 2, int, 3, int, 4, int, 5);
-+ DTRACE_PROBE(sdt__test__arg6, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6);
-+ DTRACE_PROBE(sdt__test__arg7, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7);
-+ DTRACE_PROBE(sdt__test__arg8, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8);
-+ DTRACE_PROBE(sdt__test__arg9, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9);
-+ DTRACE_PROBE(sdt__test__arga, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10);
-+ DTRACE_PROBE(sdt__test__argb, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11);
-+ DTRACE_PROBE(sdt__test__argc, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12);
-+ DTRACE_PROBE(sdt__test__argd, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13);
-+ DTRACE_PROBE(sdt__test__arge, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13, int, 14);
-+ DTRACE_PROBE(sdt__test__argf, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13, int, 14, int, 15);
-+ DTRACE_PROBE(sdt__test__argg, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13, int, 14, int, 15, int, 16);
-+ DTRACE_PROBE(sdt__test__argh, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13, int, 14, int, 15, int, 16, int, 17);
-+ DTRACE_PROBE(sdt__test__argi, int, 1, int, 2, int, 3, int, 4, int, 5, int, 6, int, 7, int, 8, int, 9, int, 10, int, 11, int, 12, int, 13, int, 14, int, 15, int, 16, int, 17, int, 18);
-+
- return -EAGAIN;
- }
-
-diff --git a/dtrace/dt_test_mod.c b/dtrace/dt_test_mod.c
-index d8af71665a37ad3157f1bf9d2ce14cb0a23f7508..a86c8bc02ae9627c62ea083a60b9c0f5aac403ea 100644
---- a/dtrace/dt_test_mod.c
-+++ b/dtrace/dt_test_mod.c
-@@ -50,3 +50,8 @@ static struct dtrace_pops dt_test_pops = {
- };
-
- DT_PROVIDER_MODULE(dt_test, DTRACE_PRIV_USER)
-+
-+void foo(void)
-+{
-+ DTRACE_PROBE(sdt__test2);
-+}
-diff --git a/dtrace/sdt_dev.c b/dtrace/sdt_dev.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..78457dad87736694dc591a04498e36c61fbb4661
---- /dev/null
-+++ b/dtrace/sdt_dev.c
-@@ -0,0 +1,562 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: sdt_dev.c
-+ * DESCRIPTION: DTrace - SDT provider device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/ctype.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/sdt.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+#include <linux/vmalloc.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "sdt_impl.h"
-+
-+#define SDT_PROBETAB_SIZE 0x1000 /* 4k entries -- 16K total */
-+
-+struct sdt_probe **sdt_probetab;
-+int sdt_probetab_size;
-+int sdt_probetab_mask;
-+
-+/*
-+ * Return, in newly-allocated space, a version of the passed-in type 'vartype'
-+ * which has been cleaned up suitably for CTF: leading and trailing spaces (if
-+ * any) removed, and optionally a trailing argument removed as well.
-+ *
-+ * Type strings look like either
-+ *
-+ * type (for SDT, as in function prototypes), or
-+ *
-+ * type argname (for perf: as in function declarations).
-+ *
-+ * Translator components ": (foo, foo)", if any, have been removed by this
-+ * stage.
-+ */
-+static char *cleanup_type(const char *vartype, int arg_strip)
-+{
-+ const char *cleaned;
-+ const char *p;
-+
-+ cleaned = vartype + strspn(vartype, " \t");
-+ for (p = cleaned + strlen(cleaned) - 1; p > cleaned && isspace(*p);
-+ p--);
-+ if (arg_strip) {
-+ for (; p > cleaned && (isalnum(*p) || *p == '_'); p--);
-+ for (; p > cleaned && isspace(*p); p--);
-+ }
-+ p++;
-+
-+ return kstrndup(cleaned, p - cleaned, GFP_KERNEL);
-+}
-+
-+/*
-+ * Set up the args lists, extracting them from their sdpd entry and parsing them
-+ * into an sdt_argdesc array for each probe.
-+ */
-+static struct sdt_argdesc *
-+sdt_setup_args(struct sdt_probedesc *sdpd,
-+ size_t *sdp_nargdesc)
-+{
-+ struct sdt_argdesc *args;
-+ char *argstr;
-+ char *p;
-+ int arg_strip = 0;
-+ char *next_arg = NULL;
-+ size_t arg = 0, sarg = 0, i;
-+
-+ *sdp_nargdesc = 0;
-+
-+ if ((sdpd->sdpd_args == NULL) || (sdpd->sdpd_args[0] == '\0'))
-+ return NULL;
-+
-+ /*
-+ * Take a copy of the string so we can mutate it without causing trouble
-+ * on module reload.
-+ */
-+ argstr = kstrdup(sdpd->sdpd_args, GFP_KERNEL);
-+ if (argstr == NULL)
-+ goto oom;
-+
-+ /*
-+ * Handle the common case of a trailing comma before we allocate space,
-+ * and elide it.
-+ */
-+ p = argstr + strlen(argstr) - 1;
-+ if (p[0] == ',' && p[1] == '\0')
-+ *p = '\0';
-+
-+ /*
-+ * This works for counting the number of args even though translator
-+ * strings can contain commas, because each comma denotes a new probe
-+ * argument. It may overcount in the case of elided arguments
-+ * ("foo : ,"): we compensate for that further down, and ignore the tiny
-+ * memory leak that results.
-+ */
-+ for (p = argstr; p != NULL; p = strchr(p + 1, ','))
-+ (*sdp_nargdesc)++;
-+
-+ args = kzalloc(*sdp_nargdesc * sizeof(struct sdt_argdesc),
-+ GFP_KERNEL);
-+ if (args == NULL)
-+ goto oom_argstr;
-+
-+ /*
-+ * We need to transform each arg (stripping off a terminal argument
-+ * name) if this is a perf probe.
-+ */
-+ if (strncmp(sdpd->sdpd_name, "__perf_", strlen("__perf_")) == 0)
-+ arg_strip = 1;
-+
-+ next_arg = argstr;
-+ do {
-+ char *tok;
-+ char *xlator = NULL, *p;
-+ char *native;
-+ int parens = 0;
-+ int empty_xlation;
-+
-+ /*
-+ * Find the end of this arg, and figure out if it has any
-+ * translators. Clean up the type of the arg (or native type,
-+ * if this is a translated type).
-+ */
-+ tok = next_arg;
-+ next_arg = NULL;
-+ p = strpbrk(tok, "():,");
-+ while (p && !next_arg) {
-+ switch (*p) {
-+ case '(':
-+ parens++;
-+ break;
-+ case ')':
-+ if (parens > 0)
-+ parens--;
-+ break;
-+ case ':':
-+ *p = '\0';
-+ xlator = p + 1;
-+ break;
-+ case ',':
-+ if (parens == 0) {
-+ *p = '\0';
-+ next_arg = p + 1;
-+ }
-+ break;
-+ }
-+ p = strpbrk(p + 1, "():,");
-+ }
-+
-+ native = cleanup_type(tok, arg_strip);
-+ if (native == NULL) {
-+ args[arg].sda_native = args[arg].sda_xlate = NULL;
-+ goto full_oom;
-+ }
-+
-+ /*
-+ * Special case: perf's DECLARE_TRACE_NOARGS passes a single arg
-+ * 'void'. Spot and skip it.
-+ */
-+ if (!xlator && arg_strip && strcmp(native, "void") == 0) {
-+ kfree(native);
-+ (*sdp_nargdesc)--;
-+ sarg++;
-+ continue;
-+ }
-+
-+ /*
-+ * No translator: straight mapping.
-+ */
-+ if (xlator == NULL) {
-+ ASSERT(arg < *sdp_nargdesc);
-+ args[arg].sda_mapping = sarg;
-+ args[arg].sda_native = native;
-+ args[arg].sda_xlate = NULL;
-+ arg++;
-+ sarg++;
-+ continue;
-+ }
-+
-+ /*
-+ * If this is a perf probe, warn: translations cannot exist for
-+ * these, and have no defined format yet in any case. We can
-+ * struggle on by assuming they look like SDT translations.
-+ */
-+ if (arg_strip)
-+ pr_warn("Perf probe %s has at least one SDT translation, "
-+ "which should be impossible.", sdpd->sdpd_name);
-+
-+ /*
-+ * Zero or more translations. (If there are zero, i.e. a pair
-+ * of empty parentheses or a colon with nothing after it, we
-+ * have to decrement the nargdesc.)
-+ */
-+
-+ empty_xlation = 1;
-+ while ((p = strsep(&xlator, "(,)")) != NULL) {
-+ /*
-+ * Skip the empty space before the ( or after the ).
-+ */
-+ if (strspn(p, " \t") == strlen(p))
-+ continue;
-+
-+ ASSERT(arg < *sdp_nargdesc);
-+
-+ empty_xlation = 0;
-+ args[arg].sda_mapping = sarg;
-+ args[arg].sda_native = kstrdup(native, GFP_KERNEL);
-+ args[arg].sda_xlate = cleanup_type(p, 0);
-+ if ((args[arg].sda_native == NULL) ||
-+ (args[arg].sda_xlate == NULL)) {
-+ pr_warn("Unable to create argdesc list for "
-+ "probe %s: out of memory\n",
-+ sdpd->sdpd_name);
-+ kfree(native);
-+ goto full_oom;
-+ }
-+ arg++;
-+ }
-+ if (empty_xlation)
-+ (*sdp_nargdesc)--;
-+
-+ kfree(native);
-+ sarg++;
-+ } while (next_arg != NULL);
-+
-+ kfree(argstr);
-+ return args;
-+
-+full_oom:
-+ for (i = 0; i < arg; i++) {
-+ kfree(args[i].sda_native);
-+ kfree(args[i].sda_xlate);
-+ }
-+ kfree(args);
-+oom_argstr:
-+ kfree(argstr);
-+oom:
-+ *sdp_nargdesc = 0;
-+ pr_warn("Unable to create argdesc list for probe %s: "
-+ "out of memory\n", sdpd->sdpd_name);
-+ return NULL;
-+}
-+
-+void sdt_provide_module(void *arg, struct module *mp)
-+{
-+ char *modname = mp->name;
-+ struct dtrace_mprovider *prov;
-+ struct sdt_probedesc *sdpd;
-+ struct sdt_probe *sdp, *prv;
-+ int idx, len;
-+ int probes_skipped = 0;
-+
-+ /* If module setup has failed then do not provide anything. */
-+ if (PDATA(mp) == NULL)
-+ return;
-+
-+ /*
-+ * Nothing to do if the module SDT probes were already created.
-+ */
-+ if (PDATA(mp)->sdt_probe_cnt != 0)
-+ return;
-+
-+ /*
-+ * Nothing to do if there are no SDT probes.
-+ */
-+ if (mp->sdt_probec == 0)
-+ return;
-+
-+ /*
-+ * Nothing if arch specific module setup fails.
-+ */
-+ if (!sdt_provide_module_arch(NULL, mp))
-+ return;
-+
-+ /*
-+ * Do not provide any probes unless all SDT providers have been created
-+ * for this meta-provider.
-+ */
-+ for (prov = sdt_providers; prov->dtmp_name != NULL; prov++) {
-+ if (prov->dtmp_id == DTRACE_PROVNONE)
-+ return;
-+ }
-+
-+ for (idx = 0, sdpd = mp->sdt_probes; idx < mp->sdt_probec;
-+ idx++, sdpd++) {
-+ char *name = sdpd->sdpd_name, *nname;
-+ int i, j;
-+ struct dtrace_mprovider *prov;
-+ dtrace_id_t id;
-+ enum fasttrap_probe_type ptype;
-+
-+ if (name[0] == '?') {
-+ ptype = SDTPT_IS_ENABLED;
-+ name++;
-+ } else
-+ ptype = SDTPT_OFFSETS;
-+
-+ for (prov = sdt_providers; prov->dtmp_pref != NULL; prov++) {
-+ char *prefix = prov->dtmp_pref;
-+ int len = strlen(prefix);
-+
-+ if (strncmp(name, prefix, len) == 0) {
-+ name += len;
-+ break;
-+ }
-+ }
-+
-+ nname = kmalloc(len = strlen(name) + 1, GFP_KERNEL);
-+ if (nname == NULL) {
-+ probes_skipped++;
-+ continue;
-+ }
-+
-+ for (i = j = 0; name[j] != '\0'; i++) {
-+ if (name[j] == '_' && name[j + 1] == '_') {
-+ nname[i] = '-';
-+ j += 2;
-+ } else
-+ nname[i] = name[j++];
-+ }
-+
-+ nname[i] = '\0';
-+
-+ sdp = kzalloc(sizeof(struct sdt_probe), GFP_KERNEL);
-+ if (sdp == NULL) {
-+ probes_skipped++;
-+ continue;
-+ }
-+
-+ sdp->sdp_loadcnt = 1; /* FIXME */
-+ sdp->sdp_module = mp;
-+ sdp->sdp_name = nname;
-+ sdp->sdp_namelen = len;
-+ sdp->sdp_provider = prov;
-+ sdp->sdp_ptype = ptype;
-+
-+ sdp->sdp_argdesc = sdt_setup_args(sdpd, &sdp->sdp_nargdesc);
-+
-+ id = dtrace_probe_lookup(prov->dtmp_id, modname,
-+ sdpd->sdpd_func, nname);
-+ if (id != DTRACE_IDNONE) {
-+ prv = dtrace_probe_arg(prov->dtmp_id, id);
-+ ASSERT(prv != NULL);
-+
-+ sdp->sdp_next = prv->sdp_next;
-+ sdp->sdp_id = id;
-+ prv->sdp_next = sdp;
-+ } else {
-+ sdp->sdp_id = dtrace_probe_create(prov->dtmp_id,
-+ modname,
-+ sdpd->sdpd_func,
-+ nname, SDT_AFRAMES,
-+ sdp);
-+
-+ /*
-+ * If we failed to create the probe just skip it.
-+ */
-+ if (sdp->sdp_id == DTRACE_IDNONE) {
-+ kfree(sdp);
-+ probes_skipped++;
-+ continue;
-+ }
-+
-+ PDATA(mp)->sdt_probe_cnt++;
-+ }
-+
-+ sdp->sdp_patchpoint = (asm_instr_t *)sdpd->sdpd_offset;
-+
-+ sdt_provide_probe_arch(sdp, mp, idx);
-+
-+ sdp->sdp_hashnext = sdt_probetab[
-+ SDT_ADDR2NDX(sdp->sdp_patchpoint)];
-+ sdt_probetab[SDT_ADDR2NDX(sdp->sdp_patchpoint)] = sdp;
-+ }
-+
-+ if (probes_skipped != 0)
-+ pr_warn("sdt: Failed to provide %d probes in %s (out of memory)\n",
-+ probes_skipped, mp->name);
-+}
-+
-+int sdt_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct sdt_probe *sdp = parg;
-+ struct sdt_probe *curr;
-+
-+ /*
-+ * Ensure that we have a reference to the module.
-+ */
-+ if (!try_module_get(sdp->sdp_module))
-+ return -EAGAIN;
-+
-+ /*
-+ * If at least one other enabled probe exists for this module, drop the
-+ * reference we took above, because we only need one to prevent the
-+ * module from being unloaded.
-+ */
-+ PDATA(sdp->sdp_module)->enabled_cnt++;
-+ if (PDATA(sdp->sdp_module)->enabled_cnt > 1)
-+ module_put(sdp->sdp_module);
-+
-+ for (curr = sdp; curr != NULL; curr = curr->sdp_next)
-+ sdt_enable_arch(curr, id, arg);
-+
-+ return 0;
-+}
-+
-+void sdt_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct sdt_probe *sdp = parg;
-+ struct sdt_probe *curr;
-+
-+ for (curr = sdp; curr != NULL; curr = curr->sdp_next)
-+ sdt_disable_arch(curr, id, arg);
-+
-+ /*
-+ * If we are disabling a probe, we know it was enabled, and therefore
-+ * we know that we have a reference on the module to prevent it from
-+ * being unloaded. If we disable the last probe on the module, we can
-+ * drop the reference.
-+ */
-+ PDATA(sdp->sdp_module)->enabled_cnt--;
-+ if (PDATA(sdp->sdp_module)->enabled_cnt == 0)
-+ module_put(sdp->sdp_module);
-+}
-+
-+void sdt_getargdesc(void *arg, dtrace_id_t id, void *parg,
-+ struct dtrace_argdesc *desc)
-+{
-+ struct sdt_probe *sdp = parg;
-+
-+ desc->dtargd_native[0] = '\0';
-+ desc->dtargd_xlate[0] = '\0';
-+
-+ while ((sdp->sdp_ptype == SDTPT_IS_ENABLED) &&
-+ (sdp->sdp_next != NULL))
-+ sdp = sdp->sdp_next;
-+
-+ if (sdp->sdp_nargdesc <= desc->dtargd_ndx) {
-+ desc->dtargd_ndx = DTRACE_ARGNONE;
-+ return;
-+ }
-+
-+ if (sdp->sdp_argdesc[desc->dtargd_ndx].sda_native != NULL)
-+ strlcpy(desc->dtargd_native,
-+ sdp->sdp_argdesc[desc->dtargd_ndx].sda_native,
-+ sizeof(desc->dtargd_native));
-+
-+ if (sdp->sdp_argdesc[desc->dtargd_ndx].sda_xlate != NULL)
-+ strlcpy(desc->dtargd_xlate,
-+ sdp->sdp_argdesc[desc->dtargd_ndx].sda_xlate,
-+ sizeof(desc->dtargd_xlate));
-+
-+ desc->dtargd_mapping = sdp->sdp_argdesc[desc->dtargd_ndx].sda_mapping;
-+}
-+
-+void sdt_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct sdt_probe *sdp = parg;
-+
-+ PDATA(sdp->sdp_module)->sdt_probe_cnt--;
-+
-+ while (sdp != NULL) {
-+ struct sdt_probe *old = sdp, *last, *hash;
-+ int ndx;
-+ size_t i;
-+
-+ ndx = SDT_ADDR2NDX(sdp->sdp_patchpoint);
-+ last = NULL;
-+ hash = sdt_probetab[ndx];
-+
-+ while (hash != sdp) {
-+ ASSERT(hash != NULL);
-+ last = hash;
-+ hash = hash->sdp_hashnext;
-+ }
-+
-+ if (last != NULL)
-+ last->sdp_hashnext = sdp->sdp_hashnext;
-+ else
-+ sdt_probetab[ndx] = sdp->sdp_hashnext;
-+
-+ for (i = 0; i < sdp->sdp_nargdesc; i++) {
-+ kfree(sdp->sdp_argdesc[i].sda_native);
-+ kfree(sdp->sdp_argdesc[i].sda_xlate);
-+ }
-+ kfree(sdp->sdp_argdesc);
-+ kfree(sdp->sdp_name);
-+ sdp = sdp->sdp_next;
-+ kfree(old);
-+ }
-+}
-+
-+static int sdt_open(struct inode *inode, struct file *file)
-+{
-+ return -EAGAIN;
-+}
-+
-+static int sdt_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations sdt_fops = {
-+ .owner = THIS_MODULE,
-+ .open = sdt_open,
-+ .release = sdt_close,
-+};
-+
-+static struct miscdevice sdt_dev = {
-+ .minor = DT_DEV_SDT_MINOR,
-+ .name = "sdt",
-+ .nodename = "dtrace/provider/sdt",
-+ .fops = &sdt_fops,
-+};
-+
-+int sdt_dev_init(void)
-+{
-+ int ret = 0;
-+
-+ ret = misc_register(&sdt_dev);
-+ if (ret) {
-+ pr_err("%s: Can't register misc device %d\n",
-+ sdt_dev.name, sdt_dev.minor);
-+ return ret;
-+ }
-+
-+ if (sdt_probetab_size == 0)
-+ sdt_probetab_size = SDT_PROBETAB_SIZE;
-+
-+ sdt_probetab_mask = sdt_probetab_size - 1;
-+ sdt_probetab = vzalloc(sdt_probetab_size * sizeof(struct sdt_probe *));
-+ if (sdt_probetab == NULL)
-+ return -ENOMEM;
-+
-+ sdt_dev_init_arch();
-+
-+ return ret;
-+}
-+
-+void sdt_dev_exit(void)
-+{
-+ sdt_dev_exit_arch();
-+
-+ vfree(sdt_probetab);
-+
-+ misc_deregister(&sdt_dev);
-+}
-diff --git a/dtrace/sdt_impl.h b/dtrace/sdt_impl.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..e5b7f4f802706a9eb0fcdd3b9958a7e29d9ae055
---- /dev/null
-+++ b/dtrace/sdt_impl.h
-@@ -0,0 +1,87 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Statically Defined Tracing provider
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _SDT_IMPL_H_
-+#define _SDT_IMPL_H_
-+
-+#include <linux/sdt.h>
-+#include <asm/dtrace_arch.h>
-+#include <dtrace/sdt_arch.h>
-+
-+extern struct module *dtrace_kmod;
-+
-+struct sdt_argdesc;
-+
-+enum fasttrap_probe_type {
-+ SDTPT_NONE = 0,
-+ SDTPT_OFFSETS,
-+ SDTPT_IS_ENABLED
-+};
-+
-+struct sdt_probe {
-+ struct dtrace_mprovider *sdp_provider; /* provider */
-+ char *sdp_name; /* name of probe */
-+ int sdp_namelen; /* length of allocated name */
-+ dtrace_id_t sdp_id; /* probe ID */
-+ struct module *sdp_module; /* modctl for module */
-+ int sdp_loadcnt; /* load count for module */
-+ int sdp_primary; /* non-zero if primary mod */
-+ enum fasttrap_probe_type sdp_ptype; /* probe type */
-+ asm_instr_t *sdp_patchpoint;/* patch point */
-+ asm_instr_t sdp_patchval; /* instruction to patch */
-+ asm_instr_t sdp_savedval; /* saved instruction value */
-+ struct sdt_argdesc *sdp_argdesc; /* arguments for this probe */
-+ size_t sdp_nargdesc; /* number of arguments */
-+ struct sdt_probe *sdp_next; /* next probe */
-+ struct sdt_probe *sdp_hashnext; /* next on hash */
-+};
-+
-+struct sdt_argdesc {
-+ int sda_mapping;
-+ char *sda_native;
-+ char *sda_xlate;
-+};
-+
-+extern struct dtrace_mprovider sdt_providers[];
-+extern struct sdt_probe **sdt_probetab;
-+extern int sdt_probetab_size;
-+extern int sdt_probetab_mask;
-+
-+#define SDT_ADDR2NDX(addr) ((((uintptr_t)(addr)) >> 4) & \
-+ sdt_probetab_mask)
-+
-+extern void sdt_provide_probe_arch(struct sdt_probe *, struct module *, int);
-+extern int sdt_provide_module_arch(void *, struct module *);
-+extern void sdt_enable_arch(struct sdt_probe *, dtrace_id_t, void *);
-+extern void sdt_disable_arch(struct sdt_probe *, dtrace_id_t, void *);
-+
-+extern void sdt_provide_module(void *, struct module *);
-+extern void sdt_destroy_module(void *, struct module *);
-+extern int sdt_enable(void *, dtrace_id_t, void *);
-+extern void sdt_disable(void *, dtrace_id_t, void *);
-+extern void sdt_getargdesc(void *, dtrace_id_t, void *,
-+ struct dtrace_argdesc *);
-+extern uint64_t sdt_getarg(void *, dtrace_id_t, void *, int, int);
-+extern void sdt_destroy(void *, dtrace_id_t, void *);
-+
-+extern int sdt_dev_init(void);
-+extern void sdt_dev_exit(void);
-+
-+extern int sdt_dev_init_arch(void);
-+extern void sdt_dev_exit_arch(void);
-+
-+#endif /* _SDT_IMPL_H_ */
-diff --git a/dtrace/sdt_mod.c b/dtrace/sdt_mod.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..1de9e72396aa001e567b05f57e2c83df602b34d2
---- /dev/null
-+++ b/dtrace/sdt_mod.c
-@@ -0,0 +1,154 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: sdt_mod.c
-+ * DESCRIPTION: DTrace - SDT provider kernel module
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "sdt_impl.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("Profile Interrupt Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+static struct dtrace_pattr vtrace_attr = {
-+{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr info_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr fc_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr fpu_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_CPU },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr fsinfo_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr stab_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr sdt_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr xpv_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_PLATFORM },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
-+};
-+
-+static struct dtrace_pattr iscsi_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pattr perf_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pops sdt_pops = {
-+ .dtps_provide = NULL,
-+ .dtps_provide_module = sdt_provide_module,
-+ .dtps_destroy_module = sdt_destroy_module,
-+ .dtps_enable = sdt_enable,
-+ .dtps_disable = sdt_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = sdt_getargdesc,
-+#ifdef CONFIG_SPARC64
-+ .dtps_getargval = NULL,
-+#else
-+ .dtps_getargval = sdt_getarg,
-+#endif
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = sdt_destroy,
-+};
-+
-+struct dtrace_mprovider sdt_providers[] = {
-+ { "vtrace", "__vtrace_", &vtrace_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "sysinfo", "__cpu_sysinfo_", &info_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "vminfo", "__cpu_vminfo_", &info_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "fpuinfo", "__fpuinfo_", &fpu_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "sched", "__sched_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "proc", "__proc_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "io", "__io_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "ip", "__ip_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "lockstat", "__lockstat_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "tcp", "__tcp_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "udp", "__udp_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "mib", "__mib_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "fsinfo", "__fsinfo_", &fsinfo_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "iscsi", "__iscsi_", &iscsi_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "nfsv3", "__nfsv3_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "nfsv4", "__nfsv4_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "xpv", "__xpv_", &xpv_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "fc", "__fc_", &fc_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "srp", "__srp_", &fc_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "sysevent", "__sysevent_", &stab_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "perf", "__perf_", &perf_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { "sdt", NULL, &sdt_attr, DTRACE_PRIV_KERNEL, &sdt_pops, 0 },
-+ { NULL }
-+};
-+
-+DT_MULTI_PROVIDER_MODULE(sdt, sdt_providers)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0010-dtrace-profile-provider-and-test-probe-core-componen.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0010-dtrace-profile-provider-and-test-probe-core-componen.patch
deleted file mode 100644
index 92372496ab66..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0010-dtrace-profile-provider-and-test-probe-core-componen.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From 59b5eca72202d66370501cd651aef50b19ceb918 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 17:18:23 +0000
-Subject: [PATCH 10/19] dtrace: profile provider and test probe core components
-
-Only Kconfig changes are needed here: everything else is purely modular.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- kernel/dtrace/Kconfig | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-index c1ec55d8750edfbaf55ab9431b7c822b3dd2afae..7b88206fe835fa14bb10484b658ce514d642112a 100644
---- a/kernel/dtrace/Kconfig
-+++ b/kernel/dtrace/Kconfig
-@@ -23,6 +23,12 @@ config DT_CORE
-
- if DT_CORE
-
-+config DT_PROFILE
-+ tristate "Profile Interrupt Tracing"
-+ default m
-+ help
-+ The profile and tick providers, firing probes at specific intervals.
-+
- config DT_SDT
- tristate "Statically Defined Tracing"
- default m
-@@ -54,6 +60,12 @@ config DT_DT_TEST
- help
- A test provider used by the testsuite.
-
-+config DT_DT_PERF
-+ tristate "DTrace Performance Test Probe"
-+ default m
-+ help
-+ A test provider used for performance testing.
-+
- config DT_DEBUG
- bool "DTrace debugging"
- default m
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch
deleted file mode 100644
index 67c6d9f83eb5..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0011-dtrace-profile-and-tick-providers-built-on-cyclics.patch
+++ /dev/null
@@ -1,641 +0,0 @@
-From f7a0d3e1af253e7887d41af5f199fc2561372448 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 18:05:13 +0000
-Subject: [PATCH 11/19] dtrace: profile and tick providers built on cyclics
-
-Probes are constructed dynamically as called upon by the user: some
-default commonly-used probes for common timing frequencies are provided
-whether or not called upon.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- dtrace/Makefile | 2 +
- dtrace/profile.h | 32 +++
- dtrace/profile_dev.c | 491 +++++++++++++++++++++++++++++++++++++++++++
- dtrace/profile_mod.c | 52 +++++
- 4 files changed, 577 insertions(+)
- create mode 100644 dtrace/profile.h
- create mode 100644 dtrace/profile_dev.c
- create mode 100644 dtrace/profile_mod.c
-
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-index 126d4985967a2478ea2df97ab42eb384e6fe14d2..5e6fb362a4e96afbcef906dc7eae12c6c6ad5b04 100644
---- a/dtrace/Makefile
-+++ b/dtrace/Makefile
-@@ -3,6 +3,7 @@
- #
-
- obj-$(CONFIG_DT_CORE) += dtrace.o
-+obj-$(CONFIG_DT_PROFILE) += profile.o
- obj-$(CONFIG_DT_SDT) += sdt.o
- obj-$(CONFIG_DT_SYSTRACE) += systrace.o
- obj-$(CONFIG_DT_DT_TEST) += dt_test.o
-@@ -16,6 +17,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \
- dtrace_probe.o dtrace_probe_ctx.o \
- dtrace_ptofapi.o dtrace_predicate.o \
- dtrace_spec.o dtrace_state.o dtrace_util.o
-+profile-y := profile_mod.o profile_dev.o
- sdt-y := sdt_mod.o sdt_dev.o
- systrace-y := systrace_mod.o systrace_dev.o
- dt_test-y := dt_test_mod.o dt_test_dev.o
-diff --git a/dtrace/profile.h b/dtrace/profile.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..713886d1d8e826fef100cb929ecb54d9a9f5a07c
---- /dev/null
-+++ b/dtrace/profile.h
-@@ -0,0 +1,32 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - profile provider
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _PROFILE_H_
-+#define _PROFILE_H_
-+
-+extern void profile_provide(void *, const struct dtrace_probedesc *);
-+extern int profile_enable(void *, dtrace_id_t, void *);
-+extern void profile_disable(void *, dtrace_id_t, void *);
-+extern int profile_usermode(void *, dtrace_id_t, void *);
-+extern void profile_destroy(void *, dtrace_id_t, void *);
-+
-+extern dtrace_provider_id_t profile_id;
-+
-+extern int profile_dev_init(void);
-+extern void profile_dev_exit(void);
-+
-+#endif /* _PROFILE_H_ */
-diff --git a/dtrace/profile_dev.c b/dtrace/profile_dev.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..ce7261fcc911fd4589502e4b170a0b3e3e97dc99
---- /dev/null
-+++ b/dtrace/profile_dev.c
-@@ -0,0 +1,491 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: profile_dev.c
-+ * DESCRIPTION: DTrace - profile provider device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/ktime.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <asm/irq_regs.h>
-+#include <asm/ptrace.h>
-+
-+#include <linux/hardirq.h>
-+#include <linux/profile.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "profile.h"
-+
-+#define PROF_NAMELEN 15
-+#define PROF_PROFILE 0
-+#define PROF_TICK 1
-+#define PROF_PREFIX_PROFILE "profile-"
-+#define PROF_PREFIX_TICK "tick-"
-+
-+struct profile_probe {
-+ char prof_name[PROF_NAMELEN];
-+ dtrace_id_t prof_id;
-+ int prof_kind;
-+ ktime_t prof_interval;
-+ cyclic_id_t prof_cyclic;
-+};
-+
-+struct profile_probe_percpu {
-+ ktime_t profc_expected;
-+ ktime_t profc_interval;
-+ struct profile_probe *profc_probe;
-+};
-+
-+static ktime_t profile_interval_min = KTIME_INIT(0, NANOSEC / 5000);
-+static int profile_aframes;
-+
-+static int profile_rates[] = {
-+ 97, 199, 499, 997, 1999,
-+ 4001, 4999, 0, 0, 0,
-+ 0, 0, 0, 0, 0,
-+ 0, 0, 0, 0, 0,
-+ };
-+static int profile_ticks[] = {
-+ 1, 10, 100, 500, 1000,
-+ 5000, 0, 0, 0, 0,
-+ 0, 0, 0, 0, 0,
-+ };
-+
-+/*
-+ * profile_max defines the upper bound on the number of profile probes that
-+ * can exist (this is to prevent malicious or clumsy users from exhausing
-+ * system resources by creating a slew of profile probes). At mod load time,
-+ * this gets its value from PROFILE_MAX_DEFAULT or profile-max-probes if it's
-+ * present as module parameter.
-+ * FIXME: module parameter yet to be implemented.
-+ */
-+#define PROFILE_MAX_DEFAULT 1000 /* default max. number of probes */
-+
-+static int profile_max; /* maximum number of profile probes */
-+static atomic_t profile_total; /* current number of profile probes */
-+
-+static void profile_tick_fn(uintptr_t arg)
-+{
-+ struct profile_probe *prof = (struct profile_probe *)arg;
-+ unsigned long pc = 0, upc = 0;
-+ struct pt_regs *regs = get_irq_regs();
-+
-+ /*
-+ * If regs == NULL, then we were called from from softirq context which
-+ * also means that we didn't actually interrupt any processing (kernel
-+ * or user space).
-+ * If regs != NULL, then we did actually get called from hardirq
-+ * because the timer interrupt did really interrupt something that was
-+ * going on on the CPU (could be user mode or kernel mode).
-+ */
-+ if (regs == NULL) {
-+ uint64_t stack[8];
-+
-+ dtrace_getpcstack(stack, 8, 0, NULL);
-+ pc = stack[7];
-+ } else if (user_mode(regs))
-+ upc = instruction_pointer(regs);
-+ else
-+ pc = instruction_pointer(regs);
-+
-+ dtrace_probe(prof->prof_id, pc, upc, 0, 0, 0, 0, 0);
-+}
-+
-+static void profile_prof_fn(uintptr_t arg)
-+{
-+ struct profile_probe_percpu *pcpu = (struct profile_probe_percpu *)arg;
-+ struct profile_probe *prof = pcpu->profc_probe;
-+ ktime_t late;
-+ struct pt_regs *regs = get_irq_regs();
-+ unsigned long pc = 0, upc = 0;
-+
-+ late = ktime_sub(dtrace_gethrtime(), pcpu->profc_expected);
-+ pcpu->profc_expected = ktime_add(pcpu->profc_expected,
-+ pcpu->profc_interval);
-+
-+ /*
-+ * If regs == NULL, then we were called from from softirq context which
-+ * also means that we didn't actually interrupt any processing (kernel
-+ * or user space).
-+ * If regs != NULL, then we did actually get called from hardirq
-+ * because the timer interrupt did really interrupt something that was
-+ * going on on the CPU (could be user mode or kernel mode).
-+ */
-+ if (regs == NULL) {
-+ uint64_t stack[8];
-+
-+ dtrace_getpcstack(stack, 8, 0, NULL);
-+ pc = stack[7];
-+ } else if (user_mode(regs))
-+ upc = instruction_pointer(regs);
-+ else
-+ pc = instruction_pointer(regs);
-+
-+ dtrace_probe(prof->prof_id, pc, upc, ktime_to_ns(late), 0, 0, 0, 0);
-+}
-+
-+static void profile_online(void *arg, processorid_t cpu,
-+ struct cyc_handler *hdlr,
-+ struct cyc_time *when)
-+{
-+ struct profile_probe *prof = arg;
-+ struct profile_probe_percpu *pcpu;
-+
-+ pcpu = kzalloc(sizeof(struct profile_probe_percpu), GFP_KERNEL);
-+ pcpu->profc_probe = prof;
-+
-+ hdlr->cyh_func = profile_prof_fn;
-+ hdlr->cyh_arg = (uintptr_t)pcpu;
-+ hdlr->cyh_level = CY_HIGH_LEVEL;
-+
-+ when->cyt_interval = prof->prof_interval;
-+ when->cyt_when = ktime_add(dtrace_gethrtime(), when->cyt_interval);
-+
-+ pcpu->profc_expected = when->cyt_when;
-+ pcpu->profc_interval = when->cyt_interval;
-+}
-+
-+static void profile_offline(void *arg, processorid_t cpu, void *oarg)
-+{
-+ struct profile_probe_percpu *pcpu = oarg;
-+
-+ if (pcpu->profc_probe == arg) {
-+ kfree(pcpu);
-+ return;
-+ }
-+
-+ WARN_ONCE(1, "%s: called with mismatched probe info (%p vs %p)"
-+ " - leaking %lu bytes\n", __func__, pcpu->profc_probe, arg,
-+ sizeof(struct profile_probe_percpu));
-+
-+}
-+
-+static void profile_create(ktime_t interval, const char *name, int kind)
-+{
-+ struct profile_probe *prof;
-+ int nr_frames = 0; /* FIXME */
-+
-+ if (profile_aframes)
-+ nr_frames = profile_aframes;
-+
-+ if (ktime_lt(interval, profile_interval_min))
-+ return;
-+
-+ if (dtrace_probe_lookup(profile_id, NULL, NULL, name) != 0)
-+ return;
-+
-+ prof = kzalloc(sizeof(struct profile_probe), GFP_KERNEL);
-+ if (prof == NULL) {
-+ pr_warn("Unable to create probe %s: out of memory\n", name);
-+ return;
-+ }
-+
-+ atomic_inc(&profile_total);
-+ if (atomic_read(&profile_total) > profile_max)
-+ goto errout;
-+
-+ strcpy(prof->prof_name, name);
-+ prof->prof_interval = interval;
-+ prof->prof_cyclic = CYCLIC_NONE;
-+ prof->prof_kind = kind;
-+ prof->prof_id = dtrace_probe_create(profile_id, NULL, NULL, name,
-+ nr_frames, prof);
-+
-+ if (prof->prof_id == DTRACE_IDNONE) {
-+ pr_warn("Unable to create probe %s: out of memory\n", name);
-+ goto errout;
-+ }
-+
-+ return;
-+
-+errout:
-+ kfree(prof);
-+ atomic_dec(&profile_total);
-+ return;
-+}
-+
-+void profile_provide(void *arg, const struct dtrace_probedesc *desc)
-+{
-+ int i, j, rate, kind;
-+ long val = 0, mult = 1, mult_s = 0, mult_ns = 0, len;
-+ ktime_t interval;
-+ const char *name, *suffix = NULL;
-+ const struct {
-+ char *prefix;
-+ int kind;
-+ } types[] = {
-+ { PROF_PREFIX_PROFILE, PROF_PROFILE },
-+ { PROF_PREFIX_TICK, PROF_TICK },
-+ { NULL, 0 },
-+ };
-+
-+ const struct {
-+ char *name;
-+ long mult_s;
-+ long mult_ns;
-+ } suffixes[] = {
-+ { "ns", 0, 1 },
-+ { "nsec", 0, 1 },
-+ { "us", 0, NANOSEC / MICROSEC },
-+ { "usec", 0, NANOSEC / MICROSEC },
-+ { "ms", 0, NANOSEC / MILLISEC },
-+ { "msec", 0, NANOSEC / MILLISEC },
-+ { "s", 1, 0 },
-+ { "sec", 1, 0 },
-+ { "m", 60, 0 },
-+ { "min", 60, 0 },
-+ { "h", 60 * 60, 0 },
-+ { "hour", 60 * 60, 0 },
-+ { "d", 24 * 60 * 60, 0 },
-+ { "day", 24 * 60 * 60, 0 },
-+ { "hz", 0, 0 },
-+ { NULL, },
-+ };
-+
-+ if (desc == NULL) {
-+ char n[PROF_NAMELEN];
-+
-+ /*
-+ * If no description was provided, provide all of our probes.
-+ */
-+ for (i = 0; i < sizeof(profile_rates) / sizeof(int); i++) {
-+ rate = profile_rates[i];
-+ if (rate == 0)
-+ continue;
-+
-+ snprintf(n, PROF_NAMELEN, "%s%d",
-+ PROF_PREFIX_PROFILE, rate);
-+ profile_create(ktime_set(0, NANOSEC / rate),
-+ n, PROF_PROFILE);
-+ }
-+
-+ for (i = 0; i < sizeof(profile_ticks) / sizeof(int); i++) {
-+ rate = profile_ticks[i];
-+ if (rate == 0)
-+ continue;
-+
-+ snprintf(n, PROF_NAMELEN, "%s%d",
-+ PROF_PREFIX_TICK, rate);
-+ profile_create(ktime_set(0, NANOSEC / rate),
-+ n, PROF_TICK);
-+ }
-+
-+ return;
-+ }
-+
-+ name = desc->dtpd_name;
-+
-+ for (i = 0; types[i].prefix != NULL; i++) {
-+ len = strlen(types[i].prefix);
-+
-+ if (strncmp(name, types[i].prefix, len) != 0)
-+ continue;
-+
-+ break;
-+ }
-+
-+ if (types[i].prefix == NULL)
-+ return;
-+
-+ kind = types[i].kind;
-+
-+ /*
-+ * We need to start before any time suffix.
-+ */
-+ for (j = strlen(name); j >= len; j--) {
-+ if (name[j] >= '0' && name[j] <= '9')
-+ break;
-+
-+ suffix = &name[j];
-+ }
-+
-+ if (suffix == NULL) {
-+ WARN_ONCE(1, "%s: missing time suffix in %s\n", __func__, name);
-+ return;
-+ }
-+
-+ /*
-+ * Now determine the numerical value present in the probe name.
-+ */
-+ for (; j >= len; j--) {
-+ if (name[j] < '0' || name[j] > '9')
-+ return;
-+
-+ val += (name[j] - '0') * mult;
-+ mult *= 10;
-+ }
-+
-+ if (val == 0)
-+ return;
-+
-+ /*
-+ * Look up the suffix to determine the multiplier.
-+ */
-+ for (i = 0; suffixes[i].name != NULL; i++) {
-+ if (strcasecmp(suffixes[i].name, suffix) == 0) {
-+ mult_s = suffixes[i].mult_s;
-+ mult_ns = suffixes[i].mult_ns;
-+ break;
-+ }
-+ }
-+
-+ if (suffixes[i].name == NULL && *suffix != '\0')
-+ return;
-+
-+ if (mult_s == 0 && mult_ns == 0) {
-+ /*
-+ * The default is frequency (per-second).
-+ */
-+ interval = ns_to_ktime((int64_t)NANOSEC / val);
-+ } else {
-+ long sec;
-+ long nsec = val * mult_ns;
-+
-+ sec = nsec / NANOSEC;
-+ nsec %= NANOSEC;
-+
-+ interval = ktime_set(val * mult_s + sec, nsec);
-+ }
-+
-+
-+ profile_create(interval, name, kind);
-+}
-+
-+int profile_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct profile_probe *prof = parg;
-+ struct cyc_time when;
-+
-+ if (!ktime_nz(prof->prof_interval)) {
-+ WARN_ONCE(1, "%s: trying to enable 0-interval probe %s\n",
-+ __func__, prof->prof_name);
-+ return 1;
-+ }
-+ if (!MUTEX_HELD(&cpu_lock)) {
-+ WARN_ONCE(1, "%s: not holding cpu_lock\n", __func__);
-+ return 1;
-+ }
-+
-+ if (prof->prof_kind == PROF_TICK) {
-+ struct cyc_handler hdlr;
-+
-+ hdlr.cyh_func = profile_tick_fn;
-+ hdlr.cyh_arg = (uintptr_t)prof;
-+ hdlr.cyh_level = CY_HIGH_LEVEL;
-+
-+ when.cyt_interval = prof->prof_interval;
-+ when.cyt_when = ktime_set(0, 0);
-+
-+ prof->prof_cyclic = cyclic_add(&hdlr, &when);
-+ } else if (prof->prof_kind == PROF_PROFILE) {
-+ struct cyc_omni_handler omni;
-+
-+ omni.cyo_online = profile_online;
-+ omni.cyo_offline = profile_offline;
-+ omni.cyo_arg = prof;
-+
-+ prof->prof_cyclic = cyclic_add_omni(&omni);
-+ } else
-+ pr_warn_once("%s: Invalid profile type %d\n",
-+ __func__, prof->prof_kind);
-+
-+ return 0;
-+}
-+
-+void profile_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct profile_probe *prof = parg;
-+
-+ if (prof->prof_cyclic == CYCLIC_NONE) {
-+ WARN_ONCE(1, "%s: trying to disable probe %s without cyclic\n",
-+ __func__, prof->prof_name);
-+ return;
-+ }
-+ if (!MUTEX_HELD(&cpu_lock)) {
-+ WARN_ONCE(1, "%s: not holding cpu_lock\n", __func__);
-+ return;
-+ }
-+
-+ cyclic_remove(prof->prof_cyclic);
-+ prof->prof_cyclic = CYCLIC_NONE;
-+}
-+
-+int profile_usermode(void *arg, dtrace_id_t id, void *parg)
-+{
-+ return 1; /* FIXME: awaiting unprivileged tracing */
-+}
-+
-+void profile_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct profile_probe *prof = parg;
-+
-+ if (prof->prof_cyclic == CYCLIC_NONE) {
-+ kfree(prof);
-+
-+ if (atomic_read(&profile_total) >= 1) {
-+ atomic_dec(&profile_total);
-+ return;
-+ }
-+
-+ WARN_ONCE(1, "%s: profile_total refcount is 0!\n", __func__);
-+ }
-+
-+ WARN_ONCE(1, "%s: %s still assigned to cyclic\n",
-+ __func__, prof->prof_name);
-+}
-+
-+static int profile_open(struct inode *inode, struct file *file)
-+{
-+ return -EAGAIN;
-+}
-+
-+static int profile_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations profile_fops = {
-+ .owner = THIS_MODULE,
-+ .open = profile_open,
-+ .release = profile_close,
-+};
-+
-+static struct miscdevice profile_dev = {
-+ .minor = DT_DEV_PROFILE_MINOR,
-+ .name = "profile",
-+ .nodename = "dtrace/provider/profile",
-+ .fops = &profile_fops,
-+};
-+
-+int profile_dev_init(void)
-+{
-+ int ret = 0;
-+
-+ ret = misc_register(&profile_dev);
-+ if (ret)
-+ pr_err("%s: Can't register misc device %d\n",
-+ profile_dev.name, profile_dev.minor);
-+
-+ profile_max = PROFILE_MAX_DEFAULT;
-+
-+ return ret;
-+}
-+
-+void profile_dev_exit(void)
-+{
-+ misc_deregister(&profile_dev);
-+}
-diff --git a/dtrace/profile_mod.c b/dtrace/profile_mod.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..1fb54a29e57ed642de6cc86615294dbf85557234
---- /dev/null
-+++ b/dtrace/profile_mod.c
-@@ -0,0 +1,52 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: profile_mod.c
-+ * DESCRIPTION: DTrace - Profile provider kernel module
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "profile.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("Profile Interrupt Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+static const struct dtrace_pattr profile_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+};
-+
-+static struct dtrace_pops profile_pops = {
-+ .dtps_provide = profile_provide,
-+ .dtps_provide_module = NULL,
-+ .dtps_destroy_module = NULL,
-+ .dtps_enable = profile_enable,
-+ .dtps_disable = profile_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = NULL,
-+ .dtps_getargval = NULL,
-+ .dtps_usermode = profile_usermode,
-+ .dtps_destroy = profile_destroy,
-+};
-+
-+DT_PROVIDER_MODULE(profile, DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch
deleted file mode 100644
index 3ade5058da9b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0012-dtrace-USDT-and-pid-provider-core-and-x86-components.patch
+++ /dev/null
@@ -1,412 +0,0 @@
-From 18dbf51fb9a2c43ac740c698ecbe91b48050e259 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 18:58:27 +0000
-Subject: [PATCH 12/19] dtrace: USDT and pid provider core and x86 components
-
-This implements the core (linked-in) machinery needed for userspace
-statically-defined tracepoints (for historical reasons, known as
-'fasttrap' by DTrace) and for the pid provider, which allows USDT
-probes to be dropped at addresses that do not correspond to symbols,
-at locations named as a symbol plus an offset. Both are implemented in
-terms of kprobes.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- include/linux/dtrace_os.h | 23 +++
- kernel/dtrace/Kconfig | 10 ++
- kernel/dtrace/dtrace_os.c | 272 ++++++++++++++++++++++++++++++++++++
- kernel/dtrace/dtrace_task.c | 15 ++
- 4 files changed, 320 insertions(+)
-
-diff --git a/include/linux/dtrace_os.h b/include/linux/dtrace_os.h
-index f2921ce039a76dd29f93c8183073b8d750681fe6..836825b1c7beb5418b6b6a78f0e4036e025706a5 100644
---- a/include/linux/dtrace_os.h
-+++ b/include/linux/dtrace_os.h
-@@ -14,6 +14,9 @@
- #include <linux/mm.h>
- #include <linux/notifier.h>
- #include <linux/timekeeper_internal.h>
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+#include <linux/uprobes.h>
-+#endif
- #include <asm/unistd.h>
- #include <linux/dtrace_cpu.h>
- #include <linux/dtrace_task.h>
-@@ -94,8 +97,28 @@ static inline int dtrace_no_pf(struct pt_regs *regs)
- }
-
- extern void (*dtrace_helpers_cleanup)(struct task_struct *);
-+extern void (*dtrace_fasttrap_probes_cleanup)(struct task_struct *);
- extern void (*dtrace_helpers_fork)(struct task_struct *, struct task_struct *);
-
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+struct fasttrap_machtp {
-+ struct inode *fmtp_ino;
-+ loff_t fmtp_off;
-+ struct uprobe_consumer fmtp_cns;
-+};
-+
-+extern int (*dtrace_tracepoint_hit)(struct fasttrap_machtp *,
-+ struct pt_regs *, int);
-+
-+extern struct task_struct *register_pid_provider(pid_t);
-+extern void unregister_pid_provider(pid_t);
-+
-+extern int dtrace_copy_code(pid_t, uint8_t *, uintptr_t, size_t);
-+extern int dtrace_tracepoint_enable(pid_t, uintptr_t, int,
-+ struct fasttrap_machtp *);
-+extern int dtrace_tracepoint_disable(pid_t, struct fasttrap_machtp *);
-+#endif /* CONFIG_DT_FASTTRAP || CONFIG_DT_FASTTRAP_MODULE */
-+
- #else
-
- /*
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-index 7b88206fe835fa14bb10484b658ce514d642112a..6bf6620981cd14bcc64cd0f7f71b499e478ea31e 100644
---- a/kernel/dtrace/Kconfig
-+++ b/kernel/dtrace/Kconfig
-@@ -23,6 +23,16 @@ config DT_CORE
-
- if DT_CORE
-
-+config DT_FASTTRAP
-+ tristate "Fasttrap Tracing"
-+ default m
-+ depends on ARCH_SUPPORTS_UPROBES
-+ select UPROBE_EVENT
-+ help
-+ Userspace tracing, providing the kernel support needed for tracing
-+ userspace programs. Currently, only statically defined probes
-+ (USDT) are supported.
-+
- config DT_PROFILE
- tristate "Profile Interrupt Tracing"
- default m
-diff --git a/kernel/dtrace/dtrace_os.c b/kernel/dtrace/dtrace_os.c
-index 931cfd0d0fbfc05c7670f4c01f1cfef140dbf408..874e097b84fd4b517cdb1e867a4b9d9ff2504078 100644
---- a/kernel/dtrace/dtrace_os.c
-+++ b/kernel/dtrace/dtrace_os.c
-@@ -40,6 +40,10 @@
- #include <linux/shmem_fs.h>
- #include <linux/dtrace_task_impl.h>
-
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+# include <linux/uprobes.h>
-+#endif /* CONFIG_DT_FASTTRAP || CONFIG_DT_FASTTRAP_MODULE */
-+
- /*
- * OS SPECIFIC DTRACE SETUP
- */
-@@ -413,3 +417,271 @@ void dtrace_disable(void)
- dtrace_enabled = 0;
- }
- EXPORT_SYMBOL(dtrace_disable);
-+
-+/*
-+ * USER SPACE TRACING (FASTTRAP) SUPPORT
-+ */
-+
-+#if IS_ENABLED(CONFIG_DT_FASTTRAP)
-+int (*dtrace_tracepoint_hit)(struct fasttrap_machtp *, struct pt_regs *, int);
-+EXPORT_SYMBOL(dtrace_tracepoint_hit);
-+
-+struct task_struct *register_pid_provider(pid_t pid)
-+{
-+ struct task_struct *p;
-+
-+ /*
-+ * Make sure the process exists, (FIXME: isn't a child created as the
-+ * result of a vfork(2)), and isn't a zombie (but may be in fork).
-+ */
-+ rcu_read_lock();
-+ p = find_task_by_vpid(pid);
-+ if (p == NULL) {
-+ rcu_read_unlock();
-+ return NULL;
-+ }
-+
-+ get_task_struct(p);
-+ rcu_read_unlock();
-+
-+ if (p->state & TASK_DEAD || p->dt_task == NULL ||
-+ p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) {
-+ put_task_struct(p);
-+ return NULL;
-+ }
-+
-+ /*
-+ * Increment dtrace_probes so that the process knows to inform us
-+ * when it exits or execs. fasttrap_provider_free() decrements this
-+ * when we're done with this provider.
-+ */
-+ if (p->dt_task != NULL)
-+ p->dt_task->dt_probes++;
-+ put_task_struct(p);
-+
-+ return p;
-+}
-+EXPORT_SYMBOL(register_pid_provider);
-+
-+void unregister_pid_provider(pid_t pid)
-+{
-+ struct task_struct *p;
-+
-+ /*
-+ * Decrement dtrace_probes on the process whose provider we're
-+ * freeing. We don't have to worry about clobbering somone else's
-+ * modifications to it because we have locked the bucket that
-+ * corresponds to this process's hash chain in the provider hash
-+ * table. Don't sweat it if we can't find the process.
-+ */
-+ rcu_read_lock();
-+ read_lock(&tasklist_lock);
-+ if ((p = find_task_by_vpid(pid)) == NULL) {
-+ read_unlock(&tasklist_lock);
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ get_task_struct(p);
-+ read_unlock(&tasklist_lock);
-+ rcu_read_unlock();
-+
-+ if (p->dt_task != NULL)
-+ p->dt_task->dt_probes--;
-+ put_task_struct(p);
-+}
-+EXPORT_SYMBOL(unregister_pid_provider);
-+
-+int dtrace_copy_code(pid_t pid, uint8_t *buf, uintptr_t addr, size_t size)
-+{
-+ struct task_struct *p;
-+ struct inode *ino;
-+ struct vm_area_struct *vma;
-+ struct address_space *map;
-+ loff_t off;
-+ int rc = 0;
-+
-+ /*
-+ * First we determine the inode and offset that 'addr' refers to in the
-+ * task referenced by 'pid'.
-+ */
-+ rcu_read_lock();
-+ p = find_task_by_vpid(pid);
-+ if (!p) {
-+ rcu_read_unlock();
-+ pr_warn("PID %d not found\n", pid);
-+ return -ESRCH;
-+ }
-+ get_task_struct(p);
-+ rcu_read_unlock();
-+
-+ mmap_write_lock(p->mm);
-+ vma = find_vma(p->mm, addr);
-+ if (vma == NULL || vma->vm_file == NULL) {
-+ rc = -EFAULT;
-+ goto out;
-+ }
-+
-+ ino = vma->vm_file->f_mapping->host;
-+ map = ino->i_mapping;
-+ off = ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (addr - vma->vm_start);
-+
-+ if (map->a_ops->readpage == NULL && !shmem_mapping(ino->i_mapping)) {
-+ rc = -EIO;
-+ goto out;
-+ }
-+
-+ /*
-+ * Armed with inode and offset, we can start reading pages...
-+ */
-+ do {
-+ int len;
-+ struct page *page;
-+ void *kaddr;
-+
-+ /*
-+ * We cannot read beyond the end of the inode content.
-+ */
-+ if (off >= i_size_read(ino))
-+ break;
-+
-+ len = min_t(int, size, PAGE_SIZE - (off & ~PAGE_MASK));
-+
-+ /*
-+ * Make sure that the page we're tring to read is populated and
-+ * in page cache.
-+ */
-+ if (map->a_ops->readpage)
-+ page = read_mapping_page(map, off >> PAGE_SHIFT,
-+ vma->vm_file);
-+ else
-+ page = shmem_read_mapping_page(map, off >> PAGE_SHIFT);
-+
-+ if (IS_ERR(page)) {
-+ rc = PTR_ERR(page);
-+ break;
-+ }
-+
-+ kaddr = kmap_atomic(page);
-+ memcpy(buf, kaddr + (off & ~PAGE_MASK), len);
-+ kunmap_atomic(kaddr);
-+ put_page(page);
-+
-+ buf += len;
-+ off += len;
-+ size -= len;
-+ } while (size > 0);
-+
-+out:
-+ mmap_write_unlock(p->mm);
-+ put_task_struct(p);
-+
-+ return rc;
-+}
-+EXPORT_SYMBOL(dtrace_copy_code);
-+
-+static int handler(struct uprobe_consumer *self, struct pt_regs *regs,
-+ int is_ret)
-+{
-+ struct fasttrap_machtp *mtp;
-+ int rc = 0;
-+
-+ mtp = container_of(self, struct fasttrap_machtp, fmtp_cns);
-+
-+ read_lock(&this_cpu_core->cpu_ft_lock);
-+ if (dtrace_tracepoint_hit == NULL)
-+ pr_warn("Fasttrap probes, but no handler\n");
-+ else
-+ rc = (*dtrace_tracepoint_hit)(mtp, regs, is_ret);
-+ read_unlock(&this_cpu_core->cpu_ft_lock);
-+
-+ return rc;
-+}
-+
-+static int prb_handler(struct uprobe_consumer *self, struct pt_regs *regs)
-+{
-+ return handler(self, regs, 0);
-+}
-+
-+static int ret_handler(struct uprobe_consumer *self, unsigned long func,
-+ struct pt_regs *regs)
-+{
-+ return handler(self, regs, 1);
-+}
-+
-+int dtrace_tracepoint_enable(pid_t pid, uintptr_t addr, int is_ret,
-+ struct fasttrap_machtp *mtp)
-+{
-+ struct task_struct *p;
-+ struct inode *ino;
-+ struct vm_area_struct *vma;
-+ loff_t off;
-+ int rc = 0;
-+
-+ mtp->fmtp_ino = NULL;
-+ mtp->fmtp_off = 0;
-+
-+ p = find_task_by_vpid(pid);
-+ if (!p) {
-+ pr_warn("PID %d not found\n", pid);
-+ return -ESRCH;
-+ }
-+
-+ if (p->dt_task == NULL) {
-+ pr_warn("PID %d no dtrace_task\n", pid);
-+ return -EFAULT;
-+ }
-+
-+ vma = find_vma(p->mm, addr);
-+ if (vma == NULL || vma->vm_file == NULL)
-+ return -EFAULT;
-+
-+ ino = vma->vm_file->f_mapping->host;
-+ off = ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (addr - vma->vm_start);
-+
-+ if (is_ret)
-+ mtp->fmtp_cns.ret_handler = ret_handler;
-+ else
-+ mtp->fmtp_cns.handler = prb_handler;
-+
-+ rc = uprobe_register(ino, off, &mtp->fmtp_cns);
-+
-+ /*
-+ * If successful, increment the count of the number of
-+ * tracepoints active in the victim process.
-+ */
-+ if (rc == 0) {
-+ mtp->fmtp_ino = ino;
-+ mtp->fmtp_off = off;
-+
-+ p->dt_task->dt_tp_count++;
-+ }
-+
-+ return rc;
-+}
-+EXPORT_SYMBOL(dtrace_tracepoint_enable);
-+
-+int dtrace_tracepoint_disable(pid_t pid, struct fasttrap_machtp *mtp)
-+{
-+ struct task_struct *p;
-+
-+ if (!mtp || !mtp->fmtp_ino)
-+ return -ENOENT;
-+
-+ uprobe_unregister(mtp->fmtp_ino, mtp->fmtp_off, &mtp->fmtp_cns);
-+
-+ mtp->fmtp_ino = NULL;
-+ mtp->fmtp_off = 0;
-+
-+ /*
-+ * Decrement the count of the number of tracepoints active in
-+ * the victim process (if it still exists).
-+ */
-+ p = find_task_by_vpid(pid);
-+ if (p != NULL && p->dt_task != NULL)
-+ p->dt_task->dt_tp_count--;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(dtrace_tracepoint_disable);
-+#endif /* CONFIG_DT_FASTTRAP || CONFIG_DT_FASTTRAP_MODULE */
-diff --git a/kernel/dtrace/dtrace_task.c b/kernel/dtrace/dtrace_task.c
-index 02bcc6b7e0a26a04f61448ac6c8d5653344b6f40..8bae6e79c7f1e854d6e9f77481e16a3c3b107270 100644
---- a/kernel/dtrace/dtrace_task.c
-+++ b/kernel/dtrace/dtrace_task.c
-@@ -22,6 +22,14 @@
-
- struct kmem_cache *dtrace_task_cachep;
-
-+/*
-+ * Fasttrap hooks that need to be called when a fasttrap meta provider
-+ * is loaded and registered with the framework.
-+ */
-+void (*dtrace_helpers_cleanup)(struct task_struct *);
-+EXPORT_SYMBOL(dtrace_helpers_cleanup);
-+void (*dtrace_fasttrap_probes_cleanup)(struct task_struct *);
-+EXPORT_SYMBOL(dtrace_fasttrap_probes_cleanup);
- void (*dtrace_helpers_fork)(struct task_struct *, struct task_struct *);
- EXPORT_SYMBOL(dtrace_helpers_fork);
-
-@@ -76,6 +84,13 @@ static void dtrace_task_cleanup(struct task_struct *tsk)
- if (tsk->dt_task == NULL)
- return;
-
-+ /* Handle fasttrap provider cleanups. */
-+ if (tsk->dt_task->dt_helpers != NULL && dtrace_helpers_cleanup != NULL)
-+ (*dtrace_helpers_cleanup)(tsk);
-+
-+ if (tsk->dt_task->dt_probes && dtrace_fasttrap_probes_cleanup != NULL)
-+ (*dtrace_fasttrap_probes_cleanup)(tsk);
-+
- /* Release psinfo if any. */
- psinfo = tsk->dt_task->dt_psinfo;
- if (psinfo != NULL) {
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0013-dtrace-USDT-and-pid-providers.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0013-dtrace-USDT-and-pid-providers.patch
deleted file mode 100644
index 16619d420253..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0013-dtrace-USDT-and-pid-providers.patch
+++ /dev/null
@@ -1,2691 +0,0 @@
-From 209f98383b9139b7d50f91f8433e50bf00c61236 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 18:08:41 +0000
-Subject: [PATCH 13/19] dtrace: USDT and pid providers
-
-For historical reasons, these are provided in a module named
-fasttrap.ko.
-
-Much of this is arch-dependent code for jump-table detection and
-implementation of globbed pid probes ("probe everything you can in this
-function"), as well as arch-dependent code to look up arguments and code
-to ensure that dropping a kprobe in a single process does not affect
-other processes running from the same binary.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/dtrace/Makefile.arch | 2 +
- arch/x86/dtrace/fasttrap_x86_64.c | 364 +++
- .../x86/dtrace/include/dtrace/fasttrap_arch.h | 29 +
- dtrace/Makefile | 2 +
- dtrace/fasttrap_dev.c | 1986 +++++++++++++++++
- dtrace/fasttrap_impl.h | 172 ++
- dtrace/fasttrap_mod.c | 38 +
- 7 files changed, 2593 insertions(+)
- create mode 100644 arch/x86/dtrace/fasttrap_x86_64.c
- create mode 100644 arch/x86/dtrace/include/dtrace/fasttrap_arch.h
- create mode 100644 dtrace/fasttrap_dev.c
- create mode 100644 dtrace/fasttrap_impl.h
- create mode 100644 dtrace/fasttrap_mod.c
-
-diff --git a/arch/x86/dtrace/Makefile.arch b/arch/x86/dtrace/Makefile.arch
-index 8492eaee426d1ba7a25769ff3c95d1dc828f69ae..e4655557e06ad7524677b9f3b0909f248d5a1c8b 100644
---- a/arch/x86/dtrace/Makefile.arch
-+++ b/arch/x86/dtrace/Makefile.arch
-@@ -7,7 +7,9 @@ DTARCHDIR = ../arch/x86/dtrace
- ccflags-y += -I$(srctree)/arch/x86/dtrace/include -Idtrace
-
- dtrace-obj += dtrace_asm_x86_64.o dtrace_isa_x86_64.o
-+fasttrap-obj += fasttrap_x86_64.o
- sdt-obj += sdt_x86_64.o
-
- dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
-+fasttrap-y += $(addprefix $(DTARCHDIR)/, $(fasttrap-obj))
- sdt-y += $(addprefix $(DTARCHDIR)/, $(sdt-obj))
-diff --git a/arch/x86/dtrace/fasttrap_x86_64.c b/arch/x86/dtrace/fasttrap_x86_64.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..012b2a50a46ab7570c1a94cbf294ffd65463099f
---- /dev/null
-+++ b/arch/x86/dtrace/fasttrap_x86_64.c
-@@ -0,0 +1,364 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fasttrap_x86_64.c
-+ * DESCRIPTION: DTrace - fasttrap provider implementation for x86
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <asm/insn.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fasttrap_impl.h"
-+
-+#define DISASM_REX_PREFIX(pfx) (((pfx) & 0xf0) == 0x40)
-+#define DISASM_MODRM_REG(modrm) (((modrm) >> 3) & 0x07)
-+
-+static int has_jump_table(const asm_instr_t *addr, size_t size)
-+{
-+ const asm_instr_t *end = addr + size;
-+
-+ while (addr < end) {
-+ int len;
-+
-+ /*
-+ * Register-dependent jump instructions start with a 0xff byte
-+ * and have the modrm.reg field set to 4. Such instructions
-+ * tend to be used for jump tables.
-+ */
-+ if ((addr[0] == 0xff && DISASM_MODRM_REG(addr[1]) == 4) ||
-+ (DISASM_REX_PREFIX(addr[0]) && addr[1] == 0xff &&
-+ DISASM_MODRM_REG(addr[2]) == 4))
-+ return 1;
-+
-+ len = dtrace_instr_size(addr);
-+
-+ /*
-+ * If we encounter a problem decoding an instruction, we will
-+ * assume that there might be a jump table. Better safe than
-+ * sorry...
-+ */
-+ if (len < 0)
-+ return 1;
-+
-+ addr += len;
-+ }
-+
-+ return 0;
-+}
-+
-+static uint64_t *fasttrap_all_offsets(asm_instr_t *text, size_t size,
-+ uint64_t *np)
-+{
-+ uint64_t *offs = NULL;
-+ uint64_t noffs;
-+ asm_instr_t *instr;
-+ asm_instr_t *end;
-+
-+ /*
-+ * Two passes are taken through this section of code. The first time
-+ * around we merely count the number of probe points. The second time,
-+ * we actually record their locations.
-+ */
-+again:
-+ noffs = 0;
-+ instr = text;
-+ end = text + size;
-+
-+ while (instr < end) {
-+ int len;
-+
-+ /*
-+ * If we fail to decode an instruction, it is time to give up.
-+ */
-+ len = dtrace_instr_size(instr);
-+ if (len < 0)
-+ goto fail;
-+
-+ if (offs)
-+ offs[noffs] = (uint64_t)(instr - text);
-+ noffs++;
-+
-+ instr += len;
-+ }
-+
-+ if (offs == NULL) {
-+ /*
-+ * No matching offsets found - we are done.
-+ */
-+ if (noffs == 0)
-+ goto fail;
-+
-+ /*
-+ * We know how many tracepoint locations there are for this
-+ * probe, so allocate member to record them, and kick off the
-+ * second pass.
-+ */
-+ offs = kmalloc(sizeof(uint64_t) * noffs, GFP_KERNEL);
-+ if (!offs)
-+ goto fail;
-+
-+ goto again;
-+ }
-+
-+ *np = noffs;
-+
-+ return offs;
-+
-+fail:
-+ *np = 0;
-+ kfree(offs);
-+
-+ return NULL;
-+}
-+
-+uint64_t *fasttrap_glob_offsets(struct fasttrap_probe_spec *probe,
-+ uint64_t *np)
-+{
-+ size_t size = probe->ftps_size;
-+ asm_instr_t *text = NULL;
-+ asm_instr_t *instr;
-+ asm_instr_t *end;
-+ uint64_t *offs = NULL;
-+ uint64_t noffs;
-+ int ret = 0;
-+ char ostr[sizeof(instr) * 2 + 1];
-+
-+ text = kmalloc(size, GFP_KERNEL);
-+ if (!text)
-+ goto fail;
-+
-+ ret = dtrace_copy_code(probe->ftps_pid, (uint8_t *)text,
-+ probe->ftps_pc, size);
-+ if (ret != 0)
-+ goto fail;
-+
-+ if (has_jump_table(text, size))
-+ goto fail;
-+
-+ if (probe->ftps_glen == 1 && probe->ftps_gstr[0] == '*') {
-+ offs = fasttrap_all_offsets(text, size, &noffs);
-+ goto out;
-+ }
-+
-+ /*
-+ * Two passes are taken through this section of code. The first time
-+ * around we merely count the number of probe points. The second time,
-+ * we actually record their locations.
-+ */
-+again:
-+ noffs = 0;
-+ instr = text;
-+ end = text + size;
-+
-+ while (instr < end) {
-+ int len;
-+ uint64_t off = (uint64_t)(instr - text);
-+
-+ /*
-+ * If we fail to decode an instruction, it is time to give up.
-+ */
-+ len = dtrace_instr_size(instr);
-+ if (len < 0)
-+ goto fail;
-+
-+ snprintf(ostr, sizeof(ostr), "%llx", off);
-+ if (dtrace_gmatch(ostr, probe->ftps_gstr)) {
-+ if (offs)
-+ offs[noffs] = off;
-+ noffs++;
-+ }
-+
-+ instr += len;
-+ }
-+
-+ if (offs == NULL) {
-+ /*
-+ * No matching offsets found - we are done.
-+ */
-+ if (noffs == 0)
-+ goto fail;
-+
-+ /*
-+ * We know how many tracepoint locations there are for this
-+ * probe, so allocate member to record them, and kick off the
-+ * second pass.
-+ */
-+ offs = kmalloc(sizeof(uint64_t) * noffs, GFP_KERNEL);
-+ if (!offs)
-+ goto fail;
-+
-+ goto again;
-+ }
-+
-+out:
-+ kfree(text);
-+
-+ *np = noffs;
-+
-+ return offs;
-+
-+fail:
-+ kfree(offs);
-+ kfree(text);
-+
-+ *np = 0;
-+ return NULL;
-+}
-+
-+uint64_t fasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ return 0;
-+
-+ switch (argno) {
-+ case 0:
-+ return regs->di;
-+ case 1:
-+ return regs->si;
-+ case 2:
-+ return regs->dx;
-+ case 3:
-+ return regs->cx;
-+ case 4:
-+ return regs->r8;
-+ case 5:
-+ return regs->r9;
-+ }
-+
-+ ASSERT(argno > 5);
-+
-+ pagefault_disable();
-+ st = (uint64_t *)regs->sp;
-+ __copy_from_user_inatomic_nocache(&val, (void *)&st[argno - 6 + 1],
-+ sizeof(st[0]));
-+ pagefault_enable();
-+
-+ return val;
-+}
-+
-+uint64_t fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg,
-+ int argno, int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ return 0;
-+
-+ switch (argno) {
-+ case 0:
-+ return regs->di;
-+ case 1:
-+ return regs->si;
-+ case 2:
-+ return regs->dx;
-+ case 3:
-+ return regs->cx;
-+ case 4:
-+ return regs->r8;
-+ case 5:
-+ return regs->r9;
-+ }
-+
-+ ASSERT(argno > 5);
-+
-+ pagefault_disable();
-+ st = (uint64_t *)regs->sp;
-+ __copy_from_user_inatomic_nocache(&val, (void *)&st[argno - 6],
-+ sizeof(st[0]));
-+ pagefault_enable();
-+
-+ return val;
-+}
-+
-+static void fasttrap_map_args(struct fasttrap_probe *probe,
-+ struct pt_regs *regs,
-+ int argc, uintptr_t *argv)
-+{
-+ int i, x, cap = min(argc, (int)probe->ftp_nargs);
-+ uintptr_t *st = (uintptr_t *)regs->sp;
-+
-+ for (i = 0; i < cap; i++) {
-+ switch (x = probe->ftp_argmap[i]) {
-+ case 0:
-+ argv[i] = regs->di;
-+ break;
-+ case 1:
-+ argv[i] = regs->si;
-+ break;
-+ case 2:
-+ argv[i] = regs->dx;
-+ break;
-+ case 3:
-+ argv[i] = regs->cx;
-+ break;
-+ case 4:
-+ argv[i] = regs->r8;
-+ break;
-+ case 5:
-+ argv[i] = regs->r9;
-+ break;
-+ default:
-+ ASSERT(x > 5);
-+
-+ __copy_from_user_inatomic_nocache(&argv[i],
-+ (void *)&st[x - 6],
-+ sizeof(st[0]));
-+ }
-+ }
-+
-+ while (i < argc)
-+ argv[i++] = 0;
-+}
-+
-+void fasttrap_pid_probe_arch(struct fasttrap_probe *ftp, struct pt_regs *regs)
-+{
-+ if (ftp->ftp_argmap == NULL) {
-+ dtrace_probe(ftp->ftp_id, regs->di, regs->si, regs->dx,
-+ regs->cx, regs->r8, regs->r9, 0);
-+ } else {
-+ uintptr_t t[6];
-+
-+ fasttrap_map_args(ftp, regs, sizeof(t) / sizeof(t[0]), t);
-+ dtrace_probe(ftp->ftp_id, t[0], t[1], t[2], t[3],
-+ t[4], t[5], 0);
-+ }
-+}
-+
-+void fasttrap_pid_retprobe_arch(struct fasttrap_probe *ftp,
-+ struct pt_regs *regs)
-+{
-+ /*
-+ * FIXME: The first argument to the probe should be the offset in the
-+ * function that the return occured at, but uprobes doesn't give
-+ * us that information (or so it seems).
-+ */
-+ dtrace_probe(ftp->ftp_id, 0, regs->ax, regs->dx, 0, 0, 0, 0);
-+}
-+
-+void fasttrap_set_enabled(struct pt_regs *regs)
-+{
-+ regs->ax = 1;
-+}
-+
-diff --git a/arch/x86/dtrace/include/dtrace/fasttrap_arch.h b/arch/x86/dtrace/include/dtrace/fasttrap_arch.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..abbe9cb2bf3852a540d2f1c535f3154285201e98
---- /dev/null
-+++ b/arch/x86/dtrace/include/dtrace/fasttrap_arch.h
-@@ -0,0 +1,29 @@
-+/*
-+ * Dynamic Tracing for Linux - Fasttrap provider implementation defines
-+ *
-+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _X86_64_FASTTRAP_ARCH_H
-+#define _X86_64_FASTTRAP_ARCH_H
-+
-+#define FASTTRAP_ENTRY_AFRAMES 8
-+#define FASTTRAP_RETURN_AFRAMES 8
-+#define FASTTRAP_OFFSET_AFRAMES 8
-+
-+#endif /* _X86_64_FASTTRAP_ARCH_H */
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-index 5e6fb362a4e96afbcef906dc7eae12c6c6ad5b04..c7e3fc512a6c7cdc40f9e3343e3cd98bec674b68 100644
---- a/dtrace/Makefile
-+++ b/dtrace/Makefile
-@@ -3,6 +3,7 @@
- #
-
- obj-$(CONFIG_DT_CORE) += dtrace.o
-+obj-$(CONFIG_DT_FASTTRAP) += fasttrap.o
- obj-$(CONFIG_DT_PROFILE) += profile.o
- obj-$(CONFIG_DT_SDT) += sdt.o
- obj-$(CONFIG_DT_SYSTRACE) += systrace.o
-@@ -17,6 +18,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \
- dtrace_probe.o dtrace_probe_ctx.o \
- dtrace_ptofapi.o dtrace_predicate.o \
- dtrace_spec.o dtrace_state.o dtrace_util.o
-+fasttrap-y := fasttrap_mod.o fasttrap_dev.o
- profile-y := profile_mod.o profile_dev.o
- sdt-y := sdt_mod.o sdt_dev.o
- systrace-y := systrace_mod.o systrace_dev.o
-diff --git a/dtrace/fasttrap_dev.c b/dtrace/fasttrap_dev.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..f48581e00f4bceb55118a8ecf083044741100e4b
---- /dev/null
-+++ b/dtrace/fasttrap_dev.c
-@@ -0,0 +1,1986 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fasttrap_dev.c
-+ * DESCRIPTION: DTrace - fasttrap provider device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/atomic.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/sort.h>
-+#include <linux/uaccess.h>
-+#include <linux/vmalloc.h>
-+#include <linux/workqueue.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fasttrap_impl.h"
-+
-+#define FASTTRAP_MAX_DEFAULT 250000
-+static uint32_t fasttrap_max;
-+static uint64_t fasttrap_pid_count;
-+static atomic_t fasttrap_total;
-+
-+#define FASTTRAP_TPOINTS_DEFAULT_SIZE 0x4000
-+#define FASTTRAP_PROVIDERS_DEFAULT_SIZE 0x100
-+#define FASTTRAP_PROCS_DEFAULT_SIZE 0x100
-+
-+#define FASTTRAP_PID_NAME "pid"
-+#define FASTTRAP_ENABLE_FAIL 1
-+#define FASTTRAP_ENABLE_PARTIAL 2
-+
-+struct fasttrap_hash fasttrap_tpoints;
-+static struct fasttrap_hash fasttrap_provs;
-+static struct fasttrap_hash fasttrap_procs;
-+
-+#define FASTTRAP_PROVS_INDEX(pid, name) \
-+ ((fasttrap_hash_str(name) + (pid)) & fasttrap_provs.fth_mask)
-+#define FASTTRAP_PROCS_INDEX(pid) ((pid) & fasttrap_procs.fth_mask)
-+
-+#define FASTTRAP_TPOINTS_ELEM(pid, pc) \
-+ FASTTRAP_ELEM_BUCKET(&fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)])
-+#define FASTTRAP_PROVS_ELEM(pid, name) \
-+ FASTTRAP_ELEM_BUCKET(&fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)])
-+#define FASTTRAP_PROCS_ELEM(pid) \
-+ FASTTRAP_ELEM_BUCKET(&fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)])
-+
-+#define CLEANUP_NONE 0
-+#define CLEANUP_SCHEDULED 1
-+#define CLEANUP_DEFERRED 2
-+
-+DEFINE_MUTEX(fasttrap_cleanup_mtx);
-+DEFINE_MUTEX(fasttrap_count_mtx);
-+static uint_t fasttrap_cleanup_state;
-+static uint_t fasttrap_cleanup_work;
-+
-+static struct kmem_cache *tracepoint_cachep;
-+
-+/*
-+ * Generation count on modifications to the global tracepoint lookup table.
-+ */
-+static volatile uint64_t fasttrap_mod_gen;
-+
-+static void fasttrap_pid_cleanup(void);
-+static void fasttrap_probes_cleanup(struct task_struct *);
-+
-+static int fasttrap_pid_probe(struct fasttrap_machtp *mtp,
-+ struct pt_regs *regs, int is_ret)
-+{
-+ struct fasttrap_tracepoint *tp;
-+ struct fasttrap_id *id;
-+ int is_enabled = 0;
-+
-+ tp = container_of(mtp, struct fasttrap_tracepoint, ftt_mtp);
-+
-+ /*
-+ * Verify that this probe event is actually related to the current
-+ * process (task group). If not, ignore it.
-+ *
-+ * TODO: The underlying probe mechanism should register a single
-+ * handler for the (inode, offset) combination. When the handler
-+ * is called, it should run through a list of fasttrap
-+ * tracepoints associated with the OS-level probe, looking for
-+ * one that is related to the current task.
-+ */
-+ if (tp->ftt_pid != current->tgid)
-+ return 0;
-+
-+ if (atomic64_read(&tp->ftt_proc->ftpc_acount) == 0)
-+ return 0;
-+
-+ this_cpu_core->cpu_dtrace_regs = regs;
-+
-+ if (!is_ret) {
-+ for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {
-+ struct fasttrap_probe *ftp = id->fti_probe;
-+
-+ if (id->fti_ptype == DTFTP_IS_ENABLED)
-+ is_enabled = 1;
-+ else
-+ fasttrap_pid_probe_arch(ftp, regs);
-+ }
-+ } else {
-+ for (id = tp->ftt_retids; id != NULL; id = id->fti_next) {
-+ struct fasttrap_probe *ftp = id->fti_probe;
-+
-+ fasttrap_pid_retprobe_arch(ftp, regs);
-+ }
-+ }
-+
-+ this_cpu_core->cpu_dtrace_regs = NULL;
-+
-+ if (is_enabled)
-+ fasttrap_set_enabled(regs);
-+
-+ return 0;
-+}
-+
-+static void fasttrap_pid_provide(void *arg,
-+ const struct dtrace_probedesc *desc)
-+{
-+ /*
-+ * There are no "default" pid probes.
-+ */
-+}
-+
-+static void fasttrap_enable_callbacks(void)
-+{
-+ /*
-+ * We don't have to play the RW lock game here because we're providing
-+ * something rather than taking something away -- we can be sure that
-+ * no threads have tried to follow these function pointers yet.
-+ */
-+ mutex_lock(&fasttrap_count_mtx);
-+ if (fasttrap_pid_count == 0) {
-+ ASSERT(dtrace_tracepoint_hit == NULL);
-+
-+ dtrace_fasttrap_probes_cleanup = &fasttrap_probes_cleanup;
-+ dtrace_tracepoint_hit = &fasttrap_pid_probe;
-+ }
-+
-+ ASSERT(dtrace_fasttrap_probes_cleanup == &fasttrap_probes_cleanup);
-+ ASSERT(dtrace_tracepoint_hit == &fasttrap_pid_probe);
-+
-+ fasttrap_pid_count++;
-+ mutex_unlock(&fasttrap_count_mtx);
-+}
-+
-+static void fasttrap_disable_callbacks(void)
-+{
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+ mutex_lock(&fasttrap_count_mtx);
-+ ASSERT(fasttrap_pid_count > 0);
-+ fasttrap_pid_count--;
-+
-+ if (fasttrap_pid_count == 0) {
-+ int cpu;
-+
-+ for_each_present_cpu(cpu) {
-+ struct cpu_core *cpuc = per_cpu_core(cpu);
-+
-+ write_lock(&cpuc->cpu_ft_lock);
-+ }
-+
-+ dtrace_tracepoint_hit = NULL;
-+ dtrace_fasttrap_probes_cleanup = NULL;
-+
-+ for_each_present_cpu(cpu) {
-+ struct cpu_core *cpuc = per_cpu_core(cpu);
-+
-+ write_unlock(&cpuc->cpu_ft_lock);
-+ }
-+ }
-+
-+ mutex_unlock(&fasttrap_count_mtx);
-+}
-+
-+/*
-+ * This function ensures that no threads are actively using the memory
-+ * associated with probes that were formerly live.
-+ */
-+static void fasttrap_mod_barrier(uint64_t gen)
-+{
-+ int cpu;
-+
-+ if (gen < fasttrap_mod_gen)
-+ return;
-+
-+ fasttrap_mod_gen++;
-+
-+ for_each_present_cpu(cpu) {
-+ struct cpu_core *cpuc = per_cpu_core(cpu);
-+
-+ mutex_lock(&cpuc->cpuc_pid_lock);
-+ mutex_unlock(&cpuc->cpuc_pid_lock);
-+ }
-+}
-+
-+static int fasttrap_tracepoint_enable(struct fasttrap_probe *probe,
-+ uint_t index)
-+{
-+ struct fasttrap_tracepoint *tp, *new_tp = NULL;
-+ struct fasttrap_bucket *bucket;
-+ struct fasttrap_id *id;
-+ pid_t pid;
-+ uintptr_t pc;
-+
-+ ASSERT(index < probe->ftp_ntps);
-+
-+ pid = probe->ftp_pid;
-+ pc = probe->ftp_tps[index].fit_tp->ftt_pc;
-+ id = &probe->ftp_tps[index].fit_id;
-+
-+ ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid);
-+
-+ /*
-+ * Before we make any modifications, make sure we've imposed a barrier
-+ * on the generation in which this probe was last modified.
-+ */
-+ fasttrap_mod_barrier(probe->ftp_gen);
-+
-+ bucket = FASTTRAP_TPOINTS_ELEM(pid, pc);
-+
-+ /*
-+ * If the tracepoint has already been enabled, just add our id to the
-+ * list of interested probes. This may be our second time through
-+ * this path in which case we'll have constructed the tracepoint we'd
-+ * like to install. If we can't find a match, and have an allocated
-+ * tracepoint ready to go, enable that one now.
-+ *
-+ * A tracepoint whose process is defunct is also considered defunct.
-+ */
-+again:
-+ mutex_lock(&bucket->ftb_mtx);
-+ for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
-+ /*
-+ * Note that it's safe to access the active count on the
-+ * associated proc structure because we know that at least one
-+ * provider (this one) will still be around throughout this
-+ * operation.
-+ */
-+ if (tp->ftt_pid != pid || tp->ftt_pc != pc ||
-+ atomic64_read(&tp->ftt_proc->ftpc_acount) == 0)
-+ continue;
-+
-+ /*
-+ * Now that we've found a matching tracepoint, it would be
-+ * a decent idea to confirm that the tracepoint is still
-+ * enabled and the trap instruction hasn't been overwritten.
-+ * Since this is a little hairy, we'll punt for now.
-+ */
-+
-+ /*
-+ * This can't be the first interested probe. We don't have
-+ * to worry about another thread being in the midst of
-+ * deleting this tracepoint (which would be the only valid
-+ * reason for a tracepoint to have no interested probes)
-+ * since we're holding P_PR_LOCK for this process.
-+ */
-+ ASSERT(tp->ftt_ids != NULL || tp->ftt_retids != NULL);
-+
-+ switch (id->fti_ptype) {
-+ case DTFTP_ENTRY:
-+ case DTFTP_OFFSETS:
-+ case DTFTP_IS_ENABLED:
-+ if (tp->ftt_ids == NULL) /* return tp */
-+ continue;
-+
-+ ASSERT(tp->ftt_retids == NULL);
-+
-+ id->fti_next = tp->ftt_ids;
-+ dtrace_membar_producer();
-+ tp->ftt_ids = id;
-+ dtrace_membar_producer();
-+ break;
-+
-+ case DTFTP_RETURN:
-+ case DTFTP_POST_OFFSETS:
-+ if (tp->ftt_retids == NULL) /* non-return tp */
-+ continue;
-+
-+ ASSERT(tp->ftt_ids == NULL);
-+
-+ id->fti_next = tp->ftt_retids;
-+ dtrace_membar_producer();
-+ tp->ftt_retids = id;
-+ dtrace_membar_producer();
-+ break;
-+
-+ default:
-+ ASSERT(0); /* FIXME */
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ if (new_tp != NULL) {
-+ new_tp->ftt_ids = NULL;
-+ new_tp->ftt_retids = NULL;
-+ }
-+
-+ return 0;
-+ }
-+
-+ /*
-+ * If we have a good tracepoint ready to go, install it now while
-+ * we have the lock held and no one can screw with us.
-+ */
-+ if (new_tp != NULL) {
-+ int rc = 0;
-+
-+ new_tp->ftt_next = bucket->ftb_data;
-+ dtrace_membar_producer();
-+ bucket->ftb_data = new_tp;
-+ dtrace_membar_producer();
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Activate the tracepoint in the ISA-specific manner.
-+ * If this fails, we need to report the failure, but
-+ * indicate that this tracepoint must still be disabled
-+ * by calling fasttrap_tracepoint_disable().
-+ */
-+ rc = dtrace_tracepoint_enable(pid, pc,
-+ id->fti_ptype == DTFTP_RETURN,
-+ &new_tp->ftt_mtp);
-+
-+ return rc ? FASTTRAP_ENABLE_PARTIAL : 0;
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Initialize the tracepoint that's been preallocated with the probe.
-+ */
-+ new_tp = probe->ftp_tps[index].fit_tp;
-+
-+ ASSERT(new_tp->ftt_pid == pid);
-+ ASSERT(new_tp->ftt_pc == pc);
-+ ASSERT(new_tp->ftt_proc == probe->ftp_prov->ftp_proc);
-+ ASSERT(new_tp->ftt_ids == NULL);
-+ ASSERT(new_tp->ftt_retids == NULL);
-+
-+ switch (id->fti_ptype) {
-+ case DTFTP_ENTRY:
-+ case DTFTP_OFFSETS:
-+ case DTFTP_IS_ENABLED:
-+ id->fti_next = NULL;
-+ new_tp->ftt_ids = id;
-+ break;
-+
-+ case DTFTP_RETURN:
-+ case DTFTP_POST_OFFSETS:
-+ id->fti_next = NULL;
-+ new_tp->ftt_retids = id;
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ }
-+
-+ goto again;
-+}
-+
-+static void fasttrap_tracepoint_disable(struct fasttrap_probe *probe,
-+ uint_t index)
-+{
-+ struct fasttrap_bucket *bucket;
-+ struct fasttrap_provider *prov = probe->ftp_prov;
-+ struct fasttrap_tracepoint **pp, *tp;
-+ struct fasttrap_id *id, **idp = NULL;
-+ pid_t pid;
-+ uintptr_t pc;
-+
-+ ASSERT(index < probe->ftp_ntps);
-+
-+ pid = probe->ftp_pid;
-+ pc = probe->ftp_tps[index].fit_tp->ftt_pc;
-+ id = &probe->ftp_tps[index].fit_id;
-+
-+ ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid);
-+
-+ /*
-+ * Find the tracepoint and make sure that our id is one of the
-+ * ones registered with it. Return probes are linked in their
-+ * own tracepoint, even though they share the (pi, pc) pair with
-+ * entry probes.
-+ */
-+ bucket = FASTTRAP_TPOINTS_ELEM(pid, pc);
-+ mutex_lock(&bucket->ftb_mtx);
-+ for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
-+ if (tp->ftt_pid != pid || tp->ftt_pc != pc ||
-+ tp->ftt_proc != prov->ftp_proc)
-+ continue;
-+
-+ if (id->fti_ptype == DTFTP_RETURN && tp->ftt_retids == NULL)
-+ continue;
-+
-+ if (id->fti_ptype != DTFTP_RETURN && tp->ftt_ids == NULL)
-+ continue;
-+
-+ break;
-+ }
-+
-+ /*
-+ * If we somehow lost this tracepoint, we are in trouble.
-+ */
-+ ASSERT(tp != NULL);
-+
-+ switch (id->fti_ptype) {
-+ case DTFTP_ENTRY:
-+ case DTFTP_OFFSETS:
-+ case DTFTP_IS_ENABLED:
-+ ASSERT(tp->ftt_ids != NULL);
-+ idp = &tp->ftt_ids;
-+ break;
-+
-+ case DTFTP_RETURN:
-+ case DTFTP_POST_OFFSETS:
-+ ASSERT(tp->ftt_retids != NULL);
-+ idp = &tp->ftt_retids;
-+ break;
-+
-+ default:
-+ ASSERT(0);
-+ }
-+
-+ while ((*idp)->fti_probe != probe) {
-+ idp = &(*idp)->fti_next;
-+ ASSERT(*idp != NULL);
-+ }
-+
-+ id = *idp;
-+ *idp = id->fti_next;
-+ dtrace_membar_producer();
-+
-+ ASSERT(id->fti_probe == probe);
-+
-+ /*
-+ * If there are other registered enablings of this tracepoint, we're
-+ * all done, but if this was the last probe assocated with this
-+ * this tracepoint, we need to remove and free it.
-+ */
-+ if (tp->ftt_ids != NULL || tp->ftt_retids != NULL) {
-+ /*
-+ * If the current probe's tracepoint is in use, swap it
-+ * for an unused tracepoint.
-+ */
-+ if (tp == probe->ftp_tps[index].fit_tp) {
-+ struct fasttrap_probe *tmp_probe;
-+ struct fasttrap_tracepoint **tmp_tp;
-+ uint_t tmp_index;
-+
-+ if (tp->ftt_ids != NULL) {
-+ tmp_probe = tp->ftt_ids->fti_probe;
-+ tmp_index = FASTTRAP_ID_INDEX(tp->ftt_ids);
-+ tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp;
-+ } else {
-+ tmp_probe = tp->ftt_retids->fti_probe;
-+ tmp_index = FASTTRAP_ID_INDEX(tp->ftt_retids);
-+ tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp;
-+ }
-+
-+ ASSERT(*tmp_tp != NULL);
-+ ASSERT(*tmp_tp != probe->ftp_tps[index].fit_tp);
-+ ASSERT((*tmp_tp)->ftt_ids == NULL);
-+ ASSERT((*tmp_tp)->ftt_retids == NULL);
-+
-+ probe->ftp_tps[index].fit_tp = *tmp_tp;
-+ *tmp_tp = tp;
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Tag the modified probe with the generation in which it was
-+ * changed.
-+ */
-+ probe->ftp_gen = fasttrap_mod_gen;
-+ return;
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ dtrace_tracepoint_disable(pid, &tp->ftt_mtp);
-+
-+ /*
-+ * Remove the probe from the hash table of active tracepoints.
-+ */
-+ mutex_lock(&bucket->ftb_mtx);
-+ pp = (struct fasttrap_tracepoint **)&bucket->ftb_data;
-+ ASSERT(*pp != NULL);
-+ while (*pp != tp) {
-+ pp = &(*pp)->ftt_next;
-+ ASSERT(*pp != NULL);
-+ }
-+
-+ *pp = tp->ftt_next;
-+ dtrace_membar_producer();
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Tag the modified probe with the generation in which it was changed.
-+ */
-+ probe->ftp_gen = fasttrap_mod_gen;
-+}
-+
-+static int fasttrap_pid_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fasttrap_probe *probe = parg;
-+ int i, rc;
-+
-+ ASSERT(probe != NULL);
-+ ASSERT(!probe->ftp_enabled);
-+ ASSERT(id == probe->ftp_id);
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+
-+ /*
-+ * Increment the count of enabled probes on this probe's provider;
-+ * the provider can't go away while the probe still exists. We
-+ * must increment this even if we aren't able to properly enable
-+ * this probe.
-+ */
-+ mutex_lock(&probe->ftp_prov->ftp_mtx);
-+ probe->ftp_prov->ftp_rcount++;
-+ mutex_unlock(&probe->ftp_prov->ftp_mtx);
-+
-+ /*
-+ * If this probe's provider is retired (meaning it was valid in a
-+ * previously exec'ed incarnation of this address space), bail out. The
-+ * provider can't go away while we're in this code path.
-+ */
-+ if (probe->ftp_prov->ftp_retired)
-+ return 0;
-+
-+#ifdef FIXME
-+ /*
-+ * If we can't find the process, it may be that we're in the context of
-+ * a fork in which the traced process is being born and we're copying
-+ * USDT probes. Otherwise, the process is gone so bail.
-+ */
-+ p = sprlock(probe->ftp_pid);
-+ if (p == NULL) {
-+ if ((curproc->p_flag & SFORKING) == 0)
-+ return 0;
-+
-+ mutex_enter(&pidlock);
-+ p = prfind(probe->ftp_pid);
-+
-+ /*
-+ * Confirm that curproc is indeed forking the process in which
-+ * we're trying to enable probes.
-+ */
-+ ASSERT(p != NULL);
-+ ASSERT(p->p_parent == curproc);
-+ ASSERT(p->p_stat == SIDL);
-+
-+ mutex_enter(&p->p_lock);
-+ mutex_exit(&pidlock);
-+
-+ sprlock_proc(p);
-+ }
-+
-+ ASSERT(!(p->p_flag & SVFORK));
-+ mutex_exit(&p->p_lock);
-+#endif
-+
-+ /*
-+ * We have to enable the trap entry point before any user threads have
-+ * the chance to execute the trap instruction we're about to place
-+ * in their process's text.
-+ */
-+ fasttrap_enable_callbacks();
-+
-+ /*
-+ * Enable all the tracepoints and add this probe's id to each
-+ * tracepoint's list of active probes.
-+ */
-+ for (i = 0; i < probe->ftp_ntps; i++) {
-+ rc = fasttrap_tracepoint_enable(probe, i);
-+ if (rc != 0) {
-+ /*
-+ * If enabling the tracepoint failed completely,
-+ * we don't have to disable it; if the failure
-+ * was only partial we must disable it.
-+ */
-+ if (rc == FASTTRAP_ENABLE_FAIL)
-+ i--;
-+ else
-+ ASSERT(rc == FASTTRAP_ENABLE_PARTIAL);
-+
-+ /*
-+ * Back up and pull out all the tracepoints we've
-+ * created so far for this probe.
-+ */
-+ while (i >= 0) {
-+ fasttrap_tracepoint_disable(probe, i);
-+ i--;
-+ }
-+
-+#ifdef FIXME
-+ mutex_enter(&p->p_lock);
-+ sprunlock(p);
-+#endif
-+
-+ /*
-+ * Since we're not actually enabling this probe,
-+ * drop our reference on the trap table entry.
-+ */
-+ fasttrap_disable_callbacks();
-+ return 0;
-+ }
-+ }
-+
-+#ifdef FIXME
-+ mutex_enter(&p->p_lock);
-+ sprunlock(p);
-+#endif
-+
-+ probe->ftp_enabled = 1;
-+ return 0;
-+}
-+
-+static void fasttrap_pid_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fasttrap_probe *probe = parg;
-+ struct fasttrap_provider *prov = probe->ftp_prov;
-+ int i, whack = 0;
-+
-+ ASSERT(id == probe->ftp_id);
-+
-+ mutex_lock(&prov->ftp_mtx);
-+
-+ /*
-+ * Disable all the associated tracepoints (for fully enabled probes).
-+ */
-+ if (probe->ftp_enabled) {
-+ for (i = 0; i < probe->ftp_ntps; i++)
-+ fasttrap_tracepoint_disable(probe, i);
-+ }
-+
-+ ASSERT(prov->ftp_rcount > 0);
-+ prov->ftp_rcount--;
-+
-+ if ((prov->ftp_retired || prov->ftp_rcount == 0) && !prov->ftp_marked)
-+ whack = prov->ftp_marked = 1;
-+
-+ mutex_unlock(&prov->ftp_mtx);
-+
-+ if (whack)
-+ fasttrap_pid_cleanup();
-+
-+ if (!probe->ftp_enabled)
-+ return;
-+
-+ probe->ftp_enabled = 0;
-+
-+ ASSERT(MUTEX_HELD(&cpu_lock));
-+ fasttrap_disable_callbacks();
-+}
-+
-+static void fasttrap_pid_getargdesc(void *arg, dtrace_id_t id, void *parg,
-+ struct dtrace_argdesc *desc)
-+{
-+ struct fasttrap_probe *probe = parg;
-+ char *str;
-+ int i, ndx;
-+
-+ desc->dtargd_native[0] = '\0';
-+ desc->dtargd_xlate[0] = '\0';
-+
-+ if (probe->ftp_prov->ftp_retired != 0 ||
-+ desc->dtargd_ndx >= probe->ftp_nargs) {
-+ desc->dtargd_ndx = DTRACE_ARGNONE;
-+ return;
-+ }
-+
-+ ndx = (probe->ftp_argmap != NULL) ? probe->ftp_argmap[desc->dtargd_ndx]
-+ : desc->dtargd_ndx;
-+
-+ str = probe->ftp_ntypes;
-+ for (i = 0; i < ndx; i++)
-+ str += strlen(str) + 1;
-+
-+ ASSERT(strlen(str + 1) < sizeof(desc->dtargd_native));
-+ strcpy(desc->dtargd_native, str);
-+
-+ if (probe->ftp_xtypes == NULL)
-+ return;
-+
-+ str = probe->ftp_xtypes;
-+ for (i = 0; i < desc->dtargd_ndx; i++)
-+ str += strlen(str) + 1;
-+
-+ ASSERT(strlen(str + 1) < sizeof(desc->dtargd_xlate));
-+ strcpy(desc->dtargd_xlate, str);
-+}
-+
-+static void fasttrap_pid_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fasttrap_probe *probe = parg;
-+ int i;
-+
-+ ASSERT(probe != NULL);
-+ ASSERT(!probe->ftp_enabled);
-+ ASSERT(atomic_read(&fasttrap_total) >= probe->ftp_ntps);
-+
-+ atomic_add(-probe->ftp_ntps, &fasttrap_total);
-+
-+ if (probe->ftp_gen + 1 >= fasttrap_mod_gen)
-+ fasttrap_mod_barrier(probe->ftp_gen);
-+
-+ for (i = 0; i < probe->ftp_ntps; i++)
-+ kmem_cache_free(tracepoint_cachep, probe->ftp_tps[i].fit_tp);
-+
-+ kfree(probe);
-+}
-+
-+static const struct dtrace_pattr pid_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+};
-+
-+static struct dtrace_pops pid_pops = {
-+ .dtps_provide = fasttrap_pid_provide,
-+ .dtps_provide_module = NULL,
-+ .dtps_destroy_module = NULL,
-+ .dtps_enable = fasttrap_pid_enable,
-+ .dtps_disable = fasttrap_pid_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = fasttrap_pid_getargdesc,
-+ .dtps_getargval = fasttrap_pid_getarg,
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = fasttrap_pid_destroy
-+};
-+
-+static struct dtrace_pops usdt_pops = {
-+ .dtps_provide = fasttrap_pid_provide,
-+ .dtps_provide_module = NULL,
-+ .dtps_destroy_module = NULL,
-+ .dtps_enable = fasttrap_pid_enable,
-+ .dtps_disable = fasttrap_pid_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = fasttrap_pid_getargdesc,
-+ .dtps_getargval = fasttrap_usdt_getarg,
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = fasttrap_pid_destroy
-+};
-+
-+static uint_t fasttrap_hash_str(const char *p)
-+{
-+ unsigned int g;
-+ uint_t hval = 0;
-+
-+ while (*p) {
-+ hval = (hval << 4) + *p++;
-+ g = hval & 0xf0000000;
-+ if (g != 0)
-+ hval ^= g >> 24;
-+ hval &= ~g;
-+ }
-+
-+ return hval;
-+}
-+
-+static int fasttrap_uint32_cmp(const void *ap, const void *bp)
-+{
-+ return (*(const uint32_t *)ap - *(const uint32_t *)bp);
-+}
-+
-+void fasttrap_meta_create_probe(void *arg, void *parg,
-+ struct dtrace_helper_probedesc *dhpb)
-+{
-+ struct fasttrap_provider *provider = parg;
-+ struct fasttrap_probe *pp;
-+ struct fasttrap_tracepoint *tp;
-+ int i, j;
-+ uint32_t ntps;
-+
-+ /*
-+ * Since the meta provider count is non-zero we don't have to worry
-+ * about this provider disappearing.
-+ */
-+ ASSERT(provider->ftp_mcount > 0);
-+
-+ /*
-+ * The offsets must be unique.
-+ */
-+ sort(dhpb->dthpb_offs, dhpb->dthpb_noffs, sizeof(uint32_t),
-+ fasttrap_uint32_cmp, NULL);
-+ for (i = 1; i < dhpb->dthpb_noffs; i++) {
-+ if (dhpb->dthpb_base + dhpb->dthpb_offs[i] <=
-+ dhpb->dthpb_base + dhpb->dthpb_offs[i - 1])
-+ return;
-+ }
-+
-+ sort(dhpb->dthpb_enoffs, dhpb->dthpb_nenoffs, sizeof(uint32_t),
-+ fasttrap_uint32_cmp, NULL);
-+ for (i = 1; i < dhpb->dthpb_nenoffs; i++) {
-+ if (dhpb->dthpb_base + dhpb->dthpb_enoffs[i] <=
-+ dhpb->dthpb_base + dhpb->dthpb_enoffs[i - 1])
-+ return;
-+ }
-+
-+ /*
-+ * Grab the creation lock to ensure consistency between calls to
-+ * dtrace_probe_lookup() and dtrace_probe_create() in the face of
-+ * other threads creating probes.
-+ */
-+ mutex_lock(&provider->ftp_cmtx);
-+
-+ if (dtrace_probe_lookup(provider->ftp_provid, dhpb->dthpb_mod,
-+ dhpb->dthpb_func, dhpb->dthpb_name) != DTRACE_IDNONE) {
-+ mutex_unlock(&provider->ftp_cmtx);
-+ return;
-+ }
-+
-+ ntps = dhpb->dthpb_noffs + dhpb->dthpb_nenoffs;
-+ ASSERT(ntps > 0);
-+
-+ pp = kzalloc(offsetof(struct fasttrap_probe, ftp_tps[ntps]),
-+ GFP_KERNEL);
-+ if (pp == NULL) {
-+ pr_warn("Unable to create probe %s: out of memory\n",
-+ dhpb->dthpb_name);
-+ mutex_unlock(&provider->ftp_cmtx);
-+ return;
-+ }
-+
-+ atomic_add(ntps, &fasttrap_total);
-+ if (atomic_read(&fasttrap_total) > fasttrap_max) {
-+ kfree(pp);
-+ atomic_add(-ntps, &fasttrap_total);
-+ mutex_unlock(&provider->ftp_cmtx);
-+ return;
-+ }
-+
-+ pp->ftp_prov = provider;
-+ pp->ftp_pid = provider->ftp_pid;
-+ pp->ftp_ntps = ntps;
-+ pp->ftp_nargs = dhpb->dthpb_xargc;
-+ pp->ftp_xtypes = dhpb->dthpb_xtypes;
-+ pp->ftp_ntypes = dhpb->dthpb_ntypes;
-+
-+ /*
-+ * First create a tracepoint for each actual point of interest.
-+ */
-+ for (i = 0; i < dhpb->dthpb_noffs; i++) {
-+ tp = kmem_cache_alloc(tracepoint_cachep, GFP_KERNEL);
-+ if (tp == NULL)
-+ goto fail;
-+
-+ tp->ftt_proc = provider->ftp_proc;
-+ tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_offs[i];
-+ tp->ftt_pid = provider->ftp_pid;
-+ memset(&tp->ftt_mtp, 0, sizeof(struct fasttrap_machtp));
-+ tp->ftt_ids = NULL;
-+ tp->ftt_retids = NULL;
-+ tp->ftt_next = NULL;
-+
-+ dt_dbg_dof(" Tracepoint at 0x%lx (0x%llx + 0x%x)\n",
-+ tp->ftt_pc, dhpb->dthpb_base, dhpb->dthpb_offs[i]);
-+
-+ pp->ftp_tps[i].fit_tp = tp;
-+ pp->ftp_tps[i].fit_id.fti_probe = pp;
-+ pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_OFFSETS;
-+ }
-+
-+ /*
-+ * Then create a tracepoint for each is-enabled point.
-+ */
-+ for (j = 0; i < ntps; i++, j++) {
-+ tp = kmem_cache_alloc(tracepoint_cachep, GFP_KERNEL);
-+ if (tp == NULL)
-+ goto fail;
-+
-+ tp->ftt_proc = provider->ftp_proc;
-+ tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_enoffs[j];
-+ tp->ftt_pid = provider->ftp_pid;
-+ memset(&tp->ftt_mtp, 0, sizeof(struct fasttrap_machtp));
-+ tp->ftt_ids = NULL;
-+ tp->ftt_retids = NULL;
-+ tp->ftt_next = NULL;
-+
-+ pp->ftp_tps[i].fit_tp = tp;
-+ pp->ftp_tps[i].fit_id.fti_probe = pp;
-+ pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_IS_ENABLED;
-+ }
-+
-+ /*
-+ * If the arguments are shuffled around we set the argument remapping
-+ * table. Later, when the probe fires, we only remap the arguments
-+ * if the table is non-NULL.
-+ */
-+ for (i = 0; i < dhpb->dthpb_xargc; i++) {
-+ if (dhpb->dthpb_args[i] != i) {
-+ pp->ftp_argmap = dhpb->dthpb_args;
-+ break;
-+ }
-+ }
-+
-+ /*
-+ * The probe is fully constructed -- register it with DTrace.
-+ */
-+ pp->ftp_id = dtrace_probe_create(provider->ftp_provid, dhpb->dthpb_mod,
-+ dhpb->dthpb_func, dhpb->dthpb_name,
-+ FASTTRAP_OFFSET_AFRAMES, pp);
-+ if (pp->ftp_id == DTRACE_IDNONE)
-+ goto fail;
-+
-+ mutex_unlock(&provider->ftp_cmtx);
-+ return;
-+
-+fail:
-+ pr_warn("Unable to create probe %s: out of memory\n",
-+ dhpb->dthpb_name);
-+
-+ for (i = 0; i < ntps; i++)
-+ kmem_cache_free(tracepoint_cachep, pp->ftp_tps[i].fit_tp);
-+
-+ kfree(pp);
-+ atomic_add(-ntps, &fasttrap_total);
-+ mutex_unlock(&provider->ftp_cmtx);
-+}
-+
-+static void fasttrap_proc_release(struct fasttrap_proc *proc)
-+{
-+ struct fasttrap_bucket *bucket;
-+ struct fasttrap_proc *fprc, **fprcp;
-+ pid_t pid = proc->ftpc_pid;
-+
-+ mutex_lock(&proc->ftpc_mtx);
-+
-+ ASSERT(proc->ftpc_rcount != 0);
-+ ASSERT(atomic64_read(&proc->ftpc_acount) <= proc->ftpc_rcount);
-+
-+ if (--proc->ftpc_rcount != 0) {
-+ mutex_unlock(&proc->ftpc_mtx);
-+ return;
-+ }
-+
-+ mutex_unlock(&proc->ftpc_mtx);
-+
-+ /*
-+ * There should definitely be no live providers associated with this
-+ * process at this point.
-+ */
-+ ASSERT(atomic64_read(&proc->ftpc_acount) == 0);
-+
-+ bucket = FASTTRAP_PROCS_ELEM(pid);
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ fprcp = (struct fasttrap_proc **)&bucket->ftb_data;
-+ while ((fprc = *fprcp) != NULL) {
-+ if (fprc == proc)
-+ break;
-+
-+ fprcp = &fprc->ftpc_next;
-+ }
-+
-+ /*
-+ * Something strange has happened if we can't find the proc.
-+ */
-+ ASSERT(fprc != NULL);
-+
-+ *fprcp = fprc->ftpc_next;
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ kfree(fprc);
-+}
-+
-+static void fasttrap_provider_free(struct fasttrap_provider *provider)
-+{
-+ pid_t pid = provider->ftp_pid;
-+
-+ /*
-+ * There need to be no associated enabled probes, no consumers
-+ * creating probes, and no meta providers referencing this provider.
-+ */
-+ ASSERT(provider->ftp_rcount == 0);
-+ ASSERT(provider->ftp_ccount == 0);
-+ ASSERT(provider->ftp_mcount == 0);
-+
-+ /*
-+ * If this provider hasn't been retired, we need to explicitly drop the
-+ * count of active providers on the associated process structure.
-+ */
-+ if (!provider->ftp_retired) {
-+ atomic64_add(-1, &provider->ftp_proc->ftpc_acount);
-+ ASSERT(atomic64_read(&provider->ftp_proc->ftpc_acount) <
-+ provider->ftp_proc->ftpc_rcount);
-+ }
-+
-+ fasttrap_proc_release(provider->ftp_proc);
-+
-+ kfree(provider);
-+
-+ unregister_pid_provider(pid);
-+}
-+
-+static struct fasttrap_proc *fasttrap_proc_lookup(pid_t pid)
-+{
-+ struct fasttrap_bucket *bucket;
-+ struct fasttrap_proc *fprc, *new_fprc;
-+
-+ bucket = FASTTRAP_PROCS_ELEM(pid);
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) {
-+ if (fprc->ftpc_pid == pid &&
-+ atomic64_read(&fprc->ftpc_acount) != 0) {
-+ mutex_lock(&fprc->ftpc_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+ fprc->ftpc_rcount++;
-+ atomic64_inc(&fprc->ftpc_acount);
-+ ASSERT(atomic64_read(&fprc->ftpc_acount) <=
-+ fprc->ftpc_rcount);
-+ mutex_unlock(&fprc->ftpc_mtx);
-+
-+ return fprc;
-+ }
-+ }
-+
-+ /*
-+ * Drop the bucket lock so we don't try to perform a sleeping
-+ * allocation under it.
-+ */
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ new_fprc = kzalloc(sizeof(struct fasttrap_proc), GFP_KERNEL);
-+ if (new_fprc == NULL)
-+ return NULL;
-+
-+ new_fprc->ftpc_pid = pid;
-+ new_fprc->ftpc_rcount = 1;
-+ atomic64_set(&new_fprc->ftpc_acount, 1);
-+ mutex_init(&new_fprc->ftpc_mtx);
-+
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Take another lap through the list to make sure a proc hasn't
-+ * been created for this pid while we weren't under the bucket lock.
-+ */
-+ for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) {
-+ if (fprc->ftpc_pid == pid &&
-+ atomic64_read(&fprc->ftpc_acount) != 0) {
-+ mutex_lock(&fprc->ftpc_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+ fprc->ftpc_rcount++;
-+ atomic64_inc(&fprc->ftpc_acount);
-+ ASSERT(atomic64_read(&fprc->ftpc_acount) <=
-+ fprc->ftpc_rcount);
-+ mutex_unlock(&fprc->ftpc_mtx);
-+
-+ kfree(new_fprc);
-+
-+ return fprc;
-+ }
-+ }
-+
-+ new_fprc->ftpc_next = bucket->ftb_data;
-+ bucket->ftb_data = new_fprc;
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ return new_fprc;
-+}
-+
-+/*
-+ * Lookup a fasttrap-managed provider based on its name and associated pid.
-+ * If the pattr argument is non-NULL, this function instantiates the provider
-+ * if it doesn't exist otherwise it returns NULL. The provider is returned
-+ * with its lock held.
-+ */
-+static struct fasttrap_provider *
-+fasttrap_provider_lookup(pid_t pid, const char *name,
-+ const struct dtrace_pattr *pa)
-+{
-+ struct fasttrap_provider *fp, *new_fp = NULL;
-+ struct fasttrap_proc *proc = NULL;
-+ struct fasttrap_bucket *bucket;
-+ char provname[DTRACE_PROVNAMELEN];
-+ struct task_struct *p;
-+ const struct cred *cred = NULL;
-+
-+ ASSERT(strlen(name) < sizeof(fp->ftp_name));
-+ ASSERT(pa != NULL);
-+
-+ bucket = FASTTRAP_PROVS_ELEM(pid, name);
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Take a lap through the list and return the match if we find it.
-+ */
-+ for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
-+ if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
-+ !fp->ftp_retired) {
-+ mutex_lock(&fp->ftp_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ return fp;
-+ }
-+ }
-+
-+ /*
-+ * Drop the bucket lock so we don't try to perform a sleeping
-+ * allocation under it.
-+ */
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ p = register_pid_provider(pid);
-+ if (p == NULL)
-+ goto fail;
-+
-+ /*
-+ * Grab the credentials for this process so we have
-+ * something to pass to dtrace_register().
-+ */
-+ cred = get_cred(p->cred);
-+
-+ proc = fasttrap_proc_lookup(pid);
-+ if (proc == NULL)
-+ goto fail;
-+
-+ new_fp = kzalloc(sizeof(struct fasttrap_provider), GFP_KERNEL);
-+ if (new_fp == NULL)
-+ goto fail;
-+
-+ new_fp->ftp_pid = pid;
-+ new_fp->ftp_proc = proc;
-+ mutex_init(&new_fp->ftp_mtx);
-+ mutex_init(&new_fp->ftp_cmtx);
-+
-+ ASSERT(new_fp->ftp_proc != NULL);
-+
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ /*
-+ * Take another lap through the list to make sure a provider hasn't
-+ * been created for this pid while we weren't under the bucket lock.
-+ */
-+ for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
-+ if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
-+ !fp->ftp_retired) {
-+ mutex_lock(&fp->ftp_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+ fasttrap_provider_free(new_fp);
-+ put_cred(cred);
-+
-+ return fp;
-+ }
-+ }
-+
-+ strcpy(new_fp->ftp_name, name);
-+
-+ /*
-+ * Fail and return NULL if either the provider name is too long
-+ * or we fail to register this new provider with the DTrace
-+ * framework. Note that this is the only place we ever construct
-+ * the full provider name -- we keep it in pieces in the provider
-+ * structure.
-+ */
-+ if (snprintf(provname, sizeof(provname), "%s%u", name, (uint_t)pid) >=
-+ sizeof(provname) ||
-+ dtrace_register(provname, pa,
-+ DTRACE_PRIV_PROC | DTRACE_PRIV_OWNER, cred,
-+ pa == &pid_attr ? &pid_pops : &usdt_pops,
-+ new_fp, &new_fp->ftp_provid) != 0) {
-+ mutex_unlock(&bucket->ftb_mtx);
-+ fasttrap_provider_free(new_fp);
-+ put_cred(cred);
-+ return NULL;
-+ }
-+
-+ new_fp->ftp_next = bucket->ftb_data;
-+ bucket->ftb_data = new_fp;
-+
-+ mutex_lock(&new_fp->ftp_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ put_cred(cred);
-+
-+ return new_fp;
-+
-+fail:
-+ if (proc)
-+ fasttrap_proc_release(proc);
-+ if (cred)
-+ put_cred(cred);
-+ if (p)
-+ unregister_pid_provider(pid);
-+
-+ return NULL;
-+}
-+
-+void *fasttrap_meta_provide(void *arg, struct dtrace_helper_provdesc *dhpv,
-+ pid_t pid)
-+{
-+ struct fasttrap_provider *provider;
-+
-+ if (strlen(dhpv->dthpv_provname) + 10 >= sizeof(provider->ftp_name)) {
-+ pr_warn("Failed to instantiate provider %s: name too long "
-+ "to accommodate pid\n", dhpv->dthpv_provname);
-+ return NULL;
-+ }
-+
-+ /*
-+ * Don't let folks spoof the true pid provider.
-+ */
-+ if (strcmp(dhpv->dthpv_provname, FASTTRAP_PID_NAME) == 0) {
-+ pr_warn("Failed to instantiate provider %s: %s is an invalid "
-+ "name\n", dhpv->dthpv_provname, FASTTRAP_PID_NAME);
-+ return NULL;
-+ }
-+
-+ /*
-+ * The highest stability class that fasttrap supports is ISA; cap
-+ * the stability of the new provider accordingly.
-+ */
-+ if (dhpv->dthpv_pattr.dtpa_provider.dtat_class > DTRACE_CLASS_ISA)
-+ dhpv->dthpv_pattr.dtpa_provider.dtat_class = DTRACE_CLASS_ISA;
-+ if (dhpv->dthpv_pattr.dtpa_mod.dtat_class > DTRACE_CLASS_ISA)
-+ dhpv->dthpv_pattr.dtpa_mod.dtat_class = DTRACE_CLASS_ISA;
-+ if (dhpv->dthpv_pattr.dtpa_func.dtat_class > DTRACE_CLASS_ISA)
-+ dhpv->dthpv_pattr.dtpa_func.dtat_class = DTRACE_CLASS_ISA;
-+ if (dhpv->dthpv_pattr.dtpa_name.dtat_class > DTRACE_CLASS_ISA)
-+ dhpv->dthpv_pattr.dtpa_name.dtat_class = DTRACE_CLASS_ISA;
-+ if (dhpv->dthpv_pattr.dtpa_args.dtat_class > DTRACE_CLASS_ISA)
-+ dhpv->dthpv_pattr.dtpa_args.dtat_class = DTRACE_CLASS_ISA;
-+
-+ provider = fasttrap_provider_lookup(pid, dhpv->dthpv_provname,
-+ &dhpv->dthpv_pattr);
-+ if (provider == NULL) {
-+ pr_warn("Failed to instantiate provider %s for process %u\n",
-+ dhpv->dthpv_provname, (uint_t)pid);
-+ return NULL;
-+ }
-+
-+ /*
-+ * Up the meta provider count so this provider isn't removed until the
-+ * meta provider has been told to remove it.
-+ */
-+ provider->ftp_mcount++;
-+
-+ mutex_unlock(&provider->ftp_mtx);
-+
-+ return provider;
-+}
-+
-+static void fasttrap_pid_cleanup_cb(struct work_struct *work)
-+{
-+ struct fasttrap_provider **fpp, *fp;
-+ struct fasttrap_bucket *bucket;
-+ dtrace_provider_id_t provid;
-+ int i, later = 0;
-+
-+ static volatile int in;
-+
-+ ASSERT(in == 0);
-+ in = 1;
-+
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ if (!fasttrap_cleanup_work && fasttrap_cleanup_state == CLEANUP_NONE) {
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+ in = 0;
-+ return;
-+ }
-+
-+ dt_dbg_prov("Fasttrap provider cleanup callback processing...\n");
-+ while (fasttrap_cleanup_work) {
-+ fasttrap_cleanup_work = 0;
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+
-+ later = 0;
-+
-+ /*
-+ * Iterate over all the providers trying to remove the marked
-+ * ones. If a provider is marked but not retired, we just
-+ * have to take a crack at removing it -- it's no big deal if
-+ * we can't.
-+ */
-+ for (i = 0; i < fasttrap_provs.fth_nent; i++) {
-+ bucket = FASTTRAP_ELEM_BUCKET(&fasttrap_provs.fth_table[i]);
-+ mutex_lock(&bucket->ftb_mtx);
-+ fpp = (struct fasttrap_provider **)&bucket->ftb_data;
-+
-+ while ((fp = *fpp) != NULL) {
-+ dt_dbg_prov(" Trying to unregister %s%d "
-+ "(%smarked)\n",
-+ fp->ftp_name, fp->ftp_pid,
-+ fp->ftp_marked ? "not " : "");
-+ if (!fp->ftp_marked) {
-+ fpp = &fp->ftp_next;
-+ continue;
-+ }
-+
-+ dt_dbg_prov(" ccount %llu, mcount %llu "
-+ "rcount %llu, %sretired, "
-+ "%smarked\n",
-+ fp->ftp_ccount, fp->ftp_mcount,
-+ fp->ftp_rcount,
-+ fp->ftp_retired ? "" : "not ",
-+ fp->ftp_marked ? "" : "not ");
-+
-+ mutex_lock(&fp->ftp_mtx);
-+
-+ /*
-+ * If this provider has consumers actively
-+ * creating probes (ftp_ccount) or is a USDT
-+ * provider (ftp_mcount), we can't unregister
-+ * or even condense.
-+ */
-+ if (fp->ftp_ccount != 0 ||
-+ fp->ftp_mcount != 0) {
-+ mutex_unlock(&fp->ftp_mtx);
-+ fp->ftp_marked = 0;
-+ continue;
-+ }
-+
-+ if (!fp->ftp_retired || fp->ftp_rcount != 0)
-+ fp->ftp_marked = 0;
-+
-+ mutex_unlock(&fp->ftp_mtx);
-+
-+ /*
-+ * If we successfully unregister this
-+ * provider we can remove it from the hash
-+ * chain and free the memory. If our attempt
-+ * to unregister fails and this is a retired
-+ * provider, increment our flag to try again
-+ * pretty soon. If we've consumed more than
-+ * half of our total permitted number of
-+ * probes call dtrace_condense() to try to
-+ * clean out the unenabled probes.
-+ */
-+ provid = fp->ftp_provid;
-+ mutex_lock(&module_mutex);
-+ if (dtrace_unregister(provid) != 0) {
-+ if (atomic_read(&fasttrap_total) >
-+ fasttrap_max / 2)
-+ dtrace_condense(provid);
-+
-+ later += fp->ftp_marked;
-+ fpp = &fp->ftp_next;
-+ } else {
-+ *fpp = fp->ftp_next;
-+ fasttrap_provider_free(fp);
-+ }
-+ mutex_unlock(&module_mutex);
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+ }
-+
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ }
-+
-+ ASSERT(fasttrap_cleanup_state != CLEANUP_NONE);
-+
-+ /*
-+ * If we were unable to remove a retired provider, try again after
-+ * a second. This situation can occur in certain circumstances where
-+ * providers cannot be unregistered even though they have no probes
-+ * enabled because of an execution of dtrace -l or something similar.
-+ * If the timeout has been disabled (set to 1 because we're trying
-+ * to detach), we set fasttrap_cleanup_work to ensure that we'll
-+ * get a chance to do that work if and when the timeout is reenabled
-+ * (if detach fails).
-+ */
-+ if (later > 0) {
-+ dt_dbg_prov(" Some providers were not removed "
-+ " (state %d, later = %d)\n",
-+ fasttrap_cleanup_state, later);
-+ if (fasttrap_cleanup_state == CLEANUP_DEFERRED)
-+ fasttrap_cleanup_work = 1;
-+ else {
-+ struct delayed_work *dw = container_of(
-+ work,
-+ struct delayed_work,
-+ work);
-+
-+ fasttrap_cleanup_state = CLEANUP_SCHEDULED;
-+ schedule_delayed_work(dw, HZ);
-+ }
-+ } else
-+ fasttrap_cleanup_state = CLEANUP_NONE;
-+
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+ in = 0;
-+
-+ dt_dbg_prov("Fasttrap provider cleanup callback done\n");
-+}
-+
-+static DECLARE_DELAYED_WORK(fasttrap_cleanup, fasttrap_pid_cleanup_cb);
-+
-+/*
-+ * Activate the asynchronous cleanup mechanism.
-+ */
-+static void fasttrap_pid_cleanup(void)
-+{
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ fasttrap_cleanup_work = 1;
-+ fasttrap_cleanup_state = CLEANUP_SCHEDULED;
-+ schedule_delayed_work(&fasttrap_cleanup, 3);
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+}
-+
-+void fasttrap_provider_retire(pid_t pid, const char *name, int mprov)
-+{
-+ struct fasttrap_provider *fp;
-+ struct fasttrap_bucket *bucket;
-+ dtrace_provider_id_t provid;
-+
-+ ASSERT(strlen(name) < sizeof(fp->ftp_name));
-+
-+ dt_dbg_prov("Retiring %s %sprovider for PID %d\n",
-+ name, mprov ? "meta-" : "", pid);
-+
-+ bucket = FASTTRAP_PROVS_ELEM(pid, name);
-+ mutex_lock(&bucket->ftb_mtx);
-+
-+ for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
-+ if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
-+ !fp->ftp_retired)
-+ break;
-+ }
-+
-+ if (fp == NULL) {
-+ mutex_unlock(&bucket->ftb_mtx);
-+ return;
-+ }
-+
-+ mutex_lock(&fp->ftp_mtx);
-+ ASSERT(!mprov || fp->ftp_mcount > 0);
-+ if (mprov && --fp->ftp_mcount != 0) {
-+ mutex_unlock(&fp->ftp_mtx);
-+ mutex_unlock(&bucket->ftb_mtx);
-+ return;
-+ }
-+
-+ /*
-+ * Mark the provider to be removed in our post-processing step, mark it
-+ * retired, and drop the active count on its proc. Marking it indicates
-+ * that we should try to remove it; setting the retired flag indicates
-+ * that we're done with this provider; dropping the active count on the
-+ * proc releases our hold, and when this reaches zero (as it will
-+ * during exit or exec) the proc and associated providers become
-+ * defunct.
-+ *
-+ * We obviously need to take the bucket lock before the provider lock
-+ * to perform the lookup, but we need to drop the provider lock
-+ * before calling into the DTrace framework since we acquire the
-+ * provider lock in callbacks invoked from the DTrace framework. The
-+ * bucket lock therefore protects the integrity of the provider hash
-+ * table.
-+ */
-+ atomic64_dec(&fp->ftp_proc->ftpc_acount);
-+ ASSERT(atomic64_read(&fp->ftp_proc->ftpc_acount) <
-+ fp->ftp_proc->ftpc_rcount);
-+
-+ fp->ftp_retired = 1;
-+ fp->ftp_marked = 1;
-+ provid = fp->ftp_provid;
-+ mutex_unlock(&fp->ftp_mtx);
-+
-+ /*
-+ * We don't have to worry about invalidating the same provider twice
-+ * since fasttrap_provider_lookup() will ignore provider that have
-+ * been marked as retired.
-+ */
-+ dtrace_invalidate(provid);
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+
-+ fasttrap_pid_cleanup();
-+}
-+
-+static void fasttrap_probes_cleanup(struct task_struct *tsk)
-+{
-+ fasttrap_provider_retire(tsk->pid, FASTTRAP_PID_NAME, 0);
-+}
-+
-+void fasttrap_meta_remove(void *arg, struct dtrace_helper_provdesc *dhpv,
-+ pid_t pid)
-+{
-+ /*
-+ * Clean up the USDT provider. There may be active consumers of the
-+ * provider busy adding probes, no damage will actually befall the
-+ * provider until that count has dropped to zero. This just puts
-+ * the provider on death row.
-+ */
-+ fasttrap_provider_retire(pid, dhpv->dthpv_provname, 1);
-+}
-+
-+static int fasttrap_add_probe(struct fasttrap_probe_spec *probe)
-+{
-+ struct fasttrap_provider *provider;
-+ struct fasttrap_probe *pp;
-+ struct fasttrap_tracepoint *tp;
-+ uint64_t *offs = NULL;
-+ uint64_t noffs;
-+ char *name;
-+ int aframes, retired;
-+
-+ switch (probe->ftps_type) {
-+ case DTFTP_ENTRY:
-+ name = "entry";
-+ aframes = FASTTRAP_ENTRY_AFRAMES;
-+ break;
-+ case DTFTP_RETURN:
-+ name = "return";
-+ aframes = FASTTRAP_RETURN_AFRAMES;
-+ break;
-+ case DTFTP_OFFSETS:
-+ if (probe->ftps_glen <= 0)
-+ return -EINVAL;
-+
-+ name = "<offsets>";
-+ aframes = FASTTRAP_OFFSET_AFRAMES;
-+ offs = fasttrap_glob_offsets(probe, &noffs);
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ provider = fasttrap_provider_lookup(probe->ftps_pid, FASTTRAP_PID_NAME,
-+ &pid_attr);
-+ if (provider == NULL)
-+ return -ESRCH;
-+
-+ /*
-+ * Increment the consumer reference count on the provider to indicate
-+ * that a new probe is being associated with the provider. This makes
-+ * sure that the provider will not be removed while we are working with
-+ * it.
-+ *
-+ * This also means that we can drop the provider lock.
-+ */
-+ provider->ftp_ccount++;
-+ mutex_unlock(&provider->ftp_mtx);
-+
-+ /*
-+ * Grab the probe creation lock for this provider to ensure consistency
-+ * between dtrace_probe_lookup() and dtrace_probe_create() because
-+ * other threads might be creating probes also.
-+ */
-+ mutex_lock(&provider->ftp_cmtx);
-+
-+ if (probe->ftps_type == DTFTP_OFFSETS) {
-+ int i;
-+
-+ for (i = 0; i < noffs; i++) {
-+ char ostr[sizeof(*offs) + 1];
-+
-+ snprintf(ostr, sizeof(ostr), "%llx", offs[i]);
-+ if (dtrace_probe_lookup(provider->ftp_provid,
-+ probe->ftps_mod,
-+ probe->ftps_func, ostr) != 0)
-+ continue;
-+
-+ atomic_add(1, &fasttrap_total);
-+ if (atomic_read(&fasttrap_total) > fasttrap_max)
-+ goto fail_reset;
-+
-+ pp = kzalloc(sizeof(struct fasttrap_probe), GFP_KERNEL);
-+ if (pp == NULL)
-+ goto fail_reset;
-+
-+ pp->ftp_prov = provider;
-+ pp->ftp_pid = provider->ftp_pid;
-+ pp->ftp_ntps = 1;
-+
-+ tp = kmem_cache_alloc(tracepoint_cachep, GFP_KERNEL);
-+ if (tp == NULL)
-+ goto fail_reset;
-+
-+ tp->ftt_proc = provider->ftp_proc;
-+ tp->ftt_pc = probe->ftps_pc + offs[i];
-+ tp->ftt_pid = provider->ftp_pid;
-+ memset(&tp->ftt_mtp, 0,
-+ sizeof(struct fasttrap_machtp));
-+ tp->ftt_ids = NULL;
-+ tp->ftt_retids = NULL;
-+ tp->ftt_next = NULL;
-+
-+ pp->ftp_tps[0].fit_tp = tp;
-+ pp->ftp_tps[0].fit_id.fti_probe = pp;
-+ pp->ftp_tps[0].fit_id.fti_ptype = probe->ftps_type;
-+
-+ pp->ftp_id = dtrace_probe_create(provider->ftp_provid,
-+ probe->ftps_mod,
-+ probe->ftps_func, ostr,
-+ aframes, pp);
-+ if (pp->ftp_id == DTRACE_IDNONE) {
-+ kmem_cache_free(tracepoint_cachep, tp);
-+ kfree(pp);
-+
-+ goto fail_reset;
-+ }
-+ }
-+ } else if (dtrace_probe_lookup(provider->ftp_provid, probe->ftps_mod,
-+ probe->ftps_func, name) == 0) {
-+ atomic_add(1, &fasttrap_total);
-+ if (atomic_read(&fasttrap_total) > fasttrap_max)
-+ goto fail_reset;
-+
-+ pp = kzalloc(sizeof(struct fasttrap_probe), GFP_KERNEL);
-+ if (pp == NULL)
-+ goto fail_reset;
-+
-+ pp->ftp_prov = provider;
-+ pp->ftp_pid = provider->ftp_pid;
-+ pp->ftp_ntps = 1;
-+
-+ tp = kmem_cache_alloc(tracepoint_cachep, GFP_KERNEL);
-+ if (tp == NULL)
-+ goto fail_reset;
-+
-+ tp->ftt_proc = provider->ftp_proc;
-+ tp->ftt_pc = probe->ftps_pc;
-+ tp->ftt_pid = provider->ftp_pid;
-+ memset(&tp->ftt_mtp, 0, sizeof(struct fasttrap_machtp));
-+ tp->ftt_ids = NULL;
-+ tp->ftt_retids = NULL;
-+ tp->ftt_next = NULL;
-+
-+ pp->ftp_tps[0].fit_tp = tp;
-+ pp->ftp_tps[0].fit_id.fti_probe = pp;
-+ pp->ftp_tps[0].fit_id.fti_ptype = probe->ftps_type;
-+
-+ pp->ftp_id = dtrace_probe_create(provider->ftp_provid,
-+ probe->ftps_mod,
-+ probe->ftps_func, name,
-+ aframes, pp);
-+ if (pp->ftp_id == DTRACE_IDNONE) {
-+ kmem_cache_free(tracepoint_cachep, tp);
-+ kfree(pp);
-+
-+ goto fail_reset;
-+ }
-+ }
-+
-+ mutex_unlock(&provider->ftp_cmtx);
-+
-+ /*
-+ * The provider is still around because of the consumer reference
-+ * count that we incremented. If another thread tried to clean up the
-+ * provider while we were using it (because the process called exec or
-+ * exit), we'll trigger a cleanup.
-+ */
-+ mutex_lock(&provider->ftp_mtx);
-+ provider->ftp_ccount--;
-+ retired = provider->ftp_retired;
-+ mutex_unlock(&provider->ftp_mtx);
-+
-+ if (retired)
-+ fasttrap_pid_cleanup();
-+
-+ return 0;
-+
-+fail_reset:
-+ atomic_add(-1, &fasttrap_total);
-+
-+ /*
-+ * If we failed to create the probe, it usually means we ran out of
-+ * memory. We'll try to remove this provider to free some. This
-+ * usually happens when a user accidentally triggers the creation of
-+ * a very large amount of probes (e.g. pid587:::).
-+ */
-+ mutex_unlock(&provider->ftp_cmtx);
-+
-+ kfree(offs);
-+
-+ mutex_lock(&provider->ftp_mtx);
-+ provider->ftp_ccount--;
-+ provider->ftp_marked = 1;
-+ mutex_unlock(&provider->ftp_mtx);
-+
-+ fasttrap_pid_cleanup();
-+
-+ return -ENOMEM;
-+}
-+
-+static long fasttrap_ioctl(struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ void __user *argp = (void __user *)arg;
-+
-+ if (cmd == FASTTRAPIOC_MAKEPROBE) {
-+ struct fasttrap_probe_spec __user *uprobe = argp;
-+ struct fasttrap_probe_spec *probe;
-+ uint8_t glen;
-+ size_t size;
-+ int ret;
-+ char *c;
-+
-+ dt_dbg_ioctl("PID IOCTL MAKEPROBE (cmd %#x), argp %p\n",
-+ cmd, argp);
-+
-+ if (copy_from_user(&glen, &uprobe->ftps_glen,
-+ sizeof(uprobe->ftps_glen)))
-+ return -EFAULT;
-+
-+ size = sizeof(struct fasttrap_probe_spec) +
-+ sizeof(probe->ftps_gstr[0]) * (glen - 1);
-+
-+ if (size > 1024 * 1024)
-+ return -ENOMEM;
-+
-+ probe = kmalloc(size, GFP_KERNEL);
-+ if (!probe)
-+ return -ENOMEM;
-+
-+ if (copy_from_user(probe, uprobe, size) != 0) {
-+ ret = -EFAULT;
-+ goto err;
-+ }
-+
-+ for (c = &probe->ftps_func[0]; *c != '\0'; c++) {
-+ if (*c < 0x20 || 0x7f <= *c) {
-+ ret = -EINVAL;
-+ goto err;
-+ }
-+ }
-+
-+ for (c = &probe->ftps_mod[0]; *c != '\0'; c++) {
-+ if (*c < 0x20 || 0x7f <= *c) {
-+ ret = -EINVAL;
-+ goto err;
-+ }
-+ }
-+
-+ ret = fasttrap_add_probe(probe);
-+err:
-+ kfree(probe);
-+
-+ return ret;
-+ }
-+
-+ return -EAGAIN;
-+}
-+
-+static int fasttrap_open(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static int fasttrap_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations fasttrap_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = fasttrap_ioctl,
-+ .open = fasttrap_open,
-+ .release = fasttrap_close,
-+};
-+
-+static struct miscdevice fasttrap_dev = {
-+ .minor = DT_DEV_FASTTRAP_MINOR,
-+ .name = "fasttrap",
-+ .nodename = "dtrace/provider/fasttrap",
-+ .fops = &fasttrap_fops,
-+};
-+
-+static int fasttrap_init_htable(struct fasttrap_hash *fth, ulong_t nent)
-+{
-+ ulong_t i;
-+
-+ if ((nent & (nent - 1)) == 0)
-+ fth->fth_nent = nent;
-+ else
-+ fth->fth_nent = 1 << fls(nent);
-+
-+ ASSERT(fth->fth_nent > 0);
-+
-+ fth->fth_mask = fth->fth_nent - 1;
-+ fth->fth_table = vzalloc(fth->fth_nent *
-+ sizeof(struct fasttrap_bucket_elem));
-+
-+ if (fth->fth_table == NULL)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < fth->fth_nent; i++)
-+ mutex_init(&fth->fth_table[i].bucket.ftb_mtx);
-+
-+ return 0;
-+}
-+
-+int fasttrap_dev_init(void)
-+{
-+ int ret = 0;
-+ ulong_t nent;
-+
-+ ret = misc_register(&fasttrap_dev);
-+ if (ret) {
-+ pr_err("%s: Can't register misc device %d\n",
-+ fasttrap_dev.name, fasttrap_dev.minor);
-+ goto fail;
-+ }
-+
-+#ifdef FIXME
-+ dtrace_fasttrap_exit_ptr = &fasttrap_exec_exit;
-+ dtrace_fasttrap_exec_ptr = &fasttrap_exec_exit;
-+#endif
-+
-+ tracepoint_cachep = KMEM_CACHE(fasttrap_tracepoint, 0);
-+
-+ fasttrap_max = FASTTRAP_MAX_DEFAULT;
-+ atomic_set(&fasttrap_total, 0);
-+
-+ /*
-+ * Conjure up the tracepoints hashtable...
-+ */
-+ nent = FASTTRAP_TPOINTS_DEFAULT_SIZE;
-+
-+ if (nent == 0 || nent > 0x1000000)
-+ nent = FASTTRAP_TPOINTS_DEFAULT_SIZE;
-+
-+ if (fasttrap_init_htable(&fasttrap_tpoints, nent) != 0)
-+ return -ENOMEM;
-+
-+ /*
-+ * ... and the providers hash table...
-+ */
-+ nent = FASTTRAP_PROVIDERS_DEFAULT_SIZE;
-+ if (fasttrap_init_htable(&fasttrap_provs, nent) != 0)
-+ return -ENOMEM;
-+
-+ /*
-+ * ... and the procs hash table.
-+ */
-+ nent = FASTTRAP_PROCS_DEFAULT_SIZE;
-+ if (fasttrap_init_htable(&fasttrap_procs, nent) != 0)
-+ return -ENOMEM;
-+
-+fail:
-+ return ret;
-+}
-+
-+/*
-+ * This function is called with module_mutex held.
-+ */
-+int fasttrap_prov_exit(void)
-+{
-+ int fail = 0;
-+ ulong_t i;
-+
-+ if (dtrace_meta_unregister(fasttrap_id) != 0)
-+ return 0;
-+
-+ /*
-+ * Prevent any new timeouts from running by setting fasttrap_timeout
-+ * to a non-zero value, and wait for the current timeout to complete.
-+ */
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ fasttrap_cleanup_work = 0;
-+
-+ while (fasttrap_cleanup_state != CLEANUP_DEFERRED) {
-+ uint_t tmp;
-+
-+ tmp = fasttrap_cleanup_state;
-+ fasttrap_cleanup_state = CLEANUP_DEFERRED;
-+
-+ if (tmp != CLEANUP_NONE) {
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+ flush_delayed_work(&fasttrap_cleanup);
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ }
-+ }
-+
-+ fasttrap_cleanup_work = 0;
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+
-+ /*
-+ * Iterate over all of our providers. If there's still a process
-+ * that corresponds to that pid, fail to detach.
-+ */
-+ for (i = 0; i < fasttrap_provs.fth_nent; i++) {
-+ struct fasttrap_provider **fpp, *fp;
-+ struct fasttrap_bucket *bucket;
-+
-+ bucket = FASTTRAP_ELEM_BUCKET(&fasttrap_provs.fth_table[i]);
-+ mutex_lock(&bucket->ftb_mtx);
-+ fpp = (struct fasttrap_provider **)&bucket->ftb_data;
-+ while ((fp = *fpp) != NULL) {
-+ /*
-+ * Acquire and release the lock as a simple way of
-+ * waiting for any other consumer to finish with
-+ * this provider. A thread must first acquire the
-+ * bucket lock so there's no chance of another thread
-+ * blocking on the provider's lock.
-+ */
-+ mutex_lock(&fp->ftp_mtx);
-+ mutex_unlock(&fp->ftp_mtx);
-+
-+ if (dtrace_unregister(fp->ftp_provid) != 0) {
-+ fail = 1;
-+ fpp = &fp->ftp_next;
-+ } else {
-+ *fpp = fp->ftp_next;
-+ fasttrap_provider_free(fp);
-+ }
-+ }
-+
-+ mutex_unlock(&bucket->ftb_mtx);
-+ }
-+
-+ if (fail) {
-+ uint_t work;
-+
-+ /*
-+ * If we're failing to detach, we need to unblock timeouts
-+ * and start a new timeout if any work has accumulated while
-+ * we've been unsuccessfully trying to detach.
-+ */
-+ mutex_lock(&fasttrap_cleanup_mtx);
-+ fasttrap_cleanup_state = CLEANUP_NONE;
-+ work = fasttrap_cleanup_work;
-+ mutex_unlock(&fasttrap_cleanup_mtx);
-+
-+ if (work)
-+ fasttrap_pid_cleanup();
-+
-+ dtrace_meta_register("fasttrap", &fasttrap_mops, NULL,
-+ &fasttrap_id);
-+
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+void fasttrap_dev_exit(void)
-+{
-+#ifdef DEBUG
-+ mutex_lock(&fasttrap_count_mtx);
-+ ASSERT(fasttrap_pid_count == 0);
-+ mutex_unlock(&fasttrap_count_mtx);
-+#endif
-+
-+ if (fasttrap_tpoints.fth_table)
-+ vfree(fasttrap_tpoints.fth_table);
-+ fasttrap_tpoints.fth_nent = 0;
-+
-+ if (fasttrap_provs.fth_table)
-+ vfree(fasttrap_provs.fth_table);
-+ fasttrap_provs.fth_nent = 0;
-+
-+ if (fasttrap_procs.fth_table)
-+ vfree(fasttrap_procs.fth_table);
-+ fasttrap_procs.fth_nent = 0;
-+
-+ kmem_cache_destroy(tracepoint_cachep);
-+
-+#ifdef FIXME
-+ ASSERT(dtrace_fasttrap_exec_ptr == &fasttrap_exec_exit);
-+ dtrace_fasttrap_exec_ptr = NULL;
-+
-+ ASSERT(dtrace_fasttrap_exit_ptr == &fasttrap_exec_exit);
-+ dtrace_fasttrap_exit_ptr = NULL;
-+#endif
-+
-+ misc_deregister(&fasttrap_dev);
-+}
-diff --git a/dtrace/fasttrap_impl.h b/dtrace/fasttrap_impl.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..cd2c4a28871eff171e5171860d600dd27e9404d7
---- /dev/null
-+++ b/dtrace/fasttrap_impl.h
-@@ -0,0 +1,172 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - fasttrap provider
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _FASTTRAP_IMPL_H_
-+#define _FASTTRAP_IMPL_H_
-+
-+#include <linux/dtrace/fasttrap.h>
-+#include <dtrace/fasttrap_arch.h>
-+#include <linux/cache.h>
-+
-+/*
-+ * Fasttrap Providers, Probes and Tracepoints
-+ *
-+ * Each Solaris process can have multiple providers -- the pid provider as
-+ * well as any number of user-level statically defined tracing (USDT)
-+ * providers. Those providers are each represented by a fasttrap_provider.
-+ * All providers for a given process have a pointer to a shared
-+ * fasttrap_proc. The fasttrap_proc has two states: active or defunct.
-+ * When the count of active providers goes to zero it becomes defunct; a
-+ * provider drops its active count when it is removed individually or as part
-+ * of a mass removal when a process exits or performs an exec.
-+ *
-+ * Each probe is represented by a fasttrap_probe which has a pointer to
-+ * its associated provider as well as a list of fasttrap_id_tp structures
-+ * which are tuples combining a fasttrap_id and a fasttrap_tracepoint.
-+ * A fasttrap_tracepoint represents the actual point of instrumentation
-+ * and it contains two lists of fasttrap_id structures (to be fired pre-
-+ * and post-instruction emulation) that identify the probes attached to the
-+ * tracepoint. Tracepoints also have a pointer to the fasttrap_proc for the
-+ * process they trace which is used when looking up a tracepoint both when a
-+ * probe fires and when enabling and disabling probes.
-+ *
-+ * It's important to note that probes are preallocated with the necessary
-+ * number of tracepoints, but that tracepoints can be shared by probes and
-+ * swapped between probes. If a probe's preallocated tracepoint is enabled
-+ * (and, therefore, the associated probe is enabled), and that probe is
-+ * then disabled, ownership of that tracepoint may be exchanged for an
-+ * unused tracepoint belonging to another probe that was attached to the
-+ * enabled tracepoint.
-+ */
-+struct fasttrap_proc {
-+ pid_t ftpc_pid; /* process ID for this proc */
-+ atomic64_t ftpc_acount; /* count of active providers */
-+ uint64_t ftpc_rcount; /* count of extant providers */
-+ struct mutex ftpc_mtx; /* lock on all but acount */
-+ struct fasttrap_proc *ftpc_next; /* next proc in hash chain */
-+};
-+
-+struct fasttrap_provider {
-+ pid_t ftp_pid; /* process ID for this prov */
-+ char ftp_name[DTRACE_PROVNAMELEN]; /* prov name (w/o the pid) */
-+ dtrace_provider_id_t ftp_provid; /* DTrace provider handle */
-+ uint_t ftp_marked; /* mark for possible removal */
-+ uint_t ftp_retired; /* mark when retired */
-+ struct mutex ftp_mtx; /* provider lock */
-+ struct mutex ftp_cmtx; /* lock on creating probes */
-+ uint64_t ftp_rcount; /* enabled probes ref count */
-+ uint64_t ftp_ccount; /* consumers creating probes */
-+ uint64_t ftp_mcount; /* meta provider count */
-+ struct fasttrap_proc *ftp_proc; /* shared proc for all provs */
-+ struct fasttrap_provider *ftp_next; /* next prov in hash chain */
-+};
-+
-+struct fasttrap_id {
-+ struct fasttrap_probe *fti_probe; /* referrring probe */
-+ struct fasttrap_id *fti_next; /* enabled probe list on tp */
-+ enum fasttrap_probe_type fti_ptype; /* probe type */
-+};
-+
-+struct fasttrap_tracepoint {
-+ struct fasttrap_proc *ftt_proc; /* associated process struct */
-+ uintptr_t ftt_pc; /* address of tracepoint */
-+ pid_t ftt_pid; /* pid of tracepoint */
-+ struct fasttrap_machtp ftt_mtp; /* ISA-specific portion */
-+ struct fasttrap_id *ftt_ids; /* NULL-terminated list */
-+ struct fasttrap_id *ftt_retids; /* NULL-terminated list */
-+ struct fasttrap_tracepoint *ftt_next; /* link in global hash */
-+};
-+
-+struct fasttrap_id_tp {
-+ struct fasttrap_id fit_id;
-+ struct fasttrap_tracepoint *fit_tp;
-+};
-+
-+struct fasttrap_probe {
-+ dtrace_id_t ftp_id; /* DTrace probe identifier */
-+ pid_t ftp_pid; /* pid for this probe */
-+ struct fasttrap_provider *ftp_prov; /* this probe's provider */
-+ uint64_t ftp_gen; /* modification generation */
-+ uint64_t ftp_ntps; /* number of tracepoints */
-+ uint8_t *ftp_argmap; /* native to translated args */
-+ uint8_t ftp_nargs; /* translated argument count */
-+ uint8_t ftp_enabled; /* is this probe enabled */
-+ char *ftp_xtypes; /* translated types index */
-+ char *ftp_ntypes; /* native types index */
-+ struct fasttrap_id_tp ftp_tps[1]; /* flexible array */
-+};
-+
-+struct fasttrap_bucket_elem {
-+ union {
-+ struct fasttrap_bucket {
-+ struct mutex ftb_mtx; /* bucket lock */
-+ void *ftb_data; /* data payload */
-+ } bucket;
-+
-+ /*
-+ * Fill a cacheline, no matter how large struct mutex is.
-+ */
-+ uint8_t ftb_pad[(sizeof(struct fasttrap_bucket) +
-+ L1_CACHE_BYTES - 1) & ~(L1_CACHE_BYTES - 1)];
-+ };
-+};
-+typedef struct fasttrap_bucket fasttrap_bucket_t;
-+
-+#define FASTTRAP_ELEM_BUCKET(elem) ((fasttrap_bucket_t *) (elem))
-+
-+struct fasttrap_hash {
-+ ulong_t fth_nent; /* power-of-2 num. of entries */
-+ ulong_t fth_mask; /* fth_nent - 1 */
-+ struct fasttrap_bucket_elem *fth_table; /* array of buckets */
-+};
-+
-+extern struct fasttrap_hash fasttrap_tpoints;
-+
-+#define FASTTRAP_ID_INDEX(id) \
-+ ((struct fasttrap_id_tp *)(((char *)(id) - \
-+ offsetof(struct fasttrap_id_tp, fit_id))) - \
-+ &(id)->fti_probe->ftp_tps[0])
-+#define FASTTRAP_TPOINTS_INDEX(pid, pc) \
-+ (((pc) / sizeof(fasttrap_instr_t) + (pid)) & \
-+ fasttrap_tpoints.fth_mask)
-+
-+extern uint64_t *fasttrap_glob_offsets(struct fasttrap_probe_spec *probe,
-+ uint64_t *np);
-+extern uint64_t fasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg,
-+ int argno, int aframes);
-+extern uint64_t fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg,
-+ int argno, int aframes);
-+extern void fasttrap_pid_probe_arch(struct fasttrap_probe *ftp,
-+ struct pt_regs *regs);
-+extern void fasttrap_pid_retprobe_arch(struct fasttrap_probe *ftp,
-+ struct pt_regs *regs);
-+extern void fasttrap_set_enabled(struct pt_regs *regs);
-+
-+extern void fasttrap_meta_create_probe(void *, void *,
-+ struct dtrace_helper_probedesc *);
-+extern void *fasttrap_meta_provide(void *, struct dtrace_helper_provdesc *,
-+ pid_t);
-+extern void fasttrap_meta_remove(void *, struct dtrace_helper_provdesc *,
-+ pid_t);
-+
-+extern dtrace_meta_provider_id_t fasttrap_id;
-+extern struct dtrace_mops fasttrap_mops;
-+
-+extern int fasttrap_dev_init(void);
-+extern void fasttrap_dev_exit(void);
-+
-+#endif /* _FASTTRAP_IMPL_H_ */
-diff --git a/dtrace/fasttrap_mod.c b/dtrace/fasttrap_mod.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..e9bd0eb065f1aeea9b771abc05c07838de42d701
---- /dev/null
-+++ b/dtrace/fasttrap_mod.c
-@@ -0,0 +1,38 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fasttrap_mod.c
-+ * DESCRIPTION: DTrace - fasttrap provider kernel module
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#define DTRACE_HAVE_PROV_EXIT
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fasttrap_impl.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("Fasttrap Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+struct dtrace_mops fasttrap_mops = {
-+ fasttrap_meta_create_probe,
-+ fasttrap_meta_provide,
-+ fasttrap_meta_remove
-+};
-+
-+DT_META_PROVIDER_MODULE(fasttrap)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch
deleted file mode 100644
index 0be10e63a35c..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0014-dtrace-function-boundary-tracing-FBT-core-and-x86-co.patch
+++ /dev/null
@@ -1,1799 +0,0 @@
-From bc81b22d39f0332275cd6834fdffb749368e62a0 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 19:02:39 +0000
-Subject: [PATCH 14/19] dtrace: function boundary tracing (FBT) core and x86
- components
-
-This commit implements the core components needed for FBT tracing.
-Unlike ftrace we allow the tracing of very large numbers of functions at
-once: the intent is that the system should still be stable when every
-eligible function in the kernel is traced simultaneously. Functions
-that are not safe for this (because e.g. they are used in trap handling,
-or by functions called by the DTrace module itself during probe
-processing) are (semi-manually) blacklisted from being probed.
-
-As part of this, a treewide change to the prototype of traps is started:
-they all return 0 by default now, with a nonzero return value indicating
-that the trap happened as a result of an FBT probe: the return value is
-the opcode atop which the trap was originally placed for later emulation.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/entry/entry_64.S | 134 ++++++++++++++++++-
- arch/x86/hyperv/hv_init.c | 1 +
- arch/x86/include/asm/idtentry.h | 86 +++++++------
- arch/x86/include/asm/irq_stack.h | 36 +++---
- arch/x86/kernel/apic/apic.c | 4 +
- arch/x86/kernel/apic/vector.c | 1 +
- arch/x86/kernel/cpu/acrn.c | 1 +
- arch/x86/kernel/cpu/mce/amd.c | 1 +
- arch/x86/kernel/cpu/mce/core.c | 3 +
- arch/x86/kernel/cpu/mce/therm_throt.c | 1 +
- arch/x86/kernel/cpu/mce/threshold.c | 1 +
- arch/x86/kernel/cpu/mshyperv.c | 2 +
- arch/x86/kernel/dtrace_fbt.c | 177 ++++++++++++++++++++++++++
- arch/x86/kernel/fbt_blacklist.h | 95 ++++++++++++++
- arch/x86/kernel/irq.c | 5 +
- arch/x86/kernel/irq_work.c | 1 +
- arch/x86/kernel/kvm.c | 1 +
- arch/x86/kernel/nmi.c | 5 +-
- arch/x86/kernel/sev-es.c | 6 +-
- arch/x86/kernel/smp.c | 4 +
- arch/x86/kernel/traps.c | 91 ++++++++-----
- arch/x86/mm/fault.c | 3 +-
- arch/x86/xen/enlighten_hvm.c | 1 +
- arch/x86/xen/enlighten_pv.c | 8 +-
- include/linux/dtrace_fbt.h | 48 +++++++
- kernel/dtrace/Kconfig | 7 +
- kernel/dtrace/Makefile | 4 +-
- kernel/dtrace/dtrace_fbt_core.c | 125 ++++++++++++++++++
- kernel/dtrace/dtrace_os.c | 2 +
- kernel/kprobes.c | 8 ++
- 30 files changed, 764 insertions(+), 98 deletions(-)
- create mode 100644 arch/x86/kernel/dtrace_fbt.c
- create mode 100644 arch/x86/kernel/fbt_blacklist.h
- create mode 100644 include/linux/dtrace_fbt.h
- create mode 100644 kernel/dtrace/dtrace_fbt_core.c
-
-diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
-index cad08703c4ad774f2e473f0dcc71b53cdb579a68..689b45e5b0c4f6c28c9b141d51a8921239b0810f 100644
---- a/arch/x86/entry/entry_64.S
-+++ b/arch/x86/entry/entry_64.S
-@@ -38,7 +38,7 @@
- #include <asm/frame.h>
- #include <asm/trapnr.h>
- #include <asm/nospec-branch.h>
--#include <asm/fsgsbase.h>
-+#include <asm/dtrace_util.h>
- #include <linux/err.h>
-
- #include "calling.h"
-@@ -335,6 +335,15 @@ SYM_CODE_END(ret_from_fork)
-
- call \cfunc
-
-+#ifdef CONFIG_DTRACE
-+ /*
-+ * Nonzero exit from a trap handler means we want to emulate
-+ * an instruction.
-+ */
-+ test %rax,%rax
-+ jnz dtrace_error_return
-+#endif
-+
- jmp error_return
- .endm
-
-@@ -1097,6 +1106,129 @@ SYM_CODE_START_LOCAL(error_return)
- jmp swapgs_restore_regs_and_return_to_usermode
- SYM_CODE_END(error_return)
-
-+#ifdef CONFIG_DTRACE
-+/*
-+ * Emulate an instruction (given by one of the DTRACE_INVOP constants) on exit
-+ * from a trap handler.
-+ */
-+SYM_CODE_START_LOCAL(dtrace_error_return)
-+ UNWIND_HINT_REGS
-+
-+ negq %rax
-+
-+ cmpl $DTRACE_INVOP_MOV_RSP_RBP,%eax
-+ je dtrace_emu_mov
-+ cmpl $DTRACE_INVOP_PUSH_BP,%eax
-+ je dtrace_emu_push
-+ cmpl $DTRACE_INVOP_LEAVE,%eax
-+ je dtrace_emu_leave
-+ cmpl $DTRACE_INVOP_NOP,%eax
-+ je dtrace_emu_nop
-+ cmpl $DTRACE_INVOP_RET,%eax
-+ je dtrace_emu_ret
-+
-+ leaq dtrace_error_msg(%rip),%rdi
-+ movq %rax,%rsi
-+ movq (%rsp),%rdx
-+ call printk
-+
-+ jmp error_return
-+
-+dtrace_emu_mov:
-+ POP_REGS
-+ addq $8, %rsp /* skip regs->orig_ax */
-+
-+ /* Emulate "mov %rsp, %rbp" instruction. */
-+ pushq %rax /* push temp */
-+ movq 8(%rsp),%rax /* load calling RIP */
-+ addq $3,%rax /* increment over trapping instr */
-+ movq %rax,8(%rsp) /* store calling RIP */
-+ movq 32(%rsp),%rbp /* load %rsp into %rbp */
-+ popq %rax /* pop off temp */
-+
-+ INTERRUPT_RETURN
-+
-+dtrace_emu_push:
-+ POP_REGS
-+ addq $8, %rsp /* skip regs->orig_ax */
-+
-+ /*
-+ * Emulate a "pushq %rbp" instruction. We need to move the stack down
-+ * to make room for the extra address getting pushed.
-+ */
-+ subq $16,%rsp /* make room for %rbp */
-+ pushq %rax /* push temp */
-+ movq 24(%rsp),%rax /* load calling RIP */
-+ addq $1,%rax /* increment over trapping instr */
-+ movq %rax,8(%rsp) /* store calling RIP */
-+ movq 32(%rsp),%rax /* load calling CS */
-+ movq %rax,16(%rsp) /* store calling CS */
-+ movq 40(%rsp),%rax /* load calling RFLAGS */
-+ movq %rax,24(%rsp) /* store calling RFLAGS */
-+ movq 48(%rsp),%rax /* load calling RSP */
-+ subq $8,%rax /* make room for %rbp */
-+ movq %rax,32(%rsp) /* store calling RSP */
-+ movq 56(%rsp),%rax /* load calling SS */
-+ movq %rax,40(%rsp) /* store calling SS */
-+ movq 32(%rsp),%rax /* reload calling RSP */
-+ movq %rbp,(%rax) /* store %rbp there */
-+ popq %rax /* pop off temp */
-+
-+ INTERRUPT_RETURN
-+
-+dtrace_emu_nop:
-+ POP_REGS
-+ addq $8, %rsp /* skip regs->orig_ax */
-+
-+ /* Emulate a "nop" instruction. */
-+ incq (%rsp)
-+
-+ INTERRUPT_RETURN
-+
-+dtrace_emu_leave:
-+ POP_REGS
-+ addq $8, %rsp /* skip regs->orig_ax */
-+
-+ /*
-+ * Emulate a "leave" instruction. This is equivalent to the sequence:
-+ * movq %rbp,%rsp
-+ * popq %rbp
-+ * We can use the fact that on x86_64 %rsp is saved explicitly, so we
-+ * do not need to move any data around.
-+ */
-+ pushq %rax /* push temp */
-+ movq 8(%rsp),%rax /* load calling RIP */
-+ addq $1,%rax /* increment over trapping instr */
-+ movq %rax,8(%rsp) /* store calling RIP */
-+ movq (%rbp),%rax /* get new %rbp */
-+ addq $8,%rbp /* adjust new %rsp */
-+ movq %rbp,32(%rsp) /* store new %rsp */
-+ movq %rax,%rbp /* set new %rbp */
-+ popq %rax /* pop off temp */
-+
-+ INTERRUPT_RETURN
-+
-+dtrace_emu_ret:
-+ POP_REGS
-+ addq $8, %rsp /* skip regs->orig_ax */
-+
-+ /* Emulate a "ret" instruction. */
-+ pushq %rax /* push temp */
-+ movq 32(%rsp),%rax /* load %rsp */
-+ movq (%rax),%rax /* load calling RIP */
-+ movq %rax,8(%rsp) /* store calling RIP */
-+ addq $8,32(%rsp) /* adjust new %rsp */
-+ popq %rax /* pop off temp */
-+
-+ INTERRUPT_RETURN
-+SYM_CODE_END(dtrace_error_return)
-+
-+.pushsection .rodata, "a"
-+dtrace_error_msg:
-+ .asciz "DTRACE: non-zero (%x) return from trap at %x\n"
-+.popsection
-+#endif
-+
- /*
- * Runs on exception stack. Xen PV does not go through this path at all,
- * so we can use real assembly here.
-diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
-index 6375967a8244dc4e6777d8ff95de1be33ea77e06..e22347681c03b49c07eaf0b7a55cfb9b3d1e709b 100644
---- a/arch/x86/hyperv/hv_init.c
-+++ b/arch/x86/hyperv/hv_init.c
-@@ -161,6 +161,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_reenlightenment)
- ack_APIC_irq();
- inc_irq_stat(irq_hv_reenlightenment_count);
- schedule_delayed_work(&hv_reenlightenment_work, HZ/10);
-+ return 0;
- }
-
- void set_hv_tscchange_cb(void (*cb)(void))
-diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h
-index b2442eb0ac2f8010bdae488a715be6e67d012b0e..2222870fb7ab975d17e1085ba3e8d27e803b38fd 100644
---- a/arch/x86/include/asm/idtentry.h
-+++ b/arch/x86/include/asm/idtentry.h
-@@ -32,7 +32,7 @@ void idtentry_exit_nmi(struct pt_regs *regs, bool irq_state);
- #define DECLARE_IDTENTRY(vector, func) \
- asmlinkage void asm_##func(void); \
- asmlinkage void xen_asm_##func(void); \
-- __visible void func(struct pt_regs *regs)
-+ __visible int func(struct pt_regs *regs)
-
- /**
- * DEFINE_IDTENTRY - Emit code for simple IDT entry points
-@@ -48,19 +48,21 @@ void idtentry_exit_nmi(struct pt_regs *regs, bool irq_state);
- * which has to run before returning to the low level assembly code.
- */
- #define DEFINE_IDTENTRY(func) \
--static __always_inline void __##func(struct pt_regs *regs); \
-+static __always_inline int __##func(struct pt_regs *regs); \
- \
--__visible noinstr void func(struct pt_regs *regs) \
-+__visible noinstr int func(struct pt_regs *regs) \
- { \
- irqentry_state_t state = irqentry_enter(regs); \
-+ int ret; \
- \
- instrumentation_begin(); \
-- __##func (regs); \
-+ ret = __##func (regs); \
- instrumentation_end(); \
- irqentry_exit(regs, state); \
-+ return ret; \
- } \
- \
--static __always_inline void __##func(struct pt_regs *regs)
-+static __always_inline int __##func(struct pt_regs *regs)
-
- /* Special case for 32bit IRET 'trap' */
- #define DECLARE_IDTENTRY_SW DECLARE_IDTENTRY
-@@ -83,7 +85,7 @@ static __always_inline void __##func(struct pt_regs *regs)
- #define DECLARE_IDTENTRY_ERRORCODE(vector, func) \
- asmlinkage void asm_##func(void); \
- asmlinkage void xen_asm_##func(void); \
-- __visible void func(struct pt_regs *regs, unsigned long error_code)
-+ __visible int func(struct pt_regs *regs, unsigned long error_code)
-
- /**
- * DEFINE_IDTENTRY_ERRORCODE - Emit code for simple IDT entry points
-@@ -93,22 +95,24 @@ static __always_inline void __##func(struct pt_regs *regs)
- * Same as DEFINE_IDTENTRY, but has an extra error_code argument
- */
- #define DEFINE_IDTENTRY_ERRORCODE(func) \
--static __always_inline void __##func(struct pt_regs *regs, \
-- unsigned long error_code); \
-+static __always_inline int __##func(struct pt_regs *regs, \
-+ unsigned long error_code); \
- \
--__visible noinstr void func(struct pt_regs *regs, \
-- unsigned long error_code) \
-+__visible noinstr int func(struct pt_regs *regs, \
-+ unsigned long error_code) \
- { \
- irqentry_state_t state = irqentry_enter(regs); \
-+ int ret; \
- \
- instrumentation_begin(); \
-- __##func (regs, error_code); \
-+ ret = __##func (regs, error_code); \
- instrumentation_end(); \
- irqentry_exit(regs, state); \
-+ return ret; \
- } \
- \
--static __always_inline void __##func(struct pt_regs *regs, \
-- unsigned long error_code)
-+static __always_inline int __##func(struct pt_regs *regs, \
-+ unsigned long error_code)
-
- /**
- * DECLARE_IDTENTRY_RAW - Declare functions for raw IDT entry points
-@@ -136,7 +140,7 @@ static __always_inline void __##func(struct pt_regs *regs, \
- * is required before the enter/exit() helpers are invoked.
- */
- #define DEFINE_IDTENTRY_RAW(func) \
--__visible noinstr void func(struct pt_regs *regs)
-+__visible noinstr int func(struct pt_regs *regs)
-
- /**
- * DECLARE_IDTENTRY_RAW_ERRORCODE - Declare functions for raw IDT entry points
-@@ -164,7 +168,7 @@ __visible noinstr void func(struct pt_regs *regs)
- * is required before the enter/exit() helpers are invoked.
- */
- #define DEFINE_IDTENTRY_RAW_ERRORCODE(func) \
--__visible noinstr void func(struct pt_regs *regs, unsigned long error_code)
-+__visible noinstr int func(struct pt_regs *regs, unsigned long error_code)
-
- /**
- * DECLARE_IDTENTRY_IRQ - Declare functions for device interrupt IDT entry
-@@ -190,23 +194,25 @@ __visible noinstr void func(struct pt_regs *regs, unsigned long error_code)
- * has to be done in the function body if necessary.
- */
- #define DEFINE_IDTENTRY_IRQ(func) \
--static __always_inline void __##func(struct pt_regs *regs, u8 vector); \
-+static __always_inline int __##func(struct pt_regs *regs, u8 vector); \
- \
--__visible noinstr void func(struct pt_regs *regs, \
-- unsigned long error_code) \
-+__visible noinstr int func(struct pt_regs *regs, \
-+ unsigned long error_code) \
- { \
- irqentry_state_t state = irqentry_enter(regs); \
-+ int ret; \
- \
- instrumentation_begin(); \
- irq_enter_rcu(); \
- kvm_set_cpu_l1tf_flush_l1d(); \
-- __##func (regs, (u8)error_code); \
-+ ret = __##func (regs, (u8)error_code); \
- irq_exit_rcu(); \
- instrumentation_end(); \
- irqentry_exit(regs, state); \
-+ return ret; \
- } \
- \
--static __always_inline void __##func(struct pt_regs *regs, u8 vector)
-+static __always_inline int __##func(struct pt_regs *regs, u8 vector)
-
- /**
- * DECLARE_IDTENTRY_SYSVEC - Declare functions for system vector entry points
-@@ -233,22 +239,24 @@ static __always_inline void __##func(struct pt_regs *regs, u8 vector)
- * Runs the function on the interrupt stack if the entry hit kernel mode
- */
- #define DEFINE_IDTENTRY_SYSVEC(func) \
--static void __##func(struct pt_regs *regs); \
-+static int __##func(struct pt_regs *regs); \
- \
--__visible noinstr void func(struct pt_regs *regs) \
-+__visible noinstr int func(struct pt_regs *regs) \
- { \
- irqentry_state_t state = irqentry_enter(regs); \
-+ int ret; \
- \
- instrumentation_begin(); \
- irq_enter_rcu(); \
- kvm_set_cpu_l1tf_flush_l1d(); \
-- run_sysvec_on_irqstack_cond(__##func, regs); \
-+ ret = run_sysvec_on_irqstack_cond(__##func, regs); \
- irq_exit_rcu(); \
- instrumentation_end(); \
- irqentry_exit(regs, state); \
-+ return ret; \
- } \
- \
--static noinline void __##func(struct pt_regs *regs)
-+static noinline int __##func(struct pt_regs *regs)
-
- /**
- * DEFINE_IDTENTRY_SYSVEC_SIMPLE - Emit code for simple system vector IDT
-@@ -262,22 +270,24 @@ static noinline void __##func(struct pt_regs *regs)
- * interrupt vectors.
- */
- #define DEFINE_IDTENTRY_SYSVEC_SIMPLE(func) \
--static __always_inline void __##func(struct pt_regs *regs); \
-+static __always_inline int __##func(struct pt_regs *regs); \
- \
--__visible noinstr void func(struct pt_regs *regs) \
-+__visible noinstr int func(struct pt_regs *regs) \
- { \
- irqentry_state_t state = irqentry_enter(regs); \
-+ int ret; \
- \
- instrumentation_begin(); \
- __irq_enter_raw(); \
- kvm_set_cpu_l1tf_flush_l1d(); \
-- __##func (regs); \
-+ ret = __##func (regs); \
- __irq_exit_raw(); \
- instrumentation_end(); \
- irqentry_exit(regs, state); \
-+ return ret; \
- } \
- \
--static __always_inline void __##func(struct pt_regs *regs)
-+static __always_inline int __##func(struct pt_regs *regs)
-
- /**
- * DECLARE_IDTENTRY_XENCB - Declare functions for XEN HV callback entry point
-@@ -306,7 +316,7 @@ static __always_inline void __##func(struct pt_regs *regs)
- */
- #define DECLARE_IDTENTRY_IST(vector, func) \
- DECLARE_IDTENTRY_RAW(vector, func); \
-- __visible void noist_##func(struct pt_regs *regs)
-+ __visible int noist_##func(struct pt_regs *regs)
-
- /**
- * DECLARE_IDTENTRY_VC - Declare functions for the VC entry point
-@@ -318,8 +328,8 @@ static __always_inline void __##func(struct pt_regs *regs)
- */
- #define DECLARE_IDTENTRY_VC(vector, func) \
- DECLARE_IDTENTRY_RAW_ERRORCODE(vector, func); \
-- __visible noinstr void ist_##func(struct pt_regs *regs, unsigned long error_code); \
-- __visible noinstr void safe_stack_##func(struct pt_regs *regs, unsigned long error_code)
-+ __visible noinstr int ist_##func(struct pt_regs *regs, unsigned long error_code); \
-+ __visible noinstr int safe_stack_##func(struct pt_regs *regs, unsigned long error_code)
-
- /**
- * DEFINE_IDTENTRY_IST - Emit code for IST entry points
-@@ -401,10 +411,10 @@ static __always_inline void __##func(struct pt_regs *regs)
- * - The C handler called from the C shim
- */
- #define DECLARE_IDTENTRY_DF(vector, func) \
-- asmlinkage void asm_##func(void); \
-- __visible void func(struct pt_regs *regs, \
-- unsigned long error_code, \
-- unsigned long address)
-+ asmlinkage int asm_##func(void); \
-+ __visible int func(struct pt_regs *regs, \
-+ unsigned long error_code, \
-+ unsigned long address)
-
- /**
- * DEFINE_IDTENTRY_DF - Emit code for double fault on 32bit
-@@ -414,9 +424,9 @@ static __always_inline void __##func(struct pt_regs *regs)
- * cr2 in the address argument.
- */
- #define DEFINE_IDTENTRY_DF(func) \
--__visible noinstr void func(struct pt_regs *regs, \
-- unsigned long error_code, \
-- unsigned long address)
-+__visible noinstr int func(struct pt_regs *regs, \
-+ unsigned long error_code, \
-+ unsigned long address)
-
- #endif /* !CONFIG_X86_64 */
-
-diff --git a/arch/x86/include/asm/irq_stack.h b/arch/x86/include/asm/irq_stack.h
-index 775816965c6ae098f249dcf83c61d131da0ced9a..04f91986cee35b4ec140ce12ab24a2141024b0f7 100644
---- a/arch/x86/include/asm/irq_stack.h
-+++ b/arch/x86/include/asm/irq_stack.h
-@@ -12,11 +12,11 @@ static __always_inline bool irqstack_active(void)
- return __this_cpu_read(irq_count) != -1;
- }
-
--void asm_call_on_stack(void *sp, void (*func)(void), void *arg);
--void asm_call_sysvec_on_stack(void *sp, void (*func)(struct pt_regs *regs),
-- struct pt_regs *regs);
--void asm_call_irq_on_stack(void *sp, void (*func)(struct irq_desc *desc),
-- struct irq_desc *desc);
-+int asm_call_on_stack(void *sp, void (*func)(void), void *arg);
-+int asm_call_sysvec_on_stack(void *sp, int (*func)(struct pt_regs *regs),
-+ struct pt_regs *regs);
-+int asm_call_irq_on_stack(void *sp, void (*func)(struct irq_desc *desc),
-+ struct irq_desc *desc);
-
- static __always_inline void __run_on_irqstack(void (*func)(void))
- {
-@@ -27,15 +27,17 @@ static __always_inline void __run_on_irqstack(void (*func)(void))
- __this_cpu_sub(irq_count, 1);
- }
-
--static __always_inline void
--__run_sysvec_on_irqstack(void (*func)(struct pt_regs *regs),
-+static __always_inline int
-+__run_sysvec_on_irqstack(int (*func)(struct pt_regs *regs),
- struct pt_regs *regs)
- {
- void *tos = __this_cpu_read(hardirq_stack_ptr);
-+ int ret;
-
- __this_cpu_add(irq_count, 1);
-- asm_call_sysvec_on_stack(tos - 8, func, regs);
-+ ret = asm_call_sysvec_on_stack(tos - 8, func, regs);
- __this_cpu_sub(irq_count, 1);
-+ return ret;
- }
-
- static __always_inline void
-@@ -51,11 +53,11 @@ __run_irq_on_irqstack(void (*func)(struct irq_desc *desc),
-
- #else /* CONFIG_X86_64 */
- static inline bool irqstack_active(void) { return false; }
--static inline void __run_on_irqstack(void (*func)(void)) { }
--static inline void __run_sysvec_on_irqstack(void (*func)(struct pt_regs *regs),
-- struct pt_regs *regs) { }
--static inline void __run_irq_on_irqstack(void (*func)(struct irq_desc *desc),
-- struct irq_desc *desc) { }
-+static inline int __run_on_irqstack(int (*func)(void)) { }
-+static inline int __run_sysvec_on_irqstack(int (*func)(struct pt_regs *regs),
-+ struct pt_regs *regs) { }
-+static inline int __run_irq_on_irqstack(int (*func)(struct irq_desc *desc),
-+ struct irq_desc *desc) { }
- #endif /* !CONFIG_X86_64 */
-
- static __always_inline bool irq_needs_irq_stack(struct pt_regs *regs)
-@@ -79,16 +81,16 @@ static __always_inline void run_on_irqstack_cond(void (*func)(void),
- func();
- }
-
--static __always_inline void
--run_sysvec_on_irqstack_cond(void (*func)(struct pt_regs *regs),
-+static __always_inline int
-+run_sysvec_on_irqstack_cond(int (*func)(struct pt_regs *regs),
- struct pt_regs *regs)
- {
- lockdep_assert_irqs_disabled();
-
- if (irq_needs_irq_stack(regs))
-- __run_sysvec_on_irqstack(func, regs);
-+ return __run_sysvec_on_irqstack(func, regs);
- else
-- func(regs);
-+ return func(regs);
- }
-
- static __always_inline void
-diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
-index 113f6ca7b82849fd18271f3661b78b479accc2e6..06bd0bf3ae5a49a53fdc80ca52c762d95b8434ff 100644
---- a/arch/x86/kernel/apic/apic.c
-+++ b/arch/x86/kernel/apic/apic.c
-@@ -1098,6 +1098,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_apic_timer_interrupt)
- trace_local_timer_exit(LOCAL_TIMER_VECTOR);
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- int setup_profiling_timer(unsigned int multiplier)
-@@ -2160,11 +2161,13 @@ DEFINE_IDTENTRY_IRQ(spurious_interrupt)
- }
- out:
- trace_spurious_apic_exit(vector);
-+ return 0;
- }
-
- DEFINE_IDTENTRY_SYSVEC(sysvec_spurious_apic_interrupt)
- {
- __spurious_interrupt(regs, SPURIOUS_APIC_VECTOR);
-+ return 0;
- }
-
- /*
-@@ -2207,6 +2210,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_error_interrupt)
- apic_printk(APIC_DEBUG, KERN_CONT "\n");
-
- trace_error_apic_exit(ERROR_APIC_VECTOR);
-+ return 0;
- }
-
- /**
-diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
-index 758bbf25ef748f2d4560eb146af6be2bc65831e1..a841e833f2672f1575f03fa603d684a23f6ede1f 100644
---- a/arch/x86/kernel/apic/vector.c
-+++ b/arch/x86/kernel/apic/vector.c
-@@ -887,6 +887,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_irq_move_cleanup)
- }
-
- raw_spin_unlock(&vector_lock);
-+ return 0;
- }
-
- static void __send_cleanup_vector(struct apic_chip_data *apicd)
-diff --git a/arch/x86/kernel/cpu/acrn.c b/arch/x86/kernel/cpu/acrn.c
-index 0b2c03943ac6b31fea3d742e5db5b379f70018c7..b17c61c16e993886527b6dc60d967daec62dd377 100644
---- a/arch/x86/kernel/cpu/acrn.c
-+++ b/arch/x86/kernel/cpu/acrn.c
-@@ -53,6 +53,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_acrn_hv_callback)
- acrn_intr_handler();
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- const __initconst struct hypervisor_x86 x86_hyper_acrn = {
-diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c
-index 0c6b02dd744c1424c3235035aab439d2f1d0d1b8..8126b080d4888e1e0125c0d3af35ace8e6f5635a 100644
---- a/arch/x86/kernel/cpu/mce/amd.c
-+++ b/arch/x86/kernel/cpu/mce/amd.c
-@@ -928,6 +928,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_deferred_error)
- deferred_error_int_vector();
- trace_deferred_error_apic_exit(DEFERRED_ERROR_VECTOR);
- ack_APIC_irq();
-+ return 0;
- }
-
- /*
-diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
-index 311688202ea51b5104a8c9391503c6db2f9a5a9a..e94cf10e05f7012142b0e8d10ca22a4ecfa98bc6 100644
---- a/arch/x86/kernel/cpu/mce/core.c
-+++ b/arch/x86/kernel/cpu/mce/core.c
-@@ -2030,6 +2030,7 @@ DEFINE_IDTENTRY_MCE(exc_machine_check)
- dr7 = local_db_save();
- exc_machine_check_kernel(regs);
- local_db_restore(dr7);
-+ return 0;
- }
-
- /* The user mode variant. */
-@@ -2040,6 +2041,7 @@ DEFINE_IDTENTRY_MCE_USER(exc_machine_check)
- dr7 = local_db_save();
- exc_machine_check_user(regs);
- local_db_restore(dr7);
-+ return 0;
- }
- #else
- /* 32bit unified entry point */
-@@ -2053,6 +2055,7 @@ DEFINE_IDTENTRY_RAW(exc_machine_check)
- else
- exc_machine_check_kernel(regs);
- local_db_restore(dr7);
-+ return 0;
- }
- #endif
-
-diff --git a/arch/x86/kernel/cpu/mce/therm_throt.c b/arch/x86/kernel/cpu/mce/therm_throt.c
-index a7cd2d203ceda64ebd711be273b97249921f1edf..8e86a3baf32e9bf9d4ebd84ade9cb8da2c24816e 100644
---- a/arch/x86/kernel/cpu/mce/therm_throt.c
-+++ b/arch/x86/kernel/cpu/mce/therm_throt.c
-@@ -621,6 +621,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_thermal)
- smp_thermal_vector();
- trace_thermal_apic_exit(THERMAL_APIC_VECTOR);
- ack_APIC_irq();
-+ return 0;
- }
-
- /* Thermal monitoring depends on APIC, ACPI and clock modulation */
-diff --git a/arch/x86/kernel/cpu/mce/threshold.c b/arch/x86/kernel/cpu/mce/threshold.c
-index 6a059a035021d87a1e0dcd342663a365ed7a2ad3..fa361a5b297ac8f04a0811935268aa2fea1a91e3 100644
---- a/arch/x86/kernel/cpu/mce/threshold.c
-+++ b/arch/x86/kernel/cpu/mce/threshold.c
-@@ -28,4 +28,5 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_threshold)
- mce_threshold_vector();
- trace_threshold_apic_exit(THRESHOLD_APIC_VECTOR);
- ack_APIC_irq();
-+ return 0;
- }
-diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
-index 6cc50ab07bded72e50ff6900d5f150ac37eea6da..5146b1f713e0b39ae7635ec6a617cdaac3f4027d 100644
---- a/arch/x86/kernel/cpu/mshyperv.c
-+++ b/arch/x86/kernel/cpu/mshyperv.c
-@@ -53,6 +53,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
- ack_APIC_irq();
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- int hv_setup_vmbus_irq(int irq, void (*handler)(void))
-@@ -88,6 +89,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_stimer0)
- ack_APIC_irq();
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- int hv_setup_stimer0_irq(int *irq, int *vector, void (*handler)(void))
-diff --git a/arch/x86/kernel/dtrace_fbt.c b/arch/x86/kernel/dtrace_fbt.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..52ff3f49d101cdcfc0bf58acbfd3e121f914ca8f
---- /dev/null
-+++ b/arch/x86/kernel/dtrace_fbt.c
-@@ -0,0 +1,177 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_fbt.c
-+ * DESCRIPTION: Dynamic Tracing: FBT registration code (arch-specific)
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/kallsyms.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_fbt.h>
-+#include <linux/slab.h>
-+#include <linux/sort.h>
-+#include <asm/insn.h>
-+#include <asm/sections.h>
-+
-+#define FBT_MOV_RSP_RBP_1 0x48
-+#define FBT_MOV_RSP_RBP_2 0x89
-+#define FBT_MOV_RSP_RBP_3 0xe5
-+#define FBT_PUSHL_EBP 0x55
-+#define FBT_NOP 0x90
-+#define FBT_RET_IMM16 0xc2
-+#define FBT_RET 0xc3
-+#define FBT_LEAVE 0xc9
-+
-+#define BL_SENTRY(tp, nm) extern tp nm;
-+#define BL_DENTRY(tp, nm)
-+#include "fbt_blacklist.h"
-+#undef BL_DENTRY
-+#undef BL_SENTRY
-+
-+static void
-+dtrace_fbt_populate_bl(void)
-+{
-+#define BL_SENTRY(tp, nm) dtrace_fbt_bl_add((unsigned long)&nm, \
-+ __stringify(nm));
-+#define BL_DENTRY(tp, nm) dtrace_fbt_bl_add(0, __stringify(nm));
-+#include "fbt_blacklist.h"
-+#undef BL_SENTRY
-+#undef BL_DENTRY
-+}
-+
-+void dtrace_fbt_init(fbt_add_probe_fn fbt_add_probe, struct module *mp,
-+ void *arg)
-+{
-+ loff_t pos;
-+ struct kallsym_iter sym;
-+ asm_instr_t *paddr = NULL;
-+ struct dt_fbt_bl_entry *blent = NULL;
-+
-+ /*
-+ * Look up any unresolved symbols in the blacklist, and sort the list
-+ * by ascending address.
-+ */
-+ dtrace_fbt_populate_bl();
-+ blent = dtrace_fbt_bl_first();
-+
-+ pos = 0;
-+ kallsyms_iter_reset(&sym, 0);
-+ while (kallsyms_iter_update(&sym, pos++)) {
-+ asm_instr_t *addr, *end;
-+ int state = 0, insc = 0;
-+ void *fbtp = NULL;
-+
-+ /*
-+ * There is no point considering non-function symbols for FBT,
-+ * or symbols that have a zero size. We could consider weak
-+ * symbols but that gets quite complicated and there is no
-+ * demands for that (so far).
-+ */
-+ if (sym.type != 'T' && sym.type != 't')
-+ continue;
-+ if (!sym.size)
-+ continue;
-+
-+ /*
-+ * Handle only symbols that belong to the module we have been
-+ * asked for.
-+ */
-+ if (mp == dtrace_kmod && !core_kernel_text(sym.value))
-+ continue;
-+
-+ /*
-+ * Ensure we have not been given .init symbol from kallsyms
-+ * interface. This could lead to memory corruption once DTrace
-+ * tries to enable probe in already freed memory.
-+ */
-+ if (mp != dtrace_kmod && !within_module_core(sym.value, mp))
-+ continue;
-+
-+ /*
-+ * See if the symbol is on the FBT's blacklist. Since both
-+ * iterators are workng in sort order by ascending address we
-+ * can use concurrent traversal.
-+ */
-+ while (blent != NULL &&
-+ dtrace_fbt_bl_entry_addr(blent) < sym.value) {
-+ blent = dtrace_fbt_bl_next(blent);
-+ }
-+ if (dtrace_fbt_bl_entry_addr(blent) == sym.value)
-+ continue;
-+
-+ /*
-+ * No FBT tracing for DTrace functions, and functions that are
-+ * crucial to probe processing.
-+ * Also weed out symbols that are not relevant here.
-+ */
-+ if (strncmp(sym.name, "dtrace_", 7) == 0)
-+ continue;
-+ if (strncmp(sym.name, "insn_", 5) == 0)
-+ continue;
-+ if (strncmp(sym.name, "inat_", 5) == 0)
-+ continue;
-+ if (strncmp(sym.name, "_GLOBAL_", 8) == 0)
-+ continue;
-+ if (strncmp(sym.name, "do_", 3) == 0)
-+ continue;
-+ if (strncmp(sym.name, "xen_", 4) == 0)
-+ continue;
-+
-+ addr = (asm_instr_t *)sym.value;
-+ end = (asm_instr_t *)(sym.value + sym.size);
-+
-+ /*
-+ * FIXME:
-+ * When there are multiple symbols for the same address, we
-+ * should link them together as probes associated with the
-+ * same function. When a probe for that function is triggered
-+ * all associated probes should fire.
-+ *
-+ * For now, we ignore duplicates.
-+ */
-+ if (addr == paddr)
-+ continue;
-+ paddr = addr;
-+
-+ while (addr < end) {
-+ struct insn insn;
-+
-+ insc++;
-+
-+ switch (state) {
-+ case 0: /* start of function */
-+ if (*addr == FBT_PUSHL_EBP) {
-+ fbt_add_probe(
-+ mp, sym.name,
-+ FBT_ENTRY, *addr, addr, 0,
-+ NULL, arg);
-+ state = 1;
-+ } else if (insc > 10)
-+ state = 2;
-+ break;
-+ case 1: /* look for ret */
-+ if (*addr == FBT_RET) {
-+ uintptr_t off;
-+
-+ off = addr - (asm_instr_t *)sym.value;
-+ fbtp = fbt_add_probe(
-+ mp, sym.name,
-+ FBT_RETURN, *addr, addr, off,
-+ fbtp, arg);
-+ }
-+ break;
-+ }
-+
-+ if (state == 2)
-+ break;
-+
-+ kernel_insn_init(&insn, addr, MAX_INSN_SIZE);
-+ insn_get_length(&insn);
-+
-+ addr += insn.length;
-+ }
-+ }
-+}
-+EXPORT_SYMBOL(dtrace_fbt_init);
-diff --git a/arch/x86/kernel/fbt_blacklist.h b/arch/x86/kernel/fbt_blacklist.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..2e1ce2a90c86ca041e89ab83fcf51dfd77e433f6
---- /dev/null
-+++ b/arch/x86/kernel/fbt_blacklist.h
-@@ -0,0 +1,95 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Functions used in die notifier chain calling.
-+ */
-+BL_SENTRY(void *, notify_die)
-+BL_DENTRY(void *, notifier_call_chain)
-+BL_SENTRY(typeof(atomic_notifier_call_chain_robust), atomic_notifier_call_chain_robust)
-+BL_SENTRY(typeof(atomic_notifier_call_chain), atomic_notifier_call_chain)
-+BL_SENTRY(typeof(raw_notifier_call_chain_robust), raw_notifier_call_chain_robust)
-+BL_SENTRY(typeof(raw_notifier_call_chain), raw_notifier_call_chain)
-+BL_DENTRY(void *, hw_breakpoint_exceptions_notify)
-+BL_DENTRY(void *, kprobe_exceptions_notify)
-+
-+/*
-+ * Functions used to update vtime in probe context.
-+ */
-+BL_SENTRY(typeof(ktime_get_raw_fast_ns), ktime_get_raw_fast_ns)
-+BL_DENTRY(void *, raw_read_seqcount)
-+BL_DENTRY(void *, read_seqcount_retry)
-+BL_DENTRY(void *, __read_seqcount_retry)
-+
-+/* xen_clocksource */
-+BL_DENTRY(void *, xen_clocksource_get_cycles)
-+BL_DENTRY(void *, xen_clocksource_read)
-+BL_DENTRY(void *, pvclock_clocksource_read)
-+BL_DENTRY(void *, pvclock_touch_watchdogs)
-+BL_DENTRY(void *, touch_softlockup_watchdog_sync)
-+BL_DENTRY(void *, clocksource_touch_watchdog)
-+BL_DENTRY(void *, clocksource_resume_watchdog)
-+BL_DENTRY(void *, reset_hung_task_detector)
-+/* clocksource_tsc */
-+BL_DENTRY(void *, read_tsc)
-+BL_DENTRY(void *, get_cycles)
-+/* clocksource_hpet */
-+BL_DENTRY(void *, read_hpet)
-+BL_DENTRY(void *, hpet_readl)
-+/* kvm_clock */
-+BL_DENTRY(void *, kvm_clock_get_cycles)
-+BL_DENTRY(void *, kvm_clock_read)
-+
-+/*
-+ * Functions used in trap handling.
-+ */
-+BL_DENTRY(void *, fixup_exception)
-+BL_DENTRY(void *, paranoid_entry)
-+BL_DENTRY(void *, kgdb_ll_trap)
-+BL_DENTRY(void *, error_entry)
-+BL_DENTRY(void *, xen_int3)
-+BL_DENTRY(void *, ftrace_int3_handler)
-+BL_DENTRY(typeof(poke_int3_handler), poke_int3_handler)
-+BL_DENTRY(void *, fixup_bad_iret)
-+BL_DENTRY(void *, xen_adjust_exception_frame)
-+BL_DENTRY(void *, paravirt_nop)
-+BL_DENTRY(void *, ist_enter)
-+BL_DENTRY(void *, rcu_nmi_enter)
-+BL_DENTRY(void *, rcu_dynticks_curr_cpu_in_eqs)
-+BL_DENTRY(void *, rcu_dynticks_eqs_exit)
-+BL_DENTRY(void *, trace_rcu_dyntick)
-+BL_DENTRY(void *, rcu_nmi_exit)
-+BL_DENTRY(void *, rcu_irq_exit)
-+BL_DENTRY(void *, rcu_nmi_exit_common)
-+BL_DENTRY(void *, rcu_dynticks_eqs_enter)
-+BL_DENTRY(void *, ist_exit)
-+
-+/*
-+ * Functions used in page fault handling.
-+ */
-+BL_DENTRY(void *, do_kern_addr_fault)
-+BL_DENTRY(void *, do_kern_addr_fault)
-+BL_DENTRY(void *, handle_page_fault)
-+BL_DENTRY(void *, huge_page_mask)
-+BL_DENTRY(void *, mmap_address_hint_valid)
-+BL_DENTRY(void *, vm_start_gap)
-+BL_DENTRY(void *, hugetlb_get_unmapped_area_bottomup)
-+BL_DENTRY(void *, hugetlb_get_unmapped_area_topdown)
-+BL_DENTRY(void *, down_read_trylock)
-+BL_DENTRY(void *, __get_user_pages_fast)
-+BL_DENTRY(void *, gup_pud_range)
-+BL_DENTRY(void *, gup_huge_pud)
-+BL_DENTRY(void *, gup_pmd_range)
-+BL_DENTRY(void *, gup_huge_pmd)
-+BL_DENTRY(void *, gup_pte_range)
-+BL_DENTRY(void *, pte_mfn_to_pfn)
-+
-+/*
-+ * Functions used under 4.12 idr_find
-+ */
-+BL_DENTRY(void *, idr_find)
-+BL_DENTRY(void *, find_next_bit)
-+BL_DENTRY(void *, _find_next_bit)
-+BL_DENTRY(void *, radix_tree_lookup)
-+BL_DENTRY(void *, __radix_tree_lookup)
-+BL_DENTRY(void *, radix_tree_load_root)
-+BL_DENTRY(void *, radix_tree_descend)
-+BL_DENTRY(void *, is_sibling_entry)
-diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
-index c5dd50369e2f3394bc483b8744ace94eaaea552b..b80211006fb2e13b0f8f0dbdab93f9868025e1d3 100644
---- a/arch/x86/kernel/irq.c
-+++ b/arch/x86/kernel/irq.c
-@@ -260,6 +260,7 @@ DEFINE_IDTENTRY_IRQ(common_interrupt)
- }
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- #ifdef CONFIG_X86_LOCAL_APIC
-@@ -279,6 +280,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_x86_platform_ipi)
- x86_platform_ipi_callback();
- trace_x86_platform_ipi_exit(X86_PLATFORM_IPI_VECTOR);
- set_irq_regs(old_regs);
-+ return 0;
- }
- #endif
-
-@@ -302,6 +304,7 @@ DEFINE_IDTENTRY_SYSVEC_SIMPLE(sysvec_kvm_posted_intr_ipi)
- {
- ack_APIC_irq();
- inc_irq_stat(kvm_posted_intr_ipis);
-+ return 0;
- }
-
- /*
-@@ -312,6 +315,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_kvm_posted_intr_wakeup_ipi)
- ack_APIC_irq();
- inc_irq_stat(kvm_posted_intr_wakeup_ipis);
- kvm_posted_intr_wakeup_handler();
-+ return 0;
- }
-
- /*
-@@ -321,6 +325,7 @@ DEFINE_IDTENTRY_SYSVEC_SIMPLE(sysvec_kvm_posted_intr_nested_ipi)
- {
- ack_APIC_irq();
- inc_irq_stat(kvm_posted_intr_nested_ipis);
-+ return 0;
- }
- #endif
-
-diff --git a/arch/x86/kernel/irq_work.c b/arch/x86/kernel/irq_work.c
-index 890d4778cd352c69866464001e5ee16f414bf621..ac74998e2faa3a587d46dce272f678a3524fd74e 100644
---- a/arch/x86/kernel/irq_work.c
-+++ b/arch/x86/kernel/irq_work.c
-@@ -21,6 +21,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_irq_work)
- inc_irq_stat(apic_irq_work_irqs);
- irq_work_run();
- trace_irq_work_exit(IRQ_WORK_VECTOR);
-+ return 0;
- }
-
- void arch_irq_work_raise(void)
-diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
-index 7f57ede3cb8e73b3fc3eb0586c1337d7c2658254..07ea0a6336e9e5a668f546810b69af4096181234 100644
---- a/arch/x86/kernel/kvm.c
-+++ b/arch/x86/kernel/kvm.c
-@@ -285,6 +285,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_kvm_asyncpf_interrupt)
- }
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- static void __init paravirt_ops_setup(void)
-diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
-index 4bc77aaf1303974753bc8ea87c678357e61325d5..c3c8eec1a597aab3320e2daa514ff60edaf51b51 100644
---- a/arch/x86/kernel/nmi.c
-+++ b/arch/x86/kernel/nmi.c
-@@ -484,11 +484,11 @@ DEFINE_IDTENTRY_RAW(exc_nmi)
- sev_es_nmi_complete();
-
- if (IS_ENABLED(CONFIG_SMP) && arch_cpu_is_offline(smp_processor_id()))
-- return;
-+ return 0;
-
- if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {
- this_cpu_write(nmi_state, NMI_LATCHED);
-- return;
-+ return 0;
- }
- this_cpu_write(nmi_state, NMI_EXECUTING);
- this_cpu_write(nmi_cr2, read_cr2());
-@@ -522,6 +522,7 @@ DEFINE_IDTENTRY_RAW(exc_nmi)
-
- if (user_mode(regs))
- mds_user_clear_cpu_buffers();
-+ return 0;
- }
-
- void stop_nmi(void)
-diff --git a/arch/x86/kernel/sev-es.c b/arch/x86/kernel/sev-es.c
-index 84c1821819afb8fb3da3b09b8d429930bd1d4da3..536e85e4932dd53d460a6ae3558c5f4d21b6f1e3 100644
---- a/arch/x86/kernel/sev-es.c
-+++ b/arch/x86/kernel/sev-es.c
-@@ -1260,7 +1260,7 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication)
- */
- if (error_code == SVM_EXIT_EXCP_BASE + X86_TRAP_DB) {
- vc_handle_trap_db(regs);
-- return;
-+ return 0;
- }
-
- instrumentation_begin();
-@@ -1326,7 +1326,7 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication)
- out:
- instrumentation_end();
-
-- return;
-+ return 0;
-
- fail:
- if (user_mode(regs)) {
-@@ -1359,6 +1359,7 @@ DEFINE_IDTENTRY_VC_IST(exc_vmm_communication)
- instrumentation_begin();
- panic("Can't handle #VC exception from unsupported context\n");
- instrumentation_end();
-+ return 0;
- }
-
- DEFINE_IDTENTRY_VC(exc_vmm_communication)
-@@ -1367,6 +1368,7 @@ DEFINE_IDTENTRY_VC(exc_vmm_communication)
- safe_stack_exc_vmm_communication(regs, error_code);
- else
- ist_exc_vmm_communication(regs, error_code);
-+ return 0;
- }
-
- bool __init handle_vc_boot_ghcb(struct pt_regs *regs)
-diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
-index eff4ce3b10da7185cb770e35b6006516e72830db..2b3046a5b07e11d23e88bd6280d6a0480ddfe15f 100644
---- a/arch/x86/kernel/smp.c
-+++ b/arch/x86/kernel/smp.c
-@@ -136,6 +136,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_reboot)
- ack_APIC_irq();
- cpu_emergency_vmxoff();
- stop_this_cpu(NULL);
-+ return 0;
- }
-
- static int register_stop_handler(void)
-@@ -229,6 +230,7 @@ DEFINE_IDTENTRY_SYSVEC_SIMPLE(sysvec_reschedule_ipi)
- inc_irq_stat(irq_resched_count);
- scheduler_ipi();
- trace_reschedule_exit(RESCHEDULE_VECTOR);
-+ return 0;
- }
-
- DEFINE_IDTENTRY_SYSVEC(sysvec_call_function)
-@@ -238,6 +240,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_call_function)
- inc_irq_stat(irq_call_count);
- generic_smp_call_function_interrupt();
- trace_call_function_exit(CALL_FUNCTION_VECTOR);
-+ return 0;
- }
-
- DEFINE_IDTENTRY_SYSVEC(sysvec_call_function_single)
-@@ -247,6 +250,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_call_function_single)
- inc_irq_stat(irq_call_count);
- generic_smp_call_function_single_interrupt();
- trace_call_function_single_exit(CALL_FUNCTION_SINGLE_VECTOR);
-+ return 0;
- }
-
- static int __init nonmi_ipi_setup(char *str)
-diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
-index 170c94ec00685de0348f39e8f1087f9e7f119fed..39f2ab128cc7b39083c457985910f824a27805c7 100644
---- a/arch/x86/kernel/traps.c
-+++ b/arch/x86/kernel/traps.c
-@@ -166,17 +166,20 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
- }
- NOKPROBE_SYMBOL(do_trap);
-
--static void do_error_trap(struct pt_regs *regs, long error_code, char *str,
-+static int do_error_trap(struct pt_regs *regs, long error_code, char *str,
- unsigned long trapnr, int signr, int sicode, void __user *addr)
- {
-+ int ret;
-+
- RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
-
-- if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) !=
-- NOTIFY_STOP) {
-+ ret = notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr);
-+ if ((ret & NOTIFY_STOP_MASK) != NOTIFY_STOP_MASK) {
- cond_local_irq_enable(regs);
- do_trap(trapnr, signr, str, regs, error_code, sicode, addr);
- cond_local_irq_disable(regs);
- }
-+ return notifier_to_errno(ret);
- }
-
- /*
-@@ -196,13 +199,14 @@ static __always_inline void __user *error_get_trap_addr(struct pt_regs *regs)
-
- DEFINE_IDTENTRY(exc_divide_error)
- {
-- do_error_trap(regs, 0, "divide error", X86_TRAP_DE, SIGFPE,
-- FPE_INTDIV, error_get_trap_addr(regs));
-+ return do_error_trap(regs, 0, "divide error", X86_TRAP_DE, SIGFPE,
-+ FPE_INTDIV, error_get_trap_addr(regs));
- }
-
- DEFINE_IDTENTRY(exc_overflow)
- {
-- do_error_trap(regs, 0, "overflow", X86_TRAP_OF, SIGSEGV, 0, NULL);
-+ return do_error_trap(regs, 0, "overflow", X86_TRAP_OF, SIGSEGV,
-+ 0, NULL);
- }
-
- #ifdef CONFIG_X86_F00F_BUG
-@@ -253,37 +257,38 @@ DEFINE_IDTENTRY_RAW(exc_invalid_op)
- * in case exception entry is the one triggering WARNs.
- */
- if (!user_mode(regs) && handle_bug(regs))
-- return;
-+ return 0;
-
- state = irqentry_enter(regs);
- instrumentation_begin();
- handle_invalid_op(regs);
- instrumentation_end();
- irqentry_exit(regs, state);
-+ return 0;
- }
-
- DEFINE_IDTENTRY(exc_coproc_segment_overrun)
- {
-- do_error_trap(regs, 0, "coprocessor segment overrun",
-- X86_TRAP_OLD_MF, SIGFPE, 0, NULL);
-+ return do_error_trap(regs, 0, "coprocessor segment overrun",
-+ X86_TRAP_OLD_MF, SIGFPE, 0, NULL);
- }
-
- DEFINE_IDTENTRY_ERRORCODE(exc_invalid_tss)
- {
-- do_error_trap(regs, error_code, "invalid TSS", X86_TRAP_TS, SIGSEGV,
-- 0, NULL);
-+ return do_error_trap(regs, error_code, "invalid TSS", X86_TRAP_TS,
-+ SIGSEGV, 0, NULL);
- }
-
- DEFINE_IDTENTRY_ERRORCODE(exc_segment_not_present)
- {
-- do_error_trap(regs, error_code, "segment not present", X86_TRAP_NP,
-- SIGBUS, 0, NULL);
-+ return do_error_trap(regs, error_code, "segment not present", X86_TRAP_NP,
-+ SIGBUS, 0, NULL);
- }
-
- DEFINE_IDTENTRY_ERRORCODE(exc_stack_segment)
- {
-- do_error_trap(regs, error_code, "stack segment", X86_TRAP_SS, SIGBUS,
-- 0, NULL);
-+ return do_error_trap(regs, error_code, "stack segment", X86_TRAP_SS,
-+ SIGBUS, 0, NULL);
- }
-
- DEFINE_IDTENTRY_ERRORCODE(exc_alignment_check)
-@@ -291,7 +296,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_alignment_check)
- char *str = "alignment check";
-
- if (notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_AC, SIGBUS) == NOTIFY_STOP)
-- return;
-+ return 0;
-
- if (!user_mode(regs))
- die("Split lock detected\n", regs, error_code);
-@@ -306,6 +311,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_alignment_check)
-
- out:
- local_irq_disable();
-+ return 0;
- }
-
- #ifdef CONFIG_VMAP_STACK
-@@ -402,7 +408,7 @@ DEFINE_IDTENTRY_DF(exc_double_fault)
- regs->ip = (unsigned long)asm_exc_general_protection;
- regs->sp = (unsigned long)&gpregs->orig_ax;
-
-- return;
-+ return 0;
- }
- #endif
-
-@@ -461,13 +467,14 @@ DEFINE_IDTENTRY_DF(exc_double_fault)
- die("double fault", regs, error_code);
- panic("Machine halted.");
- instrumentation_end();
-+ return 0;
- }
-
- DEFINE_IDTENTRY(exc_bounds)
- {
- if (notify_die(DIE_TRAP, "bounds", regs, 0,
- X86_TRAP_BR, SIGSEGV) == NOTIFY_STOP)
-- return;
-+ return 0;
- cond_local_irq_enable(regs);
-
- if (!user_mode(regs))
-@@ -476,6 +483,7 @@ DEFINE_IDTENTRY(exc_bounds)
- do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, 0, 0, NULL);
-
- cond_local_irq_disable(regs);
-+ return 0;
- }
-
- enum kernel_gp_hint {
-@@ -529,7 +537,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
- enum kernel_gp_hint hint = GP_NO_HINT;
- struct task_struct *tsk;
- unsigned long gp_addr;
-- int ret;
-+ int ret = 0;
-
- cond_local_irq_enable(regs);
-
-@@ -542,7 +550,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
- local_irq_enable();
- handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
- local_irq_disable();
-- return;
-+ return 0;
- }
-
- tsk = current;
-@@ -572,8 +580,10 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
- goto exit;
-
- ret = notify_die(DIE_GPF, desc, regs, error_code, X86_TRAP_GP, SIGSEGV);
-- if (ret == NOTIFY_STOP)
-+ if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK) {
-+ ret = notifier_to_errno(ret);
- goto exit;
-+ }
-
- if (error_code)
- snprintf(desc, sizeof(desc), "segment-related " GPFSTR);
-@@ -597,9 +607,10 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
-
- exit:
- cond_local_irq_disable(regs);
-+ return ret;
- }
-
--static bool do_int3(struct pt_regs *regs)
-+static bool do_int3(struct pt_regs *regs, int *error_code)
- {
- int res;
-
-@@ -615,28 +626,37 @@ static bool do_int3(struct pt_regs *regs)
- #endif
- res = notify_die(DIE_INT3, "int3", regs, 0, X86_TRAP_BP, SIGTRAP);
-
-- return res == NOTIFY_STOP;
-+ if ((res & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK) {
-+ *error_code = notifier_to_errno (res);
-+ return true;
-+ }
-+
-+ return false;
- }
-
--static void do_int3_user(struct pt_regs *regs)
-+static int do_int3_user(struct pt_regs *regs)
- {
-- if (do_int3(regs))
-- return;
-+ int ret = 0;
-+ if (do_int3(regs, &ret))
-+ return ret;
-
- cond_local_irq_enable(regs);
- do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, 0, 0, NULL);
- cond_local_irq_disable(regs);
-+ return 0;
- }
-
- DEFINE_IDTENTRY_RAW(exc_int3)
- {
-+ int ret = 0;
-+
- /*
- * poke_int3_handler() is completely self contained code; it does (and
- * must) *NOT* call out to anything, lest it hits upon yet another
- * INT3.
- */
- if (poke_int3_handler(regs))
-- return;
-+ return 0;
-
- /*
- * irqentry_enter_from_user_mode() uses static_branch_{,un}likely()
-@@ -648,17 +668,18 @@ DEFINE_IDTENTRY_RAW(exc_int3)
- if (user_mode(regs)) {
- irqentry_enter_from_user_mode(regs);
- instrumentation_begin();
-- do_int3_user(regs);
-+ ret = do_int3_user(regs);
- instrumentation_end();
- irqentry_exit_to_user_mode(regs);
- } else {
- bool irq_state = idtentry_enter_nmi(regs);
- instrumentation_begin();
-- if (!do_int3(regs))
-+ if (!do_int3(regs, &ret))
- die("int3", regs, 0);
- instrumentation_end();
- idtentry_exit_nmi(regs, irq_state);
- }
-+ return ret;
- }
-
- #ifdef CONFIG_X86_64
-@@ -988,12 +1009,14 @@ static __always_inline void exc_debug_user(struct pt_regs *regs,
- DEFINE_IDTENTRY_DEBUG(exc_debug)
- {
- exc_debug_kernel(regs, debug_read_clear_dr6());
-+ return 0;
- }
-
- /* User entry, runs on regular task stack */
- DEFINE_IDTENTRY_DEBUG_USER(exc_debug)
- {
- exc_debug_user(regs, debug_read_clear_dr6());
-+ return 0;
- }
- #else
- /* 32 bit does not have separate entry points. */
-@@ -1005,6 +1028,7 @@ DEFINE_IDTENTRY_RAW(exc_debug)
- exc_debug_user(regs, dr6);
- else
- exc_debug_kernel(regs, dr6);
-+ return 0;
- }
- #endif
-
-@@ -1058,6 +1082,7 @@ static void math_error(struct pt_regs *regs, int trapnr)
- DEFINE_IDTENTRY(exc_coprocessor_error)
- {
- math_error(regs, X86_TRAP_MF);
-+ return 0;
- }
-
- DEFINE_IDTENTRY(exc_simd_coprocessor_error)
-@@ -1066,10 +1091,11 @@ DEFINE_IDTENTRY(exc_simd_coprocessor_error)
- /* AMD 486 bug: INVD in CPL 0 raises #XF instead of #GP */
- if (!static_cpu_has(X86_FEATURE_XMM)) {
- __exc_general_protection(regs, 0);
-- return;
-+ return 0;
- }
- }
- math_error(regs, X86_TRAP_XF);
-+ return 0;
- }
-
- DEFINE_IDTENTRY(exc_spurious_interrupt_bug)
-@@ -1093,6 +1119,7 @@ DEFINE_IDTENTRY(exc_spurious_interrupt_bug)
- * In theory this could be limited to 32bit, but the handler is not
- * hurting and who knows which other CPUs suffer from this.
- */
-+ return 0;
- }
-
- DEFINE_IDTENTRY(exc_device_not_available)
-@@ -1109,7 +1136,7 @@ DEFINE_IDTENTRY(exc_device_not_available)
- math_emulate(&info);
-
- cond_local_irq_disable(regs);
-- return;
-+ return 0;
- }
- #endif
-
-@@ -1125,6 +1152,7 @@ DEFINE_IDTENTRY(exc_device_not_available)
- */
- die("unexpected #NM exception", regs, 0);
- }
-+ return 0;
- }
-
- #ifdef CONFIG_X86_32
-@@ -1137,6 +1165,7 @@ DEFINE_IDTENTRY_SW(iret_error)
- ILL_BADSTK, (void __user *)NULL);
- }
- local_irq_disable();
-+ return 0;
- }
- #endif
-
-diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
-index 5b16183100d07fb85d26163b11694097b774a751..d5b9734946c3b77b3451f338a37f6602cee67447 100644
---- a/arch/x86/mm/fault.c
-+++ b/arch/x86/mm/fault.c
-@@ -1493,7 +1493,7 @@ DEFINE_IDTENTRY_RAW_ERRORCODE(exc_page_fault)
- * itself.
- */
- if (kvm_handle_async_pf(regs, (u32)address))
-- return;
-+ return 0;
-
- /*
- * Entry handling for valid #PF from kernel mode is slightly
-@@ -1512,4 +1512,5 @@ DEFINE_IDTENTRY_RAW_ERRORCODE(exc_page_fault)
- instrumentation_end();
-
- irqentry_exit(regs, state);
-+ return 0;
- }
-diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
-index ec50b7423a4c8609118f3f6f1ee67aa9dd238b31..1c4b08f2dc3b43619359fa72b708f87d89b9609c 100644
---- a/arch/x86/xen/enlighten_hvm.c
-+++ b/arch/x86/xen/enlighten_hvm.c
-@@ -129,6 +129,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_xen_hvm_callback)
- xen_hvm_evtchn_do_upcall();
-
- set_irq_regs(old_regs);
-+ return 0;
- }
-
- #ifdef CONFIG_KEXEC_CORE
-diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
-index 4409306364dc3cd5c774ee190efe83a6079a9cc2..080702bf757bb1d9de12d1670a8f6a6a4e140ea8 100644
---- a/arch/x86/xen/enlighten_pv.c
-+++ b/arch/x86/xen/enlighten_pv.c
-@@ -563,12 +563,12 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
- preempt_enable();
- }
-
--void noist_exc_debug(struct pt_regs *regs);
-+int noist_exc_debug(struct pt_regs *regs);
-
- DEFINE_IDTENTRY_RAW(xenpv_exc_nmi)
- {
- /* On Xen PV, NMI doesn't use IST. The C part is the sane as native. */
-- exc_nmi(regs);
-+ return exc_nmi(regs);
- }
-
- DEFINE_IDTENTRY_RAW(xenpv_exc_debug)
-@@ -578,9 +578,9 @@ DEFINE_IDTENTRY_RAW(xenpv_exc_debug)
- * to the correct handler.
- */
- if (user_mode(regs))
-- noist_exc_debug(regs);
-+ return noist_exc_debug(regs);
- else
-- exc_debug(regs);
-+ return exc_debug(regs);
- }
-
- struct trap_array_entry {
-diff --git a/include/linux/dtrace_fbt.h b/include/linux/dtrace_fbt.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..d11e273cee317949ba85e954e4c0ead42e52b115
---- /dev/null
-+++ b/include/linux/dtrace_fbt.h
-@@ -0,0 +1,48 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ *Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef _LINUX_DTRACE_FBT_H
-+#define _LINUX_DTRACE_FBT_H
-+
-+#include <linux/module.h>
-+#include <asm/dtrace_arch.h>
-+
-+extern unsigned long dtrace_fbt_nfuncs __attribute__((weak));
-+
-+/*
-+ * Prototype for callback function that handles the actual creation of FBT
-+ * probes.
-+ *
-+ * Arguments to pass:
-+ * - Pointer to module the probe will belong to
-+ * - function name
-+ * - probe type (FBT_ENTRY or FBT_RETURN)
-+ * - probe subtype (arch-specific)
-+ * - address (location of the probe)
-+ * - offset from the function start
-+ * - return value from previous callback invocation
-+ * - cookie passed to dtrace_fbt_init
-+ * Returns:
-+ * - generic pointer (only to be used to pass back in)
-+ */
-+#define FBT_ENTRY 0
-+#define FBT_RETURN 1
-+
-+typedef void *(*fbt_add_probe_fn)(struct module *, char *, int, int,
-+ asm_instr_t *, uintptr_t, void *, void *);
-+extern void dtrace_fbt_init(fbt_add_probe_fn, struct module *, void *);
-+
-+/*
-+ * Dynamic blacklist routines.
-+ */
-+struct dt_fbt_bl_entry;
-+
-+extern struct dt_fbt_bl_entry *dtrace_fbt_bl_add(unsigned long, const char *);
-+extern struct dt_fbt_bl_entry *dtrace_fbt_bl_first(void);
-+extern struct dt_fbt_bl_entry *dtrace_fbt_bl_next(struct dt_fbt_bl_entry *);
-+extern unsigned long dtrace_fbt_bl_entry_addr(struct dt_fbt_bl_entry *);
-+extern const char *dtrace_fbt_bl_entry_name(struct dt_fbt_bl_entry *);
-+
-+#endif /* _LINUX_DTRACE_FBT_H */
-diff --git a/kernel/dtrace/Kconfig b/kernel/dtrace/Kconfig
-index 6bf6620981cd14bcc64cd0f7f71b499e478ea31e..1f070e49c69f107cfa4c940ae47ab3a72622f8f7 100644
---- a/kernel/dtrace/Kconfig
-+++ b/kernel/dtrace/Kconfig
-@@ -55,6 +55,13 @@ config DT_SDT_PERF
- Provides the perf provider, containing a DTrace probe for each
- perf-events tracepoint in the system.
-
-+config DT_FBT
-+ tristate "Function boundary tracing"
-+ default m
-+ select FTRACE
-+ help
-+ Provides function boundary tracing for functions in the kernel.
-+
- config DT_SYSTRACE
- tristate "System Call Tracing"
- default m
-diff --git a/kernel/dtrace/Makefile b/kernel/dtrace/Makefile
-index 06329cbe52cbfbd96c23e6838fc99e53cc5ec5d6..0e5fb34b7b478af215c24a57003c3988ee7a43fa 100644
---- a/kernel/dtrace/Makefile
-+++ b/kernel/dtrace/Makefile
-@@ -4,11 +4,11 @@
-
- DT_CORE_ARCH_OBJS = $(addprefix ../../arch/$(SRCARCH)/kernel/, \
- dtrace_syscall.o dtrace_syscall_stubs.o \
-- dtrace_sdt.o dtrace_util.o)
-+ dtrace_fbt.o dtrace_sdt.o dtrace_util.o)
-
- ifdef CONFIG_DT_CORE
- obj-y += cyclic.o dtrace_os.o dtrace_cpu.o \
-- dtrace_sdt_core.o \
-+ dtrace_sdt_core.o dtrace_fbt_core.o \
- dtrace_task.o dtrace_psinfo.o \
- $(DT_CORE_ARCH_OBJS)
- endif
-diff --git a/kernel/dtrace/dtrace_fbt_core.c b/kernel/dtrace/dtrace_fbt_core.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..67182a3b13fcd9cd0b6c81167ae502bbde181f4a
---- /dev/null
-+++ b/kernel/dtrace/dtrace_fbt_core.c
-@@ -0,0 +1,125 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_fbt_core.c
-+ * DESCRIPTION: DTrace - FBT common code
-+ *
-+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/kallsyms.h>
-+#include <linux/rbtree.h>
-+#include <linux/slab.h>
-+#include <linux/dtrace_fbt.h>
-+
-+struct dt_fbt_bl_entry {
-+ struct rb_node dfbe_node;
-+ unsigned long dfbe_addr;
-+ const char *dfbe_name;
-+};
-+
-+static struct rb_root dt_fbt_root = RB_ROOT;
-+
-+struct dt_fbt_bl_entry *
-+dtrace_fbt_bl_add(unsigned long addr, const char *name)
-+{
-+ struct rb_node **p = &dt_fbt_root.rb_node;
-+ struct rb_node *parent = NULL;
-+ struct dt_fbt_bl_entry *entry;
-+
-+ /*
-+ * If no address was given, we need to do a symbol name lookup:
-+ * - If no symbol name was given, we cannot add anything.
-+ * - If the lookup failed, we cannot add anything.
-+ */
-+ if (addr == 0) {
-+ if (name == NULL)
-+ return NULL;
-+
-+ addr = kallsyms_lookup_name(name);
-+
-+ if (addr == 0)
-+ return NULL;
-+ }
-+
-+ /* Find place in the tree. */
-+ while (*p) {
-+ parent = *p;
-+ entry = rb_entry(parent, struct dt_fbt_bl_entry, dfbe_node);
-+
-+ if (addr > entry->dfbe_addr)
-+ p = &parent->rb_right;
-+ else if (addr < entry->dfbe_addr)
-+ p = &parent->rb_left;
-+ else
-+ return NULL; /* no duplicates please */
-+ }
-+
-+ /* Create a new blacklist entry. */
-+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-+ if (entry == NULL)
-+ return NULL;
-+
-+ entry->dfbe_name = name;
-+ entry->dfbe_addr = addr;
-+
-+ /* Update the tree. */
-+ rb_link_node(&entry->dfbe_node, parent, p);
-+ rb_insert_color(&entry->dfbe_node, &dt_fbt_root);
-+
-+ return entry;
-+}
-+
-+/*
-+ * Iterators for blacklisted symbols. The iteration happens in sort order by
-+ * virtual memory address. Symbols with pending resolution are inored.
-+ */
-+struct dt_fbt_bl_entry *
-+dtrace_fbt_bl_first(void)
-+{
-+ struct rb_node *node = rb_first(&dt_fbt_root);
-+
-+ if (node == NULL)
-+ return (NULL);
-+
-+ return rb_entry(node, struct dt_fbt_bl_entry, dfbe_node);
-+}
-+
-+struct dt_fbt_bl_entry *
-+dtrace_fbt_bl_next(struct dt_fbt_bl_entry *entry)
-+{
-+ struct rb_node *node = rb_next(&entry->dfbe_node);
-+
-+ if (node == NULL)
-+ return (NULL);
-+
-+ return rb_entry(node, struct dt_fbt_bl_entry, dfbe_node);
-+}
-+
-+unsigned long
-+dtrace_fbt_bl_entry_addr(struct dt_fbt_bl_entry *entry)
-+{
-+ if (entry == NULL)
-+ return (0);
-+
-+ return entry->dfbe_addr;
-+}
-+
-+const char *
-+dtrace_fbt_bl_entry_name(struct dt_fbt_bl_entry *entry)
-+{
-+ if (entry == NULL)
-+ return (NULL);
-+
-+ return entry->dfbe_name;
-+}
-diff --git a/kernel/dtrace/dtrace_os.c b/kernel/dtrace/dtrace_os.c
-index 874e097b84fd4b517cdb1e867a4b9d9ff2504078..bb5650cf72ebf9177d7e2d87eabf3d849e60cd76 100644
---- a/kernel/dtrace/dtrace_os.c
-+++ b/kernel/dtrace/dtrace_os.c
-@@ -18,6 +18,7 @@
-
- #include <linux/binfmts.h>
- #include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_fbt.h>
- #include <linux/dtrace_os.h>
- #include <linux/dtrace_sdt.h>
- #include <linux/fs.h>
-@@ -103,6 +104,7 @@ void __init dtrace_os_init(void)
- dtrace_kmod->core_layout.size = 0x2000000;
- #endif
-
-+ dtrace_kmod->num_ftrace_callsites = dtrace_fbt_nfuncs;
- dtrace_kmod->state = MODULE_STATE_LIVE;
- atomic_inc(&dtrace_kmod->refcnt);
-
-diff --git a/kernel/kprobes.c b/kernel/kprobes.c
-index 41fdbb7953c60f878049b2a5807abb4aecf95320..b702c7c484e7710d2b8501f75cd83a0fb3f7775d 100644
---- a/kernel/kprobes.c
-+++ b/kernel/kprobes.c
-@@ -38,6 +38,10 @@
- #include <linux/perf_event.h>
- #include <linux/static_call.h>
-
-+#ifdef CONFIG_DTRACE
-+#include <linux/dtrace_fbt.h>
-+#endif
-+
- #include <asm/sections.h>
- #include <asm/cacheflush.h>
- #include <asm/errno.h>
-@@ -2336,6 +2340,10 @@ int kprobe_add_ksym_blacklist(unsigned long entry)
- !kallsyms_lookup_size_offset(entry, &size, &offset))
- return -EINVAL;
-
-+#ifdef CONFIG_DTRACE
-+ dtrace_fbt_bl_add(entry, NULL);
-+#endif
-+
- ent = kmalloc(sizeof(*ent), GFP_KERNEL);
- if (!ent)
- return -ENOMEM;
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0015-dtrace-fbt-provider-modular-components.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0015-dtrace-fbt-provider-modular-components.patch
deleted file mode 100644
index d62dd30f73f4..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0015-dtrace-fbt-provider-modular-components.patch
+++ /dev/null
@@ -1,683 +0,0 @@
-From b3955b4ec46d8139665fc881dd088e9fcb67ff36 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Mon, 19 Nov 2018 18:12:44 +0000
-Subject: [PATCH 15/19] dtrace: fbt provider, modular components
-
-This uses the fbt machinery added in the previous commit.
-
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/x86/dtrace/Makefile.arch | 2 +
- arch/x86/dtrace/fbt_x86_64.c | 156 ++++++++++++
- arch/x86/dtrace/include/dtrace/fbt_arch.h | 42 ++++
- dtrace/Makefile | 2 +
- dtrace/fbt_dev.c | 281 ++++++++++++++++++++++
- dtrace/fbt_impl.h | 52 ++++
- dtrace/fbt_mod.c | 56 +++++
- 7 files changed, 591 insertions(+)
- create mode 100644 arch/x86/dtrace/fbt_x86_64.c
- create mode 100644 arch/x86/dtrace/include/dtrace/fbt_arch.h
- create mode 100644 dtrace/fbt_dev.c
- create mode 100644 dtrace/fbt_impl.h
- create mode 100644 dtrace/fbt_mod.c
-
-diff --git a/arch/x86/dtrace/Makefile.arch b/arch/x86/dtrace/Makefile.arch
-index e4655557e06ad7524677b9f3b0909f248d5a1c8b..906fa8c7e17c02958fa19a5e33d043a92109c4fa 100644
---- a/arch/x86/dtrace/Makefile.arch
-+++ b/arch/x86/dtrace/Makefile.arch
-@@ -8,8 +8,10 @@ ccflags-y += -I$(srctree)/arch/x86/dtrace/include -Idtrace
-
- dtrace-obj += dtrace_asm_x86_64.o dtrace_isa_x86_64.o
- fasttrap-obj += fasttrap_x86_64.o
-+fbt-obj += fbt_x86_64.o
- sdt-obj += sdt_x86_64.o
-
- dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
- fasttrap-y += $(addprefix $(DTARCHDIR)/, $(fasttrap-obj))
-+fbt-y += $(addprefix $(DTARCHDIR)/, $(fbt-obj))
- sdt-y += $(addprefix $(DTARCHDIR)/, $(sdt-obj))
-diff --git a/arch/x86/dtrace/fbt_x86_64.c b/arch/x86/dtrace/fbt_x86_64.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..a8a05292be7e1f876d0971c133db9436f31a5eab
---- /dev/null
-+++ b/arch/x86/dtrace/fbt_x86_64.c
-@@ -0,0 +1,156 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fbt_x86_64.c
-+ * DESCRIPTION: DTrace - FBT provider implementation for x86
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_fbt.h>
-+#include <linux/vmalloc.h>
-+#include <asm/dtrace_util.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fbt_impl.h"
-+
-+/*
-+ * Use 0xf0 (LOCK Prefix) and X86_TRAP_UD for Invalid Opcode traps to be used.
-+ * Use 0xcc (INT 3) and X86_TRAP_BP for Breakpoint traps to be used.
-+ */
-+#define FBT_ENTRY_PATCHVAL 0xcc
-+#define FBT_ENTRY_TRAP X86_TRAP_BP
-+#define FBT_RETURN_PATCHVAL 0xcc
-+#define FBT_RETURN_TRAP X86_TRAP_BP
-+
-+static uint8_t fbt_invop(struct pt_regs *regs)
-+{
-+ struct fbt_probe *fbp = fbt_probetab[FBT_ADDR2NDX(regs->ip)];
-+
-+ for (; fbp != NULL; fbp = fbp->fbp_hashnext) {
-+ if ((uintptr_t)fbp->fbp_patchpoint == regs->ip) {
-+ struct pt_regs *old = this_cpu_core->cpu_dtrace_regs;
-+
-+ this_cpu_core->cpu_dtrace_regs = regs;
-+ if (fbp->fbp_roffset == 0) {
-+ dtrace_probe(fbp->fbp_id, regs->di, regs->si,
-+ regs->dx, regs->cx, regs->r8,
-+ regs->r9, 0);
-+ } else {
-+ dtrace_probe(fbp->fbp_id, fbp->fbp_roffset,
-+ regs->ax, 0, 0, 0, 0, 0);
-+ }
-+
-+ this_cpu_core->cpu_dtrace_regs = old;
-+
-+ return fbp->fbp_rval;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+uint64_t fbt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ return 0;
-+
-+ switch (argno) {
-+ case 0:
-+ return regs->di;
-+ case 1:
-+ return regs->si;
-+ case 2:
-+ return regs->dx;
-+ case 3:
-+ return regs->cx;
-+ case 4:
-+ return regs->r8;
-+ case 5:
-+ return regs->r9;
-+ }
-+
-+ ASSERT(argno > 5);
-+
-+ st = (uint64_t *)regs->sp;
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ /*
-+ * Skip the topmost slot of the stack because that holds the return
-+ * address for the call to the function we are entering. At this point
-+ * the BP has not been pushed yet, so we are still working within the
-+ * caller's stack frame.
-+ */
-+ val = st[1 + argno - 6];
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return val;
-+}
-+
-+void fbt_provide_probe_arch(struct fbt_probe *fbp, int probetype, int stype)
-+{
-+ fbp->fbp_patchval = probetype == FBT_ENTRY ? FBT_ENTRY_PATCHVAL
-+ : FBT_RETURN_PATCHVAL;
-+ fbp->fbp_savedval = *fbp->fbp_patchpoint;
-+ fbp->fbp_rval = probetype == FBT_ENTRY ? DTRACE_INVOP_PUSH_BP
-+ : DTRACE_INVOP_RET;
-+}
-+
-+int fbt_can_patch_return_arch(asm_instr_t *addr)
-+{
-+ return 1;
-+}
-+
-+int fbt_provide_module_arch(void *arg, struct module *mp)
-+{
-+ return 1;
-+}
-+
-+void fbt_destroy_module(void *arg, struct module *mp)
-+{
-+}
-+
-+void fbt_enable_arch(struct fbt_probe *fbp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_invop_enable(fbp->fbp_patchpoint, fbp->fbp_patchval);
-+}
-+
-+void fbt_disable_arch(struct fbt_probe *fbp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_invop_disable(fbp->fbp_patchpoint, fbp->fbp_savedval);
-+}
-+
-+int fbt_dev_init_arch(void)
-+{
-+ fbt_probetab_mask = fbt_probetab_size - 1;
-+ fbt_probetab = dtrace_vzalloc_try(fbt_probetab_size *
-+ sizeof(struct fbt_probe *));
-+
-+ if (fbt_probetab == NULL)
-+ return -ENOMEM;
-+
-+ return dtrace_invop_add(fbt_invop);
-+}
-+
-+void fbt_dev_exit_arch(void)
-+{
-+ vfree(fbt_probetab);
-+ fbt_probetab_mask = 0;
-+ fbt_probetab_size = 0;
-+
-+ dtrace_invop_remove(fbt_invop);
-+}
-diff --git a/arch/x86/dtrace/include/dtrace/fbt_arch.h b/arch/x86/dtrace/include/dtrace/fbt_arch.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..7e90b2b75bba0c2d45aab458af7d9f7e8e923d06
---- /dev/null
-+++ b/arch/x86/dtrace/include/dtrace/fbt_arch.h
-@@ -0,0 +1,42 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - FBT Implementation defines
-+ *
-+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _X86_64_FBT_ARCH_H
-+#define _X86_64_FBT_ARCH_H
-+
-+#define FBT_AFRAMES 7
-+
-+struct fbt_probe {
-+ char *fbp_name; /* name of probe */
-+ dtrace_id_t fbp_id; /* probe ID */
-+ struct module *fbp_module; /* defining module */
-+ int fbp_primary; /* non-zero if primary mod */
-+ asm_instr_t *fbp_patchpoint;/* patch point */
-+ asm_instr_t fbp_patchval; /* instruction to patch */
-+ asm_instr_t fbp_savedval; /* saved instruction value */
-+ uintptr_t fbp_roffset; /* relative offset */
-+ int fbp_rval;
-+ struct fbt_probe *fbp_next; /* next probe */
-+ struct fbt_probe *fbp_hashnext; /* next on hash */
-+};
-+
-+#endif /* _X86_64_FBT_ARCH_H */
-diff --git a/dtrace/Makefile b/dtrace/Makefile
-index c7e3fc512a6c7cdc40f9e3343e3cd98bec674b68..35b8b098123ff254e99c3962d1c1854202c7f623 100644
---- a/dtrace/Makefile
-+++ b/dtrace/Makefile
-@@ -4,6 +4,7 @@
-
- obj-$(CONFIG_DT_CORE) += dtrace.o
- obj-$(CONFIG_DT_FASTTRAP) += fasttrap.o
-+obj-$(CONFIG_DT_FBT) += fbt.o
- obj-$(CONFIG_DT_PROFILE) += profile.o
- obj-$(CONFIG_DT_SDT) += sdt.o
- obj-$(CONFIG_DT_SYSTRACE) += systrace.o
-@@ -19,6 +20,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.o \
- dtrace_ptofapi.o dtrace_predicate.o \
- dtrace_spec.o dtrace_state.o dtrace_util.o
- fasttrap-y := fasttrap_mod.o fasttrap_dev.o
-+fbt-y := fbt_mod.o fbt_dev.o
- profile-y := profile_mod.o profile_dev.o
- sdt-y := sdt_mod.o sdt_dev.o
- systrace-y := systrace_mod.o systrace_dev.o
-diff --git a/dtrace/fbt_dev.c b/dtrace/fbt_dev.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..281fd749aae7951b09fc2a44e5c2110eec33bc66
---- /dev/null
-+++ b/dtrace/fbt_dev.c
-@@ -0,0 +1,281 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fbt_dev.c
-+ * DESCRIPTION: DTrace - FBT provider device driver
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/kallsyms.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <linux/dtrace_fbt.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fbt_impl.h"
-+
-+#define FBT_PROBETAB_SIZE 0x8000 /* 32k entries -- 128K total */
-+
-+struct fbt_probe **fbt_probetab;
-+int fbt_probetab_size = FBT_PROBETAB_SIZE;
-+int fbt_probetab_mask;
-+
-+static void *fbt_provide_probe(struct module *mp, char *func, int probetype,
-+ int stype, asm_instr_t *addr, uintptr_t off,
-+ void *pfbt, void *arg)
-+{
-+ struct fbt_probe *fbp;
-+ struct fbt_probe *prev;
-+ int *skipped = arg;
-+
-+ switch (probetype) {
-+ case FBT_ENTRY:
-+ fbp = kzalloc(sizeof(struct fbt_probe), GFP_KERNEL);
-+ fbp->fbp_name = kstrdup(func, GFP_KERNEL);
-+ if (fbp->fbp_name == NULL)
-+ goto err_probe;
-+
-+ fbp->fbp_id = dtrace_probe_create(fbt_id, mp->name, func,
-+ "entry", FBT_AFRAMES, fbp);
-+ if (fbp->fbp_id == DTRACE_IDNONE)
-+ goto err_name;
-+
-+ fbp->fbp_module = mp;
-+ fbp->fbp_primary = 1; /* FIXME */
-+ fbp->fbp_roffset = off;
-+ fbp->fbp_patchpoint = addr;
-+ fbt_provide_probe_arch(fbp, probetype, stype);
-+
-+ fbp->fbp_hashnext = fbt_probetab[FBT_ADDR2NDX(fbp->fbp_patchpoint)];
-+ fbt_probetab[FBT_ADDR2NDX(fbp->fbp_patchpoint)] = fbp;
-+
-+ PDATA(mp)->fbt_probe_cnt++;
-+
-+ return fbp;
-+ case FBT_RETURN:
-+
-+ /* Check if we are able to patch this return probe. */
-+ if (!fbt_can_patch_return_arch(addr))
-+ return pfbt;
-+
-+ fbp = kzalloc(sizeof(struct fbt_probe), GFP_KERNEL);
-+ fbp->fbp_name = kstrdup(func, GFP_KERNEL);
-+ if (fbp->fbp_name == NULL)
-+ goto err_probe;
-+
-+ prev = (struct fbt_probe *)pfbt;
-+ if (prev != NULL) {
-+ prev->fbp_next = fbp;
-+ fbp->fbp_id = prev->fbp_id;
-+ } else {
-+ fbp->fbp_id = dtrace_probe_create(fbt_id, mp->name,
-+ func, "return",
-+ FBT_AFRAMES, fbp);
-+ if (fbp->fbp_id == DTRACE_IDNONE)
-+ goto err_name;
-+ }
-+
-+ fbp->fbp_module = mp;
-+ fbp->fbp_primary = 1; /* FIXME */
-+ fbp->fbp_roffset = off;
-+ fbp->fbp_patchpoint = addr;
-+ fbt_provide_probe_arch(fbp, probetype, stype);
-+
-+ fbp->fbp_hashnext = fbt_probetab[FBT_ADDR2NDX(fbp->fbp_patchpoint)];
-+ fbt_probetab[FBT_ADDR2NDX(fbp->fbp_patchpoint)] = fbp;
-+
-+ PDATA(mp)->fbt_probe_cnt++;
-+
-+ return fbp;
-+ default:
-+ pr_info("FBT: Invalid probe type %d (%d) for %s\n",
-+ probetype, stype, func);
-+
-+ return NULL;
-+ }
-+
-+err_name:
-+ kfree(fbp->fbp_name);
-+err_probe:
-+ kfree(fbp);
-+ (*skipped)++;
-+
-+ return NULL;
-+}
-+
-+void fbt_provide_module(void *arg, struct module *mp)
-+{
-+ struct module_use *use;
-+ int probes_skipped = 0;
-+
-+ /* If module setup has failed then do not provide anything. */
-+ if (PDATA(mp) == NULL)
-+ return;
-+
-+ /*
-+ * Nothing to do if the module FBT probes were already created.
-+ */
-+ if (PDATA(mp)->fbt_probe_cnt != 0)
-+ return;
-+
-+ /*
-+ * Do not try to instrument DTrace itself and its modules:
-+ * - dtrace module
-+ * - all modules depending on dtrace
-+ */
-+ if (!strncmp(mp->name, "dtrace", 7))
-+ return;
-+
-+ list_for_each_entry(use, &mp->target_list, target_list) {
-+ if (!strncmp(use->target->name, "dtrace", 7))
-+ return;
-+ }
-+
-+ /*
-+ * Provide probes.
-+ */
-+ if (!fbt_provide_module_arch(arg, mp))
-+ return;
-+
-+ dtrace_fbt_init((fbt_add_probe_fn)fbt_provide_probe, mp,
-+ &probes_skipped);
-+
-+ if (probes_skipped != 0)
-+ pr_warn("fbt: Failed to provide %d probes in %s (out of memory)\n",
-+ probes_skipped, mp->name);
-+}
-+
-+int fbt_enable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fbt_probe *fbp = parg;
-+ struct fbt_probe *curr;
-+
-+ /*
-+ * Ensure that we have a reference to the module.
-+ */
-+ if (!try_module_get(fbp->fbp_module))
-+ return -EAGAIN;
-+
-+ /*
-+ * If at least one other enabled probe exists for this module, drop the
-+ * reference we took above, because we only need one to prevent the
-+ * module from being unloaded.
-+ */
-+ PDATA(fbp->fbp_module)->enabled_cnt++;
-+ if (PDATA(fbp->fbp_module)->enabled_cnt > 1)
-+ module_put(fbp->fbp_module);
-+
-+ for (curr = fbp; curr != NULL; curr = curr->fbp_next)
-+ fbt_enable_arch(curr, id, arg);
-+
-+ return 0;
-+}
-+
-+void fbt_disable(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fbt_probe *fbp = parg;
-+ struct fbt_probe *curr;
-+
-+ for (curr = fbp; curr != NULL; curr = curr->fbp_next)
-+ fbt_disable_arch(curr, id, arg);
-+
-+ /*
-+ * If we are disabling a probe, we know it was enabled, and therefore
-+ * we know that we have a reference on the module to prevent it from
-+ * being unloaded. If we disable the last probe on the module, we can
-+ * drop the reference.
-+ */
-+ PDATA(fbp->fbp_module)->enabled_cnt--;
-+ if (PDATA(fbp->fbp_module)->enabled_cnt == 0)
-+ module_put(fbp->fbp_module);
-+}
-+
-+void fbt_destroy(void *arg, dtrace_id_t id, void *parg)
-+{
-+ struct fbt_probe *fbp = parg;
-+ struct fbt_probe *hbp, *lst, *nxt;
-+ int ndx;
-+ struct module *mp = fbp->fbp_module;
-+
-+ do {
-+ nxt = fbp->fbp_next;
-+
-+ ndx = FBT_ADDR2NDX(fbp->fbp_patchpoint);
-+ lst = NULL;
-+ hbp = fbt_probetab[ndx];
-+
-+ while (hbp != fbp) {
-+ ASSERT(hbp != NULL);
-+
-+ lst = hbp;
-+ hbp = hbp->fbp_hashnext;
-+ }
-+
-+ if (lst != NULL)
-+ lst->fbp_hashnext = fbp->fbp_hashnext;
-+ else
-+ fbt_probetab[ndx] = fbp->fbp_hashnext;
-+
-+ kfree(fbp->fbp_name);
-+ kfree(fbp);
-+
-+ PDATA(mp)->fbt_probe_cnt--;
-+
-+ fbp = nxt;
-+ } while (fbp != NULL);
-+}
-+
-+static int fbt_open(struct inode *inode, struct file *file)
-+{
-+ return -EAGAIN;
-+}
-+
-+static int fbt_close(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static const struct file_operations fbt_fops = {
-+ .owner = THIS_MODULE,
-+ .open = fbt_open,
-+ .release = fbt_close,
-+};
-+
-+static struct miscdevice fbt_dev = {
-+ .minor = DT_DEV_FBT_MINOR,
-+ .name = "fbt",
-+ .nodename = "dtrace/provider/fbt",
-+ .fops = &fbt_fops,
-+};
-+
-+int fbt_dev_init(void)
-+{
-+ int ret = 0;
-+
-+ ret = misc_register(&fbt_dev);
-+ if (ret)
-+ pr_err("%s: Can't register misc device %d\n",
-+ fbt_dev.name, fbt_dev.minor);
-+
-+ return fbt_dev_init_arch();
-+}
-+
-+void fbt_dev_exit(void)
-+{
-+ fbt_dev_exit_arch();
-+
-+ misc_deregister(&fbt_dev);
-+}
-diff --git a/dtrace/fbt_impl.h b/dtrace/fbt_impl.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..85f83e704988c952ab3552ac06d74982fbf34657
---- /dev/null
-+++ b/dtrace/fbt_impl.h
-@@ -0,0 +1,52 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Function Boundary Tracing provider
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef _FBT_H_
-+#define _FBT_H_
-+
-+#include <asm/dtrace_arch.h>
-+#include <dtrace/fbt_arch.h>
-+
-+#define FBT_ADDR2NDX(addr) ((((uintptr_t)(addr)) >> 4) & \
-+ fbt_probetab_mask)
-+
-+extern struct fbt_probe **fbt_probetab;
-+extern int fbt_probetab_size;
-+extern int fbt_probetab_mask;
-+
-+extern void fbt_provide_probe_arch(struct fbt_probe *, int, int);
-+extern void fbt_enable_arch(struct fbt_probe *, dtrace_id_t, void *);
-+extern void fbt_disable_arch(struct fbt_probe *, dtrace_id_t, void *);
-+extern int fbt_can_patch_return_arch(asm_instr_t *);
-+
-+extern int fbt_provide_module_arch(void *, struct module *);
-+extern void fbt_provide_module(void *, struct module *);
-+extern void fbt_destroy_module(void *, struct module *);
-+extern int fbt_enable(void *, dtrace_id_t, void *);
-+extern void fbt_disable(void *, dtrace_id_t, void *);
-+extern uint64_t fbt_getarg(void *, dtrace_id_t, void *, int, int);
-+extern void fbt_destroy(void *, dtrace_id_t, void *);
-+
-+extern dtrace_provider_id_t fbt_id;
-+
-+extern int fbt_dev_init_arch(void);
-+extern void fbt_dev_exit_arch(void);
-+
-+extern int fbt_dev_init(void);
-+extern void fbt_dev_exit(void);
-+
-+#endif /* _FBT_H_ */
-diff --git a/dtrace/fbt_mod.c b/dtrace/fbt_mod.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..3da13d71809dcaa907c4473e38047aea1c9f877d
---- /dev/null
-+++ b/dtrace/fbt_mod.c
-@@ -0,0 +1,56 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fbt_mod.c
-+ * DESCRIPTION: DTrace - FBT provider kernel module
-+ *
-+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/module.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fbt_impl.h"
-+
-+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
-+MODULE_DESCRIPTION("Function Boundary Tracing");
-+MODULE_VERSION("v0.1");
-+MODULE_LICENSE("GPL");
-+
-+static const struct dtrace_pattr fbt_attr = {
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-+};
-+
-+static struct dtrace_pops fbt_pops = {
-+ .dtps_provide = NULL,
-+ .dtps_provide_module = fbt_provide_module,
-+ .dtps_destroy_module = fbt_destroy_module,
-+ .dtps_enable = fbt_enable,
-+ .dtps_disable = fbt_disable,
-+ .dtps_suspend = NULL,
-+ .dtps_resume = NULL,
-+ .dtps_getargdesc = NULL,
-+#ifdef CONFIG_X86_64
-+ .dtps_getargval = fbt_getarg,
-+#else
-+ .dtps_getargval = NULL,
-+#endif
-+ .dtps_usermode = NULL,
-+ .dtps_destroy = fbt_destroy
-+};
-+
-+DT_PROVIDER_MODULE(fbt, DTRACE_PRIV_KERNEL)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0016-dtrace-arm-arm64-port.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0016-dtrace-arm-arm64-port.patch
deleted file mode 100644
index fda507e7c8e9..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0016-dtrace-arm-arm64-port.patch
+++ /dev/null
@@ -1,2667 +0,0 @@
-From 7448665d4354efd9fafea1149cc2adc31dc98c64 Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Thu, 8 Nov 2018 18:57:33 +0000
-Subject: [PATCH 16/19] dtrace, arm: arm64 port
-
-This provides an arm64 implementation of DTrace.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- arch/arm64/Kconfig | 3 +
- arch/arm64/dtrace/Makefile.arch | 17 +
- arch/arm64/dtrace/dtrace_asm_arm64.S | 51 +++
- arch/arm64/dtrace/dtrace_isa_arm64.c | 164 +++++++
- arch/arm64/dtrace/fasttrap_arm64.c | 282 ++++++++++++
- arch/arm64/dtrace/fbt_arm64.c | 152 +++++++
- .../dtrace/include/dtrace/fasttrap_arch.h | 30 ++
- arch/arm64/dtrace/include/dtrace/fbt_arch.h | 53 +++
- arch/arm64/dtrace/include/dtrace/sdt_arch.h | 28 ++
- arch/arm64/dtrace/sdt_arm64.c | 122 +++++
- arch/arm64/include/asm/brk-imm.h | 6 +
- arch/arm64/include/asm/cpu.h | 1 +
- arch/arm64/include/asm/debug-monitors.h | 4 +
- arch/arm64/include/asm/dtrace_arch.h | 31 ++
- arch/arm64/include/asm/dtrace_cpuinfo.h | 13 +
- arch/arm64/include/asm/dtrace_sdt_arch.h | 15 +
- arch/arm64/include/asm/dtrace_syscall.h | 3 +
- arch/arm64/include/asm/dtrace_syscall_types.h | 11 +
- arch/arm64/include/asm/dtrace_util.h | 14 +
- arch/arm64/include/asm/kdebug.h | 11 +
- arch/arm64/include/asm/syscall.h | 8 +-
- arch/arm64/kernel/dtrace_fbt.c | 187 ++++++++
- arch/arm64/kernel/dtrace_sdt.c | 25 ++
- arch/arm64/kernel/dtrace_syscall.c | 89 ++++
- arch/arm64/kernel/dtrace_syscall_stubs.S | 0
- arch/arm64/kernel/dtrace_util.c | 292 ++++++++++++
- arch/arm64/kernel/entry-common.c | 6 +-
- arch/arm64/kernel/entry.S | 53 ++-
- arch/arm64/kernel/fbt_blacklist.h | 91 ++++
- arch/arm64/kernel/probes/uprobes.c | 3 +-
- arch/arm64/kernel/sys.c | 2 +-
- arch/arm64/mm/fault.c | 18 +
- include/linux/uprobes.h | 1 +
- kernel/events/uprobes.c | 10 +
- scripts/dtrace_sdt_arm64.sh | 425 ++++++++++++++++++
- scripts/link-vmlinux.sh | 15 +-
- 36 files changed, 2221 insertions(+), 15 deletions(-)
- create mode 100644 arch/arm64/dtrace/Makefile.arch
- create mode 100644 arch/arm64/dtrace/dtrace_asm_arm64.S
- create mode 100644 arch/arm64/dtrace/dtrace_isa_arm64.c
- create mode 100644 arch/arm64/dtrace/fasttrap_arm64.c
- create mode 100644 arch/arm64/dtrace/fbt_arm64.c
- create mode 100644 arch/arm64/dtrace/include/dtrace/fasttrap_arch.h
- create mode 100644 arch/arm64/dtrace/include/dtrace/fbt_arch.h
- create mode 100644 arch/arm64/dtrace/include/dtrace/sdt_arch.h
- create mode 100644 arch/arm64/dtrace/sdt_arm64.c
- create mode 100644 arch/arm64/include/asm/dtrace_arch.h
- create mode 100644 arch/arm64/include/asm/dtrace_cpuinfo.h
- create mode 100644 arch/arm64/include/asm/dtrace_sdt_arch.h
- create mode 100644 arch/arm64/include/asm/dtrace_syscall.h
- create mode 100644 arch/arm64/include/asm/dtrace_syscall_types.h
- create mode 100644 arch/arm64/include/asm/dtrace_util.h
- create mode 100644 arch/arm64/include/asm/kdebug.h
- create mode 100644 arch/arm64/kernel/dtrace_fbt.c
- create mode 100644 arch/arm64/kernel/dtrace_sdt.c
- create mode 100644 arch/arm64/kernel/dtrace_syscall.c
- create mode 100644 arch/arm64/kernel/dtrace_syscall_stubs.S
- create mode 100644 arch/arm64/kernel/dtrace_util.c
- create mode 100644 arch/arm64/kernel/fbt_blacklist.h
- create mode 100755 scripts/dtrace_sdt_arm64.sh
-
-diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index a6b5b7ef40aea08f036e58d2684f87f378773644..72a0be5f171780292bc9e668b839f15b95860eb6 100644
---- a/arch/arm64/Kconfig
-+++ b/arch/arm64/Kconfig
-@@ -323,6 +323,9 @@ config PGTABLE_LEVELS
- config ARCH_SUPPORTS_UPROBES
- def_bool y
-
-+config ARCH_SUPPORTS_DTRACE
-+ def_bool y
-+
- config ARCH_PROC_KCORE_TEXT
- def_bool y
-
-diff --git a/arch/arm64/dtrace/Makefile.arch b/arch/arm64/dtrace/Makefile.arch
-new file mode 100644
-index 0000000000000000000000000000000000000000..393b5cea3f7c0af4eb0bb280d1e65b4c468c1f3c
---- /dev/null
-+++ b/arch/arm64/dtrace/Makefile.arch
-@@ -0,0 +1,17 @@
-+#
-+# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+#
-+
-+DTARCHDIR = ../arch/arm64/dtrace
-+
-+ccflags-y += -I$(srctree)/arch/arm64/dtrace/include -Idtrace
-+
-+dtrace-obj += dtrace_asm_arm64.o dtrace_isa_arm64.o
-+fasttrap-obj += fasttrap_arm64.o
-+fbt-obj += fbt_arm64.o
-+sdt-obj += sdt_arm64.o
-+
-+dtrace-y += $(addprefix $(DTARCHDIR)/, $(dtrace-obj))
-+fasttrap-y += $(addprefix $(DTARCHDIR)/, $(fasttrap-obj))
-+fbt-y += $(addprefix $(DTARCHDIR)/, $(fbt-obj))
-+sdt-y += $(addprefix $(DTARCHDIR)/, $(sdt-obj))
-diff --git a/arch/arm64/dtrace/dtrace_asm_arm64.S b/arch/arm64/dtrace/dtrace_asm_arm64.S
-new file mode 100644
-index 0000000000000000000000000000000000000000..d0f7bad5fb0bc687a1eca65a99582f36834995ce
---- /dev/null
-+++ b/arch/arm64/dtrace/dtrace_asm_arm64.S
-@@ -0,0 +1,51 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - ARM64 specific assembly
-+ *
-+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/linkage.h>
-+
-+SYM_CODE_START(dtrace_caller)
-+ mov x0, #-1
-+ ret
-+SYM_CODE_END(dtrace_caller)
-+
-+SYM_CODE_START(dtrace_copy)
-+ ret
-+SYM_CODE_END(dtrace_copy)
-+
-+SYM_CODE_START(dtrace_copystr)
-+ ret
-+SYM_CODE_END(dtrace_copystr)
-+
-+SYM_CODE_START(dtrace_fuword8_nocheck)
-+ ldrb w0, [x0]
-+ ret
-+SYM_CODE_END(dtrace_fuword8_nocheck)
-+
-+SYM_CODE_START(dtrace_fuword16_nocheck)
-+ ldrh w0, [x0]
-+ ret
-+SYM_CODE_END(dtrace_fuword16_nocheck)
-+
-+SYM_CODE_START(dtrace_fuword32_nocheck)
-+ ldr w0, [x0]
-+ ret
-+SYM_CODE_END(dtrace_fuword32_nocheck)
-+
-+SYM_CODE_START(dtrace_fuword64_nocheck)
-+ ldr x0, [x0]
-+ ret
-+SYM_CODE_END(dtrace_fuword64_nocheck)
-diff --git a/arch/arm64/dtrace/dtrace_isa_arm64.c b/arch/arm64/dtrace/dtrace_isa_arm64.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..2eb530149c5b4176b776d673bd3441e8afed8767
---- /dev/null
-+++ b/arch/arm64/dtrace/dtrace_isa_arm64.c
-@@ -0,0 +1,164 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_isa_arm64.c
-+ * DESCRIPTION: DTrace - arm64 architecture specific support functions
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <asm/stacktrace.h>
-+#include <linux/ptrace.h>
-+
-+#include "dtrace.h"
-+
-+uintptr_t _userlimit = 0x0000ffffffffffffLL;
-+
-+void dtrace_copyin_arch(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+}
-+
-+void dtrace_copyinstr_arch(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+}
-+
-+void dtrace_copyout(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+}
-+
-+void dtrace_copyoutstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-+ volatile uint16_t *flags)
-+{
-+}
-+
-+#define DTRACE_FUWORD(bits) \
-+ uint##bits##_t dtrace_fuword##bits(void *uaddr) \
-+ { \
-+ extern uint##bits##_t dtrace_fuword##bits##_nocheck(void *);\
-+ \
-+ if ((uintptr_t)uaddr > _userlimit) { \
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); \
-+ this_cpu_core->cpuc_dtrace_illval = (uintptr_t)uaddr; \
-+ } \
-+ \
-+ return dtrace_fuword##bits##_nocheck(uaddr); \
-+ }
-+
-+DTRACE_FUWORD(8)
-+DTRACE_FUWORD(16)
-+DTRACE_FUWORD(32)
-+DTRACE_FUWORD(64)
-+
-+static int dtrace_unwind_frame(struct task_struct *task,
-+ struct stackframe *frame)
-+{
-+ unsigned long fp = frame->fp;
-+
-+ if (fp & 0xf)
-+ return -EINVAL;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp));
-+ frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8));
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ if (!frame->fp && !frame->pc)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+uint64_t dtrace_getarg(int argno, int aframes)
-+{
-+ uint64_t *st;
-+ uint64_t val;
-+ int i;
-+ struct stackframe frame;
-+ struct task_struct *task = current;
-+
-+ if (argno < 7)
-+ return 0;
-+
-+ if (this_cpu_core->cpu_dtrace_regs)
-+ st = (uint64_t *)this_cpu_core->cpu_dtrace_regs->regs[29];
-+ else {
-+ frame.fp = (unsigned long)__builtin_frame_address(0);
-+ frame.pc = (unsigned long)dtrace_getarg;
-+
-+ aframes += 1; /* Count this function. */
-+ for (i = 0; i < aframes; i++) {
-+ if (dtrace_unwind_frame(task, &frame) < 0)
-+ break;
-+ }
-+
-+ /*
-+ * If we cannot traverse the expected number of stack frames,
-+ * there is something wrong with the stack.
-+ */
-+ if (i < aframes) {
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADSTACK);
-+
-+ return 0;
-+ }
-+
-+ st = (uint64_t *)frame.fp;
-+ }
-+
-+ /*
-+ * The first 7 arguments (arg0 through arg6) are passed in registers
-+ * to dtrace_probe(). The remaining arguments (arg7 through arg9) are
-+ * passed on the stack.
-+ *
-+ * Stack layout:
-+ * bp[0] = pushed fp from caller
-+ * bp[1] = return address
-+ * bp[2] = 8th argument (arg7 -> argno = 7)
-+ * bp[3] = 9th argument (arg8 -> argno = 8)
-+ * ...
-+ */
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ val = READ_ONCE_NOCHECK(st[2 + (argno - 7)]);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return val;
-+}
-+
-+ulong_t dtrace_getreg(struct task_struct *task, uint_t reg)
-+{
-+ struct pt_regs *rp = task_pt_regs(task);
-+
-+ return regs_get_register(rp, reg * sizeof(uint64_t));
-+}
-+
-+void pdata_init(struct dtrace_module *pdata, struct module *mp)
-+{
-+ /*
-+ * Throw away existing data as we don't support reusal at
-+ * the moment.
-+ */
-+ if (mp->pdata != NULL)
-+ pdata_cleanup(pdata, mp);
-+
-+ pdata->sdt_tab = NULL;
-+ pdata->fbt_tab = NULL;
-+}
-+
-+void pdata_cleanup(struct dtrace_module *pdata, struct module *mp)
-+{
-+ if (pdata->sdt_tab != NULL)
-+ dtrace_free_text(pdata->sdt_tab);
-+ if (pdata->fbt_tab != NULL)
-+ dtrace_free_text(pdata->fbt_tab);
-+}
-diff --git a/arch/arm64/dtrace/fasttrap_arm64.c b/arch/arm64/dtrace/fasttrap_arm64.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..cc970a11412c7934a10ce6fc7453b1ce132bdcea
---- /dev/null
-+++ b/arch/arm64/dtrace/fasttrap_arm64.c
-@@ -0,0 +1,282 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: fasttrap_arm64.c
-+ * DESCRIPTION: DTrace - fasttrap provider implementation for arm64
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <asm/insn.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fasttrap_impl.h"
-+
-+static int has_jump_table(const asm_instr_t *addr, size_t size)
-+{
-+ const asm_instr_t *end = addr + size;
-+
-+ while (addr < end) {
-+ /*
-+ * If we encounter a branch-to-register instruction, we assume
-+ * it is part of a jump table implementation.
-+ */
-+ if (aarch64_insn_is_br(addr[0]))
-+ return 1;
-+
-+ addr++;
-+ }
-+
-+ return 0;
-+}
-+
-+static uint64_t *fasttrap_all_offsets(asm_instr_t *text, size_t size,
-+ uint64_t *np)
-+{
-+ uint64_t *offs = NULL;
-+ uint64_t noffs;
-+ asm_instr_t *instr;
-+ asm_instr_t *end;
-+
-+ /*
-+ * Two passes are taken through this section of code. The first time
-+ * around we merely count the number of probe points. The second time,
-+ * we actually record their locations.
-+ */
-+again:
-+ noffs = 0;
-+ instr = text;
-+ end = text + size;
-+
-+ while (instr < end) {
-+ if (offs)
-+ offs[noffs] = (uint64_t)
-+ ((uintptr_t)instr - (uintptr_t)text);
-+ noffs++;
-+
-+ instr++;
-+ }
-+
-+ if (offs == NULL) {
-+ /*
-+ * No matching offsets found - we are done.
-+ */
-+ if (noffs == 0)
-+ goto fail;
-+
-+ /*
-+ * We know how many tracepoint locations there are for this
-+ * probe, so allocate a member to record them, and kick off the
-+ * second pass.
-+ */
-+ offs = kmalloc(sizeof(uint64_t) * noffs, GFP_KERNEL);
-+ if (!offs)
-+ goto fail;
-+
-+ goto again;
-+ }
-+
-+ *np = noffs;
-+
-+ return offs;
-+
-+fail:
-+ *np = 0;
-+ kfree(offs);
-+
-+ return NULL;
-+}
-+
-+uint64_t *fasttrap_glob_offsets(struct fasttrap_probe_spec *probe,
-+ uint64_t *np)
-+{
-+ size_t size = probe->ftps_size;
-+ asm_instr_t *text = NULL;
-+ asm_instr_t *instr;
-+ asm_instr_t *end;
-+ uint64_t *offs = NULL;
-+ uint64_t noffs;
-+ int ret = 0;
-+ char ostr[sizeof(instr) * 2 + 1]; /* 2 chars / byte + 1 */
-+
-+ if (!IS_ALIGNED(size, sizeof(instr[0])))
-+ goto fail;
-+
-+ text = kmalloc(size, GFP_KERNEL);
-+ if (!text)
-+ goto fail;
-+
-+ ret = dtrace_copy_code(probe->ftps_pid, (uint8_t *)text,
-+ probe->ftps_pc, size);
-+ if (ret != 0)
-+ goto fail;
-+
-+ /*
-+ * From this point on, size will be a count of instructions rather than
-+ * a byte count. We already verified earlier on that it is a multiple
-+ * of the instruction size.
-+ */
-+ size /= sizeof(instr[0]);
-+
-+ if (has_jump_table(text, size))
-+ goto fail;
-+
-+ if (probe->ftps_glen == 1 && probe->ftps_gstr[0] == '*') {
-+ offs = fasttrap_all_offsets(text, size, &noffs);
-+ goto out;
-+ }
-+
-+ /*
-+ * Two passes are taken through this section of code. The first time
-+ * around we merely count the number of probe points. The second time,
-+ * we actually record their locations.
-+ */
-+again:
-+ noffs = 0;
-+ instr = text;
-+ end = text + size;
-+
-+ while (instr < end) {
-+ uint64_t off = (uint64_t)
-+ ((uintptr_t)instr - (uintptr_t)text);
-+
-+ snprintf(ostr, sizeof(ostr), "%llx", off);
-+ if (dtrace_gmatch(ostr, probe->ftps_gstr)) {
-+ if (offs)
-+ offs[noffs] = off;
-+ noffs++;
-+ }
-+
-+ instr++;
-+ }
-+
-+ if (offs == NULL) {
-+ /*
-+ * No matching offsets found - we are done.
-+ */
-+ if (noffs == 0)
-+ goto fail;
-+
-+ /*
-+ * We know how many tracepoint locations there are for this
-+ * probe, so allocate member to record them, and kick off the
-+ * second pass.
-+ */
-+ offs = kmalloc(sizeof(uint64_t) * noffs, GFP_KERNEL);
-+ if (!offs)
-+ goto fail;
-+
-+ goto again;
-+ }
-+
-+out:
-+ kfree(text);
-+
-+ *np = noffs;
-+
-+ return offs;
-+
-+fail:
-+ kfree(offs);
-+ kfree(text);
-+
-+ *np = 0;
-+ return NULL;
-+}
-+
-+uint64_t fasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ return 0;
-+
-+ if (argno < 8)
-+ return regs->regs[argno];
-+
-+ pagefault_disable();
-+ st = (uint64_t *)regs->sp;
-+ __copy_from_user_inatomic_nocache(&val, (void *)&st[argno - 8],
-+ sizeof(st[0]));
-+ pagefault_enable();
-+
-+ return val;
-+}
-+
-+uint64_t fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg,
-+ int argno, int aframes)
-+{
-+ return fasttrap_pid_getarg(arg, id, parg, argno, aframes);
-+}
-+
-+static void fasttrap_map_args(struct fasttrap_probe *probe,
-+ struct pt_regs *regs, int argc, uintptr_t *argv)
-+{
-+ int i, x, cap = min(argc, (int)probe->ftp_nargs);
-+ uintptr_t *st = (uintptr_t *)regs->sp;
-+
-+ for (i = 0; i < cap; i++) {
-+ x = probe->ftp_argmap[i];
-+
-+ if (x < 8)
-+ argv[i] = regs->regs[x];
-+ else {
-+ pagefault_disable();
-+ __copy_from_user_inatomic_nocache(&argv[i],
-+ (void *)&st[x - 8],
-+ sizeof(st[0]));
-+ pagefault_enable();
-+ }
-+ }
-+
-+ while (i < argc)
-+ argv[i++] = 0;
-+}
-+
-+void fasttrap_pid_probe_arch(struct fasttrap_probe *ftp, struct pt_regs *regs)
-+{
-+ if (ftp->ftp_argmap == NULL) {
-+ dtrace_probe(ftp->ftp_id, regs->regs[0], regs->regs[1],
-+ regs->regs[2], regs->regs[3],
-+ regs->regs[4], regs->regs[5],
-+ regs->regs[6]);
-+ } else {
-+ uintptr_t t[7];
-+
-+ fasttrap_map_args(ftp, regs, sizeof(t) / sizeof(t[0]), t);
-+ dtrace_probe(ftp->ftp_id, t[0], t[1], t[2], t[3],
-+ t[4], t[5], t[6]);
-+ }
-+}
-+
-+void fasttrap_pid_retprobe_arch(struct fasttrap_probe *ftp,
-+ struct pt_regs *regs)
-+{
-+ /*
-+ * FIXME: The first argument to the probe should be the offset in the
-+ * function that the return occurred at, but uprobes doesn't give
-+ * us that information (or so it seems).
-+ */
-+ dtrace_probe(ftp->ftp_id, 0, regs->regs[0], regs->regs[1], 0, 0, 0, 0);
-+}
-+
-+void fasttrap_set_enabled(struct pt_regs *regs)
-+{
-+ regs->regs[0] = 1;
-+}
-diff --git a/arch/arm64/dtrace/fbt_arm64.c b/arch/arm64/dtrace/fbt_arm64.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..be9dcaf8db28aceb80cb82805407d041c4edced5
---- /dev/null
-+++ b/arch/arm64/dtrace/fbt_arm64.c
-@@ -0,0 +1,152 @@
-+/*
-+ * FILE: fbt_arm64.c
-+ * DESCRIPTION: DTrace - FBT provider implementation for arm64
-+ *
-+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/dtrace_fbt.h>
-+#include <linux/ptrace.h>
-+#include <linux/vmalloc.h>
-+#include <asm/dtrace_util.h>
-+#include <asm/debug-monitors.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "fbt_impl.h"
-+
-+static int fbt_brk_hook(struct pt_regs *regs, unsigned int esr)
-+{
-+ uintptr_t ip = instruction_pointer(regs);
-+ struct fbt_probe *fbp = fbt_probetab[FBT_ADDR2NDX(ip)];
-+
-+ for (; fbp != NULL; fbp = fbp->fbp_hashnext) {
-+ if ((uintptr_t)fbp->fbp_patchpoint == ip) {
-+ struct pt_regs *oregs;
-+
-+ oregs = this_cpu_core->cpu_dtrace_regs;
-+ this_cpu_core->cpu_dtrace_regs = regs;
-+
-+ if (fbp->fbp_roffset == 0) {
-+ dtrace_probe(fbp->fbp_id, regs->regs[0],
-+ regs->regs[1], regs->regs[2],
-+ regs->regs[3], regs->regs[4],
-+ regs->regs[5], regs->regs[6]);
-+ } else {
-+ dtrace_probe(fbp->fbp_id, fbp->fbp_roffset,
-+ regs->regs[0], 0, 0, 0, 0, 0);
-+ }
-+
-+ this_cpu_core->cpu_dtrace_regs = oregs;
-+
-+ return DBG_HOOK_HANDLED;
-+ }
-+ }
-+
-+ return DBG_HOOK_ERROR;
-+}
-+
-+uint64_t fbt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ regs = current_pt_regs();
-+
-+ if (argno < 8)
-+ return regs->regs[argno];
-+
-+ /*
-+ * Arguments are passed by register for the first 8 arguments, and the
-+ * rest is placed on the stack. The frame pointer (fp) points at the
-+ * beginning of the current frame, and the stack pointer (sp) will
-+ * point to the end of the frame. Arguments passed by stack are placed
-+ * in stack slots at the end of the frame, so at (sp), (sp + 1), etc...
-+ */
-+ st = (uint64_t *)regs->sp;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ val = READ_ONCE_NOCHECK(st[argno - 8]);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return 0;
-+}
-+
-+void fbt_provide_probe_arch(struct fbt_probe *fbp, int type, int stype)
-+{
-+ fbp->fbp_patchval = type == FBT_ENTRY ? BRK64_OPCODE_DPROBE_FBE
-+ : BRK64_OPCODE_DPROBE_FBR;
-+ fbp->fbp_savedval = dtrace_text_peek(fbp->fbp_patchpoint);
-+}
-+
-+int fbt_can_patch_return_arch(asm_instr_t *addr)
-+{
-+ return 1;
-+}
-+
-+int fbt_provide_module_arch(void *arg, struct module *mp)
-+{
-+ return 1;
-+}
-+
-+void fbt_destroy_module(void *arg, struct module *mp)
-+{
-+}
-+
-+void fbt_enable_arch(struct fbt_probe *fbp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_text_poke(fbp->fbp_patchpoint, fbp->fbp_patchval);
-+}
-+
-+void fbt_disable_arch(struct fbt_probe *fbp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_text_poke(fbp->fbp_patchpoint, fbp->fbp_savedval);
-+}
-+
-+static struct break_hook dtrace_fbe_break_hook = {
-+ .imm = DPROBES_FBE_BRK_IMM,
-+ .fn = fbt_brk_hook,
-+};
-+
-+static struct break_hook dtrace_fbr_break_hook = {
-+ .imm = DPROBES_FBR_BRK_IMM,
-+ .fn = fbt_brk_hook,
-+};
-+
-+int fbt_dev_init_arch(void)
-+{
-+ fbt_probetab_mask = fbt_probetab_size - 1;
-+ fbt_probetab = dtrace_vzalloc_try(fbt_probetab_size *
-+ sizeof(struct fbt_probe *));
-+
-+ if (fbt_probetab == NULL)
-+ return -ENOMEM;
-+
-+ dtrace_kernel_brk_start(&dtrace_fbe_break_hook);
-+ dtrace_kernel_brk_start(&dtrace_fbr_break_hook);
-+
-+ return 0;
-+}
-+
-+void fbt_dev_exit_arch(void)
-+{
-+ dtrace_kernel_brk_stop(&dtrace_fbr_break_hook);
-+ dtrace_kernel_brk_stop(&dtrace_fbe_break_hook);
-+
-+ vfree(fbt_probetab);
-+ fbt_probetab_mask = 0;
-+ fbt_probetab_size = 0;
-+}
-diff --git a/arch/arm64/dtrace/include/dtrace/fasttrap_arch.h b/arch/arm64/dtrace/include/dtrace/fasttrap_arch.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..d5ffa6e711dbd015e7958fbf2288afc0b72f50fe
---- /dev/null
-+++ b/arch/arm64/dtrace/include/dtrace/fasttrap_arch.h
-@@ -0,0 +1,30 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - Fasttrap provider implementation defines
-+ *
-+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _ARM64_FASTTRAP_ARCH_H
-+#define _ARM64_FASTTRAP_ARCH_H
-+
-+#define FASTTRAP_ENTRY_AFRAMES 8
-+#define FASTTRAP_RETURN_AFRAMES 8
-+#define FASTTRAP_OFFSET_AFRAMES 8
-+
-+#endif /* _ARM64_FASTTRAP_ARCH_H */
-diff --git a/arch/arm64/dtrace/include/dtrace/fbt_arch.h b/arch/arm64/dtrace/include/dtrace/fbt_arch.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..ed1cd785b3ba277a966ae9c6a15faf17be1a77a7
---- /dev/null
-+++ b/arch/arm64/dtrace/include/dtrace/fbt_arch.h
-@@ -0,0 +1,53 @@
-+/*
-+ * Dynamic Tracing for Linux - FBT Implementation defines
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _ARM64_FBT_ARCH_H
-+#define _ARM64_FBT_ARCH_H
-+
-+/*
-+ * FBT entry probes are triggered from a breakpoint. The following stack trace
-+ * illustrates the frames that are involved in the call sequence prior to the
-+ * actual FBT provider handler.
-+ *
-+ * vmlinux`brk_handler+0x70 <- to be skipped
-+ * vmlinux`do_debug_exception+0x9c <- to be skipped
-+ * vmlinux`el1_sync+0x1d8 <- to be skipped
-+ * vmlinux`SyS_read+0x4
-+ *
-+ * Therefore, 3 frames need to be skipped.
-+ */
-+#define FBT_AFRAMES 3
-+
-+struct fbt_probe {
-+ char *fbp_name; /* name of probe */
-+ dtrace_id_t fbp_id; /* probe ID */
-+ struct module *fbp_module; /* defining module */
-+ int fbp_primary; /* non-zero if primary mod */
-+ asm_instr_t *fbp_patchpoint;/* patch point */
-+ asm_instr_t fbp_patchval; /* instruction to patch */
-+ asm_instr_t fbp_savedval; /* saved instruction value */
-+ uint64_t fbp_roffset; /* relative offset */
-+ struct fbt_probe *fbp_next; /* next probe */
-+ struct fbt_probe *fbp_hashnext; /* next on hash */
-+ int fbp_isret;
-+};
-+
-+#endif /* _ARM64_FBT_ARCH_H */
-diff --git a/arch/arm64/dtrace/include/dtrace/sdt_arch.h b/arch/arm64/dtrace/include/dtrace/sdt_arch.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..237922a77495d960081082c20666afdad3ee569e
---- /dev/null
-+++ b/arch/arm64/dtrace/include/dtrace/sdt_arch.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Dynamic Tracing for Linux - SDT Implementation defines
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+/*
-+ * Note: The contents of this file are private to the implementation of the
-+ * DTrace subsystem and are subject to change at any time without notice.
-+ */
-+
-+#ifndef _ARM64_SDT_ARCH_H
-+#define _ARM64_SDT_ARCH_H
-+
-+#define SDT_AFRAMES 1
-+
-+#endif /* _ARM64_SDT_ARCH_H */
-diff --git a/arch/arm64/dtrace/sdt_arm64.c b/arch/arm64/dtrace/sdt_arm64.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..ba25824e413ecc22280bcc5aa8e4fa70bad2555f
---- /dev/null
-+++ b/arch/arm64/dtrace/sdt_arm64.c
-@@ -0,0 +1,122 @@
-+/*
-+ * FILE: sdt_arm64.c
-+ * DESCRIPTION: DTrace - SDT provider implementation for arm64
-+ *
-+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/ptrace.h>
-+#include <linux/sdt.h>
-+#include <asm/debug-monitors.h>
-+
-+#include "dtrace.h"
-+#include "dtrace_dev.h"
-+#include "sdt_impl.h"
-+
-+static int sdt_brk_hook(struct pt_regs *regs, unsigned int esr)
-+{
-+ uintptr_t ip = instruction_pointer(regs);
-+ struct sdt_probe *sdt = sdt_probetab[SDT_ADDR2NDX(ip)];
-+
-+ for (; sdt != NULL; sdt = sdt->sdp_hashnext) {
-+ if ((uintptr_t)sdt->sdp_patchpoint == ip) {
-+ if (sdt->sdp_ptype == SDTPT_IS_ENABLED)
-+ regs->regs[0] = 1;
-+ else {
-+ this_cpu_core->cpu_dtrace_regs = regs;
-+ dtrace_probe(sdt->sdp_id, regs->regs[0],
-+ regs->regs[1], regs->regs[2],
-+ regs->regs[3], regs->regs[4],
-+ regs->regs[5], regs->regs[6]);
-+ this_cpu_core->cpu_dtrace_regs = NULL;
-+ }
-+
-+ instruction_pointer_set(regs,
-+ instruction_pointer(regs) + 4);
-+
-+ return DBG_HOOK_HANDLED;
-+ }
-+ }
-+
-+ return DBG_HOOK_ERROR;
-+}
-+
-+void sdt_provide_probe_arch(struct sdt_probe *sdp, struct module *mp, int idx)
-+{
-+ sdp->sdp_patchval = BRK64_OPCODE_DPROBE_SDT;
-+ sdp->sdp_savedval = dtrace_text_peek(sdp->sdp_patchpoint);
-+}
-+
-+int sdt_provide_module_arch(void *arg, struct module *mp)
-+{
-+ return 1;
-+}
-+
-+void sdt_destroy_module(void *arg, struct module *mp)
-+{
-+}
-+
-+void sdt_enable_arch(struct sdt_probe *sdp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_text_poke(sdp->sdp_patchpoint, sdp->sdp_patchval);
-+}
-+
-+void sdt_disable_arch(struct sdt_probe *sdp, dtrace_id_t id, void *arg)
-+{
-+ dtrace_text_poke(sdp->sdp_patchpoint, sdp->sdp_savedval);
-+}
-+
-+static struct break_hook dtrace_sdt_break_hook = {
-+ .imm = DPROBES_SDT_BRK_IMM,
-+ .fn = sdt_brk_hook,
-+};
-+
-+int sdt_dev_init_arch(void)
-+{
-+ dtrace_kernel_brk_start(&dtrace_sdt_break_hook);
-+ return 0;
-+}
-+
-+void sdt_dev_exit_arch(void)
-+{
-+ dtrace_kernel_brk_stop(&dtrace_sdt_break_hook);
-+}
-+
-+uint64_t sdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-+ int aframes)
-+{
-+ struct pt_regs *regs = this_cpu_core->cpu_dtrace_regs;
-+ uint64_t *st;
-+ uint64_t val;
-+
-+ if (regs == NULL)
-+ regs = current_pt_regs();
-+
-+ if (argno < 8)
-+ return regs->regs[argno];
-+
-+ /*
-+ * Arguments are passed by register for the first 8 arguments, and the
-+ * rest is placed on the stack. The frame pointer (fp) points at the
-+ * beginning of the current frame, and the stack pointer (sp) will
-+ * point to the end of the frame. Arguments passed by stack are placed
-+ * in stack slots at the end of the frame, so at (sp), (sp + 1), etc...
-+ */
-+ st = (uint64_t *)regs->sp;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-+ val = READ_ONCE_NOCHECK(st[argno - 8]);
-+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-+
-+ return val;
-+}
-diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h
-index ec7720dbe2c801bc44344d7893cfc510fed7d0d7..405cfb7da5ea39f0bb2ed4a2208fb512ed9129df 100644
---- a/arch/arm64/include/asm/brk-imm.h
-+++ b/arch/arm64/include/asm/brk-imm.h
-@@ -11,6 +11,9 @@
- * 0x004: for installing kprobes
- * 0x005: for installing uprobes
- * 0x006: for kprobe software single-step
-+ * 0x007: for installing DTrace SDT probes
-+ * 0x008: for installing DTrace function-boundary tracing entry probes
-+ * 0x009: for installing DTrace function-boundary tracing return probes
- * Allowed values for kgdb are 0x400 - 0x7ff
- * 0x100: for triggering a fault on purpose (reserved)
- * 0x400: for dynamic BRK instruction
-@@ -21,6 +24,9 @@
- #define KPROBES_BRK_IMM 0x004
- #define UPROBES_BRK_IMM 0x005
- #define KPROBES_BRK_SS_IMM 0x006
-+#define DPROBES_SDT_BRK_IMM 0x007
-+#define DPROBES_FBE_BRK_IMM 0x008
-+#define DPROBES_FBR_BRK_IMM 0x009
- #define FAULT_BRK_IMM 0x100
- #define KGDB_DYN_DBG_BRK_IMM 0x400
- #define KGDB_COMPILED_DBG_BRK_IMM 0x401
-diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h
-index 7faae6ff3ab4d5c27896305d609494cdb13d54e6..496e8df36b56d85a7616b38a56797ee83500c0dd 100644
---- a/arch/arm64/include/asm/cpu.h
-+++ b/arch/arm64/include/asm/cpu.h
-@@ -60,6 +60,7 @@ struct cpuinfo_arm64 {
- };
-
- DECLARE_PER_CPU(struct cpuinfo_arm64, cpu_data);
-+#define cpu_data(cpu) per_cpu(cpu_data, (cpu))
-
- void cpuinfo_store_cpu(void);
- void __init cpuinfo_store_boot_cpu(void);
-diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
-index 657c921fd784a7c12a0e45d814c6bc089f9ca0ec..030756b7e008e52e0e5d8a5ea82521a23ae7045a 100644
---- a/arch/arm64/include/asm/debug-monitors.h
-+++ b/arch/arm64/include/asm/debug-monitors.h
-@@ -56,6 +56,10 @@
- #define BRK64_OPCODE_KPROBES_SS (AARCH64_BREAK_MON | (KPROBES_BRK_SS_IMM << 5))
- /* uprobes BRK opcodes with ESR encoding */
- #define BRK64_OPCODE_UPROBES (AARCH64_BREAK_MON | (UPROBES_BRK_IMM << 5))
-+/* DTrace probes BRK opcodes with ESR encoding */
-+#define BRK64_OPCODE_DPROBE_SDT (AARCH64_BREAK_MON | (DPROBES_SDT_BRK_IMM << 5))
-+#define BRK64_OPCODE_DPROBE_FBE (AARCH64_BREAK_MON | (DPROBES_FBE_BRK_IMM << 5))
-+#define BRK64_OPCODE_DPROBE_FBR (AARCH64_BREAK_MON | (DPROBES_FBR_BRK_IMM << 5))
-
- /* AArch32 */
- #define DBG_ESR_EVT_BKPT 0x4
-diff --git a/arch/arm64/include/asm/dtrace_arch.h b/arch/arm64/include/asm/dtrace_arch.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..89f883e20aa7a4ff816bbd5be125c3afd98ab5ee
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_arch.h
-@@ -0,0 +1,31 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. */
-+
-+#ifndef _ASM_ARM64_DTRACE_ARCH_H
-+#define _ASM_ARM64_DTRACE_ARCH_H
-+
-+/* Number of argumens stored inside the mstate. */
-+#define DTRACE_MSTATE_ARGS_MAX 7
-+
-+typedef uint32_t asm_instr_t;
-+
-+typedef int (*prov_exit_f)(void);
-+
-+/*
-+ * Structure to hold DTrace specific information about modules (including the
-+ * core kernel module). Note that each module (and the main kernel) already
-+ * has three fields that relate to probing:
-+ * - sdt_probes: description of SDT probes in the module
-+ * - sdt_probec: number of SDT probes in the module
-+ * - pdata: pointer to a dtrace_module struct (for DTrace)
-+ */
-+struct dtrace_module {
-+ int enabled_cnt;
-+ size_t sdt_probe_cnt;
-+ asm_instr_t *sdt_tab;
-+ size_t fbt_probe_cnt;
-+ asm_instr_t *fbt_tab;
-+ prov_exit_f prov_exit; /* Called with module_mutex held */
-+};
-+
-+#endif /* _ASM_ARM64_DTRACE_ARCH_H */
-diff --git a/arch/arm64/include/asm/dtrace_cpuinfo.h b/arch/arm64/include/asm/dtrace_cpuinfo.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..4e0ab793c92cd1e757c06754744ce799d14ed72c
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_cpuinfo.h
-@@ -0,0 +1,13 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/* Copyright (C) 2018 Oracle, Inc. */
-+
-+#ifndef _ASM_ARM64_DTRACE_CPUINFO_H_
-+#define _ASM_ARM64_DTRACE_CPUINFO_H_
-+
-+#include <asm/cpu.h>
-+
-+typedef struct cpuinfo_arm64 cpuinfo_arch_t;
-+
-+#define dtrace_cpuinfo_chip(ci) ((ci)->cpu.node_id)
-+
-+#endif /* _ASM_ARM64_DTRACE_CPUINFO_H_ */
-diff --git a/arch/arm64/include/asm/dtrace_sdt_arch.h b/arch/arm64/include/asm/dtrace_sdt_arch.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..b93a03c215b3f19c6a0ad70353c404bf0a9f1b20
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_sdt_arch.h
-@@ -0,0 +1,15 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/* Copyright (C) 2018 Oracle, Inc. */
-+
-+#ifndef _ASM_ARM64_DTRACE_SDT_ARCH_H
-+#define _ASM_ARM64_DTRACE_SDT_ARCH_H
-+
-+#include <asm/dtrace_arch.h>
-+
-+#define NOP_INSTR 0xd503201f
-+#define MOV_INSTR 0xd2800000 /* mov x0, #0x0 - default = false */
-+
-+#define __DTRACE_SDT_ISENABLED_PROTO void
-+#define __DTRACE_SDT_ISENABLED_ARGS
-+
-+#endif /* _ASM_ARM64_DTRACE_SDT_ARCH_H */
-diff --git a/arch/arm64/include/asm/dtrace_syscall.h b/arch/arm64/include/asm/dtrace_syscall.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..402826562478213976f122510d4082af23028fd3
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_syscall.h
-@@ -0,0 +1,3 @@
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-diff --git a/arch/arm64/include/asm/dtrace_syscall_types.h b/arch/arm64/include/asm/dtrace_syscall_types.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..88e6eca6e169fb6b1b82aec04a57adc7ac2bdb6b
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_syscall_types.h
-@@ -0,0 +1,11 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/dtrace_types.h>
-+
-+typedef asmlinkage long (*dt_sys_call_t)(const struct pt_regs *regs);
-+
-+#define DTRACE_SYSCALL_WRAP_PREFIX "__arm64_"
-diff --git a/arch/arm64/include/asm/dtrace_util.h b/arch/arm64/include/asm/dtrace_util.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..003bd34524d6351d1d9ae569c5703b127e9e6814
---- /dev/null
-+++ b/arch/arm64/include/asm/dtrace_util.h
-@@ -0,0 +1,14 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/* Copyright (C) 2019, Oracle and/or its affiliates. All rights reserved. */
-+
-+#ifndef _ASM_ARM64_DTRACE_UTIL_H
-+#define _ASM_ARM64_DTRACE_UTIL_H
-+
-+#include <asm/dtrace_arch.h>
-+
-+extern asm_instr_t dtrace_text_peek(asm_instr_t *addr);
-+extern void dtrace_text_poke(asm_instr_t *addr, asm_instr_t opcode);
-+extern void dtrace_kernel_brk_start(void *arg);
-+extern void dtrace_kernel_brk_stop(void *arg);
-+
-+#endif /* _ASM_ARM64_DTRACE_UTIL_H */
-diff --git a/arch/arm64/include/asm/kdebug.h b/arch/arm64/include/asm/kdebug.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..66c884086d0458ba15ef8f59f0dd50c4b130a52b
---- /dev/null
-+++ b/arch/arm64/include/asm/kdebug.h
-@@ -0,0 +1,11 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+#ifndef _ARM64_KDEBUG_H
-+#define _ARM64_KDEBUG_H
-+
-+/* Grossly misnamed. */
-+enum die_val {
-+ DIE_OOPS = 1,
-+ DIE_PAGE_FAULT,
-+};
-+
-+#endif /* _ARM64_KDEBUG_H */
-diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
-index cfc0672013f672aaf77a18b1c2f3a7a5e692266e..1ab1fc22cb8bde23107e4de85419ece0cb66dc48 100644
---- a/arch/arm64/include/asm/syscall.h
-+++ b/arch/arm64/include/asm/syscall.h
-@@ -11,7 +11,13 @@
-
- typedef long (*syscall_fn_t)(const struct pt_regs *regs);
-
--extern const syscall_fn_t sys_call_table[];
-+#if IS_ENABLED(CONFIG_DT_SYSTRACE)
-+#define CONST_SYS_CALL_TABLE
-+#else
-+#define CONST_SYS_CALL_TABLE const
-+#endif
-+
-+extern CONST_SYS_CALL_TABLE syscall_fn_t sys_call_table[];
-
- #ifdef CONFIG_COMPAT
- extern const syscall_fn_t compat_sys_call_table[];
-diff --git a/arch/arm64/kernel/dtrace_fbt.c b/arch/arm64/kernel/dtrace_fbt.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..3761e8aa4550e163e29373d3ce1d3b4f4802f79d
---- /dev/null
-+++ b/arch/arm64/kernel/dtrace_fbt.c
-@@ -0,0 +1,187 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_fbt.c
-+ * DESCRIPTION: Dynamic Tracing: FBT registration code (arch-specific)
-+ *
-+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/kallsyms.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_fbt.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/slab.h>
-+#include <linux/sort.h>
-+#include <asm/insn.h>
-+#include <asm/sections.h>
-+
-+#define FBT_REG_FP 0x1d /* fp is regiater 29 */
-+#define FBT_REG_LR 0x1e /* lr is regiater 30 */
-+#define FBT_REG_SP 0x1f /* sp is register 31 */
-+#define FBT_MOV_FP_SP 0x910003fd /* "mov x29, sp" */
-+
-+#define BL_SENTRY(tp, nm) extern tp nm;
-+#define BL_DENTRY(tp, nm)
-+#include "fbt_blacklist.h"
-+#undef BL_DENTRY
-+#undef BL_SENTRY
-+
-+static void
-+dtrace_fbt_populate_bl(void)
-+{
-+#define BL_SENTRY(tp, nm) dtrace_fbt_bl_add((unsigned long)&nm, \
-+ __stringify(nm));
-+#define BL_DENTRY(tp, nm) dtrace_fbt_bl_add(0, __stringify(nm));
-+#include "fbt_blacklist.h"
-+#undef BL_SENTRY
-+#undef BL_DENTRY
-+}
-+
-+void dtrace_fbt_init(fbt_add_probe_fn fbt_add_probe, struct module *mp,
-+ void *arg)
-+{
-+ loff_t pos;
-+ struct kallsym_iter sym;
-+ asm_instr_t *paddr = NULL;
-+ struct dt_fbt_bl_entry *blent = NULL;
-+
-+ /*
-+ * Look up any unresolved symbols in the blacklist, and sort the list
-+ * by ascending address.
-+ */
-+ dtrace_fbt_populate_bl();
-+
-+ blent = dtrace_fbt_bl_first();
-+
-+ pos = 0;
-+ kallsyms_iter_reset(&sym, 0);
-+ while (kallsyms_iter_update(&sym, pos++)) {
-+ asm_instr_t *addr, *end;
-+ asm_instr_t instr;
-+ void *fbtp = NULL;
-+
-+ /*
-+ * There is no point considering non-function symbols for FBT,
-+ * or symbols that have a zero size. We could consider weak
-+ * symbols but that gets quite complicated and there is no
-+ * demands for that (so far).
-+ */
-+ if (sym.type != 'T' && sym.type != 't')
-+ continue;
-+ if (!sym.size)
-+ continue;
-+
-+ /*
-+ * The symbol must be at a properly aligned text address.
-+ */
-+ if (!IS_ALIGNED(sym.value, sizeof(asm_instr_t)))
-+ continue;
-+
-+ /*
-+ * Handle only symbols that belong to the module we have been
-+ * asked for.
-+ */
-+ if (mp == dtrace_kmod && !core_kernel_text(sym.value))
-+ continue;
-+
-+ /*
-+ * Ensure we have not been given .init symbol from kallsyms
-+ * interface. This could lead to memory corruption once DTrace
-+ * tries to enable probe in already freed memory.
-+ */
-+ if (mp != dtrace_kmod && !within_module_core(sym.value, mp))
-+ continue;
-+
-+ /*
-+ * See if the symbol is on the FBT's blacklist. Since both
-+ * iterators are workng in sort order by ascending address we
-+ * can use concurrent traversal.
-+ */
-+ while (blent != NULL &&
-+ dtrace_fbt_bl_entry_addr(blent) < sym.value) {
-+ blent = dtrace_fbt_bl_next(blent);
-+ }
-+ if (dtrace_fbt_bl_entry_addr(blent) == sym.value)
-+ continue;
-+
-+ /*
-+ * No FBT tracing for DTrace functions, and functions that are
-+ * crucial to probe processing.
-+ * Also weed out symbols that are not relevant here.
-+ */
-+ if (strncmp(sym.name, "dtrace_", 7) == 0)
-+ continue;
-+ if (strncmp(sym.name, "insn_", 5) == 0)
-+ continue;
-+ if (strncmp(sym.name, "inat_", 5) == 0)
-+ continue;
-+ if (strncmp(sym.name, "_GLOBAL_", 8) == 0)
-+ continue;
-+ if (strncmp(sym.name, "do_", 3) == 0)
-+ continue;
-+ if (strncmp(sym.name, "xen_", 4) == 0)
-+ continue;
-+
-+ addr = (asm_instr_t *)sym.value;
-+ end = (asm_instr_t *)(sym.value + sym.size);
-+
-+ /*
-+ * FIXME:
-+ * When there are multiple symbols for the same address, we
-+ * should link them together as probes associated with the
-+ * same function. When a probe for that function is triggered
-+ * all associated probes should fire.
-+ *
-+ * For now, we ignore duplicates.
-+ */
-+ if (addr == paddr)
-+ continue;
-+ paddr = addr;
-+
-+ instr = le32_to_cpu(*addr);
-+
-+ /*
-+ * We can only instrument functions that begin with a proper
-+ * frame set-up sequence:
-+ * stp x29, x30, [sp,#-80]!
-+ * mov x29, sp
-+ * So, a STP instruction storing the FP (x29) and LR (x30)
-+ * registers as a pair in a location relative to the SP
-+ * register value. And then a MOV instruction that sets the
-+ * FP (x29) register to the current SP value (effectively
-+ * establishing the new stack frame).
-+ *
-+ * We will place our breakpoint on the MOV instruction.
-+ */
-+ if (!aarch64_insn_is_stp_pre(instr) ||
-+ aarch64_insn_decode_register(
-+ AARCH64_INSN_REGTYPE_RN, instr) != FBT_REG_SP ||
-+ aarch64_insn_decode_register(
-+ AARCH64_INSN_REGTYPE_RT, instr) != FBT_REG_FP ||
-+ aarch64_insn_decode_register(
-+ AARCH64_INSN_REGTYPE_RT2, instr) != FBT_REG_LR)
-+ continue;
-+
-+ addr++;
-+ instr = le32_to_cpu(*addr);
-+ if (instr != FBT_MOV_FP_SP)
-+ continue;
-+
-+ fbt_add_probe(mp, sym.name, FBT_ENTRY, instr, addr, 0, NULL,
-+ arg);
-+
-+ while (++addr < end) {
-+ uintptr_t off;
-+
-+ instr = le32_to_cpu(*addr);
-+ if (!aarch64_insn_is_ret(instr))
-+ continue;
-+
-+ off = (uintptr_t)addr - sym.value;
-+ fbtp = fbt_add_probe(mp, sym.name, FBT_RETURN, instr,
-+ addr, off, fbtp, arg);
-+ }
-+ }
-+}
-+EXPORT_SYMBOL(dtrace_fbt_init);
-diff --git a/arch/arm64/kernel/dtrace_sdt.c b/arch/arm64/kernel/dtrace_sdt.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..d5a6a9d398b3b9a36711a2417dc82324db332ed5
---- /dev/null
-+++ b/arch/arm64/kernel/dtrace_sdt.c
-@@ -0,0 +1,25 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_sdt.c
-+ * DESCRIPTION: Dynamic Tracing: SDT registration code (arch-specific)
-+ *
-+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/module.h>
-+#include <asm/insn.h>
-+#include <asm/dtrace_arch.h>
-+#include <asm/dtrace_sdt_arch.h>
-+
-+void __init_or_module dtrace_sdt_nop_multi(asm_instr_t **addrs,
-+ int *is_enabled, int cnt)
-+{
-+ int i;
-+
-+ for (i = 0; i < cnt; i++) {
-+ if (likely(!is_enabled[i]))
-+ aarch64_insn_patch_text_nosync(addrs[i], NOP_INSTR);
-+ else
-+ aarch64_insn_patch_text_nosync(addrs[i], MOV_INSTR);
-+ }
-+}
-diff --git a/arch/arm64/kernel/dtrace_syscall.c b/arch/arm64/kernel/dtrace_syscall.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..73730e42f3b8d1ac9d492a5746beb46c43ccc01f
---- /dev/null
-+++ b/arch/arm64/kernel/dtrace_syscall.c
-@@ -0,0 +1,89 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_syscall.c
-+ * DESCRIPTION: Dynamic Tracing: system call tracing support (arch-specific)
-+ *
-+ * Copyright (C) 2010, 2018 Oracle Corporation
-+ */
-+
-+#include <linux/dtrace_syscall.h>
-+#include <linux/ptrace.h>
-+#include <asm/syscall.h>
-+
-+void (*systrace_probe)(dtrace_id_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t,
-+ uintptr_t, uintptr_t, uintptr_t);
-+
-+void systrace_stub(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
-+ uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
-+ uintptr_t arg5, uintptr_t arg6)
-+{
-+}
-+
-+asmlinkage long systrace_syscall(const struct pt_regs *regs);
-+
-+static struct systrace_info systrace_info = {
-+ &systrace_probe,
-+ systrace_stub,
-+ systrace_syscall,
-+ {},
-+ {
-+#undef __SYSCALL
-+#define __SYSCALL(nr, sym) [nr] { .name = __stringify(sym), },
-+#include <asm/unistd.h>
-+#undef __SYSCALL
-+ }
-+ };
-+
-+
-+asmlinkage long systrace_syscall(const struct pt_regs *regs)
-+{
-+ long rc = 0;
-+ unsigned long sysnum;
-+ dtrace_id_t id;
-+ struct dtrace_syscalls *sc;
-+
-+ sysnum = syscall_get_nr(current, (struct pt_regs *) regs);
-+ sc = &systrace_info.sysent[sysnum];
-+
-+ id = sc->stsy_entry;
-+ /* TODO: arg 6. */
-+ if (id != DTRACE_IDNONE)
-+ (*systrace_probe)(id, regs->regs[0], regs->regs[1],
-+ regs->regs[2], regs->regs[3], regs->regs[4],
-+ regs->regs[5], 0);
-+
-+ /*
-+ * FIXME: Add stop functionality for DTrace.
-+ */
-+
-+ if (sc->stsy_underlying != NULL)
-+ rc = (*sc->stsy_underlying)(regs);
-+
-+ id = sc->stsy_return;
-+ if (id != DTRACE_IDNONE)
-+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
-+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0, 0);
-+
-+ return rc;
-+}
-+
-+struct systrace_info *dtrace_syscalls_init()
-+{
-+ int i;
-+
-+ /*
-+ * Only initialize this stuff once...
-+ */
-+ if (systrace_info.sysent[0].stsy_tblent != NULL)
-+ return &systrace_info;
-+
-+ for (i = 0; i < NR_syscalls; i++) {
-+ systrace_info.sysent[i].stsy_tblent =
-+ (dt_sys_call_t *)&sys_call_table[i];
-+ systrace_info.sysent[i].stsy_underlying =
-+ (dt_sys_call_t)sys_call_table[i];
-+ }
-+
-+ return &systrace_info;
-+}
-+EXPORT_SYMBOL(dtrace_syscalls_init);
-diff --git a/arch/arm64/kernel/dtrace_syscall_stubs.S b/arch/arm64/kernel/dtrace_syscall_stubs.S
-new file mode 100644
-index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
-diff --git a/arch/arm64/kernel/dtrace_util.c b/arch/arm64/kernel/dtrace_util.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..8142cf0459c28781f3b7ad981ac470e4425941fc
---- /dev/null
-+++ b/arch/arm64/kernel/dtrace_util.c
-@@ -0,0 +1,292 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * FILE: dtrace_util.c
-+ * DESCRIPTION: Dynamic Tracing: Architecture utility functions
-+ *
-+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <linux/dtrace_cpu.h>
-+#include <linux/dtrace_os.h>
-+#include <linux/dtrace_task_impl.h>
-+#include <linux/kdebug.h>
-+#include <linux/notifier.h>
-+#include <linux/ptrace.h>
-+#include <linux/uaccess.h>
-+#include <linux/uprobes.h>
-+#include <asm/debug-monitors.h>
-+#include <asm/insn.h>
-+
-+void dtrace_skip_instruction(struct pt_regs *regs)
-+{
-+ instruction_pointer_set(regs, instruction_pointer(regs) + 4);
-+}
-+
-+void dtrace_handle_badaddr(struct pt_regs *regs)
-+{
-+ unsigned long addr = current->thread.fault_address;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = addr;
-+
-+ dtrace_skip_instruction(regs);
-+}
-+
-+int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
-+ void *args)
-+{
-+ struct die_args *dargs = args;
-+
-+ switch (val) {
-+ case DIE_PAGE_FAULT: {
-+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
-+ return NOTIFY_DONE;
-+
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-+ this_cpu_core->cpuc_dtrace_illval = dargs->err;
-+
-+ dtrace_skip_instruction(dargs->regs);
-+
-+ return NOTIFY_OK | NOTIFY_STOP_MASK;
-+ }
-+ case DIE_OOPS: {
-+ pr_info("DTrace: last probe %u\n",
-+ this_cpu_core->cpuc_current_probe);
-+ return NOTIFY_DONE;
-+ }
-+ default:
-+ return NOTIFY_DONE;
-+ }
-+}
-+
-+struct user_stackframe {
-+ struct user_stackframe __user *fp;
-+ unsigned long lr;
-+} __packed;
-+
-+static int dtrace_unwind_frame(struct user_stackframe *frame)
-+{
-+ struct user_stackframe __user *ofp = frame->fp;
-+ unsigned long ret;
-+
-+ /* Verify alignment. */
-+ if ((unsigned long)ofp & 0xf)
-+ return -EINVAL;
-+
-+ /* Verify read access. */
-+ if (!access_ok(ofp, sizeof(struct user_stackframe)))
-+ return -EINVAL;
-+
-+ pagefault_disable();
-+ ret = __copy_from_user_inatomic(frame, ofp,
-+ sizeof(struct user_stackframe));
-+ pagefault_enable();
-+
-+ /* Make sure the read worked. */
-+ if (ret) {
-+ frame->fp = ofp;
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * If the frame pointer in the current frame is NULL, we have reached
-+ * the end of the call chain.
-+ */
-+ if (frame->fp == NULL)
-+ return 0;
-+
-+ /*
-+ * In older glibc versions, the call chain did not end with an initial
-+ * frame with NULL frame pointer. Instead, the initial frame stored
-+ * the beginning of the stack as frame pointer. We look for that here
-+ * as a special case, and return a frame where the frame pointer is
-+ * set to NULL (as it ought to be).
-+ *
-+ * If we do not know the beginning of the stack, we are out of luck.
-+ */
-+ if (current->dt_task && current->dt_task->dt_ustack == frame->fp) {
-+ frame->fp = NULL;
-+ return 0;
-+ }
-+
-+ /*
-+ * Verify strictly increasing consecutive values. Since the stack
-+ * grows downward, walking the call chain in reverse must yield ever
-+ * increasing frame pointers.
-+ */
-+ if (ofp >= frame->fp)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+void dtrace_user_stacktrace(struct stacktrace_state *st)
-+{
-+ struct pt_regs *regs = current_pt_regs();
-+ uint64_t *pcs = st->pcs;
-+ int limit = st->limit;
-+ int fixups, patches, skip;
-+ struct user_stackframe frame0, frame;
-+ struct user_stackframe *bos = current->dt_task
-+ ? current->dt_task->dt_ustack
-+ : NULL;
-+ struct return_instance *rilist = current->utask
-+ ? current->utask->return_instances
-+ : NULL;
-+ struct return_instance *ri;
-+
-+ /*
-+ * If we do not have user-mode registers, or if there is no known
-+ * bottom of stack, we cannot collect a call chain.
-+ */
-+ if (!user_mode(regs))
-+ goto out;
-+ if (!bos)
-+ goto out;
-+ if (!limit)
-+ goto out;
-+
-+ frame0.fp = (struct user_stackframe __user *)regs->regs[29];
-+ frame0.lr = regs->regs[30];
-+
-+ /*
-+ * The first special situation we need to deal with here is the rare
-+ * case of tracing the instruction after a call, when the current
-+ * program counter just got loaded from the link register, i.e. they
-+ * will be the same. In that case, we don't want to record both pc
-+ * and lr in the trace.
-+ *
-+ * Uretprobes are also tricky because if we are asked to provide a
-+ * ustack() while processing a uretprobe firing, we are still in the
-+ * middle of handling the probe. Things are not back to normal yet.
-+ */
-+ if (regs->pc != frame0.lr) {
-+ ri = rilist;
-+ if (pcs) {
-+ if (uprobe_return_addr_is_hijacked(frame0.lr) &&
-+ ri && ri->orig_ret_vaddr == regs->pc)
-+ *pcs++ = ri->func;
-+ else
-+ *pcs++ = regs->pc;
-+ }
-+
-+ limit--;
-+ st->depth++;
-+
-+ if (!limit)
-+ goto out;
-+ }
-+
-+ /*
-+ * First pass: determine how many return addresses need to be fixed up,
-+ * and how many return instances we have.
-+ */
-+ frame = frame0;
-+ fixups = 0;
-+ do {
-+ if (uprobe_return_addr_is_hijacked(frame.lr))
-+ fixups++;
-+
-+ if (frame.fp == NULL)
-+ break;
-+
-+ if (dtrace_unwind_frame(&frame) < 0) {
-+ this_cpu_core->cpuc_dtrace_illval = (uintptr_t)frame.fp;
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADSTACK);
-+ break;
-+ }
-+ } while (frame.lr);
-+
-+ patches = 0;
-+ for (ri = rilist; ri != NULL; ri = ri->next)
-+ patches++;
-+
-+ /*
-+ * It is possible that we think we need one more fixup than we can
-+ * satisfy with the return instances. This is because we cannot quite
-+ * determine whether the first one is actually needed or not (due to
-+ * lack of proper state when the uretprobe implementation interferes
-+ * with frame chain walking).
-+ */
-+ skip = fixups - patches;
-+ if (skip > 1) {
-+ this_cpu_core->cpuc_dtrace_illval = 0;
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADSTACK);
-+ goto out;
-+ }
-+
-+ /*
-+ * Second pass: fill in the actual stack trace.
-+ */
-+ frame = frame0;
-+ ri = rilist;
-+ do {
-+ if (uprobe_return_addr_is_hijacked(frame.lr)) {
-+ if (skip) {
-+ skip = 0;
-+ goto skip_frame;
-+ }
-+
-+ frame.lr = ri->orig_ret_vaddr;
-+ ri = ri->next;
-+ }
-+
-+ if (pcs)
-+ *pcs++ = frame.lr;
-+
-+ limit--;
-+ st->depth++;
-+
-+skip_frame:
-+ if (frame.fp == NULL)
-+ break;
-+
-+ if (dtrace_unwind_frame(&frame) < 0) {
-+ this_cpu_core->cpuc_dtrace_illval = (uintptr_t)frame.fp;
-+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADSTACK);
-+ break;
-+ }
-+ } while (limit);
-+
-+out:
-+ if (pcs) {
-+ while (limit--)
-+ *pcs++ = 0;
-+ }
-+}
-+
-+asm_instr_t dtrace_text_peek(asm_instr_t *addr)
-+{
-+ asm_instr_t opcode;
-+
-+ aarch64_insn_read(addr, &opcode);
-+
-+ return opcode;
-+}
-+EXPORT_SYMBOL(dtrace_text_peek);
-+
-+void dtrace_text_poke(asm_instr_t *addr, asm_instr_t opcode)
-+{
-+ aarch64_insn_patch_text_nosync(addr, opcode);
-+}
-+EXPORT_SYMBOL(dtrace_text_poke);
-+
-+void dtrace_kernel_brk_start(void *arg)
-+{
-+ register_kernel_break_hook((struct break_hook *)arg);
-+}
-+EXPORT_SYMBOL(dtrace_kernel_brk_start);
-+
-+void dtrace_kernel_brk_stop(void *arg)
-+{
-+ unregister_kernel_break_hook((struct break_hook *)arg);
-+}
-+EXPORT_SYMBOL(dtrace_kernel_brk_stop);
-+
-+void dtrace_mod_pdata_init(struct dtrace_module *pdata)
-+{
-+}
-+
-+void dtrace_mod_pdata_cleanup(struct dtrace_module *pdata)
-+{
-+}
-diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
-index 70e0a7591245d6a1cc1ec07c3e13a3d8e10f95e7..b4f8280d9ce322099393bde54afd382f9f412560 100644
---- a/arch/arm64/kernel/entry-common.c
-+++ b/arch/arm64/kernel/entry-common.c
-@@ -199,8 +199,7 @@ static void noinstr el1_fpac(struct pt_regs *regs, unsigned long esr)
- local_daif_mask();
- exit_to_kernel_mode(regs);
- }
--
--asmlinkage void noinstr el1_sync_handler(struct pt_regs *regs)
-+asmlinkage int noinstr el1_sync_handler(struct pt_regs *regs)
- {
- unsigned long esr = read_sysreg(esr_el1);
-
-@@ -225,13 +224,14 @@ asmlinkage void noinstr el1_sync_handler(struct pt_regs *regs)
- case ESR_ELx_EC_WATCHPT_CUR:
- case ESR_ELx_EC_BRK64:
- el1_dbg(regs, esr);
-- break;
-+ return 1;
- case ESR_ELx_EC_FPAC:
- el1_fpac(regs, esr);
- break;
- default:
- el1_inv(regs, esr);
- }
-+ return 0;
- }
-
- asmlinkage void noinstr enter_from_user_mode(void)
-diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
-index d72c818b019ca7530569fd810f356ad426f0cdf1..6ac1846a645e428f5d1ab629ca91b8b471ee36de 100644
---- a/arch/arm64/kernel/entry.S
-+++ b/arch/arm64/kernel/entry.S
-@@ -28,6 +28,7 @@
- #include <asm/thread_info.h>
- #include <asm/asm-uaccess.h>
- #include <asm/unistd.h>
-+#include <asm/debug-monitors.h>
-
- /*
- * Context tracking and irqflag tracing need to instrument transitions between
-@@ -276,7 +277,7 @@ alternative_else_nop_endif
- */
- .endm
-
-- .macro kernel_exit, el
-+ .macro kernel_exit, el, fbt_emu = 0
- .if \el != 0
- disable_daif
-
-@@ -332,7 +333,11 @@ alternative_else_nop_endif
-
- msr elr_el1, x21 // set up the return data
- msr spsr_el1, x22
-- ldp x0, x1, [sp, #16 * 0]
-+
-+ /*
-+ * No need to restore x0 and x1 - we may still clobber them. We will
-+ * restore them right before we return.
-+ */
- ldp x2, x3, [sp, #16 * 1]
- ldp x4, x5, [sp, #16 * 2]
- ldp x6, x7, [sp, #16 * 3]
-@@ -348,7 +353,44 @@ alternative_else_nop_endif
- ldp x26, x27, [sp, #16 * 13]
- ldp x28, x29, [sp, #16 * 14]
- ldr lr, [sp, #S_LR]
-+
-+ .if \fbt_emu != 0 // FBT emulation needed?
-+ mrs x0, esr_el1 // check if ESR is FBT probe
-+ and x0, x0, #0x1f // ... mask code
-+ cmp x0, #DPROBES_FBE_BRK_IMM // ... compare with FBE code
-+ beq 6f // FBT entry -> emulate instr.
-+ cmp x0, #DPROBES_FBR_BRK_IMM // ... compare with FBR code
-+ beq 7f // FBT return -> emulate instr.
-+ b 8f // not FBT -> skip next section
-+
-+6:
-+ mrs x0, elr_el1 // retrieve xeceptionx link reg
-+ add x0, x0, #0x4 // advance to next instr
-+ msr elr_el1, x0 // set exception link reg
-+
-+ ldp x0, x1, [sp, #16 * 0] // done with x0, restore orig
- add sp, sp, #S_FRAME_SIZE // restore sp
-+ mov x29, sp // instr we put probe on
-+ b 9f // FBT done -> branch to eret
-+
-+7:
-+ msr elr_el1, lr // set exception link reg to
-+ // link register value, to
-+ // simulate the 'ret' instr.
-+
-+ ldp x0, x1, [sp, #16 * 0] // done with x0, restore orig
-+ add sp, sp, #S_FRAME_SIZE // restore sp
-+ b 9f // FBT done -> branch to eret
-+
-+8:
-+ ldp x0, x1, [sp, #16 * 0] // done with x0, restore orig
-+ add sp, sp, #S_FRAME_SIZE // restore sp
-+9:
-+ .else
-+ ldp x0, x1, [sp, #16 * 0] // done with x0, restore orig
-+ add sp, sp, #S_FRAME_SIZE // restore sp
-+
-+ .endif
-
- .if \el == 0
- alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
-@@ -625,7 +667,12 @@ SYM_CODE_START_LOCAL_NOALIGN(el1_sync)
- kernel_entry 1
- mov x0, sp
- bl el1_sync_handler
-- kernel_exit 1
-+#if IS_ENABLED(CONFIG_DT_FBT)
-+ cmp x0, 1
-+ b.ne 1020f
-+ kernel_exit 1, 1
-+#endif
-+1020: kernel_exit 1
- SYM_CODE_END(el1_sync)
-
- .align 6
-diff --git a/arch/arm64/kernel/fbt_blacklist.h b/arch/arm64/kernel/fbt_blacklist.h
-new file mode 100644
-index 0000000000000000000000000000000000000000..7ad327515c8f9e2b35097f44fa4d1f0bcf76aaa2
---- /dev/null
-+++ b/arch/arm64/kernel/fbt_blacklist.h
-@@ -0,0 +1,91 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Functions used in die notifier chain calling.
-+ */
-+BL_SENTRY(void *, notify_die)
-+BL_DENTRY(void *, notifier_call_chain)
-+BL_SENTRY(typeof(atomic_notifier_call_chain_robust), atomic_notifier_call_chain_robust)
-+BL_SENTRY(typeof(atomic_notifier_call_chain), atomic_notifier_call_chain)
-+BL_SENTRY(typeof(raw_notifier_call_chain_robust), raw_notifier_call_chain_robust)
-+BL_SENTRY(typeof(raw_notifier_call_chain), raw_notifier_call_chain)
-+BL_DENTRY(void *, hw_breakpoint_exceptions_notify)
-+BL_DENTRY(void *, kprobe_exceptions_notify)
-+
-+/*
-+ * Functions used to update vtime in probe context.
-+ */
-+BL_SENTRY(typeof(ktime_get_raw_fast_ns), ktime_get_raw_fast_ns)
-+BL_DENTRY(void *, raw_read_seqcount)
-+BL_DENTRY(void *, read_seqcount_retry)
-+BL_DENTRY(void *, __read_seqcount_retry)
-+
-+/* xen_clocksource */
-+BL_DENTRY(void *, xen_clocksource_get_cycles)
-+BL_DENTRY(void *, xen_clocksource_read)
-+BL_DENTRY(void *, pvclock_clocksource_read)
-+BL_DENTRY(void *, pvclock_touch_watchdogs)
-+BL_DENTRY(void *, touch_softlockup_watchdog_sync)
-+BL_DENTRY(void *, clocksource_touch_watchdog)
-+BL_DENTRY(void *, clocksource_resume_watchdog)
-+BL_DENTRY(void *, reset_hung_task_detector)
-+/* clocksource_tsc */
-+BL_DENTRY(void *, read_tsc)
-+BL_DENTRY(void *, get_cycles)
-+/* clocksource_hpet */
-+BL_DENTRY(void *, read_hpet)
-+BL_DENTRY(void *, hpet_readl)
-+/* kvm_clock */
-+BL_DENTRY(void *, kvm_clock_get_cycles)
-+BL_DENTRY(void *, kvm_clock_read)
-+/* arm_arch */
-+BL_DENTRY(void *, arch_counter_get_cntvct);
-+BL_DENTRY(void *, arch_counter_get_cntvct_mem);
-+BL_DENTRY(void *, arch_counter_get_cntpct);
-+BL_DENTRY(void *, arch_counter_read);
-+
-+/*
-+ * Functions used in trap handling.
-+ */
-+BL_DENTRY(void *, fixup_exception)
-+BL_DENTRY(void *, paranoid_entry)
-+BL_DENTRY(void *, kgdb_ll_trap)
-+BL_DENTRY(void *, error_entry)
-+BL_DENTRY(void *, xen_int3)
-+BL_DENTRY(void *, ftrace_int3_handler)
-+BL_DENTRY(typeof(poke_int3_handler), poke_int3_handler)
-+BL_DENTRY(void *, fixup_bad_iret)
-+BL_DENTRY(void *, xen_adjust_exception_frame)
-+BL_DENTRY(void *, paravirt_nop)
-+BL_DENTRY(void *, ist_enter)
-+BL_DENTRY(void *, rcu_nmi_enter)
-+BL_DENTRY(void *, rcu_dynticks_curr_cpu_in_eqs)
-+BL_DENTRY(void *, rcu_dynticks_eqs_exit)
-+BL_DENTRY(void *, rcu_nmi_exit)
-+BL_DENTRY(void *, rcu_dynticks_eqs_enter)
-+BL_DENTRY(void *, ist_exit)
-+
-+/*
-+ * Functions used in page fault handling.
-+ */
-+BL_DENTRY(void *, do_page_fault)
-+BL_DENTRY(void *, __do_page_fault)
-+BL_DENTRY(void *, down_read_trylock)
-+BL_DENTRY(void *, __get_user_pages_fast)
-+BL_DENTRY(void *, gup_pud_range)
-+BL_DENTRY(void *, gup_huge_pud)
-+BL_DENTRY(void *, gup_pmd_range)
-+BL_DENTRY(void *, gup_huge_pmd)
-+BL_DENTRY(void *, gup_pte_range)
-+BL_DENTRY(void *, pte_mfn_to_pfn)
-+
-+/*
-+ * Functions used under 4.19 idr_find
-+ */
-+BL_DENTRY(void *, idr_find)
-+BL_DENTRY(void *, find_next_bit)
-+BL_DENTRY(void *, _find_next_bit)
-+BL_DENTRY(void *, radix_tree_lookup)
-+BL_DENTRY(void *, __radix_tree_lookup)
-+BL_DENTRY(void *, radix_tree_load_root)
-+BL_DENTRY(void *, radix_tree_descend)
-+BL_DENTRY(void *, is_sibling_entry)
-diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
-index a412d8edbcd24428150a16e93ae059d45817b355..49482af77b9f2d698cffc8c1cd8a64c128aa271a 100644
---- a/arch/arm64/kernel/probes/uprobes.c
-+++ b/arch/arm64/kernel/probes/uprobes.c
-@@ -179,7 +179,8 @@ static int uprobe_single_step_handler(struct pt_regs *regs,
- {
- struct uprobe_task *utask = current->utask;
-
-- WARN_ON(utask && (instruction_pointer(regs) != utask->xol_vaddr + 4));
-+ WARN_ON(utask && utask->active_uprobe &&
-+ (instruction_pointer(regs) != utask->xol_vaddr + 4));
- if (uprobe_post_sstep_notifier(regs))
- return DBG_HOOK_HANDLED;
-
-diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c
-index d5ffaaab31a7d1ed433e8e7bf01ae1f52848cd22..4563f0a4d0db806c52c29c80ff7eb47f75d35b04 100644
---- a/arch/arm64/kernel/sys.c
-+++ b/arch/arm64/kernel/sys.c
-@@ -55,7 +55,7 @@ asmlinkage long __arm64_sys_ni_syscall(const struct pt_regs *__unused)
- #undef __SYSCALL
- #define __SYSCALL(nr, sym) [nr] = __arm64_##sym,
-
--const syscall_fn_t sys_call_table[__NR_syscalls] = {
-+CONST_SYS_CALL_TABLE syscall_fn_t sys_call_table[__NR_syscalls] = {
- [0 ... __NR_syscalls - 1] = __arm64_sys_ni_syscall,
- #include <asm/unistd.h>
- };
-diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
-index 795d224f184ff2ce63d8427f5e70d4a9a89fd4ef..d2725a8ac9f321e4f551b907e6cacbbddc88bcd3 100644
---- a/arch/arm64/mm/fault.c
-+++ b/arch/arm64/mm/fault.c
-@@ -14,6 +14,7 @@
- #include <linux/mm.h>
- #include <linux/hardirq.h>
- #include <linux/init.h>
-+#include <linux/kdebug.h>
- #include <linux/kprobes.h>
- #include <linux/uaccess.h>
- #include <linux/page-flags.h>
-@@ -60,6 +61,19 @@ static inline const struct fault_info *esr_to_debug_fault_info(unsigned int esr)
- return debug_fault_info + DBG_ESR_EVT(esr);
- }
-
-+#ifdef CONFIG_DTRACE
-+static int dtrace_fault(struct pt_regs *regs, unsigned long addr)
-+{
-+ preempt_disable();
-+ if (notify_die(DIE_PAGE_FAULT, "page fault", regs, addr, 14,
-+ SIGKILL) == NOTIFY_STOP)
-+ return 1;
-+ preempt_enable();
-+
-+ return 0;
-+}
-+#endif
-+
- static void data_abort_decode(unsigned int esr)
- {
- pr_alert("Data abort info:\n");
-@@ -459,6 +473,10 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
-
- if (kprobe_page_fault(regs, esr))
- return 0;
-+#ifdef CONFIG_DTRACE
-+ if (dtrace_fault(regs, addr))
-+ return 0;
-+#endif
-
- /*
- * If we're in an interrupt or have no user context, we must not take
-diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
-index f46e0ca0169c722b4d5b749b2c1b0b04ab79c380..b278859820665f0fbe0509e27582fd1de41332e1 100644
---- a/include/linux/uprobes.h
-+++ b/include/linux/uprobes.h
-@@ -124,6 +124,7 @@ extern void uprobe_copy_process(struct task_struct *t, unsigned long flags);
- extern int uprobe_post_sstep_notifier(struct pt_regs *regs);
- extern int uprobe_pre_sstep_notifier(struct pt_regs *regs);
- extern void uprobe_notify_resume(struct pt_regs *regs);
-+extern bool uprobe_return_addr_is_hijacked(unsigned long addr);
- extern bool uprobe_deny_signal(void);
- extern bool arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs);
- extern void uprobe_clear_state(struct mm_struct *mm);
-diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
-index 00b0358739ab3b6b66b780e20f3374bbef4d4d34..5a7a1c0198708f54175fe6de9d3fb12d0146a3c7 100644
---- a/kernel/events/uprobes.c
-+++ b/kernel/events/uprobes.c
-@@ -1845,6 +1845,16 @@ static unsigned long get_trampoline_vaddr(void)
- return trampoline_vaddr;
- }
-
-+/*
-+ * Verify whether a return address is a trampoline address or a regular return
-+ * address. This is used by stack unwinders to determine whether a return
-+ * address in a stack trace needs to be adjusted.
-+ */
-+bool uprobe_return_addr_is_hijacked(unsigned long addr)
-+{
-+ return addr == get_trampoline_vaddr();
-+}
-+
- static void cleanup_return_instances(struct uprobe_task *utask, bool chained,
- struct pt_regs *regs)
- {
-diff --git a/scripts/dtrace_sdt_arm64.sh b/scripts/dtrace_sdt_arm64.sh
-new file mode 100755
-index 0000000000000000000000000000000000000000..a8fdc4ae0bc440e2ad9ad3a09f804a2ea9fd21c6
---- /dev/null
-+++ b/scripts/dtrace_sdt_arm64.sh
-@@ -0,0 +1,425 @@
-+#!/bin/sh
-+
-+LANG=C
-+export LANG
-+
-+#
-+# Syntax:
-+# dtrace_sdt_arm64.sh sdtinfo <S-file> <l-file> <o-file>
-+# This is used to generate DTrace SDT probe definitions for a
-+# linked kernel image file <l-file>, based on relocation info
-+# from the kernel object file <o-file>. The output is written
-+# to <S-file>.
-+#
-+
-+opr="$1"
-+shift
-+if [ -z "$opr" ]; then
-+ echo "ERROR: Missing operation" > /dev/stderr
-+ exit 1
-+elif [ "$opr" != "sdtinfo" ]; then
-+ echo "ERROR: Invalid operation: ${opr}" > /dev/stderr
-+ exit 1
-+fi
-+
-+tfn="$1"
-+shift
-+if [ -z "$tfn" ]; then
-+ echo "ERROR: Missing target filename" > /dev/stderr
-+ exit 1
-+fi
-+
-+lfn="$1"
-+ofn="$2"
-+
-+if [ -z "$lfn" ]; then
-+ echo "ERROR: Missing linked kernel file argument" > /dev/stderr
-+ exit 1
-+elif [ -z "$ofn" ]; then
-+ echo "ERROR: Missing kernel object file argument" > /dev/stderr
-+ exit 1
-+fi
-+
-+# For arm64, the kernel is built using "-ffunction-sections -fdata-sections"
-+# which due to the linked bug conflicts with "--emit-relocs". Probe discovery
-+# therefore is a bit more complicated.
-+#
-+# First we collect the VMA address of all the code sections in the linked
-+# kernel image.
-+#
-+# Subsequently, we go through the list of symbols in the linked kernel image,
-+# and write out records for some select symbols that are used in the processing
-+# of probe locations:
-+#
-+# <section> <address> B <name>
-+# Named identifier at a specific address (global variable).
-+#
-+# We also process any function symbols, and build a lookup map for section-name
-+# pairs and just name. Due to the possibility of having symbols with identical
-+# names (in the same section, e.g. global and/or one or more local), we append
-+# -<n> to every 2nd and later copy of the same symbol name in the current
-+# section.
-+# section and name
-+# name
-+# (If multiple symbols map to any of the above combinations, that specific
-+# combination is omitted from the mapping.)
-+#
-+# Next, we process the list of function symbols, and for any function that
-+# is not located in a section that starts with .exit.text, .init.text, or
-+# .meminit.text) we determine its in-section offset and output a record:
-+#
-+# <section> <offset> F <name> <address> <section-base-address>
-+# Named function at a specific address.
-+#
-+# Finally, each relocation record from a non-init or exit section that relates
-+# to SDT probes is written to the output stream:
-+#
-+# <section> <address> R <value>
-+# Relocation within a section at a specific address
-+#
-+# Probes are identified in the relocation records as symbols with either a
-+# __dtrace_probe_ or __dtrace_isenabled_ prefix.
-+#
-+# All these records are sorted by section and offset, and any SDT probe
-+# location relocation records (R) result in writing out an entry that records
-+# its offset relative to the _stext symbol, along with the name of the function
-+# it was found in, and the probe name.
-+
-+(
-+ objdump -ht ${lfn}
-+ objdump -tr ${ofn}
-+) | \
-+ gawk 'function subl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ if (v0l >= v1l) {
-+ if (v0h >= v1h) {
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "ERROR: [stage 1.a] Invalid addresses: %s - %s\n", v0, v1;
-+ d = 0;
-+ errc++;
-+ }
-+ } else {
-+ if (v0h > v1h) {
-+ v0h--;
-+ v0l += 4294967296;
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "ERROR: [stage 1.b] Invalid addresses: %s - %s\n", v0, v1;
-+ d = 0;
-+ errc++;
-+ }
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 - v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ BEGIN {
-+ phase = 0;
-+ }
-+
-+ /^SYMBOL / {
-+ phase++;
-+ delete scnt;
-+ next;
-+ }
-+
-+ phase == 0 && /^ *[1-9][0-9]* / {
-+ snam = $2;
-+ addr = $4;
-+ getline;
-+ if (/CODE/)
-+ secs[snam] = addr;
-+
-+ next;
-+ }
-+
-+ phase == 1 && $NF ~ /_(stext|_init_(begin|end))$/ {
-+ print ". " $1 " B " $NF;
-+ next;
-+ }
-+
-+ phase == 1 && / F / {
-+ if ($4 ~ /^\.(exit|init|meminit)\.text/)
-+ next;
-+
-+ off = subl($1, secs[$4]);
-+
-+ sym = $NF;
-+ scnt[sym]++;
-+ if (scnt[sym] > 1)
-+ sym = sym"-"(scnt[sym] - 1);
-+
-+ # section and name
-+ id = $4 " " sym;
-+ if (id in smap) {
-+ if (smap[id] != $1)
-+ smap[id] = 0;
-+ } else
-+ smap[id] = $1;
-+
-+ # name
-+ id = sym;
-+ if (id in smap) {
-+ if (smap[id] != $1)
-+ smap[id] = 0;
-+ } else
-+ smap[id] = $1;
-+
-+ next;
-+ }
-+
-+ phase == 2 && / F / {
-+ if ($4 ~ /^\.(exit|init|meminit)\.text/)
-+ next;
-+
-+ sym = $NF;
-+ scnt[sym]++;
-+ if (scnt[sym] > 1)
-+ sym = sym"-"(scnt[sym] - 1);
-+
-+ # section and name
-+ id = $4 " " sym;
-+ if (!(id in smap))
-+ id = sym;
-+ # name
-+ if (id in smap) {
-+ addr = smap[id];
-+ if (!addr)
-+ print "ERROR: Non-unique symbol: " $4 " " $6 " " $1 " ["sym"]";
-+ } else {
-+ print "ERROR: Could not find " $4 " " $6 " " $1 " ["sym"]";
-+ addr = 0;
-+ }
-+
-+ print $4 " " $1 " F " $6 " " addr " " secs[$4];
-+ next;
-+ }
-+
-+ /^RELOC/ {
-+ sect = substr($4, 2, length($4) - 3);
-+ next;
-+ }
-+
-+ sect ~ /^\.(exit|init|meminit)\.text/ {
-+ next;
-+ }
-+
-+ sect && /__dtrace_probe_/ {
-+ $3 = substr($3, 16);
-+ sub(/[\-+].*$/, "", $3);
-+ print sect " " $1 " R " $3;
-+ next;
-+ }
-+
-+ sect && /__dtrace_isenabled_/ {
-+ $3 = substr($3, 20);
-+ sub(/[\-+].*$/, "", $3);
-+ print sect " " $1 " R ?" $3;
-+ next;
-+ }' | \
-+ sort -u | \
-+ gawk 'function addl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8 || length(v1) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ v0l += v1l;
-+ v0h += v1h;
-+ d = sprintf("%x", v0l);
-+ if (length(d) > 8) {
-+ v0h++;
-+ v0l -= 4294967296;
-+ }
-+ d = sprintf("%x", v0h);
-+ if (length(d) <= 8) {
-+ d = sprintf("%08x%08x", v0h, v0l);
-+ } else {
-+ printf "#error [stage 2.a] Invalid addresses: %s + %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 + v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ function subl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
-+ tmp = $0;
-+ if (length(v0) > 8) {
-+ d = length(v0);
-+ v0h = strtonum("0x"substr(v0, 1, d - 8));
-+ v0l = strtonum("0x"substr(v0, d - 8 + 1));
-+ d = length(v1);
-+ v1h = strtonum("0x"substr(v1, 1, d - 8));
-+ v1l = strtonum("0x"substr(v1, d - 8 + 1));
-+
-+ if (v0l >= v1l) {
-+ if (v0h >= v1h) {
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error [stage 2.b] Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ } else {
-+ if (v0h > v1h) {
-+ v0h--;
-+ v0l += 4294967296;
-+ d = sprintf("%08x%08x", v0h - v1h, v0l - v1l);
-+ } else {
-+ printf "#error [stage 2.c] Invalid addresses: %s - %s\n", v0, v1 \
-+ >"/dev/stderr";
-+ errc++;
-+ }
-+ }
-+ } else {
-+ v0 = strtonum("0x"v0);
-+ v1 = strtonum("0x"v1);
-+ d = sprintf("%016x", v0 - v1);
-+ }
-+ $0 = tmp;
-+
-+ return d;
-+ }
-+
-+ function map_string(str, off) {
-+ if (str in strmap)
-+ off = strmap[str];
-+ else {
-+ off = strsz;
-+ strmap[str] = strsz;
-+ strv[strc++] = str;
-+ strsz += length(str) + 1;
-+ }
-+
-+ return off;
-+ }
-+
-+ BEGIN {
-+ print "#include <asm/types.h>";
-+ print "#if BITS_PER_LONG == 64";
-+ print "# define PTR .quad";
-+ if (arch == "aarch64")
-+ print "# define ALGN .align 3";
-+ else
-+ print "# define ALGN .align 8";
-+ print "#else";
-+ print "# define PTR .long";
-+ if (arch == "aarch64")
-+ print "# define ALGN .align 2";
-+ else
-+ print "# define ALGN .align 4";
-+ print "#endif";
-+
-+ print "\t.section .rodata, \042a\042";
-+ print "";
-+
-+ print ".globl dtrace_sdt_probes";
-+ print "\tALGN";
-+ print "dtrace_sdt_probes:";
-+
-+ probec = 0;
-+ stroff = 0;
-+ strc = 0;
-+ }
-+
-+ $1 == "ERROR:" {
-+ next;
-+ }
-+
-+ $4 == "_stext" {
-+ stext = $2;
-+ next;
-+ }
-+
-+ $4 == "__init_begin" {
-+ init_beg = $2;
-+ next;
-+ }
-+
-+ $4 == "__init_end" {
-+ init_end = $2;
-+ next;
-+ }
-+
-+ $3 == "F" {
-+ fnam = $4;
-+ sub(/\..*$/, "", fnam);
-+ foff = $2;
-+ fadr = $5;
-+
-+ if (fadr != padr)
-+ funcc++;
-+ padr = fadr;
-+
-+ next;
-+ }
-+
-+ $3 == "R" {
-+ addr = addl(fadr, subl($2, foff));
-+ if (addr >= init_beg && addr <= init_end)
-+ next;
-+ addr = subl(addr, stext);
-+
-+ print "/*";
-+ print " * " $1 " " foff " F " fnam " " fadr;
-+ print " * " $0;
-+ print " * (" fadr " + (" $2 " - " foff ")) - " stext;
-+ print " */";
-+ printf "\tPTR\t_stext + 0x%s\n", addr;
-+ printf "\tPTR\t%d\n", map_string($4);
-+ printf "\tPTR\t%d\n", map_string(fnam);
-+
-+ probec++;
-+
-+ next;
-+ }
-+
-+ END {
-+ print "";
-+ print ".globl dtrace_sdt_strings";
-+ print "\tALGN";
-+ print "dtrace_sdt_strings:";
-+
-+
-+ for (i = 0; i < strc; i++)
-+ printf "\t.asciz\t\042%s\042\n", strv[i];
-+
-+ print "";
-+ print ".globl dtrace_sdt_nprobes";
-+ print ".globl dtrace_fbt_nfuncs";
-+ print "\tALGN";
-+ print "dtrace_sdt_nprobes:";
-+ printf "\tPTR\t%d\n", probec;
-+ print "dtrace_fbt_nfuncs:";
-+ printf "\tPTR\t%d\n", funcc;
-+
-+ exit(errc == 0 ? 0 : 1);
-+ }' > ${tfn}
-+
-+exit $?
-diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
-index 0b2f3bb60936f81449de21f296bdaddd466c9569..aa4c70504d8c36a523d11a668c7e0c9cb5b36458 100755
---- a/scripts/link-vmlinux.sh
-+++ b/scripts/link-vmlinux.sh
-@@ -63,7 +63,12 @@ sdtinfo()
- {
- info SDTINF ${2}
-
-- ${srctree}/scripts/dtrace_sdt.sh sdtinfo .tmp_sdtinfo.S ${1}
-+ if [ -n "${CONFIG_ARM64}" ]; then
-+ ${srctree}/scripts/dtrace_sdt_arm64.sh sdtinfo .tmp_sdtinfo.S \
-+ ${1} ${3}
-+ else
-+ ${srctree}/scripts/dtrace_sdt.sh sdtinfo .tmp_sdtinfo.S ${1}
-+ fi
-
- local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
- ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
-@@ -389,16 +394,14 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
-
- # step 1
- if [ -n "${CONFIG_DTRACE}" ]; then
-- sdtinfo vmlinux.o ${sdtinfoo}
-+ sdtinfo vmlinux.o ${sdtinfoo} vmlinux.o
- fi
-
- kallsyms_step 1
-
- if [ -n "${CONFIG_DTRACE}" ]; then
-- if [ -n "${CONFIG_ARM64}" ]; then
-- kallsyms_step 1
-- else
-- kallsyms_step 1 -r
-+ if [ -n "${CONFIG_X86_64}" ]; then
-+ kallsyms_step 1 --emit-relocs
- fi
- sdtinfo ${kallsyms_vmlinux} ${sdtinfoo} vmlinux.o
- fi
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0017-dtrace-add-SDT-probes.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0017-dtrace-add-SDT-probes.patch
deleted file mode 100644
index cbb268285643..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0017-dtrace-add-SDT-probes.patch
+++ /dev/null
@@ -1,3307 +0,0 @@
-From 5694e5386d32e8fe708a76177b44244d18bd8f7b Mon Sep 17 00:00:00 2001
-From: Kris Van Hees <kris.van.hees@oracle.com>
-Date: Thu, 8 Nov 2018 18:59:39 +0000
-Subject: [PATCH 17/19] dtrace: add SDT probes
-
-This adds a variety of SDT probes.
-
-XXX add documentation here from the commit messages
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
-Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
-Signed-off-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
-Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
-Signed-off-by: David Mc Lean <david.mclean@oracle.com>
-Signed-off-by: Vincent Lim <vincent.lim@oracle.com>
----
- block/bio.c | 7 ++
- block/blk-core.c | 4 +
- fs/exec.c | 8 ++
- fs/nfs/internal.h | 13 +++
- fs/nfs/read.c | 3 +
- fs/nfs/write.c | 2 +
- fs/xfs/xfs_buf.c | 19 ++++
- include/linux/rwlock_api_smp.h | 38 +++++++
- include/linux/spinlock_api_smp.h | 12 ++
- kernel/exit.c | 5 +
- kernel/fork.c | 3 +
- kernel/locking/mutex.c | 52 ++++++++-
- kernel/locking/qrwlock.c | 24 +++-
- kernel/locking/qspinlock.c | 20 +++-
- kernel/sched/core.c | 31 +++++-
- kernel/signal.c | 31 +++++-
- kernel/time/timer.c | 3 +
- net/ipv4/ip_input.c | 66 +++++++++--
- net/ipv4/ip_output.c | 71 +++++++++++-
- net/ipv4/raw.c | 49 ++++++--
- net/ipv4/tcp.c | 26 +++++
- net/ipv4/tcp_input.c | 43 +++++++
- net/ipv4/tcp_ipv4.c | 114 ++++++++++++++++++-
- net/ipv4/tcp_minisocks.c | 15 +++
- net/ipv4/tcp_output.c | 29 +++++
- net/ipv4/udp.c | 26 ++++-
- net/ipv6/ip6_input.c | 103 ++++++++++++++---
- net/ipv6/ip6_output.c | 186 ++++++++++++++++++++++++++-----
- net/ipv6/mcast.c | 72 +++++++++---
- net/ipv6/ndisc.c | 9 ++
- net/ipv6/output_core.c | 9 ++
- net/ipv6/raw.c | 38 ++++++-
- net/ipv6/tcp_ipv6.c | 107 +++++++++++++++++-
- net/ipv6/udp.c | 26 ++++-
- 34 files changed, 1153 insertions(+), 111 deletions(-)
-
-diff --git a/block/bio.c b/block/bio.c
-index fa01bef35bb1fe77b26d797cfdb76e7e04082ac3..f2cde8dc402cab42db908b29b2ebf775bc19c85e 100644
---- a/block/bio.c
-+++ b/block/bio.c
-@@ -1153,6 +1153,8 @@ int submit_bio_wait(struct bio *bio)
- bio->bi_opf |= REQ_SYNC;
- submit_bio(bio);
-
-+ DTRACE_IO(wait__start, struct bio * : (bufinfo_t *, devinfo_t *), bio,
-+ struct file * : fileinfo_t *, NULL);
- /* Prevent hang_check timer from firing at us during very long I/O */
- hang_check = sysctl_hung_task_timeout_secs;
- if (hang_check)
-@@ -1161,6 +1163,8 @@ int submit_bio_wait(struct bio *bio)
- ;
- else
- wait_for_completion_io(&done);
-+ DTRACE_IO(wait__done, struct bio * : (bufinfo_t *, devinfo_t *), bio,
-+ struct file * : fileinfo_t *, NULL);
-
- return blk_status_to_errno(bio->bi_status);
- }
-@@ -1444,6 +1448,9 @@ void bio_endio(struct bio *bio)
- }
-
- blk_throtl_bio_endio(bio);
-+ DTRACE_IO(done, struct bio * :
-+ (bufinfo_t *, devinfo_t *), bio,
-+ struct file * : fileinfo_t *, NULL);
- /* release cgroup info */
- bio_uninit(bio);
- if (bio->bi_end_io)
-diff --git a/block/blk-core.c b/block/blk-core.c
-index 2d53e2ff48ff889889d978665eccf365d5feea8a..67523a6729fb00fe6fb401c0d31f34410fbb5e55 100644
---- a/block/blk-core.c
-+++ b/block/blk-core.c
-@@ -913,11 +913,15 @@ static noinline_for_stack bool submit_bio_checks(struct bio *bio)
- */
- bio_set_flag(bio, BIO_TRACE_COMPLETION);
- }
-+ DTRACE_IO(start, struct bio * : (bufinfo_t *, devinfo_t *), bio,
-+ struct file * : fileinfo_t *, NULL);
- return true;
-
- not_supported:
- status = BLK_STS_NOTSUPP;
- end_io:
-+ DTRACE_IO(start, struct bio * : (bufinfo_t *, devinfo_t *), bio,
-+ struct file * : fileinfo_t *, NULL);
- bio->bi_status = status;
- bio_endio(bio);
- return false;
-diff --git a/fs/exec.c b/fs/exec.c
-index 4340b28030047552a40dfa962e08d994d3f33278..acd96c0e0e5f9506f9954802dd3ecd9d5f0b2568 100644
---- a/fs/exec.c
-+++ b/fs/exec.c
-@@ -64,6 +64,7 @@
- #include <linux/compat.h>
- #include <linux/vmalloc.h>
- #include <linux/io_uring.h>
- #include <linux/random.h>
-+#include <linux/sdt.h>
- #include <linux/dtrace_os.h>
-
- #include <linux/uaccess.h>
-@@ -1797,6 +1798,7 @@ static int bprm_execve(struct linux_binprm *bprm,
- current->in_execve = 1;
-
- file = do_open_execat(fd, filename, flags);
-+ DTRACE_PROC(exec, char *, filename->name);
- retval = PTR_ERR(file);
- if (IS_ERR(file))
- goto out_unmark;
-@@ -1834,6 +1836,8 @@ static int bprm_execve(struct linux_binprm *bprm,
- task_numa_free(current, false);
- if (displaced)
- put_files_struct(displaced);
-+
-+ DTRACE_PROC(exec__success);
- return retval;
-
- out:
-@@ -1923,6 +1927,8 @@ static int do_execveat_common(int fd, struct filename *filename,
-
- out_ret:
- putname(filename);
-+ if (retval < 0)
-+ DTRACE_PROC(exec__failure, int, retval);
- return retval;
- }
-
-@@ -1976,6 +1982,8 @@ int kernel_execve(const char *kernel_filename,
- free_bprm(bprm);
- out_ret:
- putname(filename);
-+ if (retval < 0)
-+ DTRACE_PROC(exec__failure, int, retval);
- return retval;
- }
-
-diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
-index 98554dd18a7157619c2b5f85c751b4dd88c7311a..1e13fb97d642d3978fb2ae68e9caa5072ec3008c 100644
---- a/fs/nfs/internal.h
-+++ b/fs/nfs/internal.h
-@@ -10,6 +10,7 @@
- #include <linux/sunrpc/addr.h>
- #include <linux/nfs_page.h>
- #include <linux/wait_bit.h>
-+#include <linux/sdt.h>
-
- #define NFS_SB_MASK (SB_RDONLY|SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS)
-
-@@ -832,3 +833,15 @@ static inline void nfs_set_port(struct sockaddr *sap, int *port,
-
- rpc_set_port(sap, *port);
- }
-+
-+#define DTRACE_IO_NFS(name, rw, size, inode) \
-+ if (DTRACE_IO_ENABLED(name)) { \
-+ struct bio bio __maybe_unused = { \
-+ .bi_opf = rw, \
-+ .bi_iter.bi_size = size, \
-+ .bi_iter.bi_sector = NFS_FILEID(inode), \
-+ }; \
-+ DTRACE_IO(name, struct bio * : (bufinfo_t *, \
-+ devinfo_t *), &bio, \
-+ struct file * : fileinfo_t *, NULL); \
-+}
-diff --git a/fs/nfs/read.c b/fs/nfs/read.c
-index eb854f1f86e2eb10cd3ecf2a9b4559761f5027dc..7049b4540f94059b73b79941629ac1b04f53f8c3 100644
---- a/fs/nfs/read.c
-+++ b/fs/nfs/read.c
-@@ -212,6 +212,8 @@ static void nfs_initiate_read(struct nfs_pgio_header *hdr,
- struct inode *inode = hdr->inode;
- int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0;
-
-+ DTRACE_IO_NFS(start, REQ_OP_READ, hdr->args.count, hdr->inode);
-+
- task_setup_data->flags |= swap_flags;
- rpc_ops->read_setup(hdr, msg);
- trace_nfs_initiate_read(hdr);
-@@ -243,6 +245,7 @@ static int nfs_readpage_done(struct rpc_task *task,
- struct inode *inode)
- {
- int status = NFS_PROTO(inode)->read_done(task, hdr);
-+ DTRACE_IO_NFS(done, REQ_OP_READ, hdr->res.count, hdr->inode);
- if (status != 0)
- return status;
-
-diff --git a/fs/nfs/write.c b/fs/nfs/write.c
-index 639c34fec04a8488dd3a5df5b1b1c9ba0f170753..8bd0bd4e5b76435043c364688338cf2e7980e4a0 100644
---- a/fs/nfs/write.c
-+++ b/fs/nfs/write.c
-@@ -1403,6 +1403,7 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
- task_setup_data->priority = priority;
- rpc_ops->write_setup(hdr, msg, &task_setup_data->rpc_client);
- trace_nfs_initiate_write(hdr);
-+ DTRACE_IO_NFS(start, REQ_OP_WRITE, hdr->args.count, hdr->inode);
- }
-
- /* If a nfs_flush_* function fails, it should remove reqs from @head and
-@@ -1562,6 +1563,7 @@ static int nfs_writeback_done(struct rpc_task *task,
- * depend on tighter cache coherency when writing.
- */
- status = NFS_PROTO(inode)->write_done(task, hdr);
-+ DTRACE_IO_NFS(done, REQ_OP_WRITE, hdr->res.count, hdr->inode);
- if (status != 0)
- return status;
-
-diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
-index 4e4cf91f4f9fe7c5f44368a114d7aabe7bdc2e25..6550a3447816620bf0cfff58fd8f019ae51afdfa 100644
---- a/fs/xfs/xfs_buf.c
-+++ b/fs/xfs/xfs_buf.c
-@@ -52,6 +52,21 @@ static kmem_zone_t *xfs_buf_zone;
- * b_lock (trylock due to inversion)
- */
-
-+#define DTRACE_IO_XFS_WAIT(name, bp, is_write) \
-+ if (DTRACE_IO_ENABLED(name)) { \
-+ struct bio bio __maybe_unused = { \
-+ .bi_iter.bi_sector = (bp)->b_bn, \
-+ .bi_iter.bi_size = (bp)->b_length, \
-+ .bi_opf = is_write ? \
-+ REQ_OP_WRITE : REQ_OP_READ, \
-+ .bi_disk = (bp)->b_target->bt_bdev->bd_disk, \
-+ .bi_partno = (bp)->b_target->bt_bdev->bd_partno,\
-+ }; \
-+ DTRACE_IO(name, struct bio * : (bufinfo_t *, \
-+ devinfo_t *), &bio, \
-+ struct file * : fileinfo_t *, NULL); \
-+ }
-+
- static int __xfs_buf_submit(struct xfs_buf *bp, bool wait);
-
- static inline int
-@@ -1633,10 +1648,14 @@ static int
- xfs_buf_iowait(
- struct xfs_buf *bp)
- {
-+ int orig_flags __attribute__((unused)) = bp->b_flags;
-+
- ASSERT(!(bp->b_flags & XBF_ASYNC));
-
- trace_xfs_buf_iowait(bp, _RET_IP_);
-+ DTRACE_IO_XFS_WAIT(wait__start, bp, orig_flags & XBF_WRITE);
- wait_for_completion(&bp->b_iowait);
-+ DTRACE_IO_XFS_WAIT(wait__done, bp, orig_flags & XBF_WRITE);
- trace_xfs_buf_iowait_done(bp, _RET_IP_);
-
- return bp->b_error;
-diff --git a/include/linux/rwlock_api_smp.h b/include/linux/rwlock_api_smp.h
-index abfb53ab11beb4f527cea7203cda03495850ed37..2531929ccb580171256af12e81aa571ad3786227 100644
---- a/include/linux/rwlock_api_smp.h
-+++ b/include/linux/rwlock_api_smp.h
-@@ -5,6 +5,8 @@
- # error "please don't include this file directly"
- #endif
-
-+#include <linux/sdt.h>
-+
- /*
- * include/linux/rwlock_api_smp.h
- *
-@@ -119,6 +121,8 @@ static inline int __raw_read_trylock(rwlock_t *lock)
- preempt_disable();
- if (do_raw_read_trylock(lock)) {
- rwlock_acquire_read(&lock->dep_map, 0, 1, _RET_IP_);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- return 1;
- }
- preempt_enable();
-@@ -130,6 +134,8 @@ static inline int __raw_write_trylock(rwlock_t *lock)
- preempt_disable();
- if (do_raw_write_trylock(lock)) {
- rwlock_acquire(&lock->dep_map, 0, 1, _RET_IP_);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- return 1;
- }
- preempt_enable();
-@@ -148,6 +154,8 @@ static inline void __raw_read_lock(rwlock_t *lock)
- preempt_disable();
- rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- }
-
- static inline unsigned long __raw_read_lock_irqsave(rwlock_t *lock)
-@@ -159,6 +167,8 @@ static inline unsigned long __raw_read_lock_irqsave(rwlock_t *lock)
- rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED_FLAGS(lock, do_raw_read_trylock, do_raw_read_lock,
- do_raw_read_lock_flags, &flags);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- return flags;
- }
-
-@@ -168,6 +178,8 @@ static inline void __raw_read_lock_irq(rwlock_t *lock)
- preempt_disable();
- rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- }
-
- static inline void __raw_read_lock_bh(rwlock_t *lock)
-@@ -175,6 +187,8 @@ static inline void __raw_read_lock_bh(rwlock_t *lock)
- __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- }
-
- static inline unsigned long __raw_write_lock_irqsave(rwlock_t *lock)
-@@ -186,6 +200,8 @@ static inline unsigned long __raw_write_lock_irqsave(rwlock_t *lock)
- rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED_FLAGS(lock, do_raw_write_trylock, do_raw_write_lock,
- do_raw_write_lock_flags, &flags);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- return flags;
- }
-
-@@ -195,6 +211,8 @@ static inline void __raw_write_lock_irq(rwlock_t *lock)
- preempt_disable();
- rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- }
-
- static inline void __raw_write_lock_bh(rwlock_t *lock)
-@@ -202,6 +220,8 @@ static inline void __raw_write_lock_bh(rwlock_t *lock)
- __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- }
-
- static inline void __raw_write_lock(rwlock_t *lock)
-@@ -209,6 +229,8 @@ static inline void __raw_write_lock(rwlock_t *lock)
- preempt_disable();
- rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
-+ DTRACE_LOCKSTAT(rw__acquire, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- }
-
- #endif /* !CONFIG_GENERIC_LOCKBREAK || CONFIG_DEBUG_LOCK_ALLOC */
-@@ -217,6 +239,8 @@ static inline void __raw_write_unlock(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_write_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- preempt_enable();
- }
-
-@@ -224,6 +248,8 @@ static inline void __raw_read_unlock(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_read_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- preempt_enable();
- }
-
-@@ -232,6 +258,8 @@ __raw_read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_read_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- local_irq_restore(flags);
- preempt_enable();
- }
-@@ -240,6 +268,8 @@ static inline void __raw_read_unlock_irq(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_read_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- local_irq_enable();
- preempt_enable();
- }
-@@ -248,6 +278,8 @@ static inline void __raw_read_unlock_bh(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_read_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_READER);
- __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- }
-
-@@ -256,6 +288,8 @@ static inline void __raw_write_unlock_irqrestore(rwlock_t *lock,
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_write_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- local_irq_restore(flags);
- preempt_enable();
- }
-@@ -264,6 +298,8 @@ static inline void __raw_write_unlock_irq(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_write_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- local_irq_enable();
- preempt_enable();
- }
-@@ -272,6 +308,8 @@ static inline void __raw_write_unlock_bh(rwlock_t *lock)
- {
- rwlock_release(&lock->dep_map, _RET_IP_);
- do_raw_write_unlock(lock);
-+ DTRACE_LOCKSTAT(rw__release, struct rwlock *, lock, int,
-+ DTRACE_LOCKSTAT_RW_WRITER);
- __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- }
-
-diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h
-index 19a9be9d97ee531f236be5f1953ac80ce729238b..e7601d01b87d4789a3d4a3498a55a51955354e90 100644
---- a/include/linux/spinlock_api_smp.h
-+++ b/include/linux/spinlock_api_smp.h
-@@ -5,6 +5,8 @@
- # error "please don't include this file directly"
- #endif
-
-+#include <linux/sdt.h>
-+
- /*
- * include/linux/spinlock_api_smp.h
- *
-@@ -88,6 +90,7 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock)
- preempt_disable();
- if (do_raw_spin_trylock(lock)) {
- spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- return 1;
- }
- preempt_enable();
-@@ -118,6 +121,7 @@ static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)
- #else
- do_raw_spin_lock_flags(lock, &flags);
- #endif
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- return flags;
- }
-
-@@ -127,6 +131,7 @@ static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)
- preempt_disable();
- spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- }
-
- static inline void __raw_spin_lock_bh(raw_spinlock_t *lock)
-@@ -134,6 +139,7 @@ static inline void __raw_spin_lock_bh(raw_spinlock_t *lock)
- __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- }
-
- static inline void __raw_spin_lock(raw_spinlock_t *lock)
-@@ -141,6 +147,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
- preempt_disable();
- spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
- LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- }
-
- #endif /* !CONFIG_GENERIC_LOCKBREAK || CONFIG_DEBUG_LOCK_ALLOC */
-@@ -149,6 +156,7 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
- {
- spin_release(&lock->dep_map, _RET_IP_);
- do_raw_spin_unlock(lock);
-+ DTRACE_LOCKSTAT(spin__release, spinlock_t *, lock);
- preempt_enable();
- }
-
-@@ -157,6 +165,7 @@ static inline void __raw_spin_unlock_irqrestore(raw_spinlock_t *lock,
- {
- spin_release(&lock->dep_map, _RET_IP_);
- do_raw_spin_unlock(lock);
-+ DTRACE_LOCKSTAT(spin__release, spinlock_t *, lock);
- local_irq_restore(flags);
- preempt_enable();
- }
-@@ -165,6 +174,7 @@ static inline void __raw_spin_unlock_irq(raw_spinlock_t *lock)
- {
- spin_release(&lock->dep_map, _RET_IP_);
- do_raw_spin_unlock(lock);
-+ DTRACE_LOCKSTAT(spin__release, spinlock_t *, lock);
- local_irq_enable();
- preempt_enable();
- }
-@@ -173,6 +183,7 @@ static inline void __raw_spin_unlock_bh(raw_spinlock_t *lock)
- {
- spin_release(&lock->dep_map, _RET_IP_);
- do_raw_spin_unlock(lock);
-+ DTRACE_LOCKSTAT(spin__release, spinlock_t *, lock);
- __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- }
-
-@@ -181,6 +192,7 @@ static inline int __raw_spin_trylock_bh(raw_spinlock_t *lock)
- __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
- if (do_raw_spin_trylock(lock)) {
- spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
-+ DTRACE_LOCKSTAT(spin__acquire, spinlock_t *, lock);
- return 1;
- }
- __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
-diff --git a/kernel/exit.c b/kernel/exit.c
-index da498c5f029c20d162f8665cee6cd49c6de9a06c..285b0c0ff00d99eb46f0c7bc94f03abdfcbb289c 100644
---- a/kernel/exit.c
-+++ b/kernel/exit.c
-@@ -64,6 +64,7 @@
- #include <linux/rcuwait.h>
- #include <linux/compat.h>
- #include <linux/io_uring.h>
-+#include <linux/sdt.h>
- #include <linux/dtrace_os.h>
-
- #include <linux/uaccess.h>
-@@ -796,6 +797,10 @@ void __noreturn do_exit(long code)
- tsk->exit_code = code;
- taskstats_exit(tsk, group_dead);
-
-+ DTRACE_PROC(lwp__exit);
-+ if (group_dead)
-+ DTRACE_PROC(exit, int, code & 0x80 ? 3 : code & 0x7f ? 2 : 1);
-+
- /* Remove DTrace state for this task */
- dtrace_task_free(tsk);
-
-diff --git a/kernel/fork.c b/kernel/fork.c
-index 0d8a2b12fd90565fccba06804f9c0a58cbc6a064..0729e80e4ad88c3bc9919a588a771b7b91cc2706 100644
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -96,6 +96,7 @@
- #include <linux/kasan.h>
- #include <linux/scs.h>
- #include <linux/io_uring.h>
-+#include <linux/sdt.h>
- #include <linux/dtrace_task_impl.h>
-
- #include <asm/pgalloc.h>
-@@ -2513,6 +2514,8 @@ pid_t kernel_clone(struct kernel_clone_args *args)
- }
-
- put_pid(pid);
-+ DTRACE_PROC(lwp__create, struct task_struct * : (lwpsinfo_t *, psinfo_t *), p);
-+ DTRACE_PROC(create, struct task_struct * : psinfo_t *, p);
- return nr;
- }
-
-diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
-index 5352ce50a97e309b5bf8cdd2059378b17a8f14ec..e784dd89d924c4867de23c0eb60e65b2a47cad52 100644
---- a/kernel/locking/mutex.c
-+++ b/kernel/locking/mutex.c
-@@ -29,6 +29,7 @@
- #include <linux/interrupt.h>
- #include <linux/debug_locks.h>
- #include <linux/osq_lock.h>
-+#include <linux/sdt.h>
-
- #ifdef CONFIG_DEBUG_MUTEXES
- # include "mutex-debug.h"
-@@ -282,6 +283,7 @@ void __sched mutex_lock(struct mutex *lock)
-
- if (!__mutex_trylock_fast(lock))
- __mutex_lock_slowpath(lock);
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
- }
- EXPORT_SYMBOL(mutex_lock);
- #endif
-@@ -734,10 +736,14 @@ static noinline void __sched __mutex_unlock_slowpath(struct mutex *lock, unsigne
- void __sched mutex_unlock(struct mutex *lock)
- {
- #ifndef CONFIG_DEBUG_LOCK_ALLOC
-- if (__mutex_unlock_fast(lock))
-+ if (__mutex_unlock_fast(lock)) {
-+ DTRACE_LOCKSTAT(adaptive__release, struct mutex *, lock);
- return;
-+ }
- #endif
-+
- __mutex_unlock_slowpath(lock, _RET_IP_);
-+ DTRACE_LOCKSTAT(adaptive__release, struct mutex *, lock);
- }
- EXPORT_SYMBOL(mutex_unlock);
-
-@@ -927,6 +933,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- struct lockdep_map *nest_lock, unsigned long ip,
- struct ww_acquire_ctx *ww_ctx, const bool use_ww_ctx)
- {
-+ u64 spinstart = 0, spinend, spintotal = 0;
-+ u64 waitstart, waitend, waittotal = 0;
- struct mutex_waiter waiter;
- bool first = false;
- struct ww_mutex *ww;
-@@ -958,9 +966,11 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- if (__mutex_trylock(lock) ||
- mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx, NULL)) {
- /* got the lock, yay! */
-+
- lock_acquired(&lock->dep_map, ip);
- if (use_ww_ctx && ww_ctx)
- ww_mutex_set_context_fastpath(ww, ww_ctx);
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
- preempt_enable();
- return 0;
- }
-@@ -1003,6 +1013,9 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- waiter.task = current;
-
- set_current_state(state);
-+ if (DTRACE_LOCKSTAT_ENABLED(adaptive__spin))
-+ spinstart = dtrace_gethrtime_ns();
-+
- for (;;) {
- /*
- * Once we hold wait_lock, we're serialized against
-@@ -1030,7 +1043,15 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- }
-
- spin_unlock(&lock->wait_lock);
-- schedule_preempt_disabled();
-+
-+ if (DTRACE_LOCKSTAT_ENABLED(adaptive__block)) {
-+ waitstart = dtrace_gethrtime_ns();
-+ schedule_preempt_disabled();
-+ waitend = dtrace_gethrtime_ns();
-+ if (waitend > waitstart)
-+ waittotal += waitend - waitstart;
-+ } else
-+ schedule_preempt_disabled();
-
- /*
- * ww_mutex needs to always recheck its position since its waiter
-@@ -1082,6 +1103,19 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- ww_mutex_lock_acquired(ww, ww_ctx);
-
- spin_unlock(&lock->wait_lock);
-+
-+ if (DTRACE_LOCKSTAT_ENABLED(adaptive__spin) && spinstart) {
-+ spinend = dtrace_gethrtime_ns();
-+ spintotal = (spinend > spinstart) ? (spinend - spinstart) : 0;
-+ spintotal = (spintotal > waittotal) ?
-+ (spintotal - waittotal) : 0;
-+ DTRACE_LOCKSTAT(adaptive__spin, struct mutex *, lock,
-+ uint64_t, spintotal);
-+ }
-+ if (DTRACE_LOCKSTAT_ENABLED(adaptive__block) && waittotal)
-+ DTRACE_LOCKSTAT(adaptive__block, struct mutex *, lock,
-+ uint64_t, waittotal);
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
- preempt_enable();
- return 0;
-
-@@ -1092,6 +1126,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
- spin_unlock(&lock->wait_lock);
- debug_mutex_free_waiter(&waiter);
- mutex_release(&lock->dep_map, ip);
-+ DTRACE_LOCKSTAT(adaptive__acquire__error, struct mutex *, lock,
-+ int, ret);
- preempt_enable();
- return ret;
- }
-@@ -1307,8 +1343,10 @@ int __sched mutex_lock_interruptible(struct mutex *lock)
- {
- might_sleep();
-
-- if (__mutex_trylock_fast(lock))
-+ if (__mutex_trylock_fast(lock)) {
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
- return 0;
-+ }
-
- return __mutex_lock_interruptible_slowpath(lock);
- }
-@@ -1331,8 +1369,10 @@ int __sched mutex_lock_killable(struct mutex *lock)
- {
- might_sleep();
-
-- if (__mutex_trylock_fast(lock))
-+ if (__mutex_trylock_fast(lock)) {
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
- return 0;
-+ }
-
- return __mutex_lock_killable_slowpath(lock);
- }
-@@ -1416,8 +1456,10 @@ int __sched mutex_trylock(struct mutex *lock)
- #endif
-
- locked = __mutex_trylock(lock);
-- if (locked)
-+ if (locked) {
- mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_);
-+ DTRACE_LOCKSTAT(adaptive__acquire, struct mutex *, lock);
-+ }
-
- return locked;
- }
-diff --git a/kernel/locking/qrwlock.c b/kernel/locking/qrwlock.c
-index fe9ca92faa2a7a7b0915a6ae420f31b2e4fc4dd8..6b1511be7805cb9de3869367230a81ae9758df9c 100644
---- a/kernel/locking/qrwlock.c
-+++ b/kernel/locking/qrwlock.c
-@@ -11,6 +11,7 @@
- #include <linux/cpumask.h>
- #include <linux/percpu.h>
- #include <linux/hardirq.h>
-+#include <linux/sdt.h>
- #include <linux/spinlock.h>
- #include <asm/qrwlock.h>
-
-@@ -20,9 +21,13 @@
- */
- void queued_read_lock_slowpath(struct qrwlock *lock)
- {
-+ u64 spinstart = 0, spinend, spintime;
-+
- /*
- * Readers come here when they cannot get the lock without waiting
- */
-+ if (DTRACE_LOCKSTAT_ENABLED(rw__spin))
-+ spinstart = dtrace_gethrtime_ns();
- if (unlikely(in_interrupt())) {
- /*
- * Readers in interrupt context will get the lock immediately
-@@ -31,7 +36,7 @@ void queued_read_lock_slowpath(struct qrwlock *lock)
- * without waiting in the queue.
- */
- atomic_cond_read_acquire(&lock->cnts, !(VAL & _QW_LOCKED));
-- return;
-+ goto done;
- }
- atomic_sub(_QR_BIAS, &lock->cnts);
-
-@@ -52,6 +57,13 @@ void queued_read_lock_slowpath(struct qrwlock *lock)
- * Signal the next one in queue to become queue head
- */
- arch_spin_unlock(&lock->wait_lock);
-+done:
-+ if (DTRACE_LOCKSTAT_ENABLED(rw__spin) && spinstart) {
-+ spinend = dtrace_gethrtime_ns();
-+ spintime = spinend > spinstart ? spinend - spinstart : 0;
-+ DTRACE_LOCKSTAT(rw__spin, rwlock_t *, lock, uint64_t, spintime,
-+ int, DTRACE_LOCKSTAT_RW_READER);
-+ }
- }
- EXPORT_SYMBOL(queued_read_lock_slowpath);
-
-@@ -61,7 +73,11 @@ EXPORT_SYMBOL(queued_read_lock_slowpath);
- */
- void queued_write_lock_slowpath(struct qrwlock *lock)
- {
-+ u64 spinstart = 0, spinend, spintime;
-+
- /* Put the writer into the wait queue */
-+ if (DTRACE_LOCKSTAT_ENABLED(rw__spin))
-+ spinstart = dtrace_gethrtime_ns();
- arch_spin_lock(&lock->wait_lock);
-
- /* Try to acquire the lock directly if no reader is present */
-@@ -79,5 +95,11 @@ void queued_write_lock_slowpath(struct qrwlock *lock)
- _QW_LOCKED) != _QW_WAITING);
- unlock:
- arch_spin_unlock(&lock->wait_lock);
-+ if (DTRACE_LOCKSTAT_ENABLED(rw__spin) && spinstart) {
-+ spinend = dtrace_gethrtime_ns();
-+ spintime = spinend > spinstart ? spinend - spinstart : 0;
-+ DTRACE_LOCKSTAT(rw__spin, rwlock_t *, lock, uint64_t, spintime,
-+ int, DTRACE_LOCKSTAT_RW_WRITER);
-+ }
- }
- EXPORT_SYMBOL(queued_write_lock_slowpath);
-diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
-index cbff6ba53d563634791e27ad8d11e7a683065679..44853c2b018375ca95edd18237496eb4706e3779 100644
---- a/kernel/locking/qspinlock.c
-+++ b/kernel/locking/qspinlock.c
-@@ -20,6 +20,7 @@
- #include <linux/hardirq.h>
- #include <linux/mutex.h>
- #include <linux/prefetch.h>
-+#include <linux/sdt.h>
- #include <asm/byteorder.h>
- #include <asm/qspinlock.h>
-
-@@ -315,16 +316,20 @@ static __always_inline u32 __pv_wait_head_or_lock(struct qspinlock *lock,
- void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
- {
- struct mcs_spinlock *prev, *next, *node;
-+ u64 spinstart = 0, spinend, spintime;
- u32 old, tail;
- int idx;
-
- BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
-
-+ if (DTRACE_LOCKSTAT_ENABLED(spin__spin))
-+ spinstart = dtrace_gethrtime_ns();
-+
- if (pv_enabled())
- goto pv_queue;
-
- if (virt_spin_lock(lock))
-- return;
-+ goto out;
-
- /*
- * Wait for in-progress pending->locked hand-overs with a bounded
-@@ -388,7 +393,7 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
- */
- clear_pending_set_locked(lock);
- lockevent_inc(lock_pending);
-- return;
-+ goto out;
-
- /*
- * End of pending bit optimistic spinning and beginning of MCS
-@@ -558,6 +563,17 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
- * release the node
- */
- __this_cpu_dec(qnodes[0].mcs.count);
-+
-+ /*
-+ * Fire spin-spin probe to note time waiting for a lock.
-+ */
-+out:
-+ if (DTRACE_LOCKSTAT_ENABLED(spin__spin)) {
-+ spinend = dtrace_gethrtime_ns();
-+ spintime = spinend > spinstart ? spinend - spinstart : 0;
-+ DTRACE_LOCKSTAT(spin__spin, spinlock_t *, lock,
-+ uint64_t, spintime);
-+ }
- }
- EXPORT_SYMBOL(queued_spin_lock_slowpath);
-
-diff --git a/kernel/sched/core.c b/kernel/sched/core.c
-index db893818f3ea5d645ae2418906acd27889722a65..f035f9859ae71cae7880fae416acf72dccd5ffbb 100644
---- a/kernel/sched/core.c
-+++ b/kernel/sched/core.c
-@@ -1561,6 +1561,9 @@ static inline void init_uclamp(void) { }
-
- static inline void enqueue_task(struct rq *rq, struct task_struct *p, int flags)
- {
-+ DTRACE_SCHED(enqueue, struct task_struct * : (lwpsinfo_t *,
-+ psinfo_t *), p,
-+ cpuinfo_t *, rq->dtrace_cpu_info);
- if (!(flags & ENQUEUE_NOCLOCK))
- update_rq_clock(rq);
-
-@@ -1575,6 +1578,10 @@ static inline void enqueue_task(struct rq *rq, struct task_struct *p, int flags)
-
- static inline void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
- {
-+ DTRACE_SCHED(dequeue, struct task_struct * : (lwpsinfo_t *,
-+ psinfo_t *), p,
-+ cpuinfo_t *, rq->dtrace_cpu_info,
-+ int, 0);
- if (!(flags & DEQUEUE_NOCLOCK))
- update_rq_clock(rq);
-
-@@ -2864,6 +2871,8 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
- goto unlock;
-
- trace_sched_waking(p);
-+ DTRACE_SCHED(wakeup, struct task_struct * : (lwpsinfo_t *,
-+ psinfo_t *), p);
-
- /* We're going to change ->state: */
- success = 1;
-@@ -3552,6 +3561,8 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
- sched_info_switch(rq, prev, next);
- perf_event_task_sched_out(prev, next);
- rseq_preempt(prev);
-+ DTRACE_SCHED(off__cpu, struct task_struct * : (lwpsinfo_t *,
-+ psinfo_t *), next);
- fire_sched_out_preempt_notifiers(prev, next);
- prepare_task(next);
- prepare_arch_switch(next);
-@@ -3625,6 +3636,7 @@ static struct rq *finish_task_switch(struct task_struct *prev)
- finish_arch_post_lock_switch();
- kcov_finish_switch(current);
-
-+ DTRACE_SCHED(on__cpu);
- fire_sched_in_preempt_notifiers(current);
- /*
- * When switching through a kernel thread, the loop in
-@@ -3725,6 +3737,8 @@ asmlinkage __visible void schedule_tail(struct task_struct *prev)
- put_user(task_pid_vnr(current), current->set_child_tid);
-
- calculate_sigpending();
-+ DTRACE_PROC(start);
-+ DTRACE_PROC(lwp__start);
- }
-
- /*
-@@ -4467,6 +4481,7 @@ static void __sched notrace __schedule(bool preempt)
- */
- prev_state = prev->state;
- if (!preempt && prev_state) {
-+ DTRACE_SCHED(sleep);
- if (signal_pending_state(prev_state, prev)) {
- prev->state = TASK_RUNNING;
- } else {
-@@ -4497,7 +4512,8 @@ static void __sched notrace __schedule(bool preempt)
- }
- }
- switch_count = &prev->nvcsw;
-- }
-+ } else
-+ DTRACE_SCHED(preempt);
-
- next = pick_next_task(rq, prev, &rf);
- clear_tsk_need_resched(prev);
-@@ -4534,6 +4550,7 @@ static void __sched notrace __schedule(bool preempt)
- rq = context_switch(rq, prev, next, &rf);
- } else {
- rq->clock_update_flags &= ~(RQCF_ACT_SKIP|RQCF_REQ_SKIP);
-+ DTRACE_SCHED(remain__cpu);
- rq_unlock_irq(rq, &rf);
- }
-
-@@ -4999,6 +5016,9 @@ void set_user_nice(struct task_struct *p, long nice)
- old_prio = p->prio;
- p->prio = effective_prio(p);
-
-+ DTRACE_SCHED(change__pri, struct task_struct * : (lwpsinfo_t *,
-+ psinfo_t *), p,
-+ int, old_prio);
- if (queued)
- enqueue_task(rq, p, ENQUEUE_RESTORE | ENQUEUE_NOCLOCK);
- if (running)
-@@ -6110,6 +6130,9 @@ static void do_sched_yield(void)
- rq_unlock_irq(rq, &rf);
- sched_preempt_enable_no_resched();
-
-+ DTRACE_SCHED(surrender,
-+ struct task_struct * : (lwpsinfo_t *, psinfo_t *),
-+ current);
- schedule();
- }
-
-@@ -6256,8 +6279,12 @@ int __sched yield_to(struct task_struct *p, bool preempt)
- out_irq:
- local_irq_restore(flags);
-
-- if (yielded > 0)
-+ if (yielded > 0) {
-+ DTRACE_SCHED(surrender,
-+ struct task_struct * : (lwpsinfo_t *, psinfo_t *),
-+ curr);
- schedule();
-+ }
-
- return yielded;
- }
-diff --git a/kernel/signal.c b/kernel/signal.c
-index ef8f2a28d37c525b0994701448c026469a533259..23cefab66287227cc4e169a880e67914cb0da978 100644
---- a/kernel/signal.c
-+++ b/kernel/signal.c
-@@ -49,6 +49,7 @@
-
- #define CREATE_TRACE_POINTS
- #include <trace/events/signal.h>
-+#include <linux/sdt.h>
-
- #include <asm/param.h>
- #include <linux/uaccess.h>
-@@ -1079,8 +1080,12 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
- assert_spin_locked(&t->sighand->siglock);
-
- result = TRACE_SIGNAL_IGNORED;
-- if (!prepare_signal(sig, t, force))
-+ if (!prepare_signal(sig, t, force)) {
-+ DTRACE_PROC(signal__discard,
-+ struct task_struct * : (lwpsinfo_t *, psinfo_t *), t,
-+ int, sig);
- goto ret;
-+ }
-
- pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending;
- /*
-@@ -1179,6 +1184,9 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
- }
-
- complete_signal(sig, t, type);
-+ DTRACE_PROC(signal__send,
-+ struct task_struct * : (lwpsinfo_t *, psinfo_t *), t,
-+ int, sig);
- ret:
- trace_signal_generate(sig, info, t, type != PIDTYPE_PID, result);
- return ret;
-@@ -1879,6 +1887,9 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type)
- list_add_tail(&q->list, &pending->list);
- sigaddset(&pending->signal, sig);
- complete_signal(sig, t, type);
-+ DTRACE_PROC(signal__send,
-+ struct task_struct * : (lwpsinfo_t *, psinfo_t *), t,
-+ int, sig);
- result = TRACE_SIGNAL_DELIVERED;
- out:
- trace_signal_generate(sig, &q->info, t, type != PIDTYPE_PID, result);
-@@ -2601,6 +2612,11 @@ bool get_signal(struct ksignal *ksig)
-
- /* Has this task already been marked for death? */
- if (signal_group_exit(signal)) {
-+ DTRACE_PROC(signal__handle,
-+ int, signal->group_exit_code
-+ ? signal->group_exit_code
-+ : signr,
-+ siginfo_t *, NULL, void (*)(void), NULL);
- ksig->info.si_signo = signr = SIGKILL;
- sigdelset(&current->pending.signal, SIGKILL);
- trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO,
-@@ -2658,6 +2674,15 @@ bool get_signal(struct ksignal *ksig)
-
- ka = &sighand->action[signr-1];
-
-+ DTRACE_PROC(signal__handle,
-+ int, signal->group_exit_code
-+ ? signal->group_exit_code
-+ : signr,
-+ siginfo_t *, ksig->ka.sa.sa_handler != SIG_DFL
-+ ? NULL
-+ : &ksig->info,
-+ void (*)(void), ksig->ka.sa.sa_handler);
-+
- /* Trace actually delivered signals. */
- trace_signal_deliver(signr, &ksig->info, ka);
-
-@@ -3498,8 +3523,10 @@ static int do_sigtimedwait(const sigset_t *which, kernel_siginfo_t *info,
- }
- spin_unlock_irq(&tsk->sighand->siglock);
-
-- if (sig)
-+ if (sig) {
-+ DTRACE_PROC(signal__clear, int, sig);
- return sig;
-+ }
- return ret ? -EINTR : -EAGAIN;
- }
-
-diff --git a/kernel/time/timer.c b/kernel/time/timer.c
-index c3ad64fb9d8bd12151cb460e9142976b2460d1f4..a1b822cbdb80561afb288a91baa690f9181dc950 100644
---- a/kernel/time/timer.c
-+++ b/kernel/time/timer.c
-@@ -44,6 +44,7 @@
- #include <linux/slab.h>
- #include <linux/compat.h>
- #include <linux/random.h>
-+#include <linux/sdt.h>
-
- #include <linux/uaccess.h>
- #include <asm/unistd.h>
-@@ -1702,6 +1703,8 @@ void update_process_times(int user_tick)
- struct task_struct *p = current;
-
- PRANDOM_ADD_NOISE(jiffies, user_tick, p, 0);
-+ DTRACE_SCHED(tick, struct task_struct * : (lwpsinfo_t *, psinfo_t *),
-+ p);
-
- /* Note: this timer irq context must be accounted for as well. */
- account_process_tick(p, user_tick);
-diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
-index b0c244af1e4d587322b4e3490ad3d878805be670..038868b61cd803760759d6f79fef442d1fe89132 100644
---- a/net/ipv4/ip_input.c
-+++ b/net/ipv4/ip_input.c
-@@ -141,6 +141,7 @@
- #include <linux/mroute.h>
- #include <linux/netlink.h>
- #include <net/dst_metadata.h>
-+#include <linux/sdt.h>
-
- /*
- * Process Router Attention IP option (RFC 2113)
-@@ -239,16 +240,26 @@ static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_b
- */
- int ip_local_deliver(struct sk_buff *skb)
- {
-+ struct iphdr *iph = ip_hdr(skb);
-+
- /*
- * Reassemble IP fragments.
- */
- struct net *net = dev_net(skb->dev);
-
-- if (ip_is_fragment(ip_hdr(skb))) {
-+ if (ip_is_fragment(iph)) {
- if (ip_defrag(net, skb, IP_DEFRAG_LOCAL_DELIVER))
- return 0;
- }
-
-+ DTRACE_IP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, iph,
-+ struct ipv6hdr * : ipv6info_t *, NULL);
-+
- return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN,
- net, NULL, skb, skb->dev, NULL,
- ip_local_deliver_finish);
-@@ -257,7 +268,8 @@ int ip_local_deliver(struct sk_buff *skb)
- static inline bool ip_rcv_options(struct sk_buff *skb, struct net_device *dev)
- {
- struct ip_options *opt;
-- const struct iphdr *iph;
-+ const struct iphdr *iph = NULL;
-+ const char *dropreason;
-
- /* It looks as overkill, because not all
- IP options require packet mangling.
-@@ -267,6 +279,7 @@ static inline bool ip_rcv_options(struct sk_buff *skb, struct net_device *dev)
- --ANK (980813)
- */
- if (skb_cow(skb, skb_headroom(skb))) {
-+ dropreason = "copy-on-write failed";
- __IP_INC_STATS(dev_net(dev), IPSTATS_MIB_INDISCARDS);
- goto drop;
- }
-@@ -276,6 +289,7 @@ static inline bool ip_rcv_options(struct sk_buff *skb, struct net_device *dev)
- opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
-
- if (ip_options_compile(dev_net(dev), opt, skb)) {
-+ dropreason = "invalid options";
- __IP_INC_STATS(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
- goto drop;
- }
-@@ -289,16 +303,28 @@ static inline bool ip_rcv_options(struct sk_buff *skb, struct net_device *dev)
- net_info_ratelimited("source route option %pI4 -> %pI4\n",
- &iph->saddr,
- &iph->daddr);
-+ dropreason = "invalid source route options";
- goto drop;
- }
- }
-
-- if (ip_options_rcv_srr(skb, dev))
-+ if (ip_options_rcv_srr(skb, dev)) {
-+ dropreason = "invalid options";
- goto drop;
-+ }
- }
-
- return false;
- drop:
-+ DTRACE_IP(drop__in,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, iph,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- return true;
- }
-
-@@ -432,27 +458,35 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
- /*
- * Main IP Receive routine.
- */
--static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
-+static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net,
-+ struct net_device *dev
-+ __attribute__((__unused__)))
- {
-- const struct iphdr *iph;
-+ const struct iphdr *iph = NULL;
- u32 len;
-+ const char *dropreason = "header invalid";
-
- /* When the interface is in promisc. mode, drop all the crap
- * that it receives, do not try to analyse it.
- */
-- if (skb->pkt_type == PACKET_OTHERHOST)
-+ if (skb->pkt_type == PACKET_OTHERHOST) {
-+ dropreason = "for other host";
- goto drop;
-+ }
-
- __IP_UPD_PO_STATS(net, IPSTATS_MIB_IN, skb->len);
-
- skb = skb_share_check(skb, GFP_ATOMIC);
- if (!skb) {
-+ dropreason = "could not clone shared buffer";
- __IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS);
-- goto out;
-+ goto drop;
- }
-
-- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-+ if (!pskb_may_pull(skb, sizeof(struct iphdr))) {
-+ dropreason = "could not pull skb";
- goto inhdr_error;
-+ }
-
- iph = ip_hdr(skb);
-
-@@ -487,6 +521,7 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
-
- len = ntohs(iph->tot_len);
- if (skb->len < len) {
-+ dropreason = "packet too short";
- __IP_INC_STATS(net, IPSTATS_MIB_INTRUNCATEDPKTS);
- goto drop;
- } else if (len < (iph->ihl*4))
-@@ -497,6 +532,7 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
- * Note this now means skb->len holds ntohs(iph->tot_len).
- */
- if (pskb_trim_rcsum(skb, len)) {
-+ dropreason = "could not trim buffer";
- __IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS);
- goto drop;
- }
-@@ -516,11 +552,19 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
-
- csum_error:
- __IP_INC_STATS(net, IPSTATS_MIB_CSUMERRORS);
-+ dropreason = "checksum error";
- inhdr_error:
- __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
- drop:
-+ DTRACE_IP(drop__in,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, dev,
-+ struct iphdr * : ipv4info_t *, iph,
-+ void * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
- kfree_skb(skb);
--out:
- return NULL;
- }
-
-@@ -532,7 +576,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
- {
- struct net *net = dev_net(dev);
-
-- skb = ip_rcv_core(skb, net);
-+ skb = ip_rcv_core(skb, net, dev);
- if (skb == NULL)
- return NET_RX_DROP;
-
-@@ -623,7 +667,7 @@ void ip_list_rcv(struct list_head *head, struct packet_type *pt,
- struct net *net = dev_net(dev);
-
- skb_list_del_init(skb);
-- skb = ip_rcv_core(skb, net);
-+ skb = ip_rcv_core(skb, net, dev);
- if (skb == NULL)
- continue;
-
-diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
-index 97975bed491addd6bfbe461298a1ce7264f845d7..9e194f4e205055cdbefad6047f7438abaf108275 100644
---- a/net/ipv4/ip_output.c
-+++ b/net/ipv4/ip_output.c
-@@ -82,6 +82,7 @@
- #include <linux/netfilter_bridge.h>
- #include <linux/netlink.h>
- #include <linux/tcp.h>
-+#include <linux/sdt.h>
-
- static int
- ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
-@@ -112,6 +113,14 @@ int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
-
- skb->protocol = htons(ETH_P_IP);
-
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, iph,
-+ struct ipv6hdr * : ipv6info_t *, NULL);
-+
- return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
- net, sk, skb, NULL, skb_dst(skb)->dev,
- dst_output);
-@@ -983,6 +992,7 @@ static int __ip_append_data(struct sock *sk,
- unsigned int wmem_alloc_delta = 0;
- bool paged, extra_uref = false;
- u32 tskey = 0;
-+ const char *dropreason;
-
- skb = skb_peek_tail(queue);
-
-@@ -1001,9 +1011,13 @@ static int __ip_append_data(struct sock *sk,
- maxnonfragsize = ip_sk_ignore_df(sk) ? IP_MAX_MTU : mtu;
-
- if (cork->length + length > maxnonfragsize - fragheaderlen) {
-+ struct iphdr *iph __attribute__((unused)) = ip_hdr(skb);
-+
- ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
- mtu - (opt ? opt->optlen : 0));
-- return -EMSGSIZE;
-+ dropreason = "packet too big";
-+ err = -EMSGSIZE;
-+ goto error2;
- }
-
- /*
-@@ -1103,8 +1117,10 @@ static int __ip_append_data(struct sock *sk,
- 2 * sk->sk_sndbuf)
- skb = alloc_skb(alloclen + hh_len + 15,
- sk->sk_allocation);
-- if (unlikely(!skb))
-+ if (unlikely(!skb)) {
-+ dropreason = "no buffers";
- err = -ENOBUFS;
-+ }
- }
- if (!skb)
- goto error;
-@@ -1138,7 +1154,9 @@ static int __ip_append_data(struct sock *sk,
- copy = datalen - transhdrlen - fraggap - pagedlen;
- if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
- err = -EFAULT;
-+ dropreason = "could not fragment packet";
- kfree_skb(skb);
-+ skb = NULL;
- goto error;
- }
-
-@@ -1181,6 +1199,7 @@ static int __ip_append_data(struct sock *sk,
- if (getfrag(from, skb_put(skb, copy),
- offset, copy, off, skb) < 0) {
- __skb_trim(skb, off);
-+ dropreason = "could not fragment packet";
- err = -EFAULT;
- goto error;
- }
-@@ -1188,14 +1207,18 @@ static int __ip_append_data(struct sock *sk,
- int i = skb_shinfo(skb)->nr_frags;
-
- err = -ENOMEM;
-- if (!sk_page_frag_refill(sk, pfrag))
-+ if (!sk_page_frag_refill(sk, pfrag)) {
-+ dropreason = "no memory";
- goto error;
-+ }
-
- if (!skb_can_coalesce(skb, i, pfrag->page,
- pfrag->offset)) {
- err = -EMSGSIZE;
-- if (i == MAX_SKB_FRAGS)
-+ if (i == MAX_SKB_FRAGS) {
-+ dropreason = "too many fragments";
- goto error;
-+ }
-
- __skb_fill_page_desc(skb, i, pfrag->page,
- pfrag->offset, 0);
-@@ -1205,8 +1228,10 @@ static int __ip_append_data(struct sock *sk,
- copy = min_t(int, copy, pfrag->size - pfrag->offset);
- if (getfrag(from,
- page_address(pfrag->page) + pfrag->offset,
-- offset, copy, skb->len, skb) < 0)
-+ offset, copy, skb->len, skb) < 0) {
-+ dropreason = "could not framgent packet";
- goto error_efault;
-+ }
-
- pfrag->offset += copy;
- skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
-@@ -1235,6 +1260,16 @@ static int __ip_append_data(struct sock *sk,
- cork->length -= length;
- IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
- refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
-+error2:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, skb ? ip_hdr(skb) : NULL,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, skb ? ip_hdr(skb) : NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- return err;
- }
-
-@@ -1338,6 +1373,8 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
- int len;
- int err;
- unsigned int maxfraglen, fragheaderlen, fraggap, maxnonfragsize;
-+ struct iphdr *iph;
-+ const char *dropreason;
-
- if (inet->hdrincl)
- return -EPERM;
-@@ -1391,6 +1428,7 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
- alloclen = fragheaderlen + hh_len + fraggap + 15;
- skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
- if (unlikely(!skb)) {
-+ dropreason = "no buffers";
- err = -ENOBUFS;
- goto error;
- }
-@@ -1430,6 +1468,7 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
- len = size;
-
- if (skb_append_pagefrags(skb, page, offset, len)) {
-+ dropreason = "packet too big";
- err = -EMSGSIZE;
- goto error;
- }
-@@ -1452,6 +1491,16 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
- error:
- cork->length -= size;
- IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
-+ iph = skb ? ip_hdr(skb) : NULL;
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, iph,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- return err;
- }
-
-@@ -1569,8 +1618,18 @@ int ip_send_skb(struct net *net, struct sk_buff *skb)
- if (err) {
- if (err > 0)
- err = net_xmit_errno(err);
-- if (err)
-+ if (err) {
- IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
-+ /* skb may have been freed */
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, NULL,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ char * : string, "packet too short");
-+ }
- }
-
- return err;
-diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
-index 7d26e0f8bdaeb5f334e77deb5966a976db3d3ff4..7ae1ad2bad09f98f57f04fe7c034c4e649f489f2 100644
---- a/net/ipv4/raw.c
-+++ b/net/ipv4/raw.c
-@@ -75,6 +75,7 @@
- #include <linux/netfilter_ipv4.h>
- #include <linux/compat.h>
- #include <linux/uio.h>
-+#include <linux/sdt.h>
-
- struct raw_frag_vec {
- struct msghdr *msg;
-@@ -349,19 +350,25 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
- struct inet_sock *inet = inet_sk(sk);
- struct net *net = sock_net(sk);
- struct iphdr *iph;
-- struct sk_buff *skb;
-+ struct sk_buff *skb = NULL;
- unsigned int iphlen;
- int err;
- struct rtable *rt = *rtp;
- int hlen, tlen;
-+ const char *dropreason;
-
- if (length > rt->dst.dev->mtu) {
- ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
- rt->dst.dev->mtu);
-- return -EMSGSIZE;
-+ dropreason = "packet too big";
-+ err = -EMSGSIZE;
-+ goto trace_drop;
-+ }
-+ if (length < sizeof(struct iphdr)) {
-+ dropreason = "packet too short";
-+ err = -EINVAL;
-+ goto trace_drop;
- }
-- if (length < sizeof(struct iphdr))
-- return -EINVAL;
-
- if (flags&MSG_PROBE)
- goto out;
-@@ -371,8 +378,10 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
- skb = sock_alloc_send_skb(sk,
- length + hlen + tlen + 15,
- flags & MSG_DONTWAIT, &err);
-- if (!skb)
-+ if (!skb) {
-+ dropreason = "out of memory";
- goto error;
-+ }
- skb_reserve(skb, hlen);
-
- skb->priority = sk->sk_priority;
-@@ -394,8 +403,10 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
-
- skb->transport_header = skb->network_header;
- err = -EFAULT;
-- if (memcpy_from_msg(iph, msg, length))
-+ if (memcpy_from_msg(iph, msg, length)) {
-+ dropreason = "could not copy msg";
- goto error_free;
-+ }
-
- iphlen = iph->ihl * 4;
-
-@@ -407,8 +418,10 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
- * in, reject the frame as invalid
- */
- err = -EINVAL;
-- if (iphlen > length)
-+ if (iphlen > length) {
-+ dropreason = "IP header too big";
- goto error_free;
-+ }
-
- if (iphlen >= sizeof(*iph)) {
- if (!iph->saddr)
-@@ -426,20 +439,40 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
- skb_transport_header(skb))->type);
- }
-
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, iph,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, iph,
-+ struct ipv6hdr * : ipv6info_t *, NULL);
-+
- err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
- net, sk, skb, NULL, rt->dst.dev,
- dst_output);
- if (err > 0)
- err = net_xmit_errno(err);
-- if (err)
-+ if (err) {
-+ dropreason = "device dropping packets of this priority";
- goto error;
-+ }
- out:
- return 0;
-
- error_free:
- kfree_skb(skb);
-+ skb = NULL;
- error:
- IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
-+trace_drop:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, skb ? ip_hdr(skb) : NULL,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, skb ? ip_hdr(skb) : NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
- if (err == -ENOBUFS && !inet->recverr)
- err = 0;
- return err;
-diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
-index 41d03683b13d6bf613c3bd39b64fdaaa48d2870a..19794603862669bebedb6475604c7415c6407cdb 100644
---- a/net/ipv4/tcp.c
-+++ b/net/ipv4/tcp.c
-@@ -267,6 +267,7 @@
- #include <linux/slab.h>
- #include <linux/errqueue.h>
- #include <linux/static_key.h>
-+#include <linux/sdt.h>
-
- #include <net/icmp.h>
- #include <net/inet_common.h>
-@@ -2277,6 +2278,19 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
- }
- EXPORT_SYMBOL(tcp_recvmsg);
-
-+/* We wish to avoid instrumenting TCP state transitions to SYN_SENT as we trace
-+ * those state changes later once the destination address is committed to the
-+ * sk. We also need to deal with the fact that separate timewait sockets are
-+ * used to handle the TIME_WAIT state. We do not want to trace direct
-+ * transitions from CLOSING/FIN_WAIT2 -> CLOSE since they do not represent
-+ * connection close, rather a transition to using the timewait socket.
-+ * Accordingly skip instrumentation of transitions from CLOSING/FIN_WAIT2 to
-+ * CLOSE.
-+ */
-+#define REAL_STATE_CHANGE(old, new) \
-+ (old != new && new != TCP_SYN_SENT && \
-+ ((old != TCP_CLOSING && old != TCP_FIN_WAIT2) || new != TCP_CLOSE))
-+
- void tcp_set_state(struct sock *sk, int state)
- {
- int oldstate = sk->sk_state;
-@@ -2329,6 +2343,18 @@ void tcp_set_state(struct sock *sk, int state)
- * socket sitting in hash tables.
- */
- inet_sk_state_store(sk, state);
-+
-+ if (DTRACE_TCP_ENABLED(state__change) &&
-+ REAL_STATE_CHANGE(oldstate, state))
-+ DTRACE_TCP_NOCHECK(state__change,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, NULL,
-+ struct tcp_sock * : tcpsinfo_t *, tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, NULL,
-+ int : tcplsinfo_t *, oldstate,
-+ int : int, state,
-+ int : int, DTRACE_NET_PROBE_OUTBOUND);
- }
- EXPORT_SYMBOL_GPL(tcp_set_state);
-
-diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
-index 6bf066f924c15a1e14fe70dd1c90fc4d159bf7f0..e29846f273280fdbc88d491db59ec5ad0c170f20 100644
---- a/net/ipv4/tcp_input.c
-+++ b/net/ipv4/tcp_input.c
-@@ -80,6 +80,7 @@
- #include <linux/jump_label_ratelimit.h>
- #include <net/busy_poll.h>
- #include <net/mptcp.h>
-+#include <linux/sdt.h>
-
- int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
-
-@@ -5914,6 +5915,14 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
- struct tcp_sock *tp = tcp_sk(sk);
- struct inet_connection_sock *icsk = inet_csk(sk);
-
-+ DTRACE_TCP(connect__established,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *, TCP_ESTABLISHED,
-+ int, TCP_ESTABLISHED, int, DTRACE_NET_PROBE_INBOUND);
- tcp_set_state(sk, TCP_ESTABLISHED);
- icsk->icsk_ack.lrcvtime = tcp_jiffies32;
-
-@@ -6078,6 +6087,17 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
- */
-
- if (th->rst) {
-+ DTRACE_TCP(connect__refused,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *,
-+ ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, th,
-+ int : tcplsinfo_t *,
-+ sk ? sk->sk_state : TCP_CLOSE,
-+ int, sk ? sk->sk_state : TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_INBOUND);
- tcp_reset(sk);
- goto discard;
- }
-@@ -6400,6 +6420,16 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
- WRITE_ONCE(tp->copied_seq, tp->rcv_nxt);
- }
- smp_mb();
-+
-+ DTRACE_TCP(accept__established,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *, TCP_ESTABLISHED,
-+ int, TCP_ESTABLISHED,
-+ int, DTRACE_NET_PROBE_INBOUND);
- tcp_set_state(sk, TCP_ESTABLISHED);
- sk->sk_state_change(sk);
-
-@@ -6873,6 +6903,19 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
- !want_cookie ? TCP_SYNACK_NORMAL :
- TCP_SYNACK_COOKIE,
- skb);
-+ /* Do not pass in tcp sock as ports/addresses are not yet
-+ * populated - instead translators will fill them in from
-+ * skb data.
-+ */
-+ DTRACE_TCP(state__change,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, NULL,
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *, TCP_LISTEN,
-+ int, TCP_SYN_RECV, int, DTRACE_NET_PROBE_INBOUND);
-+
- if (want_cookie) {
- reqsk_free(req);
- return 0;
-diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
-index ab8ed0fc476976021332c2fe7d04b55222c8c81d..5f76469093a201b3c5d9916c24725cb305ef4980 100644
---- a/net/ipv4/tcp_ipv4.c
-+++ b/net/ipv4/tcp_ipv4.c
-@@ -80,6 +80,7 @@
-
- #include <crypto/hash.h>
- #include <linux/scatterlist.h>
-+#include <linux/sdt.h>
-
- #include <trace/events/tcp.h>
-
-@@ -642,6 +643,21 @@ void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb)
- }
- EXPORT_SYMBOL(tcp_v4_send_check);
-
-+/* Since we want to trace send events in TCP prior to pushing the segment to
-+ * IP - where the IP header is added - we need to construct an argument
-+ * containing relevant IP info so that TCP probe consumers can utilize it.
-+ */
-+static inline void dtrace_tcp_build_iphdr(__be32 saddr, __be32 daddr,
-+ struct iphdr *iph)
-+{
-+ iph->version = 4;
-+ iph->ihl = 5;
-+ iph->tot_len = 5;
-+ iph->protocol = IPPROTO_TCP;
-+ iph->saddr = saddr;
-+ iph->daddr = daddr;
-+}
-+
- /*
- * This routine will send an RST to the other tcp.
- *
-@@ -800,6 +816,39 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
- inet_twsk(sk)->tw_priority : sk->sk_priority;
- transmit_time = tcp_transmit_time(sk);
- }
-+
-+ if (DTRACE_TCP_ENABLED(send) ||
-+ DTRACE_TCP_ENABLED(accept__refused)) {
-+ struct iphdr iph;
-+
-+ dtrace_tcp_build_iphdr(ip_hdr(skb)->daddr, ip_hdr(skb)->saddr,
-+ &iph);
-+
-+ DTRACE_TCP_NOCHECK(send,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, &iph,
-+ struct tcp_sock * : tcpsinfo_t *, NULL,
-+ struct tcphdr * : tcpinfo_t *, &rep.th,
-+ int : tcplsinfo_t *, TCP_CLOSE,
-+ int : int, TCP_CLOSE,
-+ int : int, DTRACE_NET_PROBE_OUTBOUND);
-+ if (th->syn && rep.th.seq == 0)
-+ DTRACE_TCP_NOCHECK(accept__refused,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, &iph,
-+ struct tcp_sock * : tcpsinfo_t *,
-+ NULL,
-+ struct tcphdr * : tcpinfo_t *,
-+ &rep.th,
-+ int : tcplsinfo_t *, TCP_CLOSE,
-+ int : int, TCP_CLOSE,
-+ int : int,
-+ DTRACE_NET_PROBE_OUTBOUND);
-+ }
-+
- ip_send_unicast_reply(ctl_sk,
- skb, &TCP_SKB_CB(skb)->header.h4.opt,
- ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
-@@ -896,6 +945,24 @@ static void tcp_v4_send_ack(const struct sock *sk,
- ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ?
- inet_twsk(sk)->tw_priority : sk->sk_priority;
- transmit_time = tcp_transmit_time(sk);
-+
-+ if (DTRACE_TCP_ENABLED(send)) {
-+ struct iphdr iph;
-+
-+ dtrace_tcp_build_iphdr(ip_hdr(skb)->daddr, ip_hdr(skb)->saddr,
-+ &iph);
-+
-+ DTRACE_TCP_NOCHECK(send,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, &iph,
-+ struct tcp_sock * : tcpsinfo_t *, NULL,
-+ struct tcphdr * : tcpinfo_t *, &rep,
-+ int : tcplsinfo_t *, TCP_CLOSE,
-+ int : int, TCP_CLOSE,
-+ int : int, DTRACE_NET_PROBE_OUTBOUND);
-+ }
-+
- ip_send_unicast_reply(ctl_sk,
- skb, &TCP_SKB_CB(skb)->header.h4.opt,
- ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
-@@ -992,6 +1059,30 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
- tcp_bpf_ca_needs_ecn((struct sock *)req))
- tos |= INET_ECN_ECT_0;
-
-+ if (DTRACE_TCP_ENABLED(send)) {
-+ struct iphdr iph;
-+
-+ dtrace_tcp_build_iphdr(ireq->ir_loc_addr,
-+ ireq->ir_rmt_addr, &iph);
-+
-+ /* Do not supply tcp sk - addresses/ports are not
-+ * committed yet - instead translators will fill them
-+ * in from skb/IP info.
-+ */
-+ DTRACE_TCP_NOCHECK(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, &iph,
-+ struct tcp_sock * : tcpsinfo_t *,
-+ NULL,
-+ struct tcphdr * : tcpinfo_t *,
-+ tcp_hdr(skb),
-+ int : tcplsinfo_t *, TCP_LISTEN,
-+ int, TCP_LISTEN,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
-+ }
-+
- rcu_read_lock();
- err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
- ireq->ir_rmt_addr,
-@@ -1922,7 +2013,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
- const struct iphdr *iph;
- const struct tcphdr *th;
- bool refcounted;
-- struct sock *sk;
-+ struct sock *sk = NULL;
- int ret;
-
- if (skb->pkt_type != PACKET_HOST)
-@@ -1957,6 +2048,15 @@ int tcp_v4_rcv(struct sk_buff *skb)
- if (!sk)
- goto no_tcp_socket;
-
-+ DTRACE_TCP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *, sk ? sk->sk_state : TCP_CLOSE,
-+ int, sk ? sk->sk_state : TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_INBOUND);
- process:
- if (sk->sk_state == TCP_TIME_WAIT)
- goto do_time_wait;
-@@ -2084,6 +2184,18 @@ int tcp_v4_rcv(struct sk_buff *skb)
-
- discard_it:
- /* Discard frame. */
-+ if (DTRACE_TCP_ENABLED(receive) && skb->pkt_type == PACKET_HOST)
-+ DTRACE_TCP_NOCHECK(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *,
-+ ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *,
-+ sk ? sk->sk_state : TCP_CLOSE,
-+ int, sk ? sk->sk_state : TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_INBOUND);
- kfree_skb(skb);
- return 0;
-
-diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
-index 495dda2449fe5a87f78b8b03f32328328c6b8a01..d2e368b7072d2531fb38d731961d73ece3e4fd04 100644
---- a/net/ipv4/tcp_minisocks.c
-+++ b/net/ipv4/tcp_minisocks.c
-@@ -24,6 +24,7 @@
- #include <linux/slab.h>
- #include <linux/sysctl.h>
- #include <linux/workqueue.h>
-+#include <linux/sdt.h>
- #include <linux/static_key.h>
- #include <net/tcp.h>
- #include <net/inet_common.h>
-@@ -328,6 +329,20 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
- */
- inet_twsk_hashdance(tw, sk, &tcp_hashinfo);
- local_bh_enable();
-+
-+ if (DTRACE_TCP_ENABLED(state__change) &&
-+ state != sk->sk_state)
-+ DTRACE_TCP_NOCHECK(state__change,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, NULL,
-+ struct tcp_sock * : tcpsinfo_t *,
-+ tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, NULL,
-+ int : tcplsinfo_t *, sk->sk_state,
-+ int, state,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
- } else {
- /* Sorry, if we're out of memory, just CLOSE this
- * socket up. We've got bigger problems than
-diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
-index e58e2589d7f98f47bbf83ed57b047d02965034d1..aee3d4d6a2ae3a4c340fb41d98277078c48f53b7 100644
---- a/net/ipv4/tcp_output.c
-+++ b/net/ipv4/tcp_output.c
-@@ -44,6 +44,7 @@
- #include <linux/gfp.h>
- #include <linux/module.h>
- #include <linux/static_key.h>
-+#include <linux/sdt.h>
-
- #include <trace/events/tcp.h>
-
-@@ -1384,6 +1385,27 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
- tp->bytes_sent += skb->len - tcp_header_size;
- }
-
-+ DTRACE_TCP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, NULL,
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *, sk->sk_state, int, sk->sk_state,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
-+ if (DTRACE_TCP_ENABLED(connect__request) && th->syn &&
-+ th->ack_seq == 0)
-+ DTRACE_TCP_NOCHECK(connect__request,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *,
-+ ip_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, th,
-+ int : tcplsinfo_t *, sk->sk_state,
-+ int, sk->sk_state,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
-+
- if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
- TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS,
- tcp_skb_pcount(skb));
-@@ -3845,6 +3867,13 @@ int tcp_connect(struct sock *sk)
- tp->retrans_stamp = tcp_time_stamp(tp);
- tcp_connect_queue_skb(sk, buff);
- tcp_ecn_send_syn(sk, buff);
-+ DTRACE_TCP(state__change, struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, ip_hdr(buff),
-+ struct tcp_sock * : tcpsinfo_t *, tp,
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(buff),
-+ int : tcplsinfo_t *, TCP_CLOSE,
-+ int, sk->sk_state, int, DTRACE_NET_PROBE_OUTBOUND);
- tcp_rbtree_insert(&sk->tcp_rtx_queue, buff);
-
- /* Send off SYN; include data in Fast Open. */
-diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
-index e37a2fa65c2944c96929a05b3a882abe06228f5a..5d32f5471d8562795022f7f35853d5d1386c007a 100644
---- a/net/ipv4/udp.c
-+++ b/net/ipv4/udp.c
-@@ -107,6 +107,7 @@
- #include <trace/events/udp.h>
- #include <linux/static_key.h>
- #include <linux/btf_ids.h>
-+#include <linux/sdt.h>
- #include <trace/events/skb.h>
- #include <net/busy_poll.h>
- #include "udp_impl.h"
-@@ -945,6 +946,13 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
- uh->check = CSUM_MANGLED_0;
-
- send:
-+ DTRACE_UDP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *, udp_sk(sk),
-+ struct udphdr * : udpinfo_t *, uh);
-+
- err = ip_send_skb(sock_net(sk), skb);
- if (err) {
- if (err == -ENOBUFS && !inet->recverr) {
-@@ -1845,9 +1853,16 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
- return err;
- }
-
-- if (!peeking)
-+ if (!peeking) {
-+ DTRACE_UDP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *, udp_sk(sk),
-+ struct udphdr * : udpinfo_t *, udp_hdr(skb));
- UDP_INC_STATS(sock_net(sk),
- UDP_MIB_INDATAGRAMS, is_udplite);
-+ }
-
- sock_recv_ts_and_drops(msg, sk, skb);
-
-@@ -2092,6 +2107,15 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
-
- ret = encap_rcv(sk, skb);
- if (ret <= 0) {
-+ DTRACE_UDP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *,
-+ ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *,
-+ udp_sk(sk),
-+ struct udphdr * : udpinfo_t *,
-+ udp_hdr(skb));
- __UDP_INC_STATS(sock_net(sk),
- UDP_MIB_INDATAGRAMS,
- is_udplite);
-diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
-index e96304d8a4a7f70cae11754ac7532c58d61fb261..aed39e366b60565ac1eaf65c26aba2071f539c03 100644
---- a/net/ipv6/ip6_input.c
-+++ b/net/ipv6/ip6_input.c
-@@ -43,6 +43,7 @@
- #include <net/xfrm.h>
- #include <net/inet_ecn.h>
- #include <net/dst_metadata.h>
-+#include <linux/sdt.h>
-
- INDIRECT_CALLABLE_DECLARE(void udp_v6_early_demux(struct sk_buff *));
- INDIRECT_CALLABLE_DECLARE(void tcp_v6_early_demux(struct sk_buff *));
-@@ -145,13 +146,14 @@ static void ip6_list_rcv_finish(struct net *net, struct sock *sk,
- static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- struct net *net)
- {
-- const struct ipv6hdr *hdr;
-+ const struct ipv6hdr *hdr = NULL;
- u32 pkt_len;
- struct inet6_dev *idev;
-+ const char *dropreason;
-
- if (skb->pkt_type == PACKET_OTHERHOST) {
-- kfree_skb(skb);
-- return NULL;
-+ dropreason = "for other host";
-+ goto trace_drop;
- }
-
- rcu_read_lock();
-@@ -163,6 +165,7 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
- !idev || unlikely(idev->cnf.disable_ipv6)) {
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
-+ dropreason = "could not clone shared buffer";
- goto drop;
- }
-
-@@ -181,13 +184,18 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- */
- IP6CB(skb)->iif = skb_valid_dst(skb) ? ip6_dst_idev(skb_dst(skb))->dev->ifindex : dev->ifindex;
-
-- if (unlikely(!pskb_may_pull(skb, sizeof(*hdr))))
-+ if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) {
-+ hdr = ipv6_hdr(skb);
-+ dropreason = "could not pull skb";
- goto err;
-+ }
-
- hdr = ipv6_hdr(skb);
-
-- if (hdr->version != 6)
-+ if (hdr->version != 6) {
-+ dropreason = "header invalid";
- goto err;
-+ }
-
- __IP6_ADD_STATS(net, idev,
- IPSTATS_MIB_NOECTPKTS +
-@@ -203,8 +211,10 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- if ((ipv6_addr_loopback(&hdr->saddr) ||
- ipv6_addr_loopback(&hdr->daddr)) &&
- !(dev->flags & IFF_LOOPBACK) &&
-- !netif_is_l3_master(dev))
-+ !netif_is_l3_master(dev)) {
-+ dropreason = "loopback destination received on interface";
- goto err;
-+ }
-
- /* RFC4291 Errata ID: 3480
- * Interface-Local scope spans only a single interface on a
-@@ -215,8 +225,10 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- if (!(skb->pkt_type == PACKET_LOOPBACK ||
- dev->flags & IFF_LOOPBACK) &&
- ipv6_addr_is_multicast(&hdr->daddr) &&
-- IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
-+ IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1) {
-+ dropreason = "interface-local scope received from other node";
- goto err;
-+ }
-
- /* If enabled, drop unicast packets that were encapsulated in link-layer
- * multicast or broadcast to protected against the so-called "hole-196"
-@@ -225,8 +237,10 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- if (!ipv6_addr_is_multicast(&hdr->daddr) &&
- (skb->pkt_type == PACKET_BROADCAST ||
- skb->pkt_type == PACKET_MULTICAST) &&
-- idev->cnf.drop_unicast_in_l2_multicast)
-+ idev->cnf.drop_unicast_in_l2_multicast) {
-+ dropreason = "unicast packet encapsulated in multi/broadcast";
- goto err;
-+ }
-
- /* RFC4291 2.7
- * Nodes must not originate a packet to a multicast address whose scope
-@@ -234,16 +248,21 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- * must be silently dropped.
- */
- if (ipv6_addr_is_multicast(&hdr->daddr) &&
-- IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0)
-+ IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0) {
-+ dropreason =
-+ "packet to multicast address with reserved scope 0";
- goto err;
-+ }
-
- /*
- * RFC4291 2.7
- * Multicast addresses must not be used as source addresses in IPv6
- * packets or appear in any Routing header.
- */
-- if (ipv6_addr_is_multicast(&hdr->saddr))
-+ if (ipv6_addr_is_multicast(&hdr->saddr)) {
-+ dropreason = "multicast source address in IPv6 packet";
- goto err;
-+ }
-
- /* While RFC4291 is not explicit about v4mapped addresses
- * in IPv6 headers, it seems clear linux dual-stack
-@@ -253,7 +272,10 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- * https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02
- */
- if (ipv6_addr_v4mapped(&hdr->saddr))
-+ {
-+ dropreason = "v4-mapped address in IPv6 packet";
- goto err;
-+ }
-
- skb->transport_header = skb->network_header + sizeof(*hdr);
- IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
-@@ -265,10 +287,12 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- if (pkt_len + sizeof(struct ipv6hdr) > skb->len) {
- __IP6_INC_STATS(net,
- idev, IPSTATS_MIB_INTRUNCATEDPKTS);
-+ dropreason = "truncated packet";
- goto drop;
- }
- if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
-+ dropreason = "could not trim buffer";
- goto drop;
- }
- hdr = ipv6_hdr(skb);
-@@ -276,9 +300,10 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
-
- if (hdr->nexthdr == NEXTHDR_HOP) {
- if (ipv6_parse_hopopts(skb) < 0) {
-- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
-- rcu_read_unlock();
-- return NULL;
-+ dropreason = "could not parse hop opts";
-+ /* do not free skb */
-+ skb = NULL;
-+ goto err;
- }
- }
-
-@@ -293,6 +318,15 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
- drop:
- rcu_read_unlock();
-+trace_drop:
-+ DTRACE_IP(drop__in,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, hdr,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, hdr,
-+ const char * : string, dropreason);
- kfree_skb(skb);
- return NULL;
- }
-@@ -365,6 +399,8 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- struct inet6_dev *idev;
- unsigned int nhoff;
- bool raw;
-+ const struct ipv6hdr *hdr;
-+ const char *dropreason;
-
- /*
- * Parse extension headers
-@@ -374,8 +410,10 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- idev = ip6_dst_idev(skb_dst(skb));
- nhoff = IP6CB(skb)->nhoff;
- if (!have_final) {
-- if (!pskb_pull(skb, skb_transport_offset(skb)))
-+ if (!pskb_pull(skb, skb_transport_offset(skb))) {
-+ dropreason = "could not pull skb";
- goto discard;
-+ }
- nexthdr = skb_network_header(skb)[nhoff];
- }
-
-@@ -392,10 +430,10 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- * ones. This allows foo in UDP encapsulation
- * to work.
- */
-+ dropreason = "non-final protocol";
- goto discard;
- }
- } else if (ipprot->flags & INET6_PROTO_FINAL) {
-- const struct ipv6hdr *hdr;
- int sdif = inet6_sdif(skb);
- struct net_device *dev;
-
-@@ -414,8 +452,10 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- /* skb->dev passed may be master dev for vrfs. */
- if (sdif) {
- dev = dev_get_by_index_rcu(net, sdif);
-- if (!dev)
-+ if (!dev) {
-+ dropreason = "device disappeared";
- goto discard;
-+ }
- } else {
- dev = skb->dev;
- }
-@@ -423,12 +463,16 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- if (ipv6_addr_is_multicast(&hdr->daddr) &&
- !ipv6_chk_mcast_addr(dev, &hdr->daddr,
- &hdr->saddr) &&
-- !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb)))
-+ !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb))) {
-+ dropreason = "destination is multicast";
- goto discard;
-+ }
- }
- if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
-- !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
-+ !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-+ dropreason = "policy failure";
- goto discard;
-+ }
-
- ret = INDIRECT_CALL_2(ipprot->handler, tcp_v6_rcv, udpv6_rcv,
- skb);
-@@ -454,6 +498,8 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
- IPSTATS_MIB_INUNKNOWNPROTOS);
- icmpv6_send(skb, ICMPV6_PARAMPROB,
- ICMPV6_UNK_NEXTHDR, nhoff);
-+ dropreason = "policy failure";
-+ goto trace_drop;
- }
- kfree_skb(skb);
- } else {
-@@ -465,6 +511,17 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
-
- discard:
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
-+trace_drop:
-+ hdr = ipv6_hdr(skb);
-+ DTRACE_IP(drop__in,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, hdr,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, hdr,
-+ const char * : string, dropreason);
-+ rcu_read_unlock();
- kfree_skb(skb);
- }
-
-@@ -480,6 +537,16 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk
-
- int ip6_input(struct sk_buff *skb)
- {
-+ struct ipv6hdr *hdr = ipv6_hdr(skb);
-+
-+ DTRACE_IP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, hdr,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, hdr);
-+
- return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN,
- dev_net(skb->dev), NULL, skb, skb->dev, NULL,
- ip6_input_finish);
-diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
-index 077d43af8226bd202be878885eaaf274776bf648..1c972fb379b5f6e21e0905cdce54e2dff39001d4 100644
---- a/net/ipv6/ip6_output.c
-+++ b/net/ipv6/ip6_output.c
-@@ -55,6 +55,7 @@
- #include <net/l3mdev.h>
- #include <net/lwtunnel.h>
- #include <net/ip_tunnels.h>
-+#include <linux/sdt.h>
-
- static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *skb)
- {
-@@ -62,7 +63,8 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
- struct net_device *dev = dst->dev;
- const struct in6_addr *nexthop;
- struct neighbour *neigh;
-- int ret;
-+ const char *dropreason;
-+ int ret = 0;
-
- if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
- struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
-@@ -83,10 +85,11 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
- dev_loopback_xmit);
-
- if (ipv6_hdr(skb)->hop_limit == 0) {
-+ dropreason = "hoplimit exceeded";
-+
- IP6_INC_STATS(net, idev,
- IPSTATS_MIB_OUTDISCARDS);
-- kfree_skb(skb);
-- return 0;
-+ goto drop;
- }
- }
-
-@@ -95,8 +98,8 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
- if (IPV6_ADDR_MC_SCOPE(&ipv6_hdr(skb)->daddr) <=
- IPV6_ADDR_SCOPE_NODELOCAL &&
- !(dev->flags & IFF_LOOPBACK)) {
-- kfree_skb(skb);
-- return 0;
-+ dropreason = "invalid scope";
-+ goto drop;
- }
- }
-
-@@ -120,9 +123,20 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
- }
- rcu_read_unlock_bh();
-
-+ dropreason = "no route to host";
- IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
-+ ret = -EINVAL;
-+drop:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb),
-+ const char * : string, dropreason);
- kfree_skb(skb);
-- return -EINVAL;
-+ return ret;
- }
-
- static int
-@@ -207,6 +221,15 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
- skb->dev = dev;
-
- if (unlikely(idev->cnf.disable_ipv6)) {
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, "IPv6 is disabled");
-+
- IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
- kfree_skb(skb);
- return 0;
-@@ -243,8 +266,10 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
- struct ipv6hdr *hdr;
- u8 proto = fl6->flowi6_proto;
- int seg_len = skb->len;
-+ const char *dropreason;
- int hlimit = -1;
- u32 mtu;
-+ int err;
-
- head_room = sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dst->dev);
- if (opt)
-@@ -253,10 +278,12 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
- if (unlikely(skb_headroom(skb) < head_room)) {
- struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
- if (!skb2) {
-+ dropreason = "out of memory";
- IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
- IPSTATS_MIB_OUTDISCARDS);
- kfree_skb(skb);
-- return -ENOBUFS;
-+ err = -ENOBUFS;
-+ goto drop;
- }
- if (skb->sk)
- skb_set_owner_w(skb2, skb->sk);
-@@ -313,6 +340,14 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
- if (unlikely(!skb))
- return 0;
-
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, hdr,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, hdr);
-+
- /* hooks should never assume socket lock is held.
- * we promote our socket to non const
- */
-@@ -327,9 +362,21 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
- */
- ipv6_local_error((struct sock *)sk, EMSGSIZE, fl6, mtu);
-
-+ dropreason = "fragmentation failure";
- IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS);
-+ err = -EMSGSIZE;
-+drop:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- kfree_skb(skb);
-- return -EMSGSIZE;
-+ return err;
- }
- EXPORT_SYMBOL(ip6_xmit);
-
-@@ -464,22 +511,33 @@ int ip6_forward(struct sk_buff *skb)
- struct ipv6hdr *hdr = ipv6_hdr(skb);
- struct inet6_skb_parm *opt = IP6CB(skb);
- struct net *net = dev_net(dst->dev);
-+ const char *dropreason;
-+ int err = -EINVAL;
- u32 mtu;
-
-- if (net->ipv6.devconf_all->forwarding == 0)
-+ if (net->ipv6.devconf_all->forwarding == 0) {
-+ dropreason = "forwarding disabled";
- goto error;
-+ }
-
-- if (skb->pkt_type != PACKET_HOST)
-+ if (skb->pkt_type != PACKET_HOST) {
-+ dropreason = "non-host packet type cannot be forwarded";
- goto drop;
-+ }
-
-- if (unlikely(skb->sk))
-+ if (unlikely(skb->sk)) {
-+ dropreason = "socket found for packet to be forwarded";
- goto drop;
-+ }
-
-- if (skb_warn_if_lro(skb))
-+ if (skb_warn_if_lro(skb)) {
-+ dropreason = "LRO warning";
- goto drop;
-+ }
-
- if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
-+ dropreason = "forwarding disabled by policy";
- goto drop;
- }
-
-@@ -510,8 +568,9 @@ int ip6_forward(struct sk_buff *skb)
- icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0);
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
-
-- kfree_skb(skb);
-- return -ETIMEDOUT;
-+ dropreason = "hoplimit exceeded";
-+ err = -ETIMEDOUT;
-+ goto drop;
- }
-
- /* XXX: idev->cnf.proxy_ndp? */
-@@ -521,6 +580,7 @@ int ip6_forward(struct sk_buff *skb)
- if (proxied > 0)
- return ip6_input(skb);
- else if (proxied < 0) {
-+ dropreason = "proxy router cannot forward";
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
- goto drop;
- }
-@@ -528,6 +588,7 @@ int ip6_forward(struct sk_buff *skb)
-
- if (!xfrm6_route_forward(skb)) {
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
-+ dropreason = "forwarding disabled for destination";
- goto drop;
- }
- dst = skb_dst(skb);
-@@ -567,9 +628,12 @@ int ip6_forward(struct sk_buff *skb)
-
- /* This check is security critical. */
- if (addrtype == IPV6_ADDR_ANY ||
-- addrtype & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LOOPBACK))
-+ addrtype & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LOOPBACK)) {
-+ dropreason = "invalid address type for forwarding";
- goto error;
-+ }
- if (addrtype & IPV6_ADDR_LINKLOCAL) {
-+ dropreason = "invalid address type for forwarding";
- icmpv6_send(skb, ICMPV6_DEST_UNREACH,
- ICMPV6_NOT_NEIGHBOUR, 0);
- goto error;
-@@ -583,17 +647,20 @@ int ip6_forward(struct sk_buff *skb)
- if (ip6_pkt_too_big(skb, mtu)) {
- /* Again, force OUTPUT device used as source address */
- skb->dev = dst->dev;
-+
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INTOOBIGERRORS);
- __IP6_INC_STATS(net, ip6_dst_idev(dst),
- IPSTATS_MIB_FRAGFAILS);
-- kfree_skb(skb);
-- return -EMSGSIZE;
-+ dropreason = "packet too big";
-+ err = -EMSGSIZE;
-+ goto drop;
- }
-
- if (skb_cow(skb, dst->dev->hard_header_len)) {
- __IP6_INC_STATS(net, ip6_dst_idev(dst),
- IPSTATS_MIB_OUTDISCARDS);
-+ dropreason = "copy-on-write failed";
- goto drop;
- }
-
-@@ -610,6 +677,15 @@ int ip6_forward(struct sk_buff *skb)
- error:
- __IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
- drop:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, hdr,
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, hdr,
-+ const char * : string, dropreason);
-+
- kfree_skb(skb);
- return -EINVAL;
- }
-@@ -1445,6 +1521,7 @@ static int __ip6_append_data(struct sock *sk,
- unsigned int maxnonfragsize, headersize;
- unsigned int wmem_alloc_delta = 0;
- bool paged, extra_uref = false;
-+ const char *dropreason;
-
- skb = skb_peek_tail(queue);
- if (!skb) {
-@@ -1484,6 +1561,7 @@ static int __ip6_append_data(struct sock *sk,
- sk->sk_protocol == IPPROTO_RAW)) {
- ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
- sizeof(struct ipv6hdr));
-+ dropreason = "fragmentation needed but disabled";
- goto emsgsize;
- }
-
-@@ -1496,7 +1574,9 @@ static int __ip6_append_data(struct sock *sk,
- emsgsize:
- pmtu = max_t(int, mtu - headersize + sizeof(struct ipv6hdr), 0);
- ipv6_local_error(sk, EMSGSIZE, fl6, pmtu);
-- return -EMSGSIZE;
-+ dropreason = "packet too big";
-+ err = -EMSGSIZE;
-+ goto trace_drop;
- }
-
- /* CHECKSUM_PARTIAL only with no extension headers and when
-@@ -1511,8 +1591,11 @@ static int __ip6_append_data(struct sock *sk,
-
- if (flags & MSG_ZEROCOPY && length && sock_flag(sk, SOCK_ZEROCOPY)) {
- uarg = sock_zerocopy_realloc(sk, length, skb_zcopy(skb));
-- if (!uarg)
-- return -ENOBUFS;
-+ if (!uarg) {
-+ err = -ENOBUFS;
-+ dropreason = "out of memory";
-+ goto error;
-+ }
- extra_uref = !skb_zcopy(skb); /* only ref on new uarg */
- if (rt->dst.dev->features & NETIF_F_SG &&
- csummode == CHECKSUM_PARTIAL) {
-@@ -1614,6 +1697,7 @@ static int __ip6_append_data(struct sock *sk,
- copy = datalen - transhdrlen - fraggap - pagedlen;
- if (copy < 0) {
- err = -EINVAL;
-+ dropreason = "invalid fragment";
- goto error;
- }
- if (transhdrlen) {
-@@ -1626,11 +1710,13 @@ static int __ip6_append_data(struct sock *sk,
- 2 * sk->sk_sndbuf)
- skb = alloc_skb(alloclen + hh_len,
- sk->sk_allocation);
-- if (unlikely(!skb))
-- err = -ENOBUFS;
- }
-- if (!skb)
-+ if (unlikely(!skb)) {
-+ err = -ENOBUFS;
-+ dropreason = "out of memory";
- goto error;
-+ }
-+
- /*
- * Fill in the control structures
- */
-@@ -1662,7 +1748,9 @@ static int __ip6_append_data(struct sock *sk,
- getfrag(from, data + transhdrlen, offset,
- copy, fraggap, skb) < 0) {
- err = -EFAULT;
-+ dropreason = "could not get fragment";
- kfree_skb(skb);
-+ skb = NULL;
- goto error;
- }
-
-@@ -1706,20 +1794,25 @@ static int __ip6_append_data(struct sock *sk,
- offset, copy, off, skb) < 0) {
- __skb_trim(skb, off);
- err = -EFAULT;
-+ dropreason = "could not get fragment";
- goto error;
- }
- } else if (!uarg || !uarg->zerocopy) {
- int i = skb_shinfo(skb)->nr_frags;
-
- err = -ENOMEM;
-- if (!sk_page_frag_refill(sk, pfrag))
-+ if (!sk_page_frag_refill(sk, pfrag)) {
-+ dropreason = "out of memory";
- goto error;
-+ }
-
- if (!skb_can_coalesce(skb, i, pfrag->page,
- pfrag->offset)) {
- err = -EMSGSIZE;
-- if (i == MAX_SKB_FRAGS)
-+ if (i == MAX_SKB_FRAGS) {
-+ dropreason = "too many fragments";
- goto error;
-+ }
-
- __skb_fill_page_desc(skb, i, pfrag->page,
- pfrag->offset, 0);
-@@ -1729,8 +1822,10 @@ static int __ip6_append_data(struct sock *sk,
- copy = min_t(int, copy, pfrag->size - pfrag->offset);
- if (getfrag(from,
- page_address(pfrag->page) + pfrag->offset,
-- offset, copy, skb->len, skb) < 0)
-+ offset, copy, skb->len, skb) < 0) {
-+ dropreason = "could not get fragment";
- goto error_efault;
-+ }
-
- pfrag->offset += copy;
- skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
-@@ -1740,8 +1835,10 @@ static int __ip6_append_data(struct sock *sk,
- wmem_alloc_delta += copy;
- } else {
- err = skb_zerocopy_iter_dgram(skb, from, copy);
-- if (err < 0)
-+ if (err < 0) {
-+ dropreason = "skb iteration failure\n";
- goto error;
-+ }
- }
- offset += copy;
- length -= copy;
-@@ -1758,6 +1855,16 @@ static int __ip6_append_data(struct sock *sk,
- sock_zerocopy_put_abort(uarg, extra_uref);
- cork->length -= length;
- IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
-+trace_drop:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
- return err;
- }
-@@ -1905,9 +2012,20 @@ int ip6_send_skb(struct sk_buff *skb)
- if (err) {
- if (err > 0)
- err = net_xmit_errno(err);
-- if (err)
-+ if (err) {
-+ /* skb may have been freed */
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, NULL,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, "out of memory");
-+
- IP6_INC_STATS(net, rt->rt6i_idev,
- IPSTATS_MIB_OUTDISCARDS);
-+ }
- }
-
- return err;
-@@ -1933,9 +2051,19 @@ static void __ip6_flush_pending_frames(struct sock *sk,
- struct sk_buff *skb;
-
- while ((skb = __skb_dequeue_tail(queue)) != NULL) {
-- if (skb_dst(skb))
-+ if (skb_dst(skb)) {
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *,
-+ ipv6_hdr(skb),
-+ const char * : string, "flushing pending frames");
- IP6_INC_STATS(sock_net(sk), ip6_dst_idev(skb_dst(skb)),
- IPSTATS_MIB_OUTDISCARDS);
-+ }
- kfree_skb(skb);
- }
-
-diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
-index 8cd2782a31e4c38e227064cdb60eaccf45352192..e90cb6e0781d367146da70c59ed12bc757819792 100644
---- a/net/ipv6/mcast.c
-+++ b/net/ipv6/mcast.c
-@@ -60,6 +60,8 @@
-
- #include <net/ip6_checksum.h>
-
-+#include <linux/sdt.h>
-+
- /* Ensure that we have struct in6_addr aligned on 32bit word. */
- static int __mld2_query_bugs[] __attribute__((__unused__)) = {
- BUILD_BUG_ON_ZERO(offsetof(struct mld2_query, mld2q_srcs) % 4),
-@@ -1644,6 +1646,7 @@ static void mld_sendpack(struct sk_buff *skb)
- int payload_len, mldlen;
- struct inet6_dev *idev;
- struct net *net = dev_net(skb->dev);
-+ const char *dropreason;
- int err;
- struct flowi6 fl6;
- struct dst_entry *dst;
-@@ -1673,26 +1676,45 @@ static void mld_sendpack(struct sk_buff *skb)
- dst = NULL;
- }
- skb_dst_set(skb, dst);
-- if (err)
-- goto err_out;
-+ if (err) {
-+ kfree_skb(skb);
-+ skb = NULL;
-+ dropreason = "out of memory";
-+ goto out;
-+ }
-+
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
-
- err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
- net, net->ipv6.igmp_sk, skb, NULL, skb->dev,
- dst_output);
-+ dropreason = "multicast send error";
- out:
- if (!err) {
- ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT);
- ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
- } else {
-+ /* skb may have been freed */
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, idev->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
-+
- IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
- }
-
- rcu_read_unlock();
- return;
--
--err_out:
-- kfree_skb(skb);
-- goto out;
- }
-
- static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
-@@ -1979,7 +2001,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
- {
- struct net *net = dev_net(dev);
- struct sock *sk = net->ipv6.igmp_sk;
-- struct inet6_dev *idev;
-+ struct inet6_dev *idev = NULL;
- struct sk_buff *skb;
- struct mld_msg *hdr;
- const struct in6_addr *snd_addr, *saddr;
-@@ -1990,6 +2012,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
- u8 ra[8] = { IPPROTO_ICMPV6, 0,
- IPV6_TLV_ROUTERALERT, 2, 0, 0,
- IPV6_TLV_PADN, 0 };
-+ const char *dropreason;
- struct flowi6 fl6;
- struct dst_entry *dst;
-
-@@ -2011,10 +2034,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
-
- if (!skb) {
- rcu_read_lock();
-- IP6_INC_STATS(net, __in6_dev_get(dev),
-- IPSTATS_MIB_OUTDISCARDS);
-- rcu_read_unlock();
-- return;
-+ dropreason = "out of memory";
-+ goto out;
- }
- skb->priority = TC_PRIO_CONTROL;
- skb_reserve(skb, hlen);
-@@ -2049,26 +2070,43 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
- dst = icmp6_dst_alloc(skb->dev, &fl6);
- if (IS_ERR(dst)) {
- err = PTR_ERR(dst);
-- goto err_out;
-+ kfree_skb(skb);
-+ skb = NULL;
-+ dropreason = "out of memory";
-+ goto out;
- }
-
- skb_dst_set(skb, dst);
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
- err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
- net, sk, skb, NULL, skb->dev,
- dst_output);
-+ dropreason = "multicast send error";
- out:
- if (!err) {
- ICMP6MSGOUT_INC_STATS(net, idev, type);
- ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
-- } else
-+ } else {
-+ /* skb may have been freed */
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, NULL,
-+ struct net_device * : ifinfo_t *, idev->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, NULL,
-+ const char * : string, dropreason);
- IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
-+ }
-
- rcu_read_unlock();
- return;
--
--err_out:
-- kfree_skb(skb);
-- goto out;
- }
-
- static void mld_send_initial_cr(struct inet6_dev *idev)
-diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
-index 76717478f1733fb753c067efaa5dd210320e0261..35ae4eaffd89ebc7fa85c1142d75b2f3c175254b 100644
---- a/net/ipv6/ndisc.c
-+++ b/net/ipv6/ndisc.c
-@@ -68,6 +68,7 @@
-
- #include <linux/netfilter.h>
- #include <linux/netfilter_ipv6.h>
-+#include <linux/sdt.h>
-
- static u32 ndisc_hash(const void *pkey,
- const struct net_device *dev,
-@@ -505,6 +506,14 @@ static void ndisc_send_skb(struct sk_buff *skb,
- idev = __in6_dev_get(dst->dev);
- IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
-
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
-+
- err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
- net, sk, skb, NULL, dst->dev,
- dst_output);
-diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
-index af36acc1a6448104ca6c71854e84b1a4bab4b3ea..811a88767a5c67d51fd594cdcbbc4b9d51fd00f1 100644
---- a/net/ipv6/output_core.c
-+++ b/net/ipv6/output_core.c
-@@ -10,6 +10,7 @@
- #include <net/addrconf.h>
- #include <net/secure_seq.h>
- #include <linux/netfilter.h>
-+#include <linux/sdt.h>
-
- static u32 __ipv6_select_ident(struct net *net,
- const struct in6_addr *dst,
-@@ -164,6 +165,14 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
-
- skb->protocol = htons(ETH_P_IPV6);
-
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
-+
- return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
- net, sk, skb, NULL, skb_dst(skb)->dev,
- dst_output);
-diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
-index 6e4ab80a3b94420a85769edf45bbf69e2ba74e39..f88c9441ec51b817db2159c40057f3a2bbcf0268 100644
---- a/net/ipv6/raw.c
-+++ b/net/ipv6/raw.c
-@@ -58,6 +58,7 @@
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/export.h>
-+#include <linux/sdt.h>
-
- #define ICMPV6_HDRLEN 4 /* ICMPv6 header, RFC 4443 Section 2.1 */
-
-@@ -622,26 +623,34 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
- struct ipv6_pinfo *np = inet6_sk(sk);
- struct net *net = sock_net(sk);
- struct ipv6hdr *iph;
-- struct sk_buff *skb;
-+ struct sk_buff *skb = NULL;
- int err;
- struct rt6_info *rt = (struct rt6_info *)*dstp;
- int hlen = LL_RESERVED_SPACE(rt->dst.dev);
- int tlen = rt->dst.dev->needed_tailroom;
-+ const char *dropreason;
-
- if (length > rt->dst.dev->mtu) {
- ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu);
-- return -EMSGSIZE;
-+ dropreason = "packet too big";
-+ err = -EMSGSIZE;
-+ goto error_check;
-+ }
-+ if (length < sizeof(struct ipv6hdr)) {
-+ dropreason = "packet too short";
-+ err = -EINVAL;
-+ goto error_check;
- }
-- if (length < sizeof(struct ipv6hdr))
-- return -EINVAL;
- if (flags&MSG_PROBE)
- goto out;
-
- skb = sock_alloc_send_skb(sk,
- length + hlen + tlen + 15,
- flags & MSG_DONTWAIT, &err);
-- if (!skb)
-+ if (!skb) {
-+ dropreason = "out of memory";
- goto error;
-+ }
- skb_reserve(skb, hlen);
-
- skb->protocol = htons(ETH_P_IPV6);
-@@ -665,7 +674,8 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
- if (err) {
- err = -EFAULT;
- kfree_skb(skb);
-- goto error;
-+ dropreason = "could not copy msg";
-+ goto error_check;
- }
-
- skb_dst_set(skb, &rt->dst);
-@@ -684,6 +694,13 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
- */
- rcu_read_lock();
- IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
-+ DTRACE_IP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb->sk,
-+ void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-+ struct net_device * : ifinfo_t *, skb->dev,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
- err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb,
- NULL, rt->dst.dev, dst_output);
- if (err > 0)
-@@ -691,6 +708,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
- if (err) {
- IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
- rcu_read_unlock();
-+ dropreason = "raw send error";
- goto error_check;
- }
- rcu_read_unlock();
-@@ -700,6 +718,14 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
- error:
- IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
- error_check:
-+ DTRACE_IP(drop__out,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-+ void_ip_t * : ipinfo_t *, skb ? ipv6_hdr(skb) : NULL,
-+ struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
-+ struct iphdr * : ipv4info_t *, NULL,
-+ struct ipv6hdr * : ipv6info_t *, skb ? ipv6_hdr(skb) : NULL,
-+ const char * : string, dropreason);
- if (err == -ENOBUFS && !np->recverr)
- err = 0;
- return err;
-diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
-index 991dc36f95ff02b15a49dd2f77be8d2f0d94861a..acc63c45565109952355d2e2949ed971904c575d 100644
---- a/net/ipv6/tcp_ipv6.c
-+++ b/net/ipv6/tcp_ipv6.c
-@@ -65,6 +65,7 @@
-
- #include <crypto/hash.h>
- #include <linux/scatterlist.h>
-+#include <linux/sdt.h>
-
- #include <trace/events/tcp.h>
-
-@@ -496,6 +497,20 @@ static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- return 0;
- }
-
-+/* Since we want to trace send events in TCP prior to pushing the segment to
-+ * IP - where the IP header is added - we need to construct an argument
-+ * containing relevant IP info so that TCP probe consumers can utilize it.
-+ */
-+static inline void dtrace_tcp_build_ipv6hdr(struct in6_addr *saddr,
-+ struct in6_addr *daddr,
-+ struct ipv6hdr *ip6h)
-+{
-+ ip6h->version = 6;
-+ ip6h->payload_len = 0;
-+ ip6h->nexthdr = IPPROTO_TCP;
-+ ip6h->saddr = *saddr;
-+ ip6h->daddr = *daddr;
-+}
-
- static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
- struct flowi *fl,
-@@ -540,6 +555,32 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
- opt = ireq->ipv6_opt;
- if (!opt)
- opt = rcu_dereference(np->opt);
-+
-+ if (DTRACE_TCP_ENABLED(send)) {
-+ struct ipv6hdr ip6h;
-+
-+ dtrace_tcp_build_ipv6hdr(&ireq->ir_v6_loc_addr,
-+ &ireq->ir_v6_rmt_addr, &ip6h);
-+
-+ /* Do not supply tcp sk - addresses/ports are not
-+ * committed yet - instead translators will fill them
-+ * in from IP/TCP data.
-+ */
-+ DTRACE_TCP_NOCHECK(send,
-+ struct sk_buff * : pktinfo_t *,
-+ NULL,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, &ip6h,
-+ struct tcp_sock * : tcpsinfo_t *,
-+ NULL,
-+ struct tcphdr * : tcpinfo_t *,
-+ tcp_hdr(skb),
-+ int : tcplsinfo_t *, TCP_LISTEN,
-+ int, TCP_LISTEN,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
-+ }
-+
- err = ip6_xmit(sk, skb, fl6, sk->sk_mark, opt,
- tclass, sk->sk_priority);
- rcu_read_unlock();
-@@ -969,6 +1010,49 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
- dst = ip6_dst_lookup_flow(sock_net(ctl_sk), ctl_sk, &fl6, NULL);
- if (!IS_ERR(dst)) {
- skb_dst_set(buff, dst);
-+
-+ if (DTRACE_TCP_ENABLED(send) ||
-+ DTRACE_TCP_ENABLED(accept__refused)) {
-+ struct ipv6hdr ip6h;
-+
-+ dtrace_tcp_build_ipv6hdr(&fl6.saddr, &fl6.daddr,
-+ &ip6h);
-+
-+ /* Do not supply tcp sk - addresses/ports are not
-+ * committed yet - instead translators will fill them
-+ * in from IP/TCP data.
-+ */
-+ DTRACE_TCP_NOCHECK(send,
-+ struct sk_buff * : pktinfo_t *,
-+ NULL,
-+ struct sock * : csinfo_t *, NULL,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, &ip6h,
-+ struct tcp_sock * : tcpsinfo_t *,
-+ NULL,
-+ struct tcphdr * : tcpinfo_t *, t1,
-+ int : tcplsinfo_t *, TCP_CLOSE,
-+ int, TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_OUTBOUND);
-+ if (rst && th->syn && th->ack == 0)
-+ DTRACE_TCP_NOCHECK(accept__refused,
-+ struct sk_buff * :
-+ pktinfo_t *, NULL,
-+ struct sock * : csinfo_t *,
-+ NULL,
-+ __dtrace_tcp_void_ip_t * :
-+ ipinfo_t *, &ip6h,
-+ struct tcp_sock * :
-+ tcpsinfo_t *, NULL,
-+ struct tcphdr * :
-+ tcpinfo_t *, t1,
-+ int : tcplsinfo_t *,
-+ TCP_CLOSE,
-+ int, TCP_CLOSE,
-+ int,
-+ DTRACE_NET_PROBE_OUTBOUND);
-+ }
-+
- ip6_xmit(ctl_sk, buff, &fl6, fl6.flowi6_mark, NULL,
- tclass & ~INET_ECN_MASK, priority);
- TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
-@@ -1583,7 +1667,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
- const struct tcphdr *th;
- const struct ipv6hdr *hdr;
- bool refcounted;
-- struct sock *sk;
-+ struct sock *sk = NULL;
- int ret;
- struct net *net = dev_net(skb->dev);
-
-@@ -1618,6 +1702,15 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
- if (!sk)
- goto no_tcp_socket;
-
-+ DTRACE_TCP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *, hdr,
-+ struct tcp_sock * : tcpsinfo_t *, tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, th,
-+ int : tcplsinfo_t *, sk ? sk->sk_state : TCP_CLOSE,
-+ int, sk ? sk->sk_state : TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_INBOUND);
- process:
- if (sk->sk_state == TCP_TIME_WAIT)
- goto do_time_wait;
-@@ -1737,6 +1830,18 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
- }
-
- discard_it:
-+ if (DTRACE_TCP_ENABLED(receive) && skb->pkt_type == PACKET_HOST)
-+ DTRACE_TCP_NOCHECK(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ __dtrace_tcp_void_ip_t * : ipinfo_t *,
-+ ipv6_hdr(skb),
-+ struct tcp_sock * : tcpsinfo_t *, tcp_sk(sk),
-+ struct tcphdr * : tcpinfo_t *, tcp_hdr(skb),
-+ int : tcplsinfo_t *,
-+ sk ? sk->sk_state : TCP_CLOSE,
-+ int, sk ? sk->sk_state : TCP_CLOSE,
-+ int, DTRACE_NET_PROBE_INBOUND);
- kfree_skb(skb);
- return 0;
-
-diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
-index 29d9691359b9c49ccb56a11f79e3658b1a76700d..996afe0fb0571ba7afe4d0da0bfcd8cfa592f2a4 100644
---- a/net/ipv6/udp.c
-+++ b/net/ipv6/udp.c
-@@ -51,6 +51,7 @@
-
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
-+#include <linux/sdt.h>
- #include <trace/events/skb.h>
- #include "udp_impl.h"
-
-@@ -386,8 +387,15 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
- kfree_skb(skb);
- return err;
- }
-- if (!peeking)
-+ if (!peeking) {
- SNMP_INC_STATS(mib, UDP_MIB_INDATAGRAMS);
-+ DTRACE_UDP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *, udp_sk(sk),
-+ struct udphdr * : udpinfo_t *, udp_hdr(skb));
-+ }
-
- sock_recv_ts_and_drops(msg, sk, skb);
-
-@@ -685,6 +693,15 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
-
- ret = encap_rcv(sk, skb);
- if (ret <= 0) {
-+ DTRACE_UDP(receive,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *,
-+ ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *,
-+ udp_sk(sk),
-+ struct udphdr * : udpinfo_t *,
-+ udp_hdr(skb));
- __UDP_INC_STATS(sock_net(sk),
- UDP_MIB_INDATAGRAMS,
- is_udplite);
-@@ -1238,6 +1255,13 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
- err = 0;
- }
- } else {
-+ DTRACE_UDP(send,
-+ struct sk_buff * : pktinfo_t *, skb,
-+ struct sock * : csinfo_t *, sk,
-+ void_ip_t * : ipinfo_t *, ip_hdr(skb),
-+ struct udp_sock * : udpsinfo_t *, udp_sk(sk),
-+ struct udphdr * : udpinfo_t *, uh);
-+
- UDP6_INC_STATS(sock_net(sk),
- UDP_MIB_OUTDATAGRAMS, is_udplite);
- }
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch
deleted file mode 100644
index 27829eae90fd..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0018-dtrace-add-sample-script-for-building-DTrace-on-Fedo.patch
+++ /dev/null
@@ -1,241 +0,0 @@
-From 6e49525673d614475c5e9b7b164bd48bad93b4a3 Mon Sep 17 00:00:00 2001
-From: Eugene Loh <eugene.loh@oracle.com>
-Date: Mon, 12 Aug 2019 20:51:06 -0700
-Subject: [PATCH 18/19] dtrace: add sample script for building DTrace on Fedora
-
-Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
----
- samples/dtrace/DTrace-on-Fedora.sh | 221 +++++++++++++++++++++++++++++
- 1 file changed, 221 insertions(+)
- create mode 100755 samples/dtrace/DTrace-on-Fedora.sh
-
-diff --git a/samples/dtrace/DTrace-on-Fedora.sh b/samples/dtrace/DTrace-on-Fedora.sh
-new file mode 100755
-index 0000000000000000000000000000000000000000..3857027381a54e17a12245e5e511ca3c096ee6d8
---- /dev/null
-+++ b/samples/dtrace/DTrace-on-Fedora.sh
-@@ -0,0 +1,221 @@
-+#!/bin/sh
-+
-+# Oracle Linux DTrace.
-+# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
-+# Licensed under the Universal Permissive License v 1.0 as shown at
-+# http://oss.oracle.com/licenses/upl.
-+#
-+
-+# Oracle has been working in recent years on porting DTrace, the
-+# dynamic tracing tool, to Linux. DTrace offers easy-to-use, powerful,
-+# safe, and unintrusive tracing. Oracle's initial focus was the Oracle
-+# Unbreakable Enterprise Kernel (UEK), but DTrace runs on upstream Linux
-+# kernels and other distributions' Linux kernels as well. Note that at
-+# the moment, Oracle is in the process of upstreaming DTrace-related work
-+# and reimplementing DTrace itself on top of existing kernel infrastructure
-+# such as eBPF.
-+
-+# This script illustrates how to build DTrace on Fedora on x86.
-+# It is intended as a tutorial rather than a robust, turn-key utility.
-+# Read and understand the steps as you execute them. The steps are
-+# similar to what one does to build DTrace on other Linux distributions.
-+
-+# Useful references on building a custom Fedora kernel include:
-+# https://fedoraproject.org/wiki/Building_a_custom_kernel
-+# https://fedoraproject.org/wiki/Building_a_custom_kernel#Building_Vanilla_upstream_kernel
-+# Roughly speaking, you should have about 20 Gbyte of disk space
-+# available and expect to wait a few hours for the build to complete.
-+
-+# The overall process is:
-+# 1. download and build the CTF library for DTrace to use
-+# 2. download Fedora kernel source code
-+# 3. prepare DTrace patches to apply
-+# 4. prepare the kernel source code
-+# a. Linux base code
-+# b. apply Linux patches (if any)
-+# c. apply Fedora patches
-+# d. apply DTrace patches
-+# e. prepare makefile and config
-+# 5. build the kernel
-+# 6. reboot
-+# 7. download and build the DTrace userspace utility
-+
-+
-+# pick one
-+# DTrace patches change relatively infrequently.
-+# So DTrace_branch might not have to match your Fedora kernel version exactly.
-+#fedora_release=f29; DTrace_branch=5.2.7 ; num_DTrace_patches=19
-+ fedora_release=f30; DTrace_branch=5.2.7 ; num_DTrace_patches=19
-+
-+# Step 1: download and build the CTF library for DTrace to use
-+
-+sudo dnf install -y git
-+git clone https://github.com/oracle/libdtrace-ctf.git
-+cd libdtrace-ctf
-+sudo dnf builddep -y libdtrace-ctf.spec # install dependencies
-+make
-+sudo make install
-+cd ..
-+
-+# Step 2: download Fedora kernel source code
-+
-+sudo dnf install -y fedora-packager
-+fedpkg co -a kernel # anonymous clone of Fedora patches
-+cd kernel
-+git checkout origin/$fedora_release
-+fedpkg sources # download tarballs of kernel sources
-+sudo dnf builddep -y kernel.spec # install dependencies
-+cd ..
-+
-+# Step 3: prepare DTrace patches to apply
-+
-+# download DTrace kernel code
-+git clone https://github.com/oracle/dtrace-linux-kernel.git
-+cd dtrace-linux-kernel/
-+git checkout origin/$DTrace_branch
-+
-+# The DTrace patches will be the most recent commits.
-+# Make sure you use all of them but nothing before that.
-+# Make sure the top patches are DTrace
-+# and the next one after them is the Linux baseline you want.
-+# E.g., the top commits here are DTrace, and the last one is Linux upstream:
-+# [...]
-+# 66f76fef08e3 dtrace: modular components and x86 support
-+# 25f11bb97fb9 dtrace: core and x86
-+# 3c5af76fa5fb waitfd: new syscall implementing waitpid() over fds
-+# e95e4350d02b kallsyms: introduce new /proc/kallmodsyms including builtin modules too
-+# 86e43efc644c ctf: generate CTF information for the kernel
-+# a3b22b9f11d9 (tag: v5.0-rc7) Linux 5.0-rc7
-+git log -n $(($num_DTrace_patches + 1)) --oneline
-+
-+# generate the DTrace patches
-+git format-patch -$num_DTrace_patches
-+
-+cd ..
-+
-+# Step 4: prepare the kernel source code
-+
-+# Step 4a: Linux base code
-+
-+if [ -e kernel/linux-*.xz ]; then
-+ /usr/bin/xz -dc kernel/linux-*.tar.xz | /usr/bin/tar -xof -
-+else
-+ tar xzf kernel/linux-*.tar.gz
-+fi
-+
-+# make a git repo so patches can be applied
-+cd linux-*
-+git init
-+git config user.email "kernel-team@fedoraproject.org"
-+git config user.name "Fedora Kernel Team"
-+git config gc.auto 0
-+git add .
-+git commit -a -q -m "baseline"
-+
-+# Step 4b: apply Linux patches (if any)
-+
-+if [ -e ../kernel/patch-*.xz ]; then
-+ xzcat ../kernel/patch-*.xz | patch -p1 -F1 -s
-+ git commit -a -m "Stable update"
-+fi
-+
-+# Step 4c: apply Fedora patches
-+
-+for x in `awk '/^Patch/ {print $2}' ../kernel/kernel.spec`; do
-+ git am ../kernel/$x
-+done
-+
-+# Step 4d: apply DTrace patches
-+
-+for x in ../dtrace-linux-kernel/00*.patch; do
-+ git am $x
-+ if [ $? -ne 0 ]; then
-+ echo DTrace patch did not apply cleanly
-+ exit 1
-+ fi
-+done
-+
-+# Step 4e: prepare makefile and config
-+
-+# modify the version tag in the Makefile
-+sed -i.old \
-+ 's/^EXTRAVERSION =.*$/EXTRAVERSION = -200.DTrace_'$fedora_release'.x86_64/' \
-+ Makefile
-+
-+# use the Fedora config file
-+cp ../kernel/kernel-x86_64.config .config
-+
-+# modify the config file for DTrace
-+sed -i \
-+ -e 's/# CONFIG_UNWINDER_FRAME_POINTER is not set/CONFIG_UNWINDER_FRAME_POINTER=y/' \
-+ -e 's/CONFIG_UNWINDER_ORC=y/# CONFIG_UNWINDER_ORC is not set/' .config
-+echo "CONFIG_DTRACE=y" >> .config
-+echo "CONFIG_DT_CORE=m" >> .config
-+echo "CONFIG_DT_FASTTRAP=m" >> .config
-+echo "CONFIG_DT_PROFILE=m" >> .config
-+echo "CONFIG_DT_SDT=m" >> .config
-+echo "CONFIG_DT_SDT_PERF=y" >> .config
-+echo "CONFIG_DT_FBT=m" >> .config
-+echo "CONFIG_DT_SYSTRACE=m" >> .config
-+echo "CONFIG_DT_DT_TEST=m" >> .config
-+echo "CONFIG_DT_DT_PERF=m" >> .config
-+echo "CONFIG_DT_DEBUG=y" >> .config
-+echo "# CONFIG_DT_DEBUG_MUTEX is not set" >> .config
-+
-+# Step 5: build the kernel
-+
-+# (might take hours)
-+make olddefconfig
-+make -j4
-+make -j4 ctf
-+
-+# install
-+sudo make modules_install
-+sudo make install
-+sudo make INSTALL_HDR_PATH=/usr headers_install
-+cd ..
-+
-+# Step 6: reboot
-+
-+sudo reboot
-+
-+# Step 7: download and build the DTrace userspace utility
-+
-+git clone https://github.com/oracle/dtrace-utils.git
-+cd dtrace-utils
-+
-+# The DTrace packages are missing from Fedora repos,
-+# and we just built that software ourselves.
-+# So eliminate those packages from the .spec file
-+# before calling dnf builddep.
-+sed -i.old \
-+ -e 's/-devel libdtrace-ctf-devel >= [0-9\.]*/-devel/' \
-+ -e '/^BuildRequires: dtrace-kernel-headers = [0-9\.]*$/d' dtrace-utils.spec
-+sudo dnf builddep -y dtrace-utils.spec
-+
-+make
-+sudo make install
-+cd ..
-+
-+exit 0
-+
-+# Now, we can use DTrace on Fedora! (Notice that it is installed at /usr/sbin/dtrace.
-+# Some other utility is at /usr/bin/dtrace.) You must be logged in as
-+# root to use DTrace. The first thing to do is to list the available probes:
-+#
-+# # /usr/sbin/dtrace -l
-+# ID PROVIDER MODULE FUNCTION NAME
-+# 1 dtrace BEGIN
-+# 2 dtrace END
-+# 3 dtrace ERROR
-+# 5 fbt isofs isofs_hashi entry
-+# 6 fbt isofs isofs_hashi return
-+# 7 fbt isofs isofs_statfs entry
-+# 8 fbt isofs isofs_statfs return
-+# 9 fbt isofs isofs_iget5_test entry
-+# 10 fbt isofs isofs_iget5_test return
-+# [...thousands of lines omitted...]
-+#
-+# Next, check out the Oracle DTrace Guide for simple examples and more information.
-+# https://docs.oracle.com/cd/E52668_01/E38608/html/index.html
-+
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch b/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch
deleted file mode 100644
index 31b05305cc7b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/dtrace-patches/0019-locking-publicize-mutex_owner-and-mutex_owned-again.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-From cbc0fec32fc028d2e75a00f7a0609bc1960b02ee Mon Sep 17 00:00:00 2001
-From: Nick Alcock <nick.alcock@oracle.com>
-Date: Mon, 9 Dec 2019 16:51:44 +0000
-Subject: [PATCH 19/19] locking: publicize mutex_owner and mutex_owned again
-
-DTrace uses both of them.
-
-Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
----
- dtrace/dtrace_dif.c | 2 +-
- include/linux/mutex.h | 16 +++++-----------
- kernel/locking/mutex.c | 19 +++++++++++++++++++
- 3 files changed, 25 insertions(+), 12 deletions(-)
-
-diff --git a/dtrace/dtrace_dif.c b/dtrace/dtrace_dif.c
-index ae7f01b4ed9b76ea957dbfe080e1ac8fda995329..798302d322a369f92312a7b22ae41bf3e2d585e2 100644
---- a/dtrace/dtrace_dif.c
-+++ b/dtrace/dtrace_dif.c
-@@ -2439,7 +2439,7 @@ static void dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
- break;
-
- #ifdef CONFIG_SMP
-- regs[rd] = (uintptr_t)__mutex_owner(&mtx);
-+ regs[rd] = (uintptr_t)mutex_owner(&mtx);
- #else
- regs[rd] = 0;
- #endif
-diff --git a/include/linux/mutex.h b/include/linux/mutex.h
-index bb18028db361585e6ed56b1b90853c006282e727..a1f15a42ea1601468e51a2ba04f4e2b2b4a509b2 100644
---- a/include/linux/mutex.h
-+++ b/include/linux/mutex.h
-@@ -228,16 +228,10 @@ enum mutex_trylock_recursive_enum {
- extern /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
- mutex_trylock_recursive(struct mutex *lock);
-
--#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
--static inline int mutex_owned(struct mutex *lock)
--{
-- return mutex_is_locked(lock) && __mutex_owner(lock) == current;
--}
--#else
--static inline int mutex_owned(struct mutex *lock)
--{
-- return mutex_is_locked(lock);
--}
--#endif
-+extern int
-+mutex_owned(struct mutex *lock);
-+
-+extern struct task_struct *
-+mutex_owner(struct mutex *lock);
-
- #endif /* __LINUX_MUTEX_H */
-diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
-index e784dd89d924c4867de23c0eb60e65b2a47cad52..b856d7ffc51c7f1ace22768d2b2dc1e16335f619 100644
---- a/kernel/locking/mutex.c
-+++ b/kernel/locking/mutex.c
-@@ -97,6 +97,25 @@ mutex_trylock_recursive(struct mutex *lock)
- }
- EXPORT_SYMBOL(mutex_trylock_recursive);
-
-+struct task_struct *mutex_owner(struct mutex *lock)
-+{
-+ return __mutex_owner (lock);
-+}
-+EXPORT_SYMBOL(mutex_owner);
-+
-+#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
-+int mutex_owned(struct mutex *lock)
-+{
-+ return mutex_is_locked(lock) && __mutex_owner(lock) == current;
-+}
-+#else
-+int mutex_owned(struct mutex *lock)
-+{
-+ return mutex_is_locked(lock);
-+}
-+#endif
-+EXPORT_SYMBOL(mutex_owned);
-+
- static inline unsigned long __owner_flags(unsigned long owner)
- {
- return owner & MUTEX_FLAGS;
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/0000_README b/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/0000_README
deleted file mode 100644
index 897c945db2d7..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/0000_README
+++ /dev/null
@@ -1,132 +0,0 @@
-README
---------------------------------------------------------------------------
-This patchset is to be the series of patches for gentoo-sources.
-It is designed for cross-compatibility, fixes and stability, with performance
-and additional features/driver support being a second.
-
-Unless otherwise stated and marked as such, this kernel should be suitable for
-all environments.
-
-
-Patchset Numbering Scheme
---------------------------------------------------------------------------
-
-FIXES
-1000-1400 linux-stable
-1400-1500 linux-stable queue
-1500-1700 security
-1700-1800 architecture-related
-1800-1900 mm/scheduling/misc
-1900-2000 filesystems
-2000-2100 networking core
-2100-2200 storage core
-2200-2300 power management (ACPI, APM)
-2300-2400 bus (USB, IEEE1394, PCI, PCMCIA, ...)
-2400-2500 network drivers
-2500-2600 storage drivers
-2600-2700 input
-2700-2900 media (graphics, sound, tv)
-2900-3000 other
-3000-4000 reserved
-
-FEATURES
-4000-4100 network
-4100-4200 storage
-4200-4300 graphics
-4300-4400 filesystem
-4400-4500 security enhancement
-4500-4600 other
-
-EXPERIMENTAL
-5000-5100 experimental patches (BFQ, ...)
-
-Individual Patch Descriptions:
---------------------------------------------------------------------------
-
-Patch: 1000_linux-5.10.1.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.1
-
-Patch: 1001_linux-5.10.2.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.2
-
-Patch: 1002_linux-5.10.3.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.3
-
-Patch: 1003_linux-5.10.4.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.4
-
-Patch: 1004_linux-5.10.5.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.5
-
-Patch: 1005_linux-5.10.6.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.6
-
-Patch: 1006_linux-5.10.7.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.7
-
-Patch: 1007_linux-5.10.8.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.8
-
-Patch: 1008_linux-5.10.9.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.9
-
-Patch: 1009_linux-5.10.10.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.10
-
-Patch: 1010_linux-5.10.11.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.11
-
-Patch: 1011_linux-5.10.12.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.12
-
-Patch: 1012_linux-5.10.13.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.13
-
-Patch: 1013_linux-5.10.14.patch
-From: http://www.kernel.org
-Desc: Linux 5.10.14
-
-Patch: 1500_XATTR_USER_PREFIX.patch
-From: https://bugs.gentoo.org/show_bug.cgi?id=470644
-Desc: Support for namespace user.pax.* on tmpfs.
-
-Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
-From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
-Desc: Enable link security restrictions by default.
-
-Patch: 2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
-From: https://lore.kernel.org/linux-bluetooth/20190522070540.48895-1-marcel@holtmann.org/raw
-Desc: Bluetooth: Check key sizes only when Secure Simple Pairing is enabled. See bug #686758
-
-Patch: 2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch
-From: https://bugs.gentoo.org/710790
-Desc: tmp513 requies REGMAP_I2C to build. Select it by default in Kconfig. See bug #710790. Thanks to Phil Stracchino
-
-Patch: 2920_sign-file-patch-for-libressl.patch
-From: https://bugs.gentoo.org/717166
-Desc: sign-file: full functionality with modern LibreSSL
-
-Patch: 4567_distro-Gentoo-Kconfig.patch
-From: Tom Wijsman <TomWij@gentoo.org>
-Desc: Add Gentoo Linux support config settings and defaults.
-
-Patch: 5000_shifts-ubuntu-20.04.patch
-From: https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/focal
-Desc: UID/GID shifting overlay filesystem for containers
-
-Patch: 5013_enable-cpu-optimizations-for-gcc10.patch
-From: https://github.com/graysky2/kernel_gcc_patch/
-Desc: Kernel patch enables gcc = v10.1+ optimizations for additional CPUs.
diff --git a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/1500_XATTR_USER_PREFIX.patch b/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/1500_XATTR_USER_PREFIX.patch
deleted file mode 100644
index 245dcc29fa56..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/1500_XATTR_USER_PREFIX.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From: Anthony G. Basile <blueness@gentoo.org>
-
-This patch adds support for a restricted user-controlled namespace on
-tmpfs filesystem used to house PaX flags. The namespace must be of the
-form user.pax.* and its value cannot exceed a size of 8 bytes.
-
-This is needed even on all Gentoo systems so that XATTR_PAX flags
-are preserved for users who might build packages using portage on
-a tmpfs system with a non-hardened kernel and then switch to a
-hardened kernel with XATTR_PAX enabled.
-
-The namespace is added to any user with Extended Attribute support
-enabled for tmpfs. Users who do not enable xattrs will not have
-the XATTR_PAX flags preserved.
-
-diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h
-index 1590c49..5eab462 100644
---- a/include/uapi/linux/xattr.h
-+++ b/include/uapi/linux/xattr.h
-@@ -73,5 +73,9 @@
- #define XATTR_POSIX_ACL_DEFAULT "posix_acl_default"
- #define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT
-
-+/* User namespace */
-+#define XATTR_PAX_PREFIX XATTR_USER_PREFIX "pax."
-+#define XATTR_PAX_FLAGS_SUFFIX "flags"
-+#define XATTR_NAME_PAX_FLAGS XATTR_PAX_PREFIX XATTR_PAX_FLAGS_SUFFIX
-
- #endif /* _UAPI_LINUX_XATTR_H */
---- a/mm/shmem.c 2020-05-04 15:30:27.042035334 -0400
-+++ b/mm/shmem.c 2020-05-04 15:34:57.013881725 -0400
-@@ -3238,6 +3238,14 @@ static int shmem_xattr_handler_set(const
- struct shmem_inode_info *info = SHMEM_I(inode);
-
- name = xattr_full_name(handler, name);
-+
-+ if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
-+ if (strcmp(name, XATTR_NAME_PAX_FLAGS))
-+ return -EOPNOTSUPP;
-+ if (size > 8)
-+ return -EINVAL;
-+ }
-+
- return simple_xattr_set(&info->xattrs, name, value, size, flags, NULL);
- }
-
-@@ -3253,6 +3261,12 @@ static const struct xattr_handler shmem_
- .set = shmem_xattr_handler_set,
- };
-
-+static const struct xattr_handler shmem_user_xattr_handler = {
-+ .prefix = XATTR_USER_PREFIX,
-+ .get = shmem_xattr_handler_get,
-+ .set = shmem_xattr_handler_set,
-+};
-+
- static const struct xattr_handler *shmem_xattr_handlers[] = {
- #ifdef CONFIG_TMPFS_POSIX_ACL
- &posix_acl_access_xattr_handler,
-@@ -3260,6 +3274,7 @@ static const struct xattr_handler *shmem
- #endif
- &shmem_security_xattr_handler,
- &shmem_trusted_xattr_handler,
-+ &shmem_user_xattr_handler,
- NULL
- };
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch
deleted file mode 100644
index f0ed144fb17a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/1510_fs-enable-link-security-restrictions-by-default.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-From: Ben Hutchings <ben@decadent.org.uk>
-Subject: fs: Enable link security restrictions by default
-Date: Fri, 02 Nov 2012 05:32:06 +0000
-Bug-Debian: https://bugs.debian.org/609455
-Forwarded: not-needed
-This reverts commit 561ec64ae67ef25cac8d72bb9c4bfc955edfd415
-('VFS: don't do protected {sym,hard}links by default').
---- a/fs/namei.c 2018-09-28 07:56:07.770005006 -0400
-+++ b/fs/namei.c 2018-09-28 07:56:43.370349204 -0400
-@@ -885,8 +885,8 @@ static inline void put_link(struct namei
- path_put(&last->link);
- }
-
--int sysctl_protected_symlinks __read_mostly = 0;
--int sysctl_protected_hardlinks __read_mostly = 0;
-+int sysctl_protected_symlinks __read_mostly = 1;
-+int sysctl_protected_hardlinks __read_mostly = 1;
- int sysctl_protected_fifos __read_mostly;
- int sysctl_protected_regular __read_mostly;
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch b/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
deleted file mode 100644
index 394ad48fc20c..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-The encryption is only mandatory to be enforced when both sides are using
-Secure Simple Pairing and this means the key size check makes only sense
-in that case.
-
-On legacy Bluetooth 2.0 and earlier devices like mice the encryption was
-optional and thus causing an issue if the key size check is not bound to
-using Secure Simple Pairing.
-
-Fixes: d5bb334a8e17 ("Bluetooth: Align minimum encryption key size for LE and BR/EDR connections")
-Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-Cc: stable@vger.kernel.org
----
- net/bluetooth/hci_conn.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
-index 3cf0764d5793..7516cdde3373 100644
---- a/net/bluetooth/hci_conn.c
-+++ b/net/bluetooth/hci_conn.c
-@@ -1272,8 +1272,13 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
- return 0;
- }
-
-- if (hci_conn_ssp_enabled(conn) &&
-- !test_bit(HCI_CONN_ENCRYPT, &conn->flags))
-+ /* If Secure Simple Pairing is not enabled, then legacy connection
-+ * setup is used and no encryption or key sizes can be enforced.
-+ */
-+ if (!hci_conn_ssp_enabled(conn))
-+ return 1;
-+
-+ if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
- return 0;
-
- /* The minimum encryption key size needs to be enforced by the
---
-2.20.1
diff --git a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch b/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch
deleted file mode 100644
index 433568579cab..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From dc328d75a6f37f4ff11a81ae16b1ec88c3197640 Mon Sep 17 00:00:00 2001
-From: Mike Pagano <mpagano@gentoo.org>
-Date: Mon, 23 Mar 2020 08:20:06 -0400
-Subject: [PATCH 1/1] This driver requires REGMAP_I2C to build. Select it by
- default in Kconfig. Reported at gentoo bugzilla:
- https://bugs.gentoo.org/710790
-Cc: mpagano@gentoo.org
-
-Reported-by: Phil Stracchino <phils@caerllewys.net>
-
-Signed-off-by: Mike Pagano <mpagano@gentoo.org>
----
- drivers/hwmon/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
-index 47ac20aee06f..530b4f29ba85 100644
---- a/drivers/hwmon/Kconfig
-+++ b/drivers/hwmon/Kconfig
-@@ -1769,6 +1769,7 @@ config SENSORS_TMP421
- config SENSORS_TMP513
- tristate "Texas Instruments TMP513 and compatibles"
- depends on I2C
-+ select REGMAP_I2C
- help
- If you say yes here you get support for Texas Instruments TMP512,
- and TMP513 temperature and power supply sensor chips.
---
-2.24.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2920_sign-file-patch-for-libressl.patch b/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2920_sign-file-patch-for-libressl.patch
deleted file mode 100644
index e6ec017d46c8..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/2920_sign-file-patch-for-libressl.patch
+++ /dev/null
@@ -1,16 +0,0 @@
---- a/scripts/sign-file.c 2020-05-20 18:47:21.282820662 -0400
-+++ b/scripts/sign-file.c 2020-05-20 18:48:37.991081899 -0400
-@@ -41,9 +41,10 @@
- * signing with anything other than SHA1 - so we're stuck with that if such is
- * the case.
- */
--#if defined(LIBRESSL_VERSION_NUMBER) || \
-- OPENSSL_VERSION_NUMBER < 0x10000000L || \
-- defined(OPENSSL_NO_CMS)
-+#if defined(OPENSSL_NO_CMS) || \
-+ ( defined(LIBRESSL_VERSION_NUMBER) \
-+ && (LIBRESSL_VERSION_NUMBER < 0x3010000fL) ) || \
-+ OPENSSL_VERSION_NUMBER < 0x10000000L
- #define USE_PKCS7
- #endif
- #ifndef USE_PKCS7
diff --git a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/5000_shiftfs-ubuntu-20.04.patch b/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/5000_shiftfs-ubuntu-20.04.patch
deleted file mode 100644
index 665fc660b0de..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/5000_shiftfs-ubuntu-20.04.patch
+++ /dev/null
@@ -1,2203 +0,0 @@
---- /dev/null 2021-01-08 13:33:13.190303432 -0500
-+++ b/fs/shiftfs.c 2021-01-08 19:02:40.000000000 -0500
-@@ -0,0 +1,2157 @@
-+#include <linux/btrfs.h>
-+#include <linux/capability.h>
-+#include <linux/cred.h>
-+#include <linux/mount.h>
-+#include <linux/fdtable.h>
-+#include <linux/file.h>
-+#include <linux/fs.h>
-+#include <linux/namei.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/magic.h>
-+#include <linux/parser.h>
-+#include <linux/security.h>
-+#include <linux/seq_file.h>
-+#include <linux/statfs.h>
-+#include <linux/slab.h>
-+#include <linux/user_namespace.h>
-+#include <linux/uidgid.h>
-+#include <linux/xattr.h>
-+#include <linux/posix_acl.h>
-+#include <linux/posix_acl_xattr.h>
-+#include <linux/uio.h>
-+#include <linux/fiemap.h>
-+
-+struct shiftfs_super_info {
-+ struct vfsmount *mnt;
-+ struct user_namespace *userns;
-+ /* creds of process who created the super block */
-+ const struct cred *creator_cred;
-+ bool mark;
-+ unsigned int passthrough;
-+ unsigned int passthrough_mark;
-+};
-+
-+static void shiftfs_fill_inode(struct inode *inode, unsigned long ino,
-+ umode_t mode, dev_t dev, struct dentry *dentry);
-+
-+#define SHIFTFS_PASSTHROUGH_NONE 0
-+#define SHIFTFS_PASSTHROUGH_STAT 1
-+#define SHIFTFS_PASSTHROUGH_IOCTL 2
-+#define SHIFTFS_PASSTHROUGH_ALL \
-+ (SHIFTFS_PASSTHROUGH_STAT | SHIFTFS_PASSTHROUGH_IOCTL)
-+
-+static inline bool shiftfs_passthrough_ioctls(struct shiftfs_super_info *info)
-+{
-+ if (!(info->passthrough & SHIFTFS_PASSTHROUGH_IOCTL))
-+ return false;
-+
-+ return true;
-+}
-+
-+static inline bool shiftfs_passthrough_statfs(struct shiftfs_super_info *info)
-+{
-+ if (!(info->passthrough & SHIFTFS_PASSTHROUGH_STAT))
-+ return false;
-+
-+ return true;
-+}
-+
-+enum {
-+ OPT_MARK,
-+ OPT_PASSTHROUGH,
-+ OPT_LAST,
-+};
-+
-+/* global filesystem options */
-+static const match_table_t tokens = {
-+ { OPT_MARK, "mark" },
-+ { OPT_PASSTHROUGH, "passthrough=%u" },
-+ { OPT_LAST, NULL }
-+};
-+
-+static const struct cred *shiftfs_override_creds(const struct super_block *sb)
-+{
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+
-+ return override_creds(sbinfo->creator_cred);
-+}
-+
-+static inline void shiftfs_revert_object_creds(const struct cred *oldcred,
-+ struct cred *newcred)
-+{
-+ revert_creds(oldcred);
-+ put_cred(newcred);
-+}
-+
-+static kuid_t shift_kuid(struct user_namespace *from, struct user_namespace *to,
-+ kuid_t kuid)
-+{
-+ uid_t uid = from_kuid(from, kuid);
-+ return make_kuid(to, uid);
-+}
-+
-+static kgid_t shift_kgid(struct user_namespace *from, struct user_namespace *to,
-+ kgid_t kgid)
-+{
-+ gid_t gid = from_kgid(from, kgid);
-+ return make_kgid(to, gid);
-+}
-+
-+static int shiftfs_override_object_creds(const struct super_block *sb,
-+ const struct cred **oldcred,
-+ struct cred **newcred,
-+ struct dentry *dentry, umode_t mode,
-+ bool hardlink)
-+{
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+ kuid_t fsuid = current_fsuid();
-+ kgid_t fsgid = current_fsgid();
-+
-+ *oldcred = shiftfs_override_creds(sb);
-+
-+ *newcred = prepare_creds();
-+ if (!*newcred) {
-+ revert_creds(*oldcred);
-+ return -ENOMEM;
-+ }
-+
-+ (*newcred)->fsuid = shift_kuid(sb->s_user_ns, sbinfo->userns, fsuid);
-+ (*newcred)->fsgid = shift_kgid(sb->s_user_ns, sbinfo->userns, fsgid);
-+
-+ if (!hardlink) {
-+ int err = security_dentry_create_files_as(dentry, mode,
-+ &dentry->d_name,
-+ *oldcred, *newcred);
-+ if (err) {
-+ shiftfs_revert_object_creds(*oldcred, *newcred);
-+ return err;
-+ }
-+ }
-+
-+ put_cred(override_creds(*newcred));
-+ return 0;
-+}
-+
-+static void shiftfs_copyattr(struct inode *from, struct inode *to)
-+{
-+ struct user_namespace *from_ns = from->i_sb->s_user_ns;
-+ struct user_namespace *to_ns = to->i_sb->s_user_ns;
-+
-+ to->i_uid = shift_kuid(from_ns, to_ns, from->i_uid);
-+ to->i_gid = shift_kgid(from_ns, to_ns, from->i_gid);
-+ to->i_mode = from->i_mode;
-+ to->i_atime = from->i_atime;
-+ to->i_mtime = from->i_mtime;
-+ to->i_ctime = from->i_ctime;
-+ i_size_write(to, i_size_read(from));
-+}
-+
-+static void shiftfs_copyflags(struct inode *from, struct inode *to)
-+{
-+ unsigned int mask = S_SYNC | S_IMMUTABLE | S_APPEND | S_NOATIME;
-+
-+ inode_set_flags(to, from->i_flags & mask, mask);
-+}
-+
-+static void shiftfs_file_accessed(struct file *file)
-+{
-+ struct inode *upperi, *loweri;
-+
-+ if (file->f_flags & O_NOATIME)
-+ return;
-+
-+ upperi = file_inode(file);
-+ loweri = upperi->i_private;
-+
-+ if (!loweri)
-+ return;
-+
-+ upperi->i_mtime = loweri->i_mtime;
-+ upperi->i_ctime = loweri->i_ctime;
-+
-+ touch_atime(&file->f_path);
-+}
-+
-+static int shiftfs_parse_mount_options(struct shiftfs_super_info *sbinfo,
-+ char *options)
-+{
-+ char *p;
-+ substring_t args[MAX_OPT_ARGS];
-+
-+ sbinfo->mark = false;
-+ sbinfo->passthrough = 0;
-+
-+ while ((p = strsep(&options, ",")) != NULL) {
-+ int err, intarg, token;
-+
-+ if (!*p)
-+ continue;
-+
-+ token = match_token(p, tokens, args);
-+ switch (token) {
-+ case OPT_MARK:
-+ sbinfo->mark = true;
-+ break;
-+ case OPT_PASSTHROUGH:
-+ err = match_int(&args[0], &intarg);
-+ if (err)
-+ return err;
-+
-+ if (intarg & ~SHIFTFS_PASSTHROUGH_ALL)
-+ return -EINVAL;
-+
-+ sbinfo->passthrough = intarg;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static void shiftfs_d_release(struct dentry *dentry)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+
-+ if (lowerd)
-+ dput(lowerd);
-+}
-+
-+static struct dentry *shiftfs_d_real(struct dentry *dentry,
-+ const struct inode *inode)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+
-+ if (inode && d_inode(dentry) == inode)
-+ return dentry;
-+
-+ lowerd = d_real(lowerd, inode);
-+ if (lowerd && (!inode || inode == d_inode(lowerd)))
-+ return lowerd;
-+
-+ WARN(1, "shiftfs_d_real(%pd4, %s:%lu): real dentry not found\n", dentry,
-+ inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0);
-+ return dentry;
-+}
-+
-+static int shiftfs_d_weak_revalidate(struct dentry *dentry, unsigned int flags)
-+{
-+ int err = 1;
-+ struct dentry *lowerd = dentry->d_fsdata;
-+
-+ if (d_is_negative(lowerd) != d_is_negative(dentry))
-+ return 0;
-+
-+ if ((lowerd->d_flags & DCACHE_OP_WEAK_REVALIDATE))
-+ err = lowerd->d_op->d_weak_revalidate(lowerd, flags);
-+
-+ if (d_really_is_positive(dentry)) {
-+ struct inode *inode = d_inode(dentry);
-+ struct inode *loweri = d_inode(lowerd);
-+
-+ shiftfs_copyattr(loweri, inode);
-+ }
-+
-+ return err;
-+}
-+
-+static int shiftfs_d_revalidate(struct dentry *dentry, unsigned int flags)
-+{
-+ int err = 1;
-+ struct dentry *lowerd = dentry->d_fsdata;
-+
-+ if (d_unhashed(lowerd) ||
-+ ((d_is_negative(lowerd) != d_is_negative(dentry))))
-+ return 0;
-+
-+ if (flags & LOOKUP_RCU)
-+ return -ECHILD;
-+
-+ if ((lowerd->d_flags & DCACHE_OP_REVALIDATE))
-+ err = lowerd->d_op->d_revalidate(lowerd, flags);
-+
-+ if (d_really_is_positive(dentry)) {
-+ struct inode *inode = d_inode(dentry);
-+ struct inode *loweri = d_inode(lowerd);
-+
-+ shiftfs_copyattr(loweri, inode);
-+ }
-+
-+ return err;
-+}
-+
-+static const struct dentry_operations shiftfs_dentry_ops = {
-+ .d_release = shiftfs_d_release,
-+ .d_real = shiftfs_d_real,
-+ .d_revalidate = shiftfs_d_revalidate,
-+ .d_weak_revalidate = shiftfs_d_weak_revalidate,
-+};
-+
-+static const char *shiftfs_get_link(struct dentry *dentry, struct inode *inode,
-+ struct delayed_call *done)
-+{
-+ const char *p;
-+ const struct cred *oldcred;
-+ struct dentry *lowerd;
-+
-+ /* RCU lookup not supported */
-+ if (!dentry)
-+ return ERR_PTR(-ECHILD);
-+
-+ lowerd = dentry->d_fsdata;
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ p = vfs_get_link(lowerd, done);
-+ revert_creds(oldcred);
-+
-+ return p;
-+}
-+
-+static int shiftfs_setxattr(struct dentry *dentry, struct inode *inode,
-+ const char *name, const void *value,
-+ size_t size, int flags)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ int err;
-+ const struct cred *oldcred;
-+
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ err = vfs_setxattr(lowerd, name, value, size, flags);
-+ revert_creds(oldcred);
-+
-+ shiftfs_copyattr(lowerd->d_inode, inode);
-+
-+ return err;
-+}
-+
-+static int shiftfs_xattr_get(const struct xattr_handler *handler,
-+ struct dentry *dentry, struct inode *inode,
-+ const char *name, void *value, size_t size)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ int err;
-+ const struct cred *oldcred;
-+
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ err = vfs_getxattr(lowerd, name, value, size);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+static ssize_t shiftfs_listxattr(struct dentry *dentry, char *list,
-+ size_t size)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ int err;
-+ const struct cred *oldcred;
-+
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ err = vfs_listxattr(lowerd, list, size);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+static int shiftfs_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ int err;
-+ const struct cred *oldcred;
-+
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ err = vfs_removexattr(lowerd, name);
-+ revert_creds(oldcred);
-+
-+ /* update c/mtime */
-+ shiftfs_copyattr(lowerd->d_inode, d_inode(dentry));
-+
-+ return err;
-+}
-+
-+static int shiftfs_xattr_set(const struct xattr_handler *handler,
-+ struct dentry *dentry, struct inode *inode,
-+ const char *name, const void *value, size_t size,
-+ int flags)
-+{
-+ if (!value)
-+ return shiftfs_removexattr(dentry, name);
-+ return shiftfs_setxattr(dentry, inode, name, value, size, flags);
-+}
-+
-+static int shiftfs_inode_test(struct inode *inode, void *data)
-+{
-+ return inode->i_private == data;
-+}
-+
-+static int shiftfs_inode_set(struct inode *inode, void *data)
-+{
-+ inode->i_private = data;
-+ return 0;
-+}
-+
-+static int shiftfs_create_object(struct inode *diri, struct dentry *dentry,
-+ umode_t mode, const char *symlink,
-+ struct dentry *hardlink, bool excl)
-+{
-+ int err;
-+ const struct cred *oldcred;
-+ struct cred *newcred;
-+ void *loweri_iop_ptr = NULL;
-+ umode_t modei = mode;
-+ struct super_block *dir_sb = diri->i_sb;
-+ struct dentry *lowerd_new = dentry->d_fsdata;
-+ struct inode *inode = NULL, *loweri_dir = diri->i_private;
-+ const struct inode_operations *loweri_dir_iop = loweri_dir->i_op;
-+ struct dentry *lowerd_link = NULL;
-+
-+ if (hardlink) {
-+ loweri_iop_ptr = loweri_dir_iop->link;
-+ } else {
-+ switch (mode & S_IFMT) {
-+ case S_IFDIR:
-+ loweri_iop_ptr = loweri_dir_iop->mkdir;
-+ break;
-+ case S_IFREG:
-+ loweri_iop_ptr = loweri_dir_iop->create;
-+ break;
-+ case S_IFLNK:
-+ loweri_iop_ptr = loweri_dir_iop->symlink;
-+ break;
-+ case S_IFSOCK:
-+ /* fall through */
-+ case S_IFIFO:
-+ loweri_iop_ptr = loweri_dir_iop->mknod;
-+ break;
-+ }
-+ }
-+ if (!loweri_iop_ptr) {
-+ err = -EINVAL;
-+ goto out_iput;
-+ }
-+
-+ inode_lock_nested(loweri_dir, I_MUTEX_PARENT);
-+
-+ if (!hardlink) {
-+ inode = new_inode(dir_sb);
-+ if (!inode) {
-+ err = -ENOMEM;
-+ goto out_iput;
-+ }
-+
-+ /*
-+ * new_inode() will have added the new inode to the super
-+ * block's list of inodes. Further below we will call
-+ * inode_insert5() Which would perform the same operation again
-+ * thereby corrupting the list. To avoid this raise I_CREATING
-+ * in i_state which will cause inode_insert5() to skip this
-+ * step. I_CREATING will be cleared by d_instantiate_new()
-+ * below.
-+ */
-+ spin_lock(&inode->i_lock);
-+ inode->i_state |= I_CREATING;
-+ spin_unlock(&inode->i_lock);
-+
-+ inode_init_owner(inode, diri, mode);
-+ modei = inode->i_mode;
-+ }
-+
-+ err = shiftfs_override_object_creds(dentry->d_sb, &oldcred, &newcred,
-+ dentry, modei, hardlink != NULL);
-+ if (err)
-+ goto out_iput;
-+
-+ if (hardlink) {
-+ lowerd_link = hardlink->d_fsdata;
-+ err = vfs_link(lowerd_link, loweri_dir, lowerd_new, NULL);
-+ } else {
-+ switch (modei & S_IFMT) {
-+ case S_IFDIR:
-+ err = vfs_mkdir(loweri_dir, lowerd_new, modei);
-+ break;
-+ case S_IFREG:
-+ err = vfs_create(loweri_dir, lowerd_new, modei, excl);
-+ break;
-+ case S_IFLNK:
-+ err = vfs_symlink(loweri_dir, lowerd_new, symlink);
-+ break;
-+ case S_IFSOCK:
-+ /* fall through */
-+ case S_IFIFO:
-+ err = vfs_mknod(loweri_dir, lowerd_new, modei, 0);
-+ break;
-+ default:
-+ err = -EINVAL;
-+ break;
-+ }
-+ }
-+
-+ shiftfs_revert_object_creds(oldcred, newcred);
-+
-+ if (!err && WARN_ON(!lowerd_new->d_inode))
-+ err = -EIO;
-+ if (err)
-+ goto out_iput;
-+
-+ if (hardlink) {
-+ inode = d_inode(hardlink);
-+ ihold(inode);
-+
-+ /* copy up times from lower inode */
-+ shiftfs_copyattr(d_inode(lowerd_link), inode);
-+ set_nlink(d_inode(hardlink), d_inode(lowerd_link)->i_nlink);
-+ d_instantiate(dentry, inode);
-+ } else {
-+ struct inode *inode_tmp;
-+ struct inode *loweri_new = d_inode(lowerd_new);
-+
-+ inode_tmp = inode_insert5(inode, (unsigned long)loweri_new,
-+ shiftfs_inode_test, shiftfs_inode_set,
-+ loweri_new);
-+ if (unlikely(inode_tmp != inode)) {
-+ pr_err_ratelimited("shiftfs: newly created inode found in cache\n");
-+ iput(inode_tmp);
-+ err = -EINVAL;
-+ goto out_iput;
-+ }
-+
-+ ihold(loweri_new);
-+ shiftfs_fill_inode(inode, loweri_new->i_ino, loweri_new->i_mode,
-+ 0, lowerd_new);
-+ d_instantiate_new(dentry, inode);
-+ }
-+
-+ shiftfs_copyattr(loweri_dir, diri);
-+ if (loweri_iop_ptr == loweri_dir_iop->mkdir)
-+ set_nlink(diri, loweri_dir->i_nlink);
-+
-+ inode = NULL;
-+
-+out_iput:
-+ iput(inode);
-+ inode_unlock(loweri_dir);
-+
-+ return err;
-+}
-+
-+static int shiftfs_create(struct inode *dir, struct dentry *dentry,
-+ umode_t mode, bool excl)
-+{
-+ mode |= S_IFREG;
-+
-+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, excl);
-+}
-+
-+static int shiftfs_mkdir(struct inode *dir, struct dentry *dentry,
-+ umode_t mode)
-+{
-+ mode |= S_IFDIR;
-+
-+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, false);
-+}
-+
-+static int shiftfs_link(struct dentry *hardlink, struct inode *dir,
-+ struct dentry *dentry)
-+{
-+ return shiftfs_create_object(dir, dentry, 0, NULL, hardlink, false);
-+}
-+
-+static int shiftfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
-+ dev_t rdev)
-+{
-+ if (!S_ISFIFO(mode) && !S_ISSOCK(mode))
-+ return -EPERM;
-+
-+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, false);
-+}
-+
-+static int shiftfs_symlink(struct inode *dir, struct dentry *dentry,
-+ const char *symlink)
-+{
-+ return shiftfs_create_object(dir, dentry, S_IFLNK, symlink, NULL, false);
-+}
-+
-+static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ struct inode *loweri = dir->i_private;
-+ struct inode *inode = d_inode(dentry);
-+ int err;
-+ const struct cred *oldcred;
-+
-+ dget(lowerd);
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ inode_lock_nested(loweri, I_MUTEX_PARENT);
-+ if (rmdir)
-+ err = vfs_rmdir(loweri, lowerd);
-+ else
-+ err = vfs_unlink(loweri, lowerd, NULL);
-+ revert_creds(oldcred);
-+
-+ if (!err) {
-+ d_drop(dentry);
-+
-+ if (rmdir)
-+ clear_nlink(inode);
-+ else
-+ drop_nlink(inode);
-+ }
-+ inode_unlock(loweri);
-+
-+ shiftfs_copyattr(loweri, dir);
-+ dput(lowerd);
-+
-+ return err;
-+}
-+
-+static int shiftfs_unlink(struct inode *dir, struct dentry *dentry)
-+{
-+ return shiftfs_rm(dir, dentry, false);
-+}
-+
-+static int shiftfs_rmdir(struct inode *dir, struct dentry *dentry)
-+{
-+ return shiftfs_rm(dir, dentry, true);
-+}
-+
-+static int shiftfs_rename(struct inode *olddir, struct dentry *old,
-+ struct inode *newdir, struct dentry *new,
-+ unsigned int flags)
-+{
-+ struct dentry *lowerd_dir_old = old->d_parent->d_fsdata,
-+ *lowerd_dir_new = new->d_parent->d_fsdata,
-+ *lowerd_old = old->d_fsdata, *lowerd_new = new->d_fsdata,
-+ *trapd;
-+ struct inode *loweri_dir_old = lowerd_dir_old->d_inode,
-+ *loweri_dir_new = lowerd_dir_new->d_inode;
-+ int err = -EINVAL;
-+ const struct cred *oldcred;
-+
-+ trapd = lock_rename(lowerd_dir_new, lowerd_dir_old);
-+
-+ if (trapd == lowerd_old || trapd == lowerd_new)
-+ goto out_unlock;
-+
-+ oldcred = shiftfs_override_creds(old->d_sb);
-+ err = vfs_rename(loweri_dir_old, lowerd_old, loweri_dir_new, lowerd_new,
-+ NULL, flags);
-+ revert_creds(oldcred);
-+
-+ shiftfs_copyattr(loweri_dir_old, olddir);
-+ shiftfs_copyattr(loweri_dir_new, newdir);
-+
-+out_unlock:
-+ unlock_rename(lowerd_dir_new, lowerd_dir_old);
-+
-+ return err;
-+}
-+
-+static struct dentry *shiftfs_lookup(struct inode *dir, struct dentry *dentry,
-+ unsigned int flags)
-+{
-+ struct dentry *new;
-+ struct inode *newi;
-+ const struct cred *oldcred;
-+ struct dentry *lowerd = dentry->d_parent->d_fsdata;
-+ struct inode *inode = NULL, *loweri = lowerd->d_inode;
-+
-+ inode_lock(loweri);
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ new = lookup_one_len(dentry->d_name.name, lowerd, dentry->d_name.len);
-+ revert_creds(oldcred);
-+ inode_unlock(loweri);
-+
-+ if (IS_ERR(new))
-+ return new;
-+
-+ dentry->d_fsdata = new;
-+
-+ newi = new->d_inode;
-+ if (!newi)
-+ goto out;
-+
-+ inode = iget5_locked(dentry->d_sb, (unsigned long)newi,
-+ shiftfs_inode_test, shiftfs_inode_set, newi);
-+ if (!inode) {
-+ dput(new);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+ if (inode->i_state & I_NEW) {
-+ /*
-+ * inode->i_private set by shiftfs_inode_set(), but we still
-+ * need to take a reference
-+ */
-+ ihold(newi);
-+ shiftfs_fill_inode(inode, newi->i_ino, newi->i_mode, 0, new);
-+ unlock_new_inode(inode);
-+ }
-+
-+out:
-+ return d_splice_alias(inode, dentry);
-+}
-+
-+static int shiftfs_permission(struct inode *inode, int mask)
-+{
-+ int err;
-+ const struct cred *oldcred;
-+ struct inode *loweri = inode->i_private;
-+
-+ if (!loweri) {
-+ WARN_ON(!(mask & MAY_NOT_BLOCK));
-+ return -ECHILD;
-+ }
-+
-+ err = generic_permission(inode, mask);
-+ if (err)
-+ return err;
-+
-+ oldcred = shiftfs_override_creds(inode->i_sb);
-+ err = inode_permission(loweri, mask);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+static int shiftfs_fiemap(struct inode *inode,
-+ struct fiemap_extent_info *fieinfo, u64 start,
-+ u64 len)
-+{
-+ int err;
-+ const struct cred *oldcred;
-+ struct inode *loweri = inode->i_private;
-+
-+ if (!loweri->i_op->fiemap)
-+ return -EOPNOTSUPP;
-+
-+ oldcred = shiftfs_override_creds(inode->i_sb);
-+ if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC)
-+ filemap_write_and_wait(loweri->i_mapping);
-+ err = loweri->i_op->fiemap(loweri, fieinfo, start, len);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+static int shiftfs_tmpfile(struct inode *dir, struct dentry *dentry,
-+ umode_t mode)
-+{
-+ int err;
-+ const struct cred *oldcred;
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ struct inode *loweri = dir->i_private;
-+
-+ if (!loweri->i_op->tmpfile)
-+ return -EOPNOTSUPP;
-+
-+ oldcred = shiftfs_override_creds(dir->i_sb);
-+ err = loweri->i_op->tmpfile(loweri, lowerd, mode);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
-+{
-+ struct dentry *lowerd = dentry->d_fsdata;
-+ struct inode *loweri = lowerd->d_inode;
-+ struct iattr newattr;
-+ const struct cred *oldcred;
-+ struct super_block *sb = dentry->d_sb;
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+ int err;
-+
-+ err = setattr_prepare(dentry, attr);
-+ if (err)
-+ return err;
-+
-+ newattr = *attr;
-+ newattr.ia_uid = shift_kuid(sb->s_user_ns, sbinfo->userns, attr->ia_uid);
-+ newattr.ia_gid = shift_kgid(sb->s_user_ns, sbinfo->userns, attr->ia_gid);
-+
-+ /*
-+ * mode change is for clearing setuid/setgid bits. Allow lower fs
-+ * to interpret this in its own way.
-+ */
-+ if (newattr.ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
-+ newattr.ia_valid &= ~ATTR_MODE;
-+
-+ inode_lock(loweri);
-+ oldcred = shiftfs_override_creds(dentry->d_sb);
-+ err = notify_change(lowerd, &newattr, NULL);
-+ revert_creds(oldcred);
-+ inode_unlock(loweri);
-+
-+ shiftfs_copyattr(loweri, d_inode(dentry));
-+
-+ return err;
-+}
-+
-+static int shiftfs_getattr(const struct path *path, struct kstat *stat,
-+ u32 request_mask, unsigned int query_flags)
-+{
-+ struct inode *inode = path->dentry->d_inode;
-+ struct dentry *lowerd = path->dentry->d_fsdata;
-+ struct inode *loweri = lowerd->d_inode;
-+ struct shiftfs_super_info *info = path->dentry->d_sb->s_fs_info;
-+ struct path newpath = { .mnt = info->mnt, .dentry = lowerd };
-+ struct user_namespace *from_ns = loweri->i_sb->s_user_ns;
-+ struct user_namespace *to_ns = inode->i_sb->s_user_ns;
-+ const struct cred *oldcred;
-+ int err;
-+
-+ oldcred = shiftfs_override_creds(inode->i_sb);
-+ err = vfs_getattr(&newpath, stat, request_mask, query_flags);
-+ revert_creds(oldcred);
-+
-+ if (err)
-+ return err;
-+
-+ /* transform the underlying id */
-+ stat->uid = shift_kuid(from_ns, to_ns, stat->uid);
-+ stat->gid = shift_kgid(from_ns, to_ns, stat->gid);
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SHIFT_FS_POSIX_ACL
-+
-+static int
-+shift_acl_ids(struct user_namespace *from, struct user_namespace *to,
-+ struct posix_acl *acl)
-+{
-+ int i;
-+
-+ for (i = 0; i < acl->a_count; i++) {
-+ struct posix_acl_entry *e = &acl->a_entries[i];
-+ switch(e->e_tag) {
-+ case ACL_USER:
-+ e->e_uid = shift_kuid(from, to, e->e_uid);
-+ if (!uid_valid(e->e_uid))
-+ return -EOVERFLOW;
-+ break;
-+ case ACL_GROUP:
-+ e->e_gid = shift_kgid(from, to, e->e_gid);
-+ if (!gid_valid(e->e_gid))
-+ return -EOVERFLOW;
-+ break;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static void
-+shift_acl_xattr_ids(struct user_namespace *from, struct user_namespace *to,
-+ void *value, size_t size)
-+{
-+ struct posix_acl_xattr_header *header = value;
-+ struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
-+ int count;
-+ kuid_t kuid;
-+ kgid_t kgid;
-+
-+ if (!value)
-+ return;
-+ if (size < sizeof(struct posix_acl_xattr_header))
-+ return;
-+ if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
-+ return;
-+
-+ count = posix_acl_xattr_count(size);
-+ if (count < 0)
-+ return;
-+ if (count == 0)
-+ return;
-+
-+ for (end = entry + count; entry != end; entry++) {
-+ switch(le16_to_cpu(entry->e_tag)) {
-+ case ACL_USER:
-+ kuid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id));
-+ kuid = shift_kuid(from, to, kuid);
-+ entry->e_id = cpu_to_le32(from_kuid(&init_user_ns, kuid));
-+ break;
-+ case ACL_GROUP:
-+ kgid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id));
-+ kgid = shift_kgid(from, to, kgid);
-+ entry->e_id = cpu_to_le32(from_kgid(&init_user_ns, kgid));
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+}
-+
-+static struct posix_acl *shiftfs_get_acl(struct inode *inode, int type)
-+{
-+ struct inode *loweri = inode->i_private;
-+ const struct cred *oldcred;
-+ struct posix_acl *lower_acl, *acl = NULL;
-+ struct user_namespace *from_ns = loweri->i_sb->s_user_ns;
-+ struct user_namespace *to_ns = inode->i_sb->s_user_ns;
-+ int size;
-+ int err;
-+
-+ if (!IS_POSIXACL(loweri))
-+ return NULL;
-+
-+ oldcred = shiftfs_override_creds(inode->i_sb);
-+ lower_acl = get_acl(loweri, type);
-+ revert_creds(oldcred);
-+
-+ if (lower_acl && !IS_ERR(lower_acl)) {
-+ /* XXX: export posix_acl_clone? */
-+ size = sizeof(struct posix_acl) +
-+ lower_acl->a_count * sizeof(struct posix_acl_entry);
-+ acl = kmemdup(lower_acl, size, GFP_KERNEL);
-+ posix_acl_release(lower_acl);
-+
-+ if (!acl)
-+ return ERR_PTR(-ENOMEM);
-+
-+ refcount_set(&acl->a_refcount, 1);
-+
-+ err = shift_acl_ids(from_ns, to_ns, acl);
-+ if (err) {
-+ kfree(acl);
-+ return ERR_PTR(err);
-+ }
-+ }
-+
-+ return acl;
-+}
-+
-+static int
-+shiftfs_posix_acl_xattr_get(const struct xattr_handler *handler,
-+ struct dentry *dentry, struct inode *inode,
-+ const char *name, void *buffer, size_t size)
-+{
-+ struct inode *loweri = inode->i_private;
-+ int ret;
-+
-+ ret = shiftfs_xattr_get(NULL, dentry, inode, handler->name,
-+ buffer, size);
-+ if (ret < 0)
-+ return ret;
-+
-+ inode_lock(loweri);
-+ shift_acl_xattr_ids(loweri->i_sb->s_user_ns, inode->i_sb->s_user_ns,
-+ buffer, size);
-+ inode_unlock(loweri);
-+ return ret;
-+}
-+
-+static int
-+shiftfs_posix_acl_xattr_set(const struct xattr_handler *handler,
-+ struct dentry *dentry, struct inode *inode,
-+ const char *name, const void *value,
-+ size_t size, int flags)
-+{
-+ struct inode *loweri = inode->i_private;
-+ int err;
-+
-+ if (!IS_POSIXACL(loweri) || !loweri->i_op->set_acl)
-+ return -EOPNOTSUPP;
-+ if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
-+ return value ? -EACCES : 0;
-+ if (!inode_owner_or_capable(inode))
-+ return -EPERM;
-+
-+ if (value) {
-+ shift_acl_xattr_ids(inode->i_sb->s_user_ns,
-+ loweri->i_sb->s_user_ns,
-+ (void *)value, size);
-+ err = shiftfs_setxattr(dentry, inode, handler->name, value,
-+ size, flags);
-+ } else {
-+ err = shiftfs_removexattr(dentry, handler->name);
-+ }
-+
-+ if (!err)
-+ shiftfs_copyattr(loweri, inode);
-+
-+ return err;
-+}
-+
-+static const struct xattr_handler
-+shiftfs_posix_acl_access_xattr_handler = {
-+ .name = XATTR_NAME_POSIX_ACL_ACCESS,
-+ .flags = ACL_TYPE_ACCESS,
-+ .get = shiftfs_posix_acl_xattr_get,
-+ .set = shiftfs_posix_acl_xattr_set,
-+};
-+
-+static const struct xattr_handler
-+shiftfs_posix_acl_default_xattr_handler = {
-+ .name = XATTR_NAME_POSIX_ACL_DEFAULT,
-+ .flags = ACL_TYPE_DEFAULT,
-+ .get = shiftfs_posix_acl_xattr_get,
-+ .set = shiftfs_posix_acl_xattr_set,
-+};
-+
-+#else /* !CONFIG_SHIFT_FS_POSIX_ACL */
-+
-+#define shiftfs_get_acl NULL
-+
-+#endif /* CONFIG_SHIFT_FS_POSIX_ACL */
-+
-+static const struct inode_operations shiftfs_dir_inode_operations = {
-+ .lookup = shiftfs_lookup,
-+ .mkdir = shiftfs_mkdir,
-+ .symlink = shiftfs_symlink,
-+ .unlink = shiftfs_unlink,
-+ .rmdir = shiftfs_rmdir,
-+ .rename = shiftfs_rename,
-+ .link = shiftfs_link,
-+ .setattr = shiftfs_setattr,
-+ .create = shiftfs_create,
-+ .mknod = shiftfs_mknod,
-+ .permission = shiftfs_permission,
-+ .getattr = shiftfs_getattr,
-+ .listxattr = shiftfs_listxattr,
-+ .get_acl = shiftfs_get_acl,
-+};
-+
-+static const struct inode_operations shiftfs_file_inode_operations = {
-+ .fiemap = shiftfs_fiemap,
-+ .getattr = shiftfs_getattr,
-+ .get_acl = shiftfs_get_acl,
-+ .listxattr = shiftfs_listxattr,
-+ .permission = shiftfs_permission,
-+ .setattr = shiftfs_setattr,
-+ .tmpfile = shiftfs_tmpfile,
-+};
-+
-+static const struct inode_operations shiftfs_special_inode_operations = {
-+ .getattr = shiftfs_getattr,
-+ .get_acl = shiftfs_get_acl,
-+ .listxattr = shiftfs_listxattr,
-+ .permission = shiftfs_permission,
-+ .setattr = shiftfs_setattr,
-+};
-+
-+static const struct inode_operations shiftfs_symlink_inode_operations = {
-+ .getattr = shiftfs_getattr,
-+ .get_link = shiftfs_get_link,
-+ .listxattr = shiftfs_listxattr,
-+ .setattr = shiftfs_setattr,
-+};
-+
-+static struct file *shiftfs_open_realfile(const struct file *file,
-+ struct inode *realinode)
-+{
-+ struct file *realfile;
-+ const struct cred *old_cred;
-+ struct inode *inode = file_inode(file);
-+ struct dentry *lowerd = file->f_path.dentry->d_fsdata;
-+ struct shiftfs_super_info *info = inode->i_sb->s_fs_info;
-+ struct path realpath = { .mnt = info->mnt, .dentry = lowerd };
-+
-+ old_cred = shiftfs_override_creds(inode->i_sb);
-+ realfile = open_with_fake_path(&realpath, file->f_flags, realinode,
-+ info->creator_cred);
-+ revert_creds(old_cred);
-+
-+ return realfile;
-+}
-+
-+#define SHIFTFS_SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT)
-+
-+static int shiftfs_change_flags(struct file *file, unsigned int flags)
-+{
-+ struct inode *inode = file_inode(file);
-+ int err;
-+
-+ /* if some flag changed that cannot be changed then something's amiss */
-+ if (WARN_ON((file->f_flags ^ flags) & ~SHIFTFS_SETFL_MASK))
-+ return -EIO;
-+
-+ flags &= SHIFTFS_SETFL_MASK;
-+
-+ if (((flags ^ file->f_flags) & O_APPEND) && IS_APPEND(inode))
-+ return -EPERM;
-+
-+ if (flags & O_DIRECT) {
-+ if (!file->f_mapping->a_ops ||
-+ !file->f_mapping->a_ops->direct_IO)
-+ return -EINVAL;
-+ }
-+
-+ if (file->f_op->check_flags) {
-+ err = file->f_op->check_flags(flags);
-+ if (err)
-+ return err;
-+ }
-+
-+ spin_lock(&file->f_lock);
-+ file->f_flags = (file->f_flags & ~SHIFTFS_SETFL_MASK) | flags;
-+ spin_unlock(&file->f_lock);
-+
-+ return 0;
-+}
-+
-+static int shiftfs_open(struct inode *inode, struct file *file)
-+{
-+ struct file *realfile;
-+
-+ realfile = shiftfs_open_realfile(file, inode->i_private);
-+ if (IS_ERR(realfile))
-+ return PTR_ERR(realfile);
-+
-+ file->private_data = realfile;
-+ /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO. */
-+ file->f_mapping = realfile->f_mapping;
-+
-+ return 0;
-+}
-+
-+static int shiftfs_dir_open(struct inode *inode, struct file *file)
-+{
-+ struct file *realfile;
-+ const struct cred *oldcred;
-+ struct dentry *lowerd = file->f_path.dentry->d_fsdata;
-+ struct shiftfs_super_info *info = inode->i_sb->s_fs_info;
-+ struct path realpath = { .mnt = info->mnt, .dentry = lowerd };
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ realfile = dentry_open(&realpath, file->f_flags | O_NOATIME,
-+ info->creator_cred);
-+ revert_creds(oldcred);
-+ if (IS_ERR(realfile))
-+ return PTR_ERR(realfile);
-+
-+ file->private_data = realfile;
-+
-+ return 0;
-+}
-+
-+static int shiftfs_release(struct inode *inode, struct file *file)
-+{
-+ struct file *realfile = file->private_data;
-+
-+ if (realfile)
-+ fput(realfile);
-+
-+ return 0;
-+}
-+
-+static int shiftfs_dir_release(struct inode *inode, struct file *file)
-+{
-+ return shiftfs_release(inode, file);
-+}
-+
-+static loff_t shiftfs_dir_llseek(struct file *file, loff_t offset, int whence)
-+{
-+ struct file *realfile = file->private_data;
-+
-+ return vfs_llseek(realfile, offset, whence);
-+}
-+
-+static loff_t shiftfs_file_llseek(struct file *file, loff_t offset, int whence)
-+{
-+ struct inode *realinode = file_inode(file)->i_private;
-+
-+ return generic_file_llseek_size(file, offset, whence,
-+ realinode->i_sb->s_maxbytes,
-+ i_size_read(realinode));
-+}
-+
-+/* XXX: Need to figure out what to to about atime updates, maybe other
-+ * timestamps too ... ref. ovl_file_accessed() */
-+
-+static rwf_t shiftfs_iocb_to_rwf(struct kiocb *iocb)
-+{
-+ int ifl = iocb->ki_flags;
-+ rwf_t flags = 0;
-+
-+ if (ifl & IOCB_NOWAIT)
-+ flags |= RWF_NOWAIT;
-+ if (ifl & IOCB_HIPRI)
-+ flags |= RWF_HIPRI;
-+ if (ifl & IOCB_DSYNC)
-+ flags |= RWF_DSYNC;
-+ if (ifl & IOCB_SYNC)
-+ flags |= RWF_SYNC;
-+
-+ return flags;
-+}
-+
-+static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd)
-+{
-+ struct file *realfile;
-+
-+ if (file->f_op->open != shiftfs_open &&
-+ file->f_op->open != shiftfs_dir_open)
-+ return -EINVAL;
-+
-+ realfile = file->private_data;
-+ lowerfd->flags = 0;
-+ lowerfd->file = realfile;
-+
-+ /* Did the flags change since open? */
-+ if (unlikely(file->f_flags & ~lowerfd->file->f_flags))
-+ return shiftfs_change_flags(lowerfd->file, file->f_flags);
-+
-+ return 0;
-+}
-+
-+static ssize_t shiftfs_read_iter(struct kiocb *iocb, struct iov_iter *iter)
-+{
-+ struct file *file = iocb->ki_filp;
-+ struct fd lowerfd;
-+ const struct cred *oldcred;
-+ ssize_t ret;
-+
-+ if (!iov_iter_count(iter))
-+ return 0;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ return ret;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ ret = vfs_iter_read(lowerfd.file, iter, &iocb->ki_pos,
-+ shiftfs_iocb_to_rwf(iocb));
-+ revert_creds(oldcred);
-+
-+ shiftfs_file_accessed(file);
-+
-+ fdput(lowerfd);
-+ return ret;
-+}
-+
-+static ssize_t shiftfs_write_iter(struct kiocb *iocb, struct iov_iter *iter)
-+{
-+ struct file *file = iocb->ki_filp;
-+ struct inode *inode = file_inode(file);
-+ struct fd lowerfd;
-+ const struct cred *oldcred;
-+ ssize_t ret;
-+
-+ if (!iov_iter_count(iter))
-+ return 0;
-+
-+ inode_lock(inode);
-+ /* Update mode */
-+ shiftfs_copyattr(inode->i_private, inode);
-+ ret = file_remove_privs(file);
-+ if (ret)
-+ goto out_unlock;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ goto out_unlock;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ file_start_write(lowerfd.file);
-+ ret = vfs_iter_write(lowerfd.file, iter, &iocb->ki_pos,
-+ shiftfs_iocb_to_rwf(iocb));
-+ file_end_write(lowerfd.file);
-+ revert_creds(oldcred);
-+
-+ /* Update size */
-+ shiftfs_copyattr(inode->i_private, inode);
-+
-+ fdput(lowerfd);
-+
-+out_unlock:
-+ inode_unlock(inode);
-+ return ret;
-+}
-+
-+static int shiftfs_fsync(struct file *file, loff_t start, loff_t end,
-+ int datasync)
-+{
-+ struct fd lowerfd;
-+ const struct cred *oldcred;
-+ int ret;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ return ret;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ ret = vfs_fsync_range(lowerfd.file, start, end, datasync);
-+ revert_creds(oldcred);
-+
-+ fdput(lowerfd);
-+ return ret;
-+}
-+
-+static int shiftfs_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ struct file *realfile = file->private_data;
-+ const struct cred *oldcred;
-+ int ret;
-+
-+ if (!realfile->f_op->mmap)
-+ return -ENODEV;
-+
-+ if (WARN_ON(file != vma->vm_file))
-+ return -EIO;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ vma->vm_file = get_file(realfile);
-+ ret = call_mmap(vma->vm_file, vma);
-+ revert_creds(oldcred);
-+
-+ shiftfs_file_accessed(file);
-+
-+ if (ret) {
-+ /*
-+ * Drop refcount from new vm_file value and restore original
-+ * vm_file value
-+ */
-+ vma->vm_file = file;
-+ fput(realfile);
-+ } else {
-+ /* Drop refcount from previous vm_file value */
-+ fput(file);
-+ }
-+
-+ return ret;
-+}
-+
-+static long shiftfs_fallocate(struct file *file, int mode, loff_t offset,
-+ loff_t len)
-+{
-+ struct inode *inode = file_inode(file);
-+ struct inode *loweri = inode->i_private;
-+ struct fd lowerfd;
-+ const struct cred *oldcred;
-+ int ret;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ return ret;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ ret = vfs_fallocate(lowerfd.file, mode, offset, len);
-+ revert_creds(oldcred);
-+
-+ /* Update size */
-+ shiftfs_copyattr(loweri, inode);
-+
-+ fdput(lowerfd);
-+ return ret;
-+}
-+
-+static int shiftfs_fadvise(struct file *file, loff_t offset, loff_t len,
-+ int advice)
-+{
-+ struct fd lowerfd;
-+ const struct cred *oldcred;
-+ int ret;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ return ret;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ ret = vfs_fadvise(lowerfd.file, offset, len, advice);
-+ revert_creds(oldcred);
-+
-+ fdput(lowerfd);
-+ return ret;
-+}
-+
-+static int shiftfs_override_ioctl_creds(int cmd, const struct super_block *sb,
-+ const struct cred **oldcred,
-+ struct cred **newcred)
-+{
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+ kuid_t fsuid = current_fsuid();
-+ kgid_t fsgid = current_fsgid();
-+
-+ *oldcred = shiftfs_override_creds(sb);
-+
-+ *newcred = prepare_creds();
-+ if (!*newcred) {
-+ revert_creds(*oldcred);
-+ return -ENOMEM;
-+ }
-+
-+ (*newcred)->fsuid = shift_kuid(sb->s_user_ns, sbinfo->userns, fsuid);
-+ (*newcred)->fsgid = shift_kgid(sb->s_user_ns, sbinfo->userns, fsgid);
-+
-+ /* clear all caps to prevent bypassing capable() checks */
-+ cap_clear((*newcred)->cap_bset);
-+ cap_clear((*newcred)->cap_effective);
-+ cap_clear((*newcred)->cap_inheritable);
-+ cap_clear((*newcred)->cap_permitted);
-+
-+ if (cmd == BTRFS_IOC_SNAP_DESTROY) {
-+ kuid_t kuid_root = make_kuid(sb->s_user_ns, 0);
-+ /*
-+ * Allow the root user in the container to remove subvolumes
-+ * from other users.
-+ */
-+ if (uid_valid(kuid_root) && uid_eq(fsuid, kuid_root))
-+ cap_raise((*newcred)->cap_effective, CAP_DAC_OVERRIDE);
-+ }
-+
-+ put_cred(override_creds(*newcred));
-+ return 0;
-+}
-+
-+static inline void shiftfs_revert_ioctl_creds(const struct cred *oldcred,
-+ struct cred *newcred)
-+{
-+ return shiftfs_revert_object_creds(oldcred, newcred);
-+}
-+
-+static inline bool is_btrfs_snap_ioctl(int cmd)
-+{
-+ if ((cmd == BTRFS_IOC_SNAP_CREATE) || (cmd == BTRFS_IOC_SNAP_CREATE_V2))
-+ return true;
-+
-+ return false;
-+}
-+
-+static int shiftfs_btrfs_ioctl_fd_restore(int cmd, int fd, void __user *arg,
-+ struct btrfs_ioctl_vol_args *v1,
-+ struct btrfs_ioctl_vol_args_v2 *v2)
-+{
-+ int ret;
-+
-+ if (!is_btrfs_snap_ioctl(cmd))
-+ return 0;
-+
-+ if (cmd == BTRFS_IOC_SNAP_CREATE)
-+ ret = copy_to_user(arg, v1, sizeof(*v1));
-+ else
-+ ret = copy_to_user(arg, v2, sizeof(*v2));
-+
-+ __close_fd(current->files, fd);
-+ kfree(v1);
-+ kfree(v2);
-+
-+ return ret;
-+}
-+
-+static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
-+ struct btrfs_ioctl_vol_args **b1,
-+ struct btrfs_ioctl_vol_args_v2 **b2,
-+ int *newfd)
-+{
-+ int oldfd, ret;
-+ struct fd src;
-+ struct fd lfd = {};
-+ struct btrfs_ioctl_vol_args *v1 = NULL;
-+ struct btrfs_ioctl_vol_args_v2 *v2 = NULL;
-+
-+ if (!is_btrfs_snap_ioctl(cmd))
-+ return 0;
-+
-+ if (cmd == BTRFS_IOC_SNAP_CREATE) {
-+ v1 = memdup_user(arg, sizeof(*v1));
-+ if (IS_ERR(v1))
-+ return PTR_ERR(v1);
-+ oldfd = v1->fd;
-+ *b1 = v1;
-+ } else {
-+ v2 = memdup_user(arg, sizeof(*v2));
-+ if (IS_ERR(v2))
-+ return PTR_ERR(v2);
-+ oldfd = v2->fd;
-+ *b2 = v2;
-+ }
-+
-+ src = fdget(oldfd);
-+ if (!src.file)
-+ return -EINVAL;
-+
-+ ret = shiftfs_real_fdget(src.file, &lfd);
-+ if (ret) {
-+ fdput(src);
-+ return ret;
-+ }
-+
-+ /*
-+ * shiftfs_real_fdget() does not take a reference to lfd.file, so
-+ * take a reference here to offset the one which will be put by
-+ * __close_fd(), and make sure that reference is put on fdput(lfd).
-+ */
-+ get_file(lfd.file);
-+ lfd.flags |= FDPUT_FPUT;
-+ fdput(src);
-+
-+ *newfd = get_unused_fd_flags(lfd.file->f_flags);
-+ if (*newfd < 0) {
-+ fdput(lfd);
-+ return *newfd;
-+ }
-+
-+ fd_install(*newfd, lfd.file);
-+
-+ if (cmd == BTRFS_IOC_SNAP_CREATE) {
-+ v1->fd = *newfd;
-+ ret = copy_to_user(arg, v1, sizeof(*v1));
-+ v1->fd = oldfd;
-+ } else {
-+ v2->fd = *newfd;
-+ ret = copy_to_user(arg, v2, sizeof(*v2));
-+ v2->fd = oldfd;
-+ }
-+
-+ if (ret)
-+ shiftfs_btrfs_ioctl_fd_restore(cmd, *newfd, arg, v1, v2);
-+
-+ return ret;
-+}
-+
-+static long shiftfs_real_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ struct fd lowerfd;
-+ struct cred *newcred;
-+ const struct cred *oldcred;
-+ int newfd = -EBADF;
-+ long err = 0, ret = 0;
-+ void __user *argp = (void __user *)arg;
-+ struct super_block *sb = file->f_path.dentry->d_sb;
-+ struct btrfs_ioctl_vol_args *btrfs_v1 = NULL;
-+ struct btrfs_ioctl_vol_args_v2 *btrfs_v2 = NULL;
-+
-+ ret = shiftfs_btrfs_ioctl_fd_replace(cmd, argp, &btrfs_v1, &btrfs_v2,
-+ &newfd);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = shiftfs_real_fdget(file, &lowerfd);
-+ if (ret)
-+ goto out_restore;
-+
-+ ret = shiftfs_override_ioctl_creds(cmd, sb, &oldcred, &newcred);
-+ if (ret)
-+ goto out_fdput;
-+
-+ ret = vfs_ioctl(lowerfd.file, cmd, arg);
-+
-+ shiftfs_revert_ioctl_creds(oldcred, newcred);
-+
-+ shiftfs_copyattr(file_inode(lowerfd.file), file_inode(file));
-+ shiftfs_copyflags(file_inode(lowerfd.file), file_inode(file));
-+
-+out_fdput:
-+ fdput(lowerfd);
-+
-+out_restore:
-+ err = shiftfs_btrfs_ioctl_fd_restore(cmd, newfd, argp,
-+ btrfs_v1, btrfs_v2);
-+ if (!ret)
-+ ret = err;
-+
-+ return ret;
-+}
-+
-+static bool in_ioctl_whitelist(int flag, unsigned long arg)
-+{
-+ void __user *argp = (void __user *)arg;
-+ u64 flags = 0;
-+
-+ switch (flag) {
-+ case BTRFS_IOC_FS_INFO:
-+ return true;
-+ case BTRFS_IOC_SNAP_CREATE:
-+ return true;
-+ case BTRFS_IOC_SNAP_CREATE_V2:
-+ return true;
-+ case BTRFS_IOC_SUBVOL_CREATE:
-+ return true;
-+ case BTRFS_IOC_SUBVOL_CREATE_V2:
-+ return true;
-+ case BTRFS_IOC_SUBVOL_GETFLAGS:
-+ return true;
-+ case BTRFS_IOC_SUBVOL_SETFLAGS:
-+ if (copy_from_user(&flags, argp, sizeof(flags)))
-+ return false;
-+
-+ if (flags & ~BTRFS_SUBVOL_RDONLY)
-+ return false;
-+
-+ return true;
-+ case BTRFS_IOC_SNAP_DESTROY:
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+static long shiftfs_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ switch (cmd) {
-+ case FS_IOC_GETVERSION:
-+ /* fall through */
-+ case FS_IOC_GETFLAGS:
-+ /* fall through */
-+ case FS_IOC_SETFLAGS:
-+ break;
-+ default:
-+ if (!in_ioctl_whitelist(cmd, arg) ||
-+ !shiftfs_passthrough_ioctls(file->f_path.dentry->d_sb->s_fs_info))
-+ return -ENOTTY;
-+ }
-+
-+ return shiftfs_real_ioctl(file, cmd, arg);
-+}
-+
-+static long shiftfs_compat_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ switch (cmd) {
-+ case FS_IOC32_GETVERSION:
-+ /* fall through */
-+ case FS_IOC32_GETFLAGS:
-+ /* fall through */
-+ case FS_IOC32_SETFLAGS:
-+ break;
-+ default:
-+ if (!in_ioctl_whitelist(cmd, arg) ||
-+ !shiftfs_passthrough_ioctls(file->f_path.dentry->d_sb->s_fs_info))
-+ return -ENOIOCTLCMD;
-+ }
-+
-+ return shiftfs_real_ioctl(file, cmd, arg);
-+}
-+
-+enum shiftfs_copyop {
-+ SHIFTFS_COPY,
-+ SHIFTFS_CLONE,
-+ SHIFTFS_DEDUPE,
-+};
-+
-+static ssize_t shiftfs_copyfile(struct file *file_in, loff_t pos_in,
-+ struct file *file_out, loff_t pos_out, u64 len,
-+ unsigned int flags, enum shiftfs_copyop op)
-+{
-+ ssize_t ret;
-+ struct fd real_in, real_out;
-+ const struct cred *oldcred;
-+ struct inode *inode_out = file_inode(file_out);
-+ struct inode *loweri = inode_out->i_private;
-+
-+ ret = shiftfs_real_fdget(file_out, &real_out);
-+ if (ret)
-+ return ret;
-+
-+ ret = shiftfs_real_fdget(file_in, &real_in);
-+ if (ret) {
-+ fdput(real_out);
-+ return ret;
-+ }
-+
-+ oldcred = shiftfs_override_creds(inode_out->i_sb);
-+ switch (op) {
-+ case SHIFTFS_COPY:
-+ ret = vfs_copy_file_range(real_in.file, pos_in, real_out.file,
-+ pos_out, len, flags);
-+ break;
-+
-+ case SHIFTFS_CLONE:
-+ ret = vfs_clone_file_range(real_in.file, pos_in, real_out.file,
-+ pos_out, len, flags);
-+ break;
-+
-+ case SHIFTFS_DEDUPE:
-+ ret = vfs_dedupe_file_range_one(real_in.file, pos_in,
-+ real_out.file, pos_out, len,
-+ flags);
-+ break;
-+ }
-+ revert_creds(oldcred);
-+
-+ /* Update size */
-+ shiftfs_copyattr(loweri, inode_out);
-+
-+ fdput(real_in);
-+ fdput(real_out);
-+
-+ return ret;
-+}
-+
-+static ssize_t shiftfs_copy_file_range(struct file *file_in, loff_t pos_in,
-+ struct file *file_out, loff_t pos_out,
-+ size_t len, unsigned int flags)
-+{
-+ return shiftfs_copyfile(file_in, pos_in, file_out, pos_out, len, flags,
-+ SHIFTFS_COPY);
-+}
-+
-+static loff_t shiftfs_remap_file_range(struct file *file_in, loff_t pos_in,
-+ struct file *file_out, loff_t pos_out,
-+ loff_t len, unsigned int remap_flags)
-+{
-+ enum shiftfs_copyop op;
-+
-+ if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
-+ return -EINVAL;
-+
-+ if (remap_flags & REMAP_FILE_DEDUP)
-+ op = SHIFTFS_DEDUPE;
-+ else
-+ op = SHIFTFS_CLONE;
-+
-+ return shiftfs_copyfile(file_in, pos_in, file_out, pos_out, len,
-+ remap_flags, op);
-+}
-+
-+static int shiftfs_iterate_shared(struct file *file, struct dir_context *ctx)
-+{
-+ const struct cred *oldcred;
-+ int err = -ENOTDIR;
-+ struct file *realfile = file->private_data;
-+
-+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
-+ err = iterate_dir(realfile, ctx);
-+ revert_creds(oldcred);
-+
-+ return err;
-+}
-+
-+const struct file_operations shiftfs_file_operations = {
-+ .open = shiftfs_open,
-+ .release = shiftfs_release,
-+ .llseek = shiftfs_file_llseek,
-+ .read_iter = shiftfs_read_iter,
-+ .write_iter = shiftfs_write_iter,
-+ .fsync = shiftfs_fsync,
-+ .mmap = shiftfs_mmap,
-+ .fallocate = shiftfs_fallocate,
-+ .fadvise = shiftfs_fadvise,
-+ .unlocked_ioctl = shiftfs_ioctl,
-+ .compat_ioctl = shiftfs_compat_ioctl,
-+ .copy_file_range = shiftfs_copy_file_range,
-+ .remap_file_range = shiftfs_remap_file_range,
-+};
-+
-+const struct file_operations shiftfs_dir_operations = {
-+ .open = shiftfs_dir_open,
-+ .release = shiftfs_dir_release,
-+ .compat_ioctl = shiftfs_compat_ioctl,
-+ .fsync = shiftfs_fsync,
-+ .iterate_shared = shiftfs_iterate_shared,
-+ .llseek = shiftfs_dir_llseek,
-+ .read = generic_read_dir,
-+ .unlocked_ioctl = shiftfs_ioctl,
-+};
-+
-+static const struct address_space_operations shiftfs_aops = {
-+ /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO */
-+ .direct_IO = noop_direct_IO,
-+};
-+
-+static void shiftfs_fill_inode(struct inode *inode, unsigned long ino,
-+ umode_t mode, dev_t dev, struct dentry *dentry)
-+{
-+ struct inode *loweri;
-+
-+ inode->i_ino = ino;
-+ inode->i_flags |= S_NOCMTIME;
-+
-+ mode &= S_IFMT;
-+ inode->i_mode = mode;
-+ switch (mode & S_IFMT) {
-+ case S_IFDIR:
-+ inode->i_op = &shiftfs_dir_inode_operations;
-+ inode->i_fop = &shiftfs_dir_operations;
-+ break;
-+ case S_IFLNK:
-+ inode->i_op = &shiftfs_symlink_inode_operations;
-+ break;
-+ case S_IFREG:
-+ inode->i_op = &shiftfs_file_inode_operations;
-+ inode->i_fop = &shiftfs_file_operations;
-+ inode->i_mapping->a_ops = &shiftfs_aops;
-+ break;
-+ default:
-+ inode->i_op = &shiftfs_special_inode_operations;
-+ init_special_inode(inode, mode, dev);
-+ break;
-+ }
-+
-+ if (!dentry)
-+ return;
-+
-+ loweri = dentry->d_inode;
-+ if (!loweri->i_op->get_link)
-+ inode->i_opflags |= IOP_NOFOLLOW;
-+
-+ shiftfs_copyattr(loweri, inode);
-+ shiftfs_copyflags(loweri, inode);
-+ set_nlink(inode, loweri->i_nlink);
-+}
-+
-+static int shiftfs_show_options(struct seq_file *m, struct dentry *dentry)
-+{
-+ struct super_block *sb = dentry->d_sb;
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+
-+ if (sbinfo->mark)
-+ seq_show_option(m, "mark", NULL);
-+
-+ if (sbinfo->passthrough)
-+ seq_printf(m, ",passthrough=%u", sbinfo->passthrough);
-+
-+ return 0;
-+}
-+
-+static int shiftfs_statfs(struct dentry *dentry, struct kstatfs *buf)
-+{
-+ struct super_block *sb = dentry->d_sb;
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+ struct dentry *root = sb->s_root;
-+ struct dentry *realroot = root->d_fsdata;
-+ struct path realpath = { .mnt = sbinfo->mnt, .dentry = realroot };
-+ int err;
-+
-+ err = vfs_statfs(&realpath, buf);
-+ if (err)
-+ return err;
-+
-+ if (!shiftfs_passthrough_statfs(sbinfo))
-+ buf->f_type = sb->s_magic;
-+
-+ return 0;
-+}
-+
-+static void shiftfs_evict_inode(struct inode *inode)
-+{
-+ struct inode *loweri = inode->i_private;
-+
-+ clear_inode(inode);
-+
-+ if (loweri)
-+ iput(loweri);
-+}
-+
-+static void shiftfs_put_super(struct super_block *sb)
-+{
-+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
-+
-+ if (sbinfo) {
-+ mntput(sbinfo->mnt);
-+ put_cred(sbinfo->creator_cred);
-+ kfree(sbinfo);
-+ }
-+}
-+
-+static const struct xattr_handler shiftfs_xattr_handler = {
-+ .prefix = "",
-+ .get = shiftfs_xattr_get,
-+ .set = shiftfs_xattr_set,
-+};
-+
-+const struct xattr_handler *shiftfs_xattr_handlers[] = {
-+#ifdef CONFIG_SHIFT_FS_POSIX_ACL
-+ &shiftfs_posix_acl_access_xattr_handler,
-+ &shiftfs_posix_acl_default_xattr_handler,
-+#endif
-+ &shiftfs_xattr_handler,
-+ NULL
-+};
-+
-+static inline bool passthrough_is_subset(int old_flags, int new_flags)
-+{
-+ if ((new_flags & old_flags) != new_flags)
-+ return false;
-+
-+ return true;
-+}
-+
-+static int shiftfs_super_check_flags(unsigned long old_flags,
-+ unsigned long new_flags)
-+{
-+ if ((old_flags & SB_RDONLY) && !(new_flags & SB_RDONLY))
-+ return -EPERM;
-+
-+ if ((old_flags & SB_NOSUID) && !(new_flags & SB_NOSUID))
-+ return -EPERM;
-+
-+ if ((old_flags & SB_NODEV) && !(new_flags & SB_NODEV))
-+ return -EPERM;
-+
-+ if ((old_flags & SB_NOEXEC) && !(new_flags & SB_NOEXEC))
-+ return -EPERM;
-+
-+ if ((old_flags & SB_NOATIME) && !(new_flags & SB_NOATIME))
-+ return -EPERM;
-+
-+ if ((old_flags & SB_NODIRATIME) && !(new_flags & SB_NODIRATIME))
-+ return -EPERM;
-+
-+ if (!(old_flags & SB_POSIXACL) && (new_flags & SB_POSIXACL))
-+ return -EPERM;
-+
-+ return 0;
-+}
-+
-+static int shiftfs_remount(struct super_block *sb, int *flags, char *data)
-+{
-+ int err;
-+ struct shiftfs_super_info new = {};
-+ struct shiftfs_super_info *info = sb->s_fs_info;
-+
-+ err = shiftfs_parse_mount_options(&new, data);
-+ if (err)
-+ return err;
-+
-+ err = shiftfs_super_check_flags(sb->s_flags, *flags);
-+ if (err)
-+ return err;
-+
-+ /* Mark mount option cannot be changed. */
-+ if (info->mark || (info->mark != new.mark))
-+ return -EPERM;
-+
-+ if (info->passthrough != new.passthrough) {
-+ /* Don't allow exceeding passthrough options of mark mount. */
-+ if (!passthrough_is_subset(info->passthrough_mark,
-+ info->passthrough))
-+ return -EPERM;
-+
-+ info->passthrough = new.passthrough;
-+ }
-+
-+ return 0;
-+}
-+
-+static const struct super_operations shiftfs_super_ops = {
-+ .put_super = shiftfs_put_super,
-+ .show_options = shiftfs_show_options,
-+ .statfs = shiftfs_statfs,
-+ .remount_fs = shiftfs_remount,
-+ .evict_inode = shiftfs_evict_inode,
-+};
-+
-+struct shiftfs_data {
-+ void *data;
-+ const char *path;
-+};
-+
-+static void shiftfs_super_force_flags(struct super_block *sb,
-+ unsigned long lower_flags)
-+{
-+ sb->s_flags |= lower_flags & (SB_RDONLY | SB_NOSUID | SB_NODEV |
-+ SB_NOEXEC | SB_NOATIME | SB_NODIRATIME);
-+
-+ if (!(lower_flags & SB_POSIXACL))
-+ sb->s_flags &= ~SB_POSIXACL;
-+}
-+
-+static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
-+ int silent)
-+{
-+ int err;
-+ struct path path = {};
-+ struct shiftfs_super_info *sbinfo_mp;
-+ char *name = NULL;
-+ struct inode *inode = NULL;
-+ struct dentry *dentry = NULL;
-+ struct shiftfs_data *data = raw_data;
-+ struct shiftfs_super_info *sbinfo = NULL;
-+
-+ if (!data->path)
-+ return -EINVAL;
-+
-+ sb->s_fs_info = kzalloc(sizeof(*sbinfo), GFP_KERNEL);
-+ if (!sb->s_fs_info)
-+ return -ENOMEM;
-+ sbinfo = sb->s_fs_info;
-+
-+ err = shiftfs_parse_mount_options(sbinfo, data->data);
-+ if (err)
-+ return err;
-+
-+ /* to mount a mark, must be userns admin */
-+ if (!sbinfo->mark && !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
-+ return -EPERM;
-+
-+ name = kstrdup(data->path, GFP_KERNEL);
-+ if (!name)
-+ return -ENOMEM;
-+
-+ err = kern_path(name, LOOKUP_FOLLOW, &path);
-+ if (err)
-+ goto out_free_name;
-+
-+ if (!S_ISDIR(path.dentry->d_inode->i_mode)) {
-+ err = -ENOTDIR;
-+ goto out_put_path;
-+ }
-+
-+ sb->s_flags |= SB_POSIXACL;
-+
-+ if (sbinfo->mark) {
-+ struct cred *cred_tmp;
-+ struct super_block *lower_sb = path.mnt->mnt_sb;
-+
-+ /* to mark a mount point, must root wrt lower s_user_ns */
-+ if (!ns_capable(lower_sb->s_user_ns, CAP_SYS_ADMIN)) {
-+ err = -EPERM;
-+ goto out_put_path;
-+ }
-+
-+ /*
-+ * this part is visible unshifted, so make sure no
-+ * executables that could be used to give suid
-+ * privileges
-+ */
-+ sb->s_iflags = SB_I_NOEXEC;
-+
-+ shiftfs_super_force_flags(sb, lower_sb->s_flags);
-+
-+ /*
-+ * Handle nesting of shiftfs mounts by referring this mark
-+ * mount back to the original mark mount. This is more
-+ * efficient and alleviates concerns about stack depth.
-+ */
-+ if (lower_sb->s_magic == SHIFTFS_MAGIC) {
-+ sbinfo_mp = lower_sb->s_fs_info;
-+
-+ /* Doesn't make sense to mark a mark mount */
-+ if (sbinfo_mp->mark) {
-+ err = -EINVAL;
-+ goto out_put_path;
-+ }
-+
-+ if (!passthrough_is_subset(sbinfo_mp->passthrough,
-+ sbinfo->passthrough)) {
-+ err = -EPERM;
-+ goto out_put_path;
-+ }
-+
-+ sbinfo->mnt = mntget(sbinfo_mp->mnt);
-+ dentry = dget(path.dentry->d_fsdata);
-+ /*
-+ * Copy up the passthrough mount options from the
-+ * parent mark mountpoint.
-+ */
-+ sbinfo->passthrough_mark = sbinfo_mp->passthrough_mark;
-+ sbinfo->creator_cred = get_cred(sbinfo_mp->creator_cred);
-+ } else {
-+ sbinfo->mnt = mntget(path.mnt);
-+ dentry = dget(path.dentry);
-+ /*
-+ * For a new mark passthrough_mark and passthrough
-+ * are identical.
-+ */
-+ sbinfo->passthrough_mark = sbinfo->passthrough;
-+
-+ cred_tmp = prepare_creds();
-+ if (!cred_tmp) {
-+ err = -ENOMEM;
-+ goto out_put_path;
-+ }
-+ /* Don't override disk quota limits or use reserved space. */
-+ cap_lower(cred_tmp->cap_effective, CAP_SYS_RESOURCE);
-+ sbinfo->creator_cred = cred_tmp;
-+ }
-+ } else {
-+ /*
-+ * This leg executes if we're admin capable in the namespace,
-+ * so be very careful.
-+ */
-+ err = -EPERM;
-+ if (path.dentry->d_sb->s_magic != SHIFTFS_MAGIC)
-+ goto out_put_path;
-+
-+ sbinfo_mp = path.dentry->d_sb->s_fs_info;
-+ if (!sbinfo_mp->mark)
-+ goto out_put_path;
-+
-+ if (!passthrough_is_subset(sbinfo_mp->passthrough,
-+ sbinfo->passthrough))
-+ goto out_put_path;
-+
-+ sbinfo->mnt = mntget(sbinfo_mp->mnt);
-+ sbinfo->creator_cred = get_cred(sbinfo_mp->creator_cred);
-+ dentry = dget(path.dentry->d_fsdata);
-+ /*
-+ * Copy up passthrough settings from mark mountpoint so we can
-+ * verify when the overlay wants to remount with different
-+ * passthrough settings.
-+ */
-+ sbinfo->passthrough_mark = sbinfo_mp->passthrough;
-+ shiftfs_super_force_flags(sb, path.mnt->mnt_sb->s_flags);
-+ }
-+
-+ sb->s_stack_depth = dentry->d_sb->s_stack_depth + 1;
-+ if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
-+ printk(KERN_ERR "shiftfs: maximum stacking depth exceeded\n");
-+ err = -EINVAL;
-+ goto out_put_path;
-+ }
-+
-+ inode = new_inode(sb);
-+ if (!inode) {
-+ err = -ENOMEM;
-+ goto out_put_path;
-+ }
-+ shiftfs_fill_inode(inode, dentry->d_inode->i_ino, S_IFDIR, 0, dentry);
-+
-+ ihold(dentry->d_inode);
-+ inode->i_private = dentry->d_inode;
-+
-+ sb->s_magic = SHIFTFS_MAGIC;
-+ sb->s_maxbytes = MAX_LFS_FILESIZE;
-+ sb->s_op = &shiftfs_super_ops;
-+ sb->s_xattr = shiftfs_xattr_handlers;
-+ sb->s_d_op = &shiftfs_dentry_ops;
-+ sb->s_root = d_make_root(inode);
-+ if (!sb->s_root) {
-+ err = -ENOMEM;
-+ goto out_put_path;
-+ }
-+
-+ sb->s_root->d_fsdata = dentry;
-+ sbinfo->userns = get_user_ns(dentry->d_sb->s_user_ns);
-+ shiftfs_copyattr(dentry->d_inode, sb->s_root->d_inode);
-+
-+ dentry = NULL;
-+ err = 0;
-+
-+out_put_path:
-+ path_put(&path);
-+
-+out_free_name:
-+ kfree(name);
-+
-+ dput(dentry);
-+
-+ return err;
-+}
-+
-+static struct dentry *shiftfs_mount(struct file_system_type *fs_type,
-+ int flags, const char *dev_name, void *data)
-+{
-+ struct shiftfs_data d = { data, dev_name };
-+
-+ return mount_nodev(fs_type, flags, &d, shiftfs_fill_super);
-+}
-+
-+static struct file_system_type shiftfs_type = {
-+ .owner = THIS_MODULE,
-+ .name = "shiftfs",
-+ .mount = shiftfs_mount,
-+ .kill_sb = kill_anon_super,
-+ .fs_flags = FS_USERNS_MOUNT,
-+};
-+
-+static int __init shiftfs_init(void)
-+{
-+ return register_filesystem(&shiftfs_type);
-+}
-+
-+static void __exit shiftfs_exit(void)
-+{
-+ unregister_filesystem(&shiftfs_type);
-+}
-+
-+MODULE_ALIAS_FS("shiftfs");
-+MODULE_AUTHOR("James Bottomley");
-+MODULE_AUTHOR("Seth Forshee <seth.forshee@canonical.com>");
-+MODULE_AUTHOR("Christian Brauner <christian.brauner@ubuntu.com>");
-+MODULE_DESCRIPTION("id shifting filesystem");
-+MODULE_LICENSE("GPL v2");
-+module_init(shiftfs_init)
-+module_exit(shiftfs_exit)
---- a/include/uapi/linux/magic.h 2021-01-06 19:08:45.234777659 -0500
-+++ b/include/uapi/linux/magic.h 2021-01-06 19:09:53.900375394 -0500
-@@ -96,4 +96,6 @@
- #define DEVMEM_MAGIC 0x454d444d /* "DMEM" */
- #define Z3FOLD_MAGIC 0x33
-
-+#define SHIFTFS_MAGIC 0x6a656a62
-+
- #endif /* __LINUX_MAGIC_H__ */
---- a/fs/Makefile 2021-01-08 18:08:28.187064015 -0500
-+++ b/fs/Makefile 2021-01-08 18:09:00.788217579 -0500
-@@ -136,3 +136,4 @@ obj-$(CONFIG_EFIVAR_FS) += efivarfs/
- obj-$(CONFIG_EROFS_FS) += erofs/
- obj-$(CONFIG_VBOXSF_FS) += vboxsf/
- obj-$(CONFIG_ZONEFS_FS) += zonefs/
-+obj-$(CONFIG_SHIFT_FS) += shiftfs.o
---- a/fs/Kconfig 2021-01-06 19:14:17.709697891 -0500
-+++ b/fs/Kconfig 2021-01-06 19:15:23.413281282 -0500
-@@ -122,6 +122,24 @@ source "fs/autofs/Kconfig"
- source "fs/fuse/Kconfig"
- source "fs/overlayfs/Kconfig"
-
-+config SHIFT_FS
-+ tristate "UID/GID shifting overlay filesystem for containers"
-+ help
-+ This filesystem can overlay any mounted filesystem and shift
-+ the uid/gid the files appear at. The idea is that
-+ unprivileged containers can use this to mount root volumes
-+ using this technique.
-+
-+config SHIFT_FS_POSIX_ACL
-+ bool "shiftfs POSIX Access Control Lists"
-+ depends on SHIFT_FS
-+ select FS_POSIX_ACL
-+ help
-+ POSIX Access Control Lists (ACLs) support permissions for users and
-+ groups beyond the owner/group/world scheme.
-+
-+ If you don't know what Access Control Lists are, say N.
-+
- menu "Caches"
-
- source "fs/fscache/Kconfig"
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch
deleted file mode 100644
index f8f2122cb3cd..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0001-make-DEFAULT_MMAP_MIN_ADDR-match-LSM_MMAP_MIN_ADDR.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 30c2f2c6db2cf258ae0dd7fb30884f55bac154f1 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 27 May 2017 07:22:12 -0400
-Subject: [PATCH 001/113] make DEFAULT_MMAP_MIN_ADDR match LSM_MMAP_MIN_ADDR
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/Kconfig | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/mm/Kconfig b/mm/Kconfig
-index 390165ffbb0f..3b24c9e3535e 100644
---- a/mm/Kconfig
-+++ b/mm/Kconfig
-@@ -321,7 +321,8 @@ config KSM
- config DEFAULT_MMAP_MIN_ADDR
- int "Low address space to protect from user allocation"
- depends on MMU
-- default 4096
-+ default 32768 if ARM || (ARM64 && COMPAT)
-+ default 65536
- help
- This is the portion of low virtual memory which should be protected
- from userspace allocation. Keeping a user from writing to low pages
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0002-enable-HARDENED_USERCOPY-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0002-enable-HARDENED_USERCOPY-by-default.patch
deleted file mode 100644
index 9f78840ae492..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0002-enable-HARDENED_USERCOPY-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 437cb2ad97254b24e60ba133808b7cae0fe6b298 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 29 May 2017 06:17:41 -0400
-Subject: [PATCH 002/113] enable HARDENED_USERCOPY by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- security/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 7561f6f99f1d..9446ddf40974 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -154,6 +154,7 @@ config HARDENED_USERCOPY
- bool "Harden memory copies between kernel and userspace"
- depends on HAVE_HARDENED_USERCOPY_ALLOCATOR
- imply STRICT_DEVMEM
-+ default y
- help
- This option checks for obviously wrong memory regions when
- copying memory to/from the kernel (via copy_to_user() and
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch
deleted file mode 100644
index 024742c47f89..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0003-disable-HARDENED_USERCOPY_FALLBACK-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 0857d86274507a026ccd8910d307b2e4874b14ac Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 26 Apr 2018 02:01:26 -0400
-Subject: [PATCH 003/113] disable HARDENED_USERCOPY_FALLBACK by default
-
----
- security/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 9446ddf40974..5c388f7fe09d 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -167,7 +167,6 @@ config HARDENED_USERCOPY
- config HARDENED_USERCOPY_FALLBACK
- bool "Allow usercopy whitelist violations to fallback to object size"
- depends on HARDENED_USERCOPY
-- default y
- help
- This is a temporary option that allows missing usercopy whitelists
- to be discovered via a WARN() to the kernel log, instead of
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch
deleted file mode 100644
index 12711244396e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0004-enable-SECURITY_DMESG_RESTRICT-by-default.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From a9943395a6697f68e4f77f622f0325fb3b447d67 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:05:15 -0400
-Subject: [PATCH 004/113] enable SECURITY_DMESG_RESTRICT by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- security/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 5c388f7fe09d..428ad7622370 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -9,7 +9,7 @@ source "security/keys/Kconfig"
-
- config SECURITY_DMESG_RESTRICT
- bool "Restrict unprivileged access to the kernel syslog"
-- default n
-+ default y
- help
- This enforces restrictions on unprivileged users reading the kernel
- syslog via dmesg(8).
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0005-set-kptr_restrict-2-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0005-set-kptr_restrict-2-by-default.patch
deleted file mode 100644
index b7ec66b45535..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0005-set-kptr_restrict-2-by-default.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 0455b0e44f264e2151355933b2207155573d8ca9 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:06:14 -0400
-Subject: [PATCH 005/113] set kptr_restrict=2 by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- lib/vsprintf.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/lib/vsprintf.c b/lib/vsprintf.c
-index 14c9a6af1b23..2501f75bd74d 100644
---- a/lib/vsprintf.c
-+++ b/lib/vsprintf.c
-@@ -821,7 +821,7 @@ static char *ptr_to_id(char *buf, char *end, const void *ptr,
- return pointer_string(buf, end, (const void *)hashval, spec);
- }
-
--int kptr_restrict __read_mostly;
-+int kptr_restrict __read_mostly = 2;
-
- static noinline_for_stack
- char *restricted_pointer(char *buf, char *end, const void *ptr,
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0006-enable-DEBUG_LIST-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0006-enable-DEBUG_LIST-by-default.patch
deleted file mode 100644
index 09889dd0d500..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0006-enable-DEBUG_LIST-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From e2559a54cae54f9df791118b3134fa9ec5a0fc41 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:10:57 -0400
-Subject: [PATCH 006/113] enable DEBUG_LIST by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- lib/Kconfig.debug | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index c789b39ed527..89c9d6aebf77 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -1471,6 +1471,7 @@ menu "Debug kernel data structures"
- config DEBUG_LIST
- bool "Debug linked list manipulation"
- depends on DEBUG_KERNEL || BUG_ON_DATA_CORRUPTION
-+ default y
- help
- Enable this to turn on extended checks in the linked-list
- walking routines.
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch
deleted file mode 100644
index 63c45608206d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0007-enable-BUG_ON_DATA_CORRUPTION-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 3699b64980b7d8779c2b72fe906e89a9e3411211 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 29 May 2017 12:21:21 -0400
-Subject: [PATCH 007/113] enable BUG_ON_DATA_CORRUPTION by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- lib/Kconfig.debug | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index 89c9d6aebf77..11068e77d146 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -1511,6 +1511,7 @@ config DEBUG_NOTIFIERS
- config BUG_ON_DATA_CORRUPTION
- bool "Trigger a BUG when data corruption is detected"
- select DEBUG_LIST
-+ default y
- help
- Select this option if the kernel should BUG when it encounters
- data corruption in kernel memory structures when they get checked
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch
deleted file mode 100644
index 8d956207b61f..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0008-enable-ARM64_SW_TTBR0_PAN-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 1f7bedc814d9bec78d93858a91a1c41c72fb5d9b Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 01:39:32 -0500
-Subject: [PATCH 008/113] enable ARM64_SW_TTBR0_PAN by default
-
----
- arch/arm64/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index a6b5b7ef40ae..a145245ec5e7 100644
---- a/arch/arm64/Kconfig
-+++ b/arch/arm64/Kconfig
-@@ -1199,6 +1199,7 @@ config RODATA_FULL_DEFAULT_ENABLED
-
- config ARM64_SW_TTBR0_PAN
- bool "Emulate Privileged Access Never using TTBR0_EL1 switching"
-+ default y
- help
- Enabling this option prevents the kernel from accessing
- user-space memory directly by pointing TTBR0_EL1 to a reserved
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0009-arm64-enable-RANDOMIZE_BASE-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0009-arm64-enable-RANDOMIZE_BASE-by-default.patch
deleted file mode 100644
index 6d04cc08d09e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0009-arm64-enable-RANDOMIZE_BASE-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 0a215fddffc20c8f2aa776111937c4d690fe14f8 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 01:33:48 -0500
-Subject: [PATCH 009/113] arm64: enable RANDOMIZE_BASE by default
-
----
- arch/arm64/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index a145245ec5e7..21088a6532d8 100644
---- a/arch/arm64/Kconfig
-+++ b/arch/arm64/Kconfig
-@@ -1790,6 +1790,7 @@ config RANDOMIZE_BASE
- bool "Randomize the address of the kernel image"
- select ARM64_MODULE_PLTS if MODULES
- select RELOCATABLE
-+ default y
- help
- Randomizes the virtual address at which the kernel image is
- loaded, as a security feature that deters exploit attempts
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0010-enable-SLAB_FREELIST_RANDOM-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0010-enable-SLAB_FREELIST_RANDOM-by-default.patch
deleted file mode 100644
index 53cdf0f3ba22..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0010-enable-SLAB_FREELIST_RANDOM-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From ccd7ee1cce3fc4f9fa54520f3adbbf47a4fcad27 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 19:43:38 -0400
-Subject: [PATCH 010/113] enable SLAB_FREELIST_RANDOM by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- init/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 0872a5a2e759..dcbcb4243316 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1929,6 +1929,7 @@ config SLAB_MERGE_DEFAULT
- config SLAB_FREELIST_RANDOM
- bool "Randomize slab freelist"
- depends on SLAB || SLUB
-+ default y
- help
- Randomizes the freelist order used on creating new pages. This
- security feature reduces the predictability of the kernel slab
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0011-enable-SLAB_FREELIST_HARDENED-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0011-enable-SLAB_FREELIST_HARDENED-by-default.patch
deleted file mode 100644
index 2664e4fe0cac..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0011-enable-SLAB_FREELIST_HARDENED-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 3bdf61f4fd15f83c6c68ec80a1075cc97fcc27a7 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 20 Aug 2017 15:39:25 -0400
-Subject: [PATCH 011/113] enable SLAB_FREELIST_HARDENED by default
-
----
- init/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index dcbcb4243316..667d1c6c021b 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1938,6 +1938,7 @@ config SLAB_FREELIST_RANDOM
- config SLAB_FREELIST_HARDENED
- bool "Harden slab freelist metadata"
- depends on SLAB || SLUB
-+ default y
- help
- Many kernel heap attacks try to target slab cache metadata and
- other infrastructure. This options makes minor performance
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0012-disable-SLAB_MERGE_DEFAULT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0012-disable-SLAB_MERGE_DEFAULT-by-default.patch
deleted file mode 100644
index a318069e51d3..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0012-disable-SLAB_MERGE_DEFAULT-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 0b6f9a21063ad87550e8ad3c585bfc2af8ac1d49 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 8 Jul 2017 02:38:54 -0400
-Subject: [PATCH 012/113] disable SLAB_MERGE_DEFAULT by default
-
----
- init/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 667d1c6c021b..859ab5ae66ff 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1914,7 +1914,6 @@ endchoice
-
- config SLAB_MERGE_DEFAULT
- bool "Allow slab caches to be merged"
-- default y
- help
- For reduced kernel memory fragmentation, slab caches can be
- merged when they share the same size and other characteristics.
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0013-enable-FORTIFY_SOURCE-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0013-enable-FORTIFY_SOURCE-by-default.patch
deleted file mode 100644
index 9637a356b0c6..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0013-enable-FORTIFY_SOURCE-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 877645788ff6bb326cb8f90aedf431fac367c92f Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 8 May 2017 12:51:54 -0400
-Subject: [PATCH 013/113] enable FORTIFY_SOURCE by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- security/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 428ad7622370..3a2c68c7b50f 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -191,6 +191,7 @@ config HARDENED_USERCOPY_PAGESPAN
- config FORTIFY_SOURCE
- bool "Harden common str/mem functions against buffer overflows"
- depends on ARCH_HAS_FORTIFY_SOURCE
-+ default y
- help
- Detect overflows of buffers in common string and memory functions
- where the compiler can determine and validate the buffer sizes.
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0014-enable-PANIC_ON_OOPS-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0014-enable-PANIC_ON_OOPS-by-default.patch
deleted file mode 100644
index 752187981ff1..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0014-enable-PANIC_ON_OOPS-by-default.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From f56cae64efe0e211d99aea8175098433e1fa2ee9 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:09:17 -0400
-Subject: [PATCH 014/113] enable PANIC_ON_OOPS by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- lib/Kconfig.debug | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index 11068e77d146..45b169177fb9 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -894,6 +894,7 @@ menu "Debug Oops, Lockups and Hangs"
-
- config PANIC_ON_OOPS
- bool "Panic on Oops"
-+ default y
- help
- Say Y here to enable the kernel to panic when it oopses. This
- has the same effect as setting oops=panic on the kernel command
-@@ -903,7 +904,7 @@ config PANIC_ON_OOPS
- anything erroneous after an oops which could result in data
- corruption or other issues.
-
-- Say N if unsure.
-+ Say Y if unsure.
-
- config PANIC_ON_OOPS_VALUE
- int
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch
deleted file mode 100644
index 6e2c2fd764ab..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0015-stop-hiding-SLUB_DEBUG-behind-EXPERT.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From aac553a70c3506a97cb33821e5b15fbf5fba3158 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 14 May 2017 22:39:34 -0400
-Subject: [PATCH 015/113] stop hiding SLUB_DEBUG behind EXPERT
-
-It can make sense to disable this to reduce attack surface / complexity.
----
- init/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 859ab5ae66ff..74680a15ceb4 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1843,7 +1843,7 @@ config VM_EVENT_COUNTERS
-
- config SLUB_DEBUG
- default y
-- bool "Enable SLUB debugging support" if EXPERT
-+ bool "Enable SLUB debugging support"
- depends on SLUB && SYSFS
- help
- SLUB has extensive debug support features. Disabling these can
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0016-stop-hiding-X86_16BIT-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0016-stop-hiding-X86_16BIT-behind-EXPERT.patch
deleted file mode 100644
index 49895dc51e47..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0016-stop-hiding-X86_16BIT-behind-EXPERT.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 6bec6634466c70d12acaddacd5e1023684dbb3c0 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 18:11:31 -0400
-Subject: [PATCH 016/113] stop hiding X86_16BIT behind EXPERT
-
----
- arch/x86/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 3a5ecb1039bf..d2d5e0cbf85c 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -1194,7 +1194,7 @@ config VM86
- default X86_LEGACY_VM86
-
- config X86_16BIT
-- bool "Enable support for 16-bit segments" if EXPERT
-+ bool "Enable support for 16-bit segments"
- default y
- depends on MODIFY_LDT_SYSCALL
- help
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0017-disable-X86_16BIT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0017-disable-X86_16BIT-by-default.patch
deleted file mode 100644
index 47e1a1e829c8..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0017-disable-X86_16BIT-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 2820aa8f5dc49f6b52dd3913fd873d0256543f20 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 18:11:52 -0400
-Subject: [PATCH 017/113] disable X86_16BIT by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index d2d5e0cbf85c..ab6e7e2d3cf0 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -1195,7 +1195,6 @@ config VM86
-
- config X86_16BIT
- bool "Enable support for 16-bit segments"
-- default y
- depends on MODIFY_LDT_SYSCALL
- help
- This option is required by programs like Wine to run 16-bit
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch
deleted file mode 100644
index a72e45a811cc..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0018-stop-hiding-MODIFY_LDT_SYSCALL-behind-EXPERT.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From ca5dce9c47de65f90b9b826e7514a37ce23f9a42 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 18:15:52 -0400
-Subject: [PATCH 018/113] stop hiding MODIFY_LDT_SYSCALL behind EXPERT
-
----
- arch/x86/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index ab6e7e2d3cf0..7b9df510469b 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -2392,7 +2392,7 @@ config CMDLINE_OVERRIDE
- be set to 'N' under normal conditions.
-
- config MODIFY_LDT_SYSCALL
-- bool "Enable the LDT (local descriptor table)" if EXPERT
-+ bool "Enable the LDT (local descriptor table)"
- default y
- help
- Linux can allow user programs to install a per-process x86
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0019-disable-MODIFY_LDT_SYSCALL-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0019-disable-MODIFY_LDT_SYSCALL-by-default.patch
deleted file mode 100644
index 178e0a193c3e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0019-disable-MODIFY_LDT_SYSCALL-by-default.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 9c1be96e8fbf27df4ce830b2e270b231870d38fb Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 18:16:16 -0400
-Subject: [PATCH 019/113] disable MODIFY_LDT_SYSCALL by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- arch/x86/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 7b9df510469b..63e1e9fc18dd 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -2393,7 +2393,6 @@ config CMDLINE_OVERRIDE
-
- config MODIFY_LDT_SYSCALL
- bool "Enable the LDT (local descriptor table)"
-- default y
- help
- Linux can allow user programs to install a per-process x86
- Local Descriptor Table (LDT) using the modify_ldt(2) system
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0020-set-LEGACY_VSYSCALL_NONE-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0020-set-LEGACY_VSYSCALL_NONE-by-default.patch
deleted file mode 100644
index 732f786b952b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0020-set-LEGACY_VSYSCALL_NONE-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From df005ca65f037830f2ccc1f85cd03172e4f122cb Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 29 May 2017 07:08:42 -0400
-Subject: [PATCH 020/113] set LEGACY_VSYSCALL_NONE by default
-
----
- arch/x86/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 63e1e9fc18dd..4fd082de7420 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -2296,7 +2296,7 @@ config COMPAT_VDSO
- choice
- prompt "vsyscall table for legacy applications"
- depends on X86_64
-- default LEGACY_VSYSCALL_XONLY
-+ default LEGACY_VSYSCALL_NONE
- help
- Legacy user code that does not know how to find the vDSO expects
- to be able to issue three syscalls by calling fixed addresses in
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0021-stop-hiding-AIO-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0021-stop-hiding-AIO-behind-EXPERT.patch
deleted file mode 100644
index bb40a91fc527..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0021-stop-hiding-AIO-behind-EXPERT.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 99991cae01d880237386a0947862557fb4bd5eba Mon Sep 17 00:00:00 2001
-From: Bernhard40 <32568352+Bernhard40@users.noreply.github.com>
-Date: Fri, 6 Oct 2017 10:21:50 +0000
-Subject: [PATCH 021/113] stop hiding AIO behind EXPERT
-
----
- init/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 74680a15ceb4..8605f3e78e47 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1591,7 +1591,7 @@ config SHMEM
- which may be appropriate on small systems without swap.
-
- config AIO
-- bool "Enable AIO support" if EXPERT
-+ bool "Enable AIO support"
- default y
- help
- This option enables POSIX asynchronous I/O which may by used
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0022-disable-AIO-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0022-disable-AIO-by-default.patch
deleted file mode 100644
index fc9abea42075..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0022-disable-AIO-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From c3899f4ac55a90679c7b1e1175edd30a3dbf077c Mon Sep 17 00:00:00 2001
-From: Bernhard40 <32568352+Bernhard40@users.noreply.github.com>
-Date: Fri, 6 Oct 2017 10:24:10 +0000
-Subject: [PATCH 022/113] disable AIO by default
-
----
- init/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 8605f3e78e47..21f0b6926cf3 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1592,7 +1592,6 @@ config SHMEM
-
- config AIO
- bool "Enable AIO support"
-- default y
- help
- This option enables POSIX asynchronous I/O which may by used
- by some high performance threaded applications. Disabling
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch
deleted file mode 100644
index 928b654e89f3..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0023-remove-SYSVIPC-from-arm64-x86_64-defconfigs.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 693f07d2bccfff30ec58776bfe988a37a36037b6 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 02:08:49 -0500
-Subject: [PATCH 023/113] remove SYSVIPC from arm64/x86_64 defconfigs
-
----
- arch/arm64/configs/defconfig | 1 -
- arch/x86/configs/x86_64_defconfig | 1 -
- 2 files changed, 2 deletions(-)
-
-diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
-index 5cfe3cf6f2ac..f25871361bdc 100644
---- a/arch/arm64/configs/defconfig
-+++ b/arch/arm64/configs/defconfig
-@@ -1,4 +1,3 @@
--CONFIG_SYSVIPC=y
- CONFIG_POSIX_MQUEUE=y
- CONFIG_AUDIT=y
- CONFIG_NO_HZ_IDLE=y
-diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
-index 9936528e1939..981ee8c0e330 100644
---- a/arch/x86/configs/x86_64_defconfig
-+++ b/arch/x86/configs/x86_64_defconfig
-@@ -1,5 +1,4 @@
- # CONFIG_LOCALVERSION_AUTO is not set
--CONFIG_SYSVIPC=y
- CONFIG_POSIX_MQUEUE=y
- CONFIG_AUDIT=y
- CONFIG_NO_HZ=y
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0024-disable-DEVPORT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0024-disable-DEVPORT-by-default.patch
deleted file mode 100644
index ef7ce5bb4558..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0024-disable-DEVPORT-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 366eacb7f45ab0cd377af20025eae1ca418c76f5 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 27 May 2017 07:28:10 -0400
-Subject: [PATCH 024/113] disable DEVPORT by default
-
----
- drivers/char/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
-index d229a2d0c017..68178c3a25de 100644
---- a/drivers/char/Kconfig
-+++ b/drivers/char/Kconfig
-@@ -391,7 +391,6 @@ config MAX_RAW_DEVS
- config DEVPORT
- bool "/dev/port character device"
- depends on ISA || PCI
-- default y
- help
- Say Y here if you want to support the /dev/port device. The /dev/port
- device is similar to /dev/mem, but for I/O ports.
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0025-disable-PROC_VMCORE-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0025-disable-PROC_VMCORE-by-default.patch
deleted file mode 100644
index af9e7d9115ff..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0025-disable-PROC_VMCORE-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 470f9d68246af103dc79d3f804eccf2114326c52 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 27 May 2017 07:29:45 -0400
-Subject: [PATCH 025/113] disable PROC_VMCORE by default
-
----
- fs/proc/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig
-index c930001056f9..6a0a51b3f593 100644
---- a/fs/proc/Kconfig
-+++ b/fs/proc/Kconfig
-@@ -41,7 +41,6 @@ config PROC_KCORE
- config PROC_VMCORE
- bool "/proc/vmcore support"
- depends on PROC_FS && CRASH_DUMP
-- default y
- help
- Exports the dump image of crashed kernel in ELF format.
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0026-disable-NFS_DEBUG-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0026-disable-NFS_DEBUG-by-default.patch
deleted file mode 100644
index 9cb6bc268713..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0026-disable-NFS_DEBUG-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 64dc800cbfe0c7dde04e471807e80140d1989ef6 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 28 May 2017 03:03:46 -0400
-Subject: [PATCH 026/113] disable NFS_DEBUG by default
-
----
- fs/nfs/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
-index e2a488d403a6..ce54c1c693a8 100644
---- a/fs/nfs/Kconfig
-+++ b/fs/nfs/Kconfig
-@@ -195,7 +195,6 @@ config NFS_DEBUG
- bool
- depends on NFS_FS && SUNRPC_DEBUG
- select CRC32
-- default y
-
- config NFS_DISABLE_UDP_SUPPORT
- bool "NFS: Disable NFS UDP protocol support"
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0027-enable-DEBUG_WX-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0027-enable-DEBUG_WX-by-default.patch
deleted file mode 100644
index 417e81fc7833..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0027-enable-DEBUG_WX-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 839523af4d580520035120f486271943234a7503 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 29 May 2017 12:11:11 -0400
-Subject: [PATCH 027/113] enable DEBUG_WX by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/Kconfig.debug | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug
-index 864f129f1937..929d585bd267 100644
---- a/mm/Kconfig.debug
-+++ b/mm/Kconfig.debug
-@@ -126,6 +126,7 @@ config DEBUG_WX
- depends on ARCH_HAS_DEBUG_WX
- depends on MMU
- select PTDUMP_CORE
-+ default y
- help
- Generate a warning if any W+X mappings are found at boot.
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0028-disable-LEGACY_PTYS-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0028-disable-LEGACY_PTYS-by-default.patch
deleted file mode 100644
index 83b44562583e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0028-disable-LEGACY_PTYS-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 3b75ae9d5a52b590f4e4538b54605e260ce36569 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Fri, 5 Jan 2018 13:21:16 -0500
-Subject: [PATCH 028/113] disable LEGACY_PTYS by default
-
----
- drivers/tty/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
-index 93fd984eb2f5..d9086484d2de 100644
---- a/drivers/tty/Kconfig
-+++ b/drivers/tty/Kconfig
-@@ -122,7 +122,6 @@ config UNIX98_PTYS
-
- config LEGACY_PTYS
- bool "Legacy (BSD) PTY support"
-- default y
- help
- A pseudo terminal (PTY) is a software device consisting of two
- halves: a master and a slave. The slave device behaves identical to
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0029-disable-DEVMEM-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0029-disable-DEVMEM-by-default.patch
deleted file mode 100644
index d5fff73b8eb0..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0029-disable-DEVMEM-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 9c70639fa73518a3cd963b8c97f067712b3eaac4 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Fri, 5 Jan 2018 12:41:42 -0500
-Subject: [PATCH 029/113] disable DEVMEM by default
-
----
- drivers/char/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
-index 68178c3a25de..2fd45f01e7a2 100644
---- a/drivers/char/Kconfig
-+++ b/drivers/char/Kconfig
-@@ -327,7 +327,6 @@ config NSC_GPIO
-
- config DEVMEM
- bool "/dev/mem virtual device support"
-- default y
- help
- Say Y here if you want to support the /dev/mem device.
- The /dev/mem device is used to access areas of physical
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0030-enable-IO_STRICT_DEVMEM-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0030-enable-IO_STRICT_DEVMEM-by-default.patch
deleted file mode 100644
index f21c4186740c..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0030-enable-IO_STRICT_DEVMEM-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From f713dfa97e016d7210b7eeb735e06bb3f3b2deb4 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Fri, 5 Jan 2018 12:43:49 -0500
-Subject: [PATCH 030/113] enable IO_STRICT_DEVMEM by default
-
----
- lib/Kconfig.debug | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index 45b169177fb9..a46f21a56125 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -1668,6 +1668,7 @@ config STRICT_DEVMEM
- config IO_STRICT_DEVMEM
- bool "Filter I/O access to /dev/mem"
- depends on STRICT_DEVMEM
-+ default y
- help
- If this option is disabled, you allow userspace (root) access to all
- io-memory regardless of whether a driver is actively using that
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0031-disable-COMPAT_BRK-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0031-disable-COMPAT_BRK-by-default.patch
deleted file mode 100644
index f91a762cabef..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0031-disable-COMPAT_BRK-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From a98740f42e35ebe09a9de4cc15ac9aa536e4267d Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 7 May 2017 18:28:33 -0400
-Subject: [PATCH 031/113] disable COMPAT_BRK by default
-
----
- init/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 21f0b6926cf3..4f5827e10be3 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1866,7 +1866,6 @@ config SLUB_MEMCG_SYSFS_ON
-
- config COMPAT_BRK
- bool "Disable heap randomization"
-- default y
- help
- Randomizing heap placement makes heap exploits harder, but it
- also breaks ancient binaries (including anything libc5 based).
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch
deleted file mode 100644
index fd00e53e7383..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0032-use-maximum-supported-mmap-rnd-entropy-by-default.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 839e25dfcaf76cfef8915ed945c40a5c4ce5eea2 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 7 May 2017 16:16:39 -0400
-Subject: [PATCH 032/113] use maximum supported mmap rnd entropy by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/Kconfig | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/Kconfig b/arch/Kconfig
-index 69fe7133c765..8b5c346d5dd8 100644
---- a/arch/Kconfig
-+++ b/arch/Kconfig
-@@ -752,7 +752,7 @@ config ARCH_MMAP_RND_BITS
- int "Number of bits to use for ASLR of mmap base address" if EXPERT
- range ARCH_MMAP_RND_BITS_MIN ARCH_MMAP_RND_BITS_MAX
- default ARCH_MMAP_RND_BITS_DEFAULT if ARCH_MMAP_RND_BITS_DEFAULT
-- default ARCH_MMAP_RND_BITS_MIN
-+ default ARCH_MMAP_RND_BITS_MAX
- depends on HAVE_ARCH_MMAP_RND_BITS
- help
- This value can be used to select the number of bits to use to
-@@ -786,7 +786,7 @@ config ARCH_MMAP_RND_COMPAT_BITS
- int "Number of bits to use for ASLR of mmap base address for compatible applications" if EXPERT
- range ARCH_MMAP_RND_COMPAT_BITS_MIN ARCH_MMAP_RND_COMPAT_BITS_MAX
- default ARCH_MMAP_RND_COMPAT_BITS_DEFAULT if ARCH_MMAP_RND_COMPAT_BITS_DEFAULT
-- default ARCH_MMAP_RND_COMPAT_BITS_MIN
-+ default ARCH_MMAP_RND_COMPAT_BITS_MAX
- depends on HAVE_ARCH_MMAP_RND_COMPAT_BITS
- help
- This value can be used to select the number of bits to use to
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0033-enable-protected_-symlinks-hardlinks-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0033-enable-protected_-symlinks-hardlinks-by-default.patch
deleted file mode 100644
index f2b9d2b30907..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0033-enable-protected_-symlinks-hardlinks-by-default.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 2ecda519277297017ca2e87e49e78f1edbbdca2a Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 30 May 2017 10:47:23 -0400
-Subject: [PATCH 033/113] enable protected_{symlinks,hardlinks} by default
-
----
- fs/namei.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/fs/namei.c b/fs/namei.c
-index d4a6dd772303..59ff3ce21026 100644
---- a/fs/namei.c
-+++ b/fs/namei.c
-@@ -932,8 +932,8 @@ static inline void put_link(struct nameidata *nd)
- path_put(&last->link);
- }
-
--int sysctl_protected_symlinks __read_mostly = 0;
--int sysctl_protected_hardlinks __read_mostly = 0;
-+int sysctl_protected_symlinks __read_mostly = 1;
-+int sysctl_protected_hardlinks __read_mostly = 1;
- int sysctl_protected_fifos __read_mostly;
- int sysctl_protected_regular __read_mostly;
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0034-enable-SECURITY-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0034-enable-SECURITY-by-default.patch
deleted file mode 100644
index 435d798bd297..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0034-enable-SECURITY-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 0d8729414a95cc7297ac6097a4bcaece22697226 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 02:13:48 -0500
-Subject: [PATCH 034/113] enable SECURITY by default
-
----
- security/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 3a2c68c7b50f..fa037a250821 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -23,6 +23,7 @@ config SECURITY
- bool "Enable different security models"
- depends on SYSFS
- depends on MULTIUSER
-+ default y
- help
- This allows you to choose different security modules to be
- configured into your kernel.
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0035-enable-SECURITY_YAMA-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0035-enable-SECURITY_YAMA-by-default.patch
deleted file mode 100644
index ff50b48426b1..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0035-enable-SECURITY_YAMA-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 73c695d1e1bfb621be54428c1affd07e93cd46fa Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 29 May 2017 06:17:59 -0400
-Subject: [PATCH 035/113] enable SECURITY_YAMA by default
-
----
- security/yama/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/security/yama/Kconfig b/security/yama/Kconfig
-index a810304123ca..b809050b25d2 100644
---- a/security/yama/Kconfig
-+++ b/security/yama/Kconfig
-@@ -2,7 +2,7 @@
- config SECURITY_YAMA
- bool "Yama support"
- depends on SECURITY
-- default n
-+ default y
- help
- This selects Yama, which extends DAC support with additional
- system-wide security settings beyond regular Linux discretionary
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0036-enable-SECURITY_NETWORK-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0036-enable-SECURITY_NETWORK-by-default.patch
deleted file mode 100644
index 022ffff944e3..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0036-enable-SECURITY_NETWORK-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 2974a5ecf4226a6f0e1e3e342631a655a8ddb70e Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 02:14:02 -0500
-Subject: [PATCH 036/113] enable SECURITY_NETWORK by default
-
----
- security/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index fa037a250821..81d0a08736aa 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -49,6 +49,7 @@ config SECURITYFS
- config SECURITY_NETWORK
- bool "Socket and Networking Security Hooks"
- depends on SECURITY
-+ default y
- help
- This enables the socket and networking security hooks.
- If enabled, a security module can use these hooks to
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0037-enable-AUDIT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0037-enable-AUDIT-by-default.patch
deleted file mode 100644
index 9f76b64138ea..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0037-enable-AUDIT-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 89109cfb13f3f0afb69c8c1eb709e54b2d193165 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 02:15:24 -0500
-Subject: [PATCH 037/113] enable AUDIT by default
-
----
- init/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 4f5827e10be3..9b75a4921575 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -419,6 +419,7 @@ config USELIB
- config AUDIT
- bool "Auditing support"
- depends on NET
-+ default y
- help
- Enable auditing infrastructure that can be used with another
- kernel subsystem, such as SELinux (which requires this for
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0038-enable-SECURITY_SELINUX-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0038-enable-SECURITY_SELINUX-by-default.patch
deleted file mode 100644
index d68f6f23e745..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0038-enable-SECURITY_SELINUX-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 47c4b37b8826887f8473b52a6b06f0374c130358 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 02:16:49 -0500
-Subject: [PATCH 038/113] enable SECURITY_SELINUX by default
-
----
- security/selinux/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
-index 9e921fc72538..76d7ed11513c 100644
---- a/security/selinux/Kconfig
-+++ b/security/selinux/Kconfig
-@@ -3,7 +3,7 @@ config SECURITY_SELINUX
- bool "NSA SELinux Support"
- depends on SECURITY_NETWORK && AUDIT && NET && INET
- select NETWORK_SECMARK
-- default n
-+ default y
- help
- This selects NSA Security-Enhanced Linux (SELinux).
- You will also need a policy configuration and a labeled filesystem.
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0039-enable-SYN_COOKIES-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0039-enable-SYN_COOKIES-by-default.patch
deleted file mode 100644
index 63397ccd6f1a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0039-enable-SYN_COOKIES-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 9f8e5278fc3651a3977892421cf73110b6fdddfc Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 6 Jan 2018 13:41:11 -0500
-Subject: [PATCH 039/113] enable SYN_COOKIES by default
-
----
- net/ipv4/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
-index 87983e70f03f..989e005bf698 100644
---- a/net/ipv4/Kconfig
-+++ b/net/ipv4/Kconfig
-@@ -267,6 +267,7 @@ config IP_PIMSM_V2
-
- config SYN_COOKIES
- bool "IP: TCP syncookie support"
-+ default y
- help
- Normal TCP/IP networking is open to an attack known as "SYN
- flooding". This denial-of-service attack prevents legitimate remote
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch
deleted file mode 100644
index 48a2656615d2..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0040-enable-INIT_ON_ALLOC_DEFAULT_ON-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 82e4cd51bfc9b9374eab357f06daf07fac70c05a Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Thu, 19 Sep 2019 19:02:23 +0200
-Subject: [PATCH 040/113] enable INIT_ON_ALLOC_DEFAULT_ON by default
-
----
- security/Kconfig.hardening | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
-index 269967c4fc1b..1e279f6d7633 100644
---- a/security/Kconfig.hardening
-+++ b/security/Kconfig.hardening
-@@ -190,6 +190,7 @@ config STACKLEAK_RUNTIME_DISABLE
-
- config INIT_ON_ALLOC_DEFAULT_ON
- bool "Enable heap memory zeroing on allocation by default"
-+ default yes
- help
- This has the effect of setting "init_on_alloc=1" on the kernel
- command line. This can be disabled with "init_on_alloc=0".
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch
deleted file mode 100644
index 2d9de4987928..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0041-enable-INIT_ON_FREE_DEFAULT_ON-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 4f104133b8eb1694bb390d2326d058cd6088447e Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Thu, 19 Sep 2019 19:03:01 +0200
-Subject: [PATCH 041/113] enable INIT_ON_FREE_DEFAULT_ON by default
-
----
- security/Kconfig.hardening | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
-index 1e279f6d7633..2fa447823405 100644
---- a/security/Kconfig.hardening
-+++ b/security/Kconfig.hardening
-@@ -203,6 +203,7 @@ config INIT_ON_ALLOC_DEFAULT_ON
-
- config INIT_ON_FREE_DEFAULT_ON
- bool "Enable heap memory zeroing on free by default"
-+ default yes
- help
- This has the effect of setting "init_on_free=1" on the kernel
- command line. This can be disabled with "init_on_free=0".
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch
deleted file mode 100644
index 9d60e6ac8351..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0042-kconfig-select-DEBUG_FS_ALLOW_NONE-by-default-if-DEB.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 86156651b3157fe340ae16dc525e3e14f0859b06 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Sun, 27 Sep 2020 00:43:48 +0200
-Subject: [PATCH 042/113] kconfig: select DEBUG_FS_ALLOW_NONE by default if
- DEBUG_FS is enabled
-
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- lib/Kconfig.debug | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index a46f21a56125..4a1a32a059f4 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -488,7 +488,7 @@ config DEBUG_FS
- choice
- prompt "Debugfs default access"
- depends on DEBUG_FS
-- default DEBUG_FS_ALLOW_ALL
-+ default DEBUG_FS_ALLOW_NONE
- help
- This selects the default access restrictions for debugfs.
- It can be overridden with kernel command line option
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch
deleted file mode 100644
index c17caeb4b96a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0043-stop-hiding-SYSFS_SYSCALL-behind-EXPERT.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 674970612ddb058c0031c6ba49a2df1538878db5 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Tue, 22 Dec 2020 23:35:53 +0100
-Subject: [PATCH 043/113] stop hiding SYSFS_SYSCALL behind EXPERT
-
----
- init/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 9b75a4921575..006d4d41e3af 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1434,7 +1434,7 @@ config SGETMASK_SYSCALL
- If unsure, leave the default option here.
-
- config SYSFS_SYSCALL
-- bool "Sysfs syscall support" if EXPERT
-+ bool "Sysfs syscall support"
- default y
- help
- sys_sysfs is an obsolete system call no longer supported in libc.
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0044-disable-SYSFS_SYSCALL-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0044-disable-SYSFS_SYSCALL-by-default.patch
deleted file mode 100644
index 2b43d650c0d6..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0044-disable-SYSFS_SYSCALL-by-default.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 0fce7abfe363d96288a40ac6e3a920eea334383c Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Tue, 22 Dec 2020 23:36:54 +0100
-Subject: [PATCH 044/113] disable SYSFS_SYSCALL by default
-
----
- init/Kconfig | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 006d4d41e3af..3d6b1b23e2db 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1435,13 +1435,12 @@ config SGETMASK_SYSCALL
-
- config SYSFS_SYSCALL
- bool "Sysfs syscall support"
-- default y
- help
- sys_sysfs is an obsolete system call no longer supported in libc.
- Note that disabling this option is more secure but might break
- compatibility with some systems.
-
-- If unsure say Y here.
-+ If unsure say N here.
-
- config FHANDLE
- bool "open by fhandle syscalls" if EXPERT
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0045-stop-hiding-UID16-behind-EXPERT.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0045-stop-hiding-UID16-behind-EXPERT.patch
deleted file mode 100644
index 976ca6bcc895..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0045-stop-hiding-UID16-behind-EXPERT.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 21e9ece3ab19a46b0c68ae28c8a8ecb4f335baf7 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Tue, 22 Dec 2020 23:40:09 +0100
-Subject: [PATCH 045/113] stop hiding UID16 behind EXPERT
-
----
- init/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 3d6b1b23e2db..2b6d0492def5 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1403,7 +1403,7 @@ menuconfig EXPERT
- Only use this if you really know what you are doing.
-
- config UID16
-- bool "Enable 16-bit UID system calls" if EXPERT
-+ bool "Enable 16-bit UID system calls"
- depends on HAVE_UID16 && MULTIUSER
- default y
- help
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0046-disable-UID16-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0046-disable-UID16-by-default.patch
deleted file mode 100644
index e4e59aa23874..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0046-disable-UID16-by-default.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From e6c5d24e9ce65b9e86c79851271153e54af2d752 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Tue, 22 Dec 2020 23:41:32 +0100
-Subject: [PATCH 046/113] disable UID16 by default
-
----
- init/Kconfig | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 2b6d0492def5..58df4930995f 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1405,7 +1405,6 @@ menuconfig EXPERT
- config UID16
- bool "Enable 16-bit UID system calls"
- depends on HAVE_UID16 && MULTIUSER
-- default y
- help
- This enables the legacy 16-bit UID syscall wrappers.
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0047-add-__read_only-for-non-init-related-usage.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0047-add-__read_only-for-non-init-related-usage.patch
deleted file mode 100644
index 6e2dfaf2c313..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0047-add-__read_only-for-non-init-related-usage.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 18f2367d9fc0726dedebfb290482d22aa59ff059 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 7 May 2017 00:28:23 -0400
-Subject: [PATCH 047/113] add __read_only for non-init related usage
-
----
- include/linux/cache.h | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/include/linux/cache.h b/include/linux/cache.h
-index d742c57eaee5..f0222c070458 100644
---- a/include/linux/cache.h
-+++ b/include/linux/cache.h
-@@ -37,6 +37,8 @@
- #define __ro_after_init __section(".data..ro_after_init")
- #endif
-
-+#define __read_only __ro_after_init
-+
- #ifndef ____cacheline_aligned
- #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
- #endif
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0048-make-sysctl-constants-read-only.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0048-make-sysctl-constants-read-only.patch
deleted file mode 100644
index a331bc7123db..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0048-make-sysctl-constants-read-only.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-From da389cc424df461626e323414e71be25640074b9 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 7 May 2017 00:43:03 -0400
-Subject: [PATCH 048/113] make sysctl constants read-only
-
-Most of this is extracted from the last publicly available version of
-the PaX patches where it's part of KERNEXEC as __read_only. It has been
-extended to a few more of these constants.
----
- kernel/sysctl.c | 54 ++++++++++++++++++++++++-------------------------
- 1 file changed, 27 insertions(+), 27 deletions(-)
-
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index afad085960b8..b2cd3dbbb17a 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -108,33 +108,33 @@
-
- /* Constants used for minimum and maximum */
- #ifdef CONFIG_LOCKUP_DETECTOR
--static int sixty = 60;
--#endif
--
--static int __maybe_unused neg_one = -1;
--static int __maybe_unused two = 2;
--static int __maybe_unused four = 4;
--static unsigned long zero_ul;
--static unsigned long one_ul = 1;
--static unsigned long long_max = LONG_MAX;
--static int one_hundred = 100;
--static int two_hundred = 200;
--static int one_thousand = 1000;
-+static int sixty __read_only = 60;
-+#endif
-+
-+static int __maybe_unused neg_one __read_only = -1;
-+static int __maybe_unused two __read_only = 2;
-+static int __maybe_unused four __read_only = 4;
-+static unsigned long zero_ul __read_only;
-+static unsigned long one_ul __read_only = 1;
-+static unsigned long long_max __read_only = LONG_MAX;
-+static int one_hundred __read_only = 100;
-+static int two_hundred __read_only = 200;
-+static int one_thousand __read_only = 1000;
- #ifdef CONFIG_PRINTK
--static int ten_thousand = 10000;
-+static int ten_thousand __read_only = 10000;
- #endif
- #ifdef CONFIG_PERF_EVENTS
--static int six_hundred_forty_kb = 640 * 1024;
-+static int six_hundred_forty_kb __read_only = 640 * 1024;
- #endif
-
- /* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */
--static unsigned long dirty_bytes_min = 2 * PAGE_SIZE;
-+static unsigned long dirty_bytes_min __read_only = 2 * PAGE_SIZE;
-
- /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
--static int maxolduid = 65535;
--static int minolduid;
-+static int maxolduid __read_only = 65535;
-+static int minolduid __read_only;
-
--static int ngroups_max = NGROUPS_MAX;
-+static int ngroups_max __read_only = NGROUPS_MAX;
- static const int cap_last_cap = CAP_LAST_CAP;
-
- /*
-@@ -142,7 +142,7 @@ static const int cap_last_cap = CAP_LAST_CAP;
- * and hung_task_check_interval_secs
- */
- #ifdef CONFIG_DETECT_HUNG_TASK
--static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
-+static unsigned long hung_task_timeout_max __read_only = (LONG_MAX/HZ);
- #endif
-
- #ifdef CONFIG_INOTIFY_USER
-@@ -185,19 +185,19 @@ int sysctl_legacy_va_layout;
- #endif
-
- #ifdef CONFIG_SCHED_DEBUG
--static int min_sched_granularity_ns = 100000; /* 100 usecs */
--static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */
--static int min_wakeup_granularity_ns; /* 0 usecs */
--static int max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */
-+static int min_sched_granularity_ns __read_only = 100000; /* 100 usecs */
-+static int max_sched_granularity_ns __read_only = NSEC_PER_SEC; /* 1 second */
-+static int min_wakeup_granularity_ns __read_only; /* 0 usecs */
-+static int max_wakeup_granularity_ns __read_only = NSEC_PER_SEC; /* 1 second */
- #ifdef CONFIG_SMP
--static int min_sched_tunable_scaling = SCHED_TUNABLESCALING_NONE;
--static int max_sched_tunable_scaling = SCHED_TUNABLESCALING_END-1;
-+static int min_sched_tunable_scaling __read_only = SCHED_TUNABLESCALING_NONE;
-+static int max_sched_tunable_scaling __read_only = SCHED_TUNABLESCALING_END-1;
- #endif /* CONFIG_SMP */
- #endif /* CONFIG_SCHED_DEBUG */
-
- #ifdef CONFIG_COMPACTION
--static int min_extfrag_threshold;
--static int max_extfrag_threshold = 1000;
-+static int min_extfrag_threshold __read_only;
-+static int max_extfrag_threshold __read_only = 1000;
- #endif
-
- #endif /* CONFIG_SYSCTL */
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch
deleted file mode 100644
index 7e10b9b59d45..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0049-mark-kernel_set_to_readonly-as-__ro_after_init.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 5427cc4e11d447f4141f6656d0f320f3c201d621 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Fri, 12 May 2017 03:22:00 -0400
-Subject: [PATCH 049/113] mark kernel_set_to_readonly as __ro_after_init
-
-This change was extracted from PaX where it's part of KERNEXEC.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/mm/init_32.c | 5 ++---
- arch/x86/mm/init_64.c | 5 ++---
- 2 files changed, 4 insertions(+), 6 deletions(-)
-
-diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
-index 7c055259de3a..77192cbc1dd7 100644
---- a/arch/x86/mm/init_32.c
-+++ b/arch/x86/mm/init_32.c
-@@ -828,7 +828,7 @@ void arch_remove_memory(int nid, u64 start, u64 size,
- }
- #endif
-
--int kernel_set_to_readonly __read_mostly;
-+int kernel_set_to_readonly __ro_after_init;
-
- static void mark_nxdata_nx(void)
- {
-@@ -852,12 +852,11 @@ void mark_rodata_ro(void)
- unsigned long start = PFN_ALIGN(_text);
- unsigned long size = (unsigned long)__end_rodata - start;
-
-+ kernel_set_to_readonly = 1;
- set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
- pr_info("Write protecting kernel text and read-only data: %luk\n",
- size >> 10);
-
-- kernel_set_to_readonly = 1;
--
- #ifdef CONFIG_CPA_DEBUG
- pr_info("Testing CPA: Reverting %lx-%lx\n", start, start + size);
- set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT);
-diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
-index b5a3fa4033d3..63a0f8097d0a 100644
---- a/arch/x86/mm/init_64.c
-+++ b/arch/x86/mm/init_64.c
-@@ -1322,7 +1322,7 @@ int __init deferred_page_init_max_threads(const struct cpumask *node_cpumask)
- }
- #endif
-
--int kernel_set_to_readonly;
-+int kernel_set_to_readonly __ro_after_init;
-
- void mark_rodata_ro(void)
- {
-@@ -1335,9 +1335,8 @@ void mark_rodata_ro(void)
-
- printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
- (end - start) >> 10);
-- set_memory_ro(start, (end - start) >> PAGE_SHIFT);
--
- kernel_set_to_readonly = 1;
-+ set_memory_ro(start, (end - start) >> PAGE_SHIFT);
-
- /*
- * The rodata/data/bss/brk section (but not the kernel text!)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch
deleted file mode 100644
index cb8f5198eb72..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0050-Revert-mark-kernel_set_to_readonly-as-__ro_after_ini.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From 4c1123c432c6467d6258e52dfa7293e64bc99ef1 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Sun, 13 Jan 2019 21:42:45 +0100
-Subject: [PATCH 050/113] Revert "mark kernel_set_to_readonly as
- __ro_after_init"
-
- This commit causes CPA conflicts, cf.
- https://github.com/anthraxx/linux-hardened/issues/4.
-
- Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
----
- arch/x86/mm/init_32.c | 5 +++--
- arch/x86/mm/init_64.c | 5 +++--
- 2 files changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
-index 77192cbc1dd7..7c055259de3a 100644
---- a/arch/x86/mm/init_32.c
-+++ b/arch/x86/mm/init_32.c
-@@ -828,7 +828,7 @@ void arch_remove_memory(int nid, u64 start, u64 size,
- }
- #endif
-
--int kernel_set_to_readonly __ro_after_init;
-+int kernel_set_to_readonly __read_mostly;
-
- static void mark_nxdata_nx(void)
- {
-@@ -852,11 +852,12 @@ void mark_rodata_ro(void)
- unsigned long start = PFN_ALIGN(_text);
- unsigned long size = (unsigned long)__end_rodata - start;
-
-- kernel_set_to_readonly = 1;
- set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
- pr_info("Write protecting kernel text and read-only data: %luk\n",
- size >> 10);
-
-+ kernel_set_to_readonly = 1;
-+
- #ifdef CONFIG_CPA_DEBUG
- pr_info("Testing CPA: Reverting %lx-%lx\n", start, start + size);
- set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT);
-diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
-index 63a0f8097d0a..b5a3fa4033d3 100644
---- a/arch/x86/mm/init_64.c
-+++ b/arch/x86/mm/init_64.c
-@@ -1322,7 +1322,7 @@ int __init deferred_page_init_max_threads(const struct cpumask *node_cpumask)
- }
- #endif
-
--int kernel_set_to_readonly __ro_after_init;
-+int kernel_set_to_readonly;
-
- void mark_rodata_ro(void)
- {
-@@ -1335,9 +1335,10 @@ void mark_rodata_ro(void)
-
- printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
- (end - start) >> 10);
-- kernel_set_to_readonly = 1;
- set_memory_ro(start, (end - start) >> PAGE_SHIFT);
-
-+ kernel_set_to_readonly = 1;
-+
- /*
- * The rodata/data/bss/brk section (but not the kernel text!)
- * should also be not-executable.
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0051-mark-slub-runtime-configuration-as-__ro_after_init.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0051-mark-slub-runtime-configuration-as-__ro_after_init.patch
deleted file mode 100644
index 8477af69188b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0051-mark-slub-runtime-configuration-as-__ro_after_init.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From c828ce6ad8640cd0fc71c26f4792595a9f1355ed Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 14 May 2017 19:01:58 -0400
-Subject: [PATCH 051/113] mark slub runtime configuration as __ro_after_init
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/slub.c | 16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/mm/slub.c b/mm/slub.c
-index 071e41067ea6..e01d54dc46e1 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -486,13 +486,13 @@ static inline void *restore_red_left(struct kmem_cache *s, void *p)
- * Debug settings:
- */
- #if defined(CONFIG_SLUB_DEBUG_ON)
--static slab_flags_t slub_debug = DEBUG_DEFAULT_FLAGS;
-+static slab_flags_t slub_debug __ro_after_init = DEBUG_DEFAULT_FLAGS;
- #else
--static slab_flags_t slub_debug;
-+static slab_flags_t slub_debug __ro_after_init;
- #endif
-
--static char *slub_debug_string;
--static int disable_higher_order_debug;
-+static char *slub_debug_string __ro_after_init;
-+static int disable_higher_order_debug __ro_after_init;
-
- /*
- * slub is about to manipulate internal object metadata. This memory lies
-@@ -3363,9 +3363,9 @@ EXPORT_SYMBOL(kmem_cache_alloc_bulk);
- * and increases the number of allocations possible without having to
- * take the list_lock.
- */
--static unsigned int slub_min_order;
--static unsigned int slub_max_order = PAGE_ALLOC_COSTLY_ORDER;
--static unsigned int slub_min_objects;
-+static unsigned int slub_min_order __ro_after_init;
-+static unsigned int slub_max_order __ro_after_init = PAGE_ALLOC_COSTLY_ORDER;
-+static unsigned int slub_min_objects __ro_after_init;
-
- /*
- * Calculate the order of allocation given an slab object size.
-@@ -4883,7 +4883,7 @@ enum slab_stat_type {
- #define SO_TOTAL (1 << SL_TOTAL)
-
- #ifdef CONFIG_MEMCG
--static bool memcg_sysfs_enabled = IS_ENABLED(CONFIG_SLUB_MEMCG_SYSFS_ON);
-+static bool memcg_sysfs_enabled __ro_after_init = IS_ENABLED(CONFIG_SLUB_MEMCG_SYSFS_ON);
-
- static int __init setup_slub_memcg_sysfs(char *str)
- {
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch
deleted file mode 100644
index e38988d5c8c5..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0052-add-__ro_after_init-to-slab_nomerge-and-slab_state.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 44af11562c2ddc1bb62c531fa37bf6dc1caa104a Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 11:35:35 -0400
-Subject: [PATCH 052/113] add __ro_after_init to slab_nomerge and slab_state
-
-This was extracted from the PaX patch where it's part of the KERNEXEC
-feature as __read_only.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/slab_common.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/mm/slab_common.c b/mm/slab_common.c
-index f9ccd5dc13f3..bff04048559f 100644
---- a/mm/slab_common.c
-+++ b/mm/slab_common.c
-@@ -30,7 +30,7 @@
-
- #include "slab.h"
-
--enum slab_state slab_state;
-+enum slab_state slab_state __ro_after_init;
- LIST_HEAD(slab_caches);
- DEFINE_MUTEX(slab_mutex);
- struct kmem_cache *kmem_cache;
-@@ -61,7 +61,7 @@ static DECLARE_WORK(slab_caches_to_rcu_destroy_work,
- /*
- * Merge control. If this is set then no merging of slab caches will occur.
- */
--static bool slab_nomerge = !IS_ENABLED(CONFIG_SLAB_MERGE_DEFAULT);
-+static bool slab_nomerge __ro_after_init = !IS_ENABLED(CONFIG_SLAB_MERGE_DEFAULT);
-
- static int __init setup_slab_nomerge(char *str)
- {
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0053-mark-kmem_cache-as-__ro_after_init.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0053-mark-kmem_cache-as-__ro_after_init.patch
deleted file mode 100644
index fb682b743fd7..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0053-mark-kmem_cache-as-__ro_after_init.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 32c99733e4e166930213239e2b0249c1b93645ee Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 28 May 2017 18:51:30 -0400
-Subject: [PATCH 053/113] mark kmem_cache as __ro_after_init
-
----
- mm/slab_common.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/mm/slab_common.c b/mm/slab_common.c
-index bff04048559f..2b73c12d8fce 100644
---- a/mm/slab_common.c
-+++ b/mm/slab_common.c
-@@ -33,7 +33,7 @@
- enum slab_state slab_state __ro_after_init;
- LIST_HEAD(slab_caches);
- DEFINE_MUTEX(slab_mutex);
--struct kmem_cache *kmem_cache;
-+struct kmem_cache *kmem_cache __ro_after_init;
-
- #ifdef CONFIG_HARDENED_USERCOPY
- bool usercopy_fallback __ro_after_init =
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0054-mark-__supported_pte_mask-as-__ro_after_init.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0054-mark-__supported_pte_mask-as-__ro_after_init.patch
deleted file mode 100644
index 19c854f99503..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0054-mark-__supported_pte_mask-as-__ro_after_init.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 975692afa5eb106ff97cf87cc2c20827225b1e54 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Fri, 12 May 2017 00:06:16 -0400
-Subject: [PATCH 054/113] mark __supported_pte_mask as __ro_after_init
-
-These changes were extracted from PaX where it was part of KERNEXEC as
-__read_only.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/mm/init_32.c | 4 ++--
- arch/x86/mm/init_64.c | 4 ++--
- 2 files changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
-index 7c055259de3a..291b7b4476a9 100644
---- a/arch/x86/mm/init_32.c
-+++ b/arch/x86/mm/init_32.c
-@@ -546,9 +546,9 @@ static void __init pagetable_init(void)
-
- #define DEFAULT_PTE_MASK ~(_PAGE_NX | _PAGE_GLOBAL)
- /* Bits supported by the hardware: */
--pteval_t __supported_pte_mask __read_mostly = DEFAULT_PTE_MASK;
-+pteval_t __supported_pte_mask __ro_after_init = DEFAULT_PTE_MASK;
- /* Bits allowed in normal kernel mappings: */
--pteval_t __default_kernel_pte_mask __read_mostly = DEFAULT_PTE_MASK;
-+pteval_t __default_kernel_pte_mask __ro_after_init = DEFAULT_PTE_MASK;
- EXPORT_SYMBOL_GPL(__supported_pte_mask);
- /* Used in PAGE_KERNEL_* macros which are reasonably used out-of-tree: */
- EXPORT_SYMBOL(__default_kernel_pte_mask);
-diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
-index b5a3fa4033d3..c3d771ffc178 100644
---- a/arch/x86/mm/init_64.c
-+++ b/arch/x86/mm/init_64.c
-@@ -97,9 +97,9 @@ DEFINE_ENTRY(pte, pte, init)
- */
-
- /* Bits supported by the hardware: */
--pteval_t __supported_pte_mask __read_mostly = ~0;
-+pteval_t __supported_pte_mask __ro_after_init = ~0;
- /* Bits allowed in normal kernel mappings: */
--pteval_t __default_kernel_pte_mask __read_mostly = ~0;
-+pteval_t __default_kernel_pte_mask __ro_after_init = ~0;
- EXPORT_SYMBOL_GPL(__supported_pte_mask);
- /* Used in PAGE_KERNEL_* macros which are reasonably used out-of-tree: */
- EXPORT_SYMBOL(__default_kernel_pte_mask);
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0055-mark-kobj_ns_type_register-as-only-used-for-init.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0055-mark-kobj_ns_type_register-as-only-used-for-init.patch
deleted file mode 100644
index 3f011c02c9e5..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0055-mark-kobj_ns_type_register-as-only-used-for-init.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From 5e42d85e11c2782634935d3d5157ce73af6b8d8b Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 01:24:28 -0400
-Subject: [PATCH 055/113] mark kobj_ns_type_register as only used for init
-
-This allows kobj_ns_ops_tbl to be __ro_after_init.
-
-Extracted from PaX.
----
- include/linux/kobject_ns.h | 2 +-
- lib/kobject.c | 4 ++--
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/include/linux/kobject_ns.h b/include/linux/kobject_ns.h
-index 2b5b64256cf4..8cdce21dce0f 100644
---- a/include/linux/kobject_ns.h
-+++ b/include/linux/kobject_ns.h
-@@ -45,7 +45,7 @@ struct kobj_ns_type_operations {
- void (*drop_ns)(void *);
- };
-
--int kobj_ns_type_register(const struct kobj_ns_type_operations *ops);
-+int __init kobj_ns_type_register(const struct kobj_ns_type_operations *ops);
- int kobj_ns_type_registered(enum kobj_ns_type type);
- const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent);
- const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj);
-diff --git a/lib/kobject.c b/lib/kobject.c
-index ea53b30cf483..5343bbeea5f8 100644
---- a/lib/kobject.c
-+++ b/lib/kobject.c
-@@ -1023,9 +1023,9 @@ EXPORT_SYMBOL_GPL(kset_create_and_add);
-
-
- static DEFINE_SPINLOCK(kobj_ns_type_lock);
--static const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES];
-+static const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES] __ro_after_init;
-
--int kobj_ns_type_register(const struct kobj_ns_type_operations *ops)
-+int __init kobj_ns_type_register(const struct kobj_ns_type_operations *ops)
- {
- enum kobj_ns_type type = ops->type;
- int error;
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0056-mark-open_softirq-as-only-used-for-init.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0056-mark-open_softirq-as-only-used-for-init.patch
deleted file mode 100644
index 48c704ee363b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0056-mark-open_softirq-as-only-used-for-init.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 7423c05941ce6d13b295148068ab08f5581860af Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 01:32:30 -0400
-Subject: [PATCH 056/113] mark open_softirq as only used for init
-
----
- include/linux/interrupt.h | 2 +-
- kernel/softirq.c | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
-index ee8299eb1f52..f03b78ae5f0a 100644
---- a/include/linux/interrupt.h
-+++ b/include/linux/interrupt.h
-@@ -569,7 +569,7 @@ static inline void do_softirq_own_stack(void)
- }
- #endif
-
--extern void open_softirq(int nr, void (*action)(struct softirq_action *));
-+extern void __init open_softirq(int nr, void (*action)(struct softirq_action *));
- extern void softirq_init(void);
- extern void __raise_softirq_irqoff(unsigned int nr);
-
-diff --git a/kernel/softirq.c b/kernel/softirq.c
-index 09229ad82209..0595a8248c4a 100644
---- a/kernel/softirq.c
-+++ b/kernel/softirq.c
-@@ -486,7 +486,7 @@ void __raise_softirq_irqoff(unsigned int nr)
- or_softirq_pending(1UL << nr);
- }
-
--void open_softirq(int nr, void (*action)(struct softirq_action *))
-+void __init open_softirq(int nr, void (*action)(struct softirq_action *))
- {
- softirq_vec[nr].action = action;
- }
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0057-remove-unused-softirq_action-callback-parameter.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0057-remove-unused-softirq_action-callback-parameter.patch
deleted file mode 100644
index f036cb331dfc..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0057-remove-unused-softirq_action-callback-parameter.patch
+++ /dev/null
@@ -1,208 +0,0 @@
-From 8732aabd990d6eb6d2ae2d2618b605925373db1b Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 01:41:11 -0400
-Subject: [PATCH 057/113] remove unused softirq_action callback parameter
-
-Extracted from PaX.
----
- block/blk-mq.c | 2 +-
- include/linux/interrupt.h | 4 ++--
- kernel/rcu/tiny.c | 2 +-
- kernel/rcu/tree.c | 2 +-
- kernel/sched/fair.c | 2 +-
- kernel/softirq.c | 15 +++++++--------
- kernel/time/hrtimer.c | 2 +-
- kernel/time/timer.c | 2 +-
- lib/irq_poll.c | 2 +-
- net/core/dev.c | 4 ++--
- 10 files changed, 18 insertions(+), 19 deletions(-)
-
-diff --git a/block/blk-mq.c b/block/blk-mq.c
-index 2a1eff60c797..75a0077ea1a9 100644
---- a/block/blk-mq.c
-+++ b/block/blk-mq.c
-@@ -569,7 +569,7 @@ EXPORT_SYMBOL(blk_mq_end_request);
- * Softirq action handler - move entries to local list and loop over them
- * while passing them to the queue registered handler.
- */
--static __latent_entropy void blk_done_softirq(struct softirq_action *h)
-+static __latent_entropy void blk_done_softirq(void)
- {
- struct list_head *cpu_list, local_list;
-
-diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
-index f03b78ae5f0a..4381b79f76cf 100644
---- a/include/linux/interrupt.h
-+++ b/include/linux/interrupt.h
-@@ -554,7 +554,7 @@ extern const char * const softirq_to_name[NR_SOFTIRQS];
-
- struct softirq_action
- {
-- void (*action)(struct softirq_action *);
-+ void (*action)(void);
- };
-
- asmlinkage void do_softirq(void);
-@@ -569,7 +569,7 @@ static inline void do_softirq_own_stack(void)
- }
- #endif
-
--extern void __init open_softirq(int nr, void (*action)(struct softirq_action *));
-+extern void __init open_softirq(int nr, void (*action)(void));
- extern void softirq_init(void);
- extern void __raise_softirq_irqoff(unsigned int nr);
-
-diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
-index aa897c3f2e92..d8976886fd68 100644
---- a/kernel/rcu/tiny.c
-+++ b/kernel/rcu/tiny.c
-@@ -101,7 +101,7 @@ static inline bool rcu_reclaim_tiny(struct rcu_head *head)
- }
-
- /* Invoke the RCU callbacks whose grace period has elapsed. */
--static __latent_entropy void rcu_process_callbacks(struct softirq_action *unused)
-+static __latent_entropy void rcu_process_callbacks(void)
- {
- struct rcu_head *next, *list;
- unsigned long flags;
-diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
-index 593df7edfe97..3285d81d8a26 100644
---- a/kernel/rcu/tree.c
-+++ b/kernel/rcu/tree.c
-@@ -2722,7 +2722,7 @@ static __latent_entropy void rcu_core(void)
- queue_work_on(rdp->cpu, rcu_gp_wq, &rdp->strict_work);
- }
-
--static void rcu_core_si(struct softirq_action *h)
-+static void rcu_core_si(void)
- {
- rcu_core();
- }
-diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
-index ae7ceba8fd4f..d118be5f18b8 100644
---- a/kernel/sched/fair.c
-+++ b/kernel/sched/fair.c
-@@ -10628,7 +10628,7 @@ static int newidle_balance(struct rq *this_rq, struct rq_flags *rf)
- * run_rebalance_domains is triggered when needed from the scheduler tick.
- * Also triggered for nohz idle balancing (with nohz_balancing_kick set).
- */
--static __latent_entropy void run_rebalance_domains(struct softirq_action *h)
-+static __latent_entropy void run_rebalance_domains(void)
- {
- struct rq *this_rq = this_rq();
- enum cpu_idle_type idle = this_rq->idle_balance ?
-diff --git a/kernel/softirq.c b/kernel/softirq.c
-index 0595a8248c4a..3a21b22227c1 100644
---- a/kernel/softirq.c
-+++ b/kernel/softirq.c
-@@ -295,7 +295,7 @@ asmlinkage __visible void __softirq_entry __do_softirq(void)
- kstat_incr_softirqs_this_cpu(vec_nr);
-
- trace_softirq_entry(vec_nr);
-- h->action(h);
-+ h->action();
- trace_softirq_exit(vec_nr);
- if (unlikely(prev_count != preempt_count())) {
- pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n",
-@@ -486,7 +486,7 @@ void __raise_softirq_irqoff(unsigned int nr)
- or_softirq_pending(1UL << nr);
- }
-
--void __init open_softirq(int nr, void (*action)(struct softirq_action *))
-+void __init open_softirq(int nr, void (*action)(void))
- {
- softirq_vec[nr].action = action;
- }
-@@ -532,8 +532,7 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
- }
- EXPORT_SYMBOL(__tasklet_hi_schedule);
-
--static void tasklet_action_common(struct softirq_action *a,
-- struct tasklet_head *tl_head,
-+static void tasklet_action_common(struct tasklet_head *tl_head,
- unsigned int softirq_nr)
- {
- struct tasklet_struct *list;
-@@ -573,14 +572,14 @@ static void tasklet_action_common(struct softirq_action *a,
- }
- }
-
--static __latent_entropy void tasklet_action(struct softirq_action *a)
-+static __latent_entropy void tasklet_action(void)
- {
-- tasklet_action_common(a, this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ);
-+ tasklet_action_common(this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ);
- }
-
--static __latent_entropy void tasklet_hi_action(struct softirq_action *a)
-+static __latent_entropy void tasklet_hi_action(void)
- {
-- tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);
-+ tasklet_action_common(this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);
- }
-
- void tasklet_setup(struct tasklet_struct *t,
-diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
-index 387b4bef7dd1..8fe28c28a906 100644
---- a/kernel/time/hrtimer.c
-+++ b/kernel/time/hrtimer.c
-@@ -1587,7 +1587,7 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now,
- }
- }
-
--static __latent_entropy void hrtimer_run_softirq(struct softirq_action *h)
-+static __latent_entropy void hrtimer_run_softirq(void)
- {
- struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
- unsigned long flags;
-diff --git a/kernel/time/timer.c b/kernel/time/timer.c
-index c3ad64fb9d8b..217bc49a3856 100644
---- a/kernel/time/timer.c
-+++ b/kernel/time/timer.c
-@@ -1753,7 +1753,7 @@ static inline void __run_timers(struct timer_base *base)
- /*
- * This function runs timers and the timer-tq in bottom half context.
- */
--static __latent_entropy void run_timer_softirq(struct softirq_action *h)
-+static __latent_entropy void run_timer_softirq(void)
- {
- struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
-
-diff --git a/lib/irq_poll.c b/lib/irq_poll.c
-index 2f17b488d58e..b6e7996a0058 100644
---- a/lib/irq_poll.c
-+++ b/lib/irq_poll.c
-@@ -75,7 +75,7 @@ void irq_poll_complete(struct irq_poll *iop)
- }
- EXPORT_SYMBOL(irq_poll_complete);
-
--static void __latent_entropy irq_poll_softirq(struct softirq_action *h)
-+static void __latent_entropy irq_poll_softirq(void)
- {
- struct list_head *list = this_cpu_ptr(&blk_cpu_iopoll);
- int rearm = 0, budget = irq_poll_budget;
-diff --git a/net/core/dev.c b/net/core/dev.c
-index 81e5d482c238..172fd10f4b01 100644
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -4856,7 +4856,7 @@ int netif_rx_any_context(struct sk_buff *skb)
- }
- EXPORT_SYMBOL(netif_rx_any_context);
-
--static __latent_entropy void net_tx_action(struct softirq_action *h)
-+static __latent_entropy void net_tx_action(void)
- {
- struct softnet_data *sd = this_cpu_ptr(&softnet_data);
-
-@@ -6803,7 +6803,7 @@ static int napi_poll(struct napi_struct *n, struct list_head *repoll)
- return work;
- }
-
--static __latent_entropy void net_rx_action(struct softirq_action *h)
-+static __latent_entropy void net_rx_action(void)
- {
- struct softnet_data *sd = this_cpu_ptr(&softnet_data);
- unsigned long time_limit = jiffies +
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0058-mark-softirq_vec-as-__ro_after_init.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0058-mark-softirq_vec-as-__ro_after_init.patch
deleted file mode 100644
index 192cd1556a93..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0058-mark-softirq_vec-as-__ro_after_init.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 4f5625b066a4e114cd589c71c727cca582427ce6 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 01:42:33 -0400
-Subject: [PATCH 058/113] mark softirq_vec as __ro_after_init
-
-Note: __cacheline_aligned_in_smp conflicts with __ro_after_init on x86.
-
-Extracted from PaX.
----
- kernel/softirq.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/kernel/softirq.c b/kernel/softirq.c
-index 3a21b22227c1..6a02d63b135a 100644
---- a/kernel/softirq.c
-+++ b/kernel/softirq.c
-@@ -52,7 +52,7 @@ DEFINE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat);
- EXPORT_PER_CPU_SYMBOL(irq_stat);
- #endif
-
--static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
-+static struct softirq_action softirq_vec[NR_SOFTIRQS] __ro_after_init __aligned(PAGE_SIZE);
-
- DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch
deleted file mode 100644
index e523352621b3..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0059-mm-slab-trigger-BUG-if-requested-object-is-not-a-sla.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From b4a191009357361eefdc0e13f9f0f9d184850490 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 17 Sep 2019 18:00:54 +0200
-Subject: [PATCH 059/113] mm: slab: trigger BUG if requested object is not a
- slab page
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
----
- mm/slab.h | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/mm/slab.h b/mm/slab.h
-index f9977d6613d6..5adb48bb2e68 100644
---- a/mm/slab.h
-+++ b/mm/slab.h
-@@ -435,9 +435,13 @@ static inline struct kmem_cache *virt_to_cache(const void *obj)
- struct page *page;
-
- page = virt_to_head_page(obj);
-+#ifdef CONFIG_BUG_ON_DATA_CORRUPTION
-+ BUG_ON(!PageSlab(page));
-+#else
- if (WARN_ONCE(!PageSlab(page), "%s: Object is not a Slab page!\n",
- __func__))
- return NULL;
-+#endif
- return page->slab_cache;
- }
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch
deleted file mode 100644
index b3eaf289b2ca..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0060-bug-on-kmem_cache_free-with-the-wrong-cache.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 6ba516f97cc8db1d67620bc2145258f922cba79a Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 11:50:53 -0400
-Subject: [PATCH 060/113] bug on kmem_cache_free with the wrong cache
-
-At least when CONFIG_BUG_ON_DATA_CORRUPTION is enabled.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- mm/slab.h | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
-diff --git a/mm/slab.h b/mm/slab.h
-index 5adb48bb2e68..9fef4285514a 100644
---- a/mm/slab.h
-+++ b/mm/slab.h
-@@ -471,10 +471,15 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x)
- return s;
-
- cachep = virt_to_cache(x);
-- if (WARN(cachep && cachep != s,
-- "%s: Wrong slab cache. %s but object is from %s\n",
-- __func__, s->name, cachep->name))
-+ if (cachep && cachep != s) {
-+#ifdef CONFIG_BUG_ON_DATA_CORRUPTION
-+ BUG();
-+#else
-+ WARN(1, "%s: Wrong slab cache. %s but object is from %s\n",
-+ __func__, s->name, cachep->name);
-+#endif
- print_tracking(cachep, x);
-+ }
- return cachep;
- }
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0061-bug-on-PageSlab-PageCompound-in-ksize.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0061-bug-on-PageSlab-PageCompound-in-ksize.patch
deleted file mode 100644
index b3d4819f67df..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0061-bug-on-PageSlab-PageCompound-in-ksize.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From ca3e5dd002a2862545da66983a242d30a611f200 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 11:57:35 -0400
-Subject: [PATCH 061/113] bug on !PageSlab && !PageCompound in ksize
-
-At least when CONFIG_BUG_ON_DATA_CORRUPTION is enabled.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/slub.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/mm/slub.c b/mm/slub.c
-index e01d54dc46e1..07ce7cac2612 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -4092,7 +4092,11 @@ size_t __ksize(const void *object)
- page = virt_to_head_page(object);
-
- if (unlikely(!PageSlab(page))) {
-+#ifdef CONFIG_BUG_ON_DATA_CORRUPTION
-+ BUG_ON(!PageCompound(page));
-+#else
- WARN_ON(!PageCompound(page));
-+#endif
- return page_size(page);
- }
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0062-mm-add-support-for-verifying-page-sanitization.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0062-mm-add-support-for-verifying-page-sanitization.patch
deleted file mode 100644
index 7d2d59bf3683..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0062-mm-add-support-for-verifying-page-sanitization.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From 268be364ad71a62af690cd31c9656856aca0ea76 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 21:54:56 -0400
-Subject: [PATCH 062/113] mm: add support for verifying page sanitization
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- include/linux/highmem.h | 7 +++++++
- mm/page_alloc.c | 6 ++++++
- security/Kconfig.hardening | 7 +++++++
- 3 files changed, 20 insertions(+)
-
-diff --git a/include/linux/highmem.h b/include/linux/highmem.h
-index 14e6202ce47f..4348ad7f5c50 100644
---- a/include/linux/highmem.h
-+++ b/include/linux/highmem.h
-@@ -284,6 +284,13 @@ static inline void clear_highpage(struct page *page)
- kunmap_atomic(kaddr);
- }
-
-+static inline void verify_zero_highpage(struct page *page)
-+{
-+ void *kaddr = kmap_atomic(page);
-+ BUG_ON(memchr_inv(kaddr, 0, PAGE_SIZE));
-+ kunmap_atomic(kaddr);
-+}
-+
- static inline void zero_user_segments(struct page *page,
- unsigned start1, unsigned end1,
- unsigned start2, unsigned end2)
-diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index 88639706ae17..e014e6df1f39 100644
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -2284,6 +2284,12 @@ static void prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags
- {
- post_alloc_hook(page, order, gfp_flags);
-
-+ if (IS_ENABLED(CONFIG_PAGE_SANITIZE_VERIFY) && want_init_on_free()) {
-+ int i;
-+ for (i = 0; i < (1 << order); i++)
-+ verify_zero_highpage(page + i);
-+ }
-+
- if (!free_pages_prezeroed() && want_init_on_alloc(gfp_flags))
- kernel_init_free_pages(page, 1 << order);
-
-diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
-index 2fa447823405..83ad70ae6bc3 100644
---- a/security/Kconfig.hardening
-+++ b/security/Kconfig.hardening
-@@ -219,6 +219,13 @@ config INIT_ON_FREE_DEFAULT_ON
- touching "cold" memory areas. Most cases see 3-5% impact. Some
- synthetic workloads have measured as high as 8%.
-
-+config PAGE_SANITIZE_VERIFY
-+ bool "Verify sanitized pages"
-+ default y
-+ help
-+ When init_on_free is enabled, verify that newly allocated pages
-+ are zeroed to detect write-after-free bugs.
-+
- endmenu
-
- endmenu
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch
deleted file mode 100644
index 72f9ba18ae82..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0063-slub-Extend-init_on_free-to-slab-caches-with-constru.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From 9144a6cce3d87056048b9ed092eb6a9391f12cf4 Mon Sep 17 00:00:00 2001
-From: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Date: Fri, 20 Sep 2019 14:02:42 +0200
-Subject: [PATCH 063/113] slub: Extend init_on_free to slab caches with
- constructors
-
-This is the remaining non-upstream part of SLAB_SANITIZE, which was a
-partial port, from Daniel Micay, of the feature from PaX without the
-default fast mode based on passing SLAB_NO_SANITIZE in
-performance-critical cases that are not particularly security sensitive.
-
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
----
- mm/slab.h | 12 +++++++++---
- mm/slub.c | 14 +++++++++++++-
- 2 files changed, 22 insertions(+), 4 deletions(-)
-
-diff --git a/mm/slab.h b/mm/slab.h
-index 9fef4285514a..0fcd97a4eb6f 100644
---- a/mm/slab.h
-+++ b/mm/slab.h
-@@ -641,9 +641,15 @@ static inline bool slab_want_init_on_alloc(gfp_t flags, struct kmem_cache *c)
-
- static inline bool slab_want_init_on_free(struct kmem_cache *c)
- {
-- if (static_branch_unlikely(&init_on_free))
-- return !(c->ctor ||
-- (c->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON)));
-+ if (static_branch_unlikely(&init_on_free)) {
-+#ifndef CONFIG_SLUB
-+ if (c->ctor)
-+ return false;
-+#endif
-+ if (c->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON))
-+ return false;
-+ return true;
-+ }
- return false;
- }
-
-diff --git a/mm/slub.c b/mm/slub.c
-index 07ce7cac2612..ac22d6831b9b 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -1571,7 +1571,8 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- : 0;
- memset((char *)object + s->inuse, 0,
- s->size - s->inuse - rsize);
--
-+ if (s->ctor)
-+ s->ctor(object);
- }
- /* If object's reuse doesn't have to be delayed */
- if (!slab_free_hook(s, object)) {
-@@ -1580,6 +1581,17 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- *head = object;
- if (!*tail)
- *tail = object;
-+ } else if (slab_want_init_on_free(s) && s->ctor) {
-+ /* Objects that are put into quarantine by KASAN will
-+ * still undergo free_consistency_checks() and thus
-+ * need to show a valid freepointer to check_object().
-+ *
-+ * Note that doing this for all caches (not just ctor
-+ * ones, which have s->offset != NULL)) causes a GPF,
-+ * due to KASAN poisoning and the way set_freepointer()
-+ * eventually dereferences the freepointer.
-+ */
-+ set_freepointer(s, object, NULL);
- }
- } while (object != old_tail);
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0064-slub-Add-support-for-verifying-slab-sanitization.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0064-slub-Add-support-for-verifying-slab-sanitization.patch
deleted file mode 100644
index a41940a4b623..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0064-slub-Add-support-for-verifying-slab-sanitization.patch
+++ /dev/null
@@ -1,116 +0,0 @@
-From 256e4ff40bc4e2ecebaaa65ce1ac4a75023ba640 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 15:58:57 -0400
-Subject: [PATCH 064/113] slub: Add support for verifying slab sanitization
-
-This is an extension to the sanitization feature in PaX for when
-sacricifing more performance for security is acceptable.
-
-The initial version from Daniel Micay was relying on PAGE_SANITIZE. It
-now relies on upstream's init_on_free.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- mm/slub.c | 36 ++++++++++++++++++++++++++++++++----
- security/Kconfig.hardening | 8 ++++++++
- 2 files changed, 40 insertions(+), 4 deletions(-)
-
-diff --git a/mm/slub.c b/mm/slub.c
-index ac22d6831b9b..e8e0efa18bd3 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -127,6 +127,12 @@ static inline bool kmem_cache_debug(struct kmem_cache *s)
- return kmem_cache_debug_flags(s, SLAB_DEBUG_FLAGS);
- }
-
-+static inline bool has_sanitize_verify(struct kmem_cache *s)
-+{
-+ return IS_ENABLED(CONFIG_SLAB_SANITIZE_VERIFY) &&
-+ slab_want_init_on_free(s);
-+}
-+
- void *fixup_red_left(struct kmem_cache *s, void *p)
- {
- if (kmem_cache_debug_flags(s, SLAB_RED_ZONE))
-@@ -1571,7 +1577,7 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- : 0;
- memset((char *)object + s->inuse, 0,
- s->size - s->inuse - rsize);
-- if (s->ctor)
-+ if (!IS_ENABLED(CONFIG_SLAB_SANITIZE_VERIFY) && s->ctor)
- s->ctor(object);
- }
- /* If object's reuse doesn't have to be delayed */
-@@ -1606,7 +1612,7 @@ static void *setup_object(struct kmem_cache *s, struct page *page,
- {
- setup_object_debug(s, page, object);
- object = kasan_init_slab_obj(s, object);
-- if (unlikely(s->ctor)) {
-+ if (unlikely(s->ctor) && !has_sanitize_verify(s)) {
- kasan_unpoison_object_data(s, object);
- s->ctor(object);
- kasan_poison_object_data(s, object);
-@@ -2897,7 +2903,16 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
-
- maybe_wipe_obj_freeptr(s, object);
-
-- if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
-+ if (has_sanitize_verify(s) && object) {
-+ /* KASAN hasn't unpoisoned the object yet (this is done in the
-+ * post-alloc hook), so let's do it temporarily.
-+ */
-+ kasan_unpoison_object_data(s, object);
-+ BUG_ON(memchr_inv(object, 0, s->object_size));
-+ if (s->ctor)
-+ s->ctor(object);
-+ kasan_poison_object_data(s, object);
-+ } else if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
- memset(object, 0, s->object_size);
-
- slab_post_alloc_hook(s, objcg, gfpflags, 1, &object);
-@@ -3337,7 +3352,20 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
- local_irq_enable();
-
- /* Clear memory outside IRQ disabled fastpath loop */
-- if (unlikely(slab_want_init_on_alloc(flags, s))) {
-+ if (has_sanitize_verify(s)) {
-+ int j;
-+
-+ for (j = 0; j < i; j++) {
-+ /* KASAN hasn't unpoisoned the object yet (this is done
-+ * in the post-alloc hook), so let's do it temporarily.
-+ */
-+ kasan_unpoison_object_data(s, p[j]);
-+ BUG_ON(memchr_inv(p[j], 0, s->object_size));
-+ if (s->ctor)
-+ s->ctor(p[j]);
-+ kasan_poison_object_data(s, p[j]);
-+ }
-+ } else if (unlikely(slab_want_init_on_alloc(flags, s))) {
- int j;
-
- for (j = 0; j < i; j++)
-diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
-index 83ad70ae6bc3..7dede18f1074 100644
---- a/security/Kconfig.hardening
-+++ b/security/Kconfig.hardening
-@@ -226,6 +226,14 @@ config PAGE_SANITIZE_VERIFY
- When init_on_free is enabled, verify that newly allocated pages
- are zeroed to detect write-after-free bugs.
-
-+config SLAB_SANITIZE_VERIFY
-+ bool "Verify sanitized SLAB allocations"
-+ default y
-+ depends on !KASAN
-+ help
-+ When init_on_free is enabled, verify that newly allocated slab
-+ objects are zeroed to detect write-after-free bugs.
-+
- endmenu
-
- endmenu
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0065-slub-add-multi-purpose-random-canaries.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0065-slub-add-multi-purpose-random-canaries.patch
deleted file mode 100644
index 5de5c89a82b7..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0065-slub-add-multi-purpose-random-canaries.patch
+++ /dev/null
@@ -1,264 +0,0 @@
-From 9b9069e3779352ffa3af0924d5cdf4872b18a98c Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 16:16:58 -0400
-Subject: [PATCH 065/113] slub: add multi-purpose random canaries
-
-From the configuration option:
-
- Place canaries at the end of kernel slab allocations, sacrificing
- some performance and memory usage for security.
-
- Canaries can detect some forms of heap corruption when allocations
- are freed and as part of the HARDENED_USERCOPY feature. It provides
- basic use-after-free detection for HARDENED_USERCOPY.
-
- Canaries absorb small overflows (rendering them harmless), mitigate
- non-NUL terminated C string overflows on 64-bit via a guaranteed zero
- byte and provide basic double-free detection.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/slub_def.h | 5 +++
- init/Kconfig | 17 ++++++++++
- mm/slab.h | 2 +-
- mm/slub.c | 69 ++++++++++++++++++++++++++++++++++++++--
- 4 files changed, 89 insertions(+), 4 deletions(-)
-
-diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
-index 1be0ed5befa1..c71cf30b5987 100644
---- a/include/linux/slub_def.h
-+++ b/include/linux/slub_def.h
-@@ -113,6 +113,11 @@ struct kmem_cache {
- unsigned long random;
- #endif
-
-+#ifdef CONFIG_SLAB_CANARY
-+ unsigned long random_active;
-+ unsigned long random_inactive;
-+#endif
-+
- #ifdef CONFIG_NUMA
- /*
- * Defragmentation by allocating from a remote node.
-diff --git a/init/Kconfig b/init/Kconfig
-index 58df4930995f..2af6689d9e71 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1943,6 +1943,23 @@ config SLAB_FREELIST_HARDENED
- sanity-checking than others. This option is most effective with
- CONFIG_SLUB.
-
-+config SLAB_CANARY
-+ depends on SLUB
-+ depends on !SLAB_MERGE_DEFAULT
-+ bool "SLAB canaries"
-+ default y
-+ help
-+ Place canaries at the end of kernel slab allocations, sacrificing
-+ some performance and memory usage for security.
-+
-+ Canaries can detect some forms of heap corruption when allocations
-+ are freed and as part of the HARDENED_USERCOPY feature. It provides
-+ basic use-after-free detection for HARDENED_USERCOPY.
-+
-+ Canaries absorb small overflows (rendering them harmless), mitigate
-+ non-NUL terminated C string overflows on 64-bit via a guaranteed zero
-+ byte and provide basic double-free detection.
-+
- config SHUFFLE_PAGE_ALLOCATOR
- bool "Page allocator randomization"
- default SLAB_FREELIST_RANDOM && ACPI_NUMA
-diff --git a/mm/slab.h b/mm/slab.h
-index 0fcd97a4eb6f..105dba485a7e 100644
---- a/mm/slab.h
-+++ b/mm/slab.h
-@@ -504,7 +504,7 @@ static inline size_t slab_ksize(const struct kmem_cache *s)
- * back there or track user information then we can
- * only use the space before that information.
- */
-- if (s->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_STORE_USER))
-+ if ((s->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_STORE_USER)) || IS_ENABLED(CONFIG_SLAB_CANARY))
- return s->inuse;
- /*
- * Else we can use all the padding etc for the allocation
-diff --git a/mm/slub.c b/mm/slub.c
-index e8e0efa18bd3..dd68308c94a9 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -569,6 +569,33 @@ static inline unsigned int get_info_end(struct kmem_cache *s)
- return s->inuse;
- }
-
-+#ifdef CONFIG_SLAB_CANARY
-+static inline unsigned long *get_canary(struct kmem_cache *s, void *object)
-+{
-+ return object + get_info_end(s);
-+}
-+
-+static inline unsigned long get_canary_value(const void *canary, unsigned long value)
-+{
-+ return (value ^ (unsigned long)canary) & CANARY_MASK;
-+}
-+
-+static inline void set_canary(struct kmem_cache *s, void *object, unsigned long value)
-+{
-+ unsigned long *canary = get_canary(s, object);
-+ *canary = get_canary_value(canary, value);
-+}
-+
-+static inline void check_canary(struct kmem_cache *s, void *object, unsigned long value)
-+{
-+ unsigned long *canary = get_canary(s, object);
-+ BUG_ON(*canary != get_canary_value(canary, value));
-+}
-+#else
-+#define set_canary(s, object, value)
-+#define check_canary(s, object, value)
-+#endif
-+
- static struct track *get_track(struct kmem_cache *s, void *object,
- enum track_item alloc)
- {
-@@ -576,6 +603,9 @@ static struct track *get_track(struct kmem_cache *s, void *object,
-
- p = object + get_info_end(s);
-
-+ if (IS_ENABLED(CONFIG_SLAB_CANARY))
-+ p = (void *)p + sizeof(void *);
-+
- return p + alloc;
- }
-
-@@ -717,6 +747,9 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
-
- off = get_info_end(s);
-
-+ if (IS_ENABLED(CONFIG_SLAB_CANARY))
-+ off += sizeof(void *);
-+
- if (s->flags & SLAB_STORE_USER)
- off += 2 * sizeof(struct track);
-
-@@ -825,8 +858,9 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
- * Meta data starts here.
- *
- * A. Free pointer (if we cannot overwrite object on free)
-- * B. Tracking data for SLAB_STORE_USER
-- * C. Padding to reach required alignment boundary or at mininum
-+ * B. Canary for SLAB_CANARY
-+ * C. Tracking data for SLAB_STORE_USER
-+ * D. Padding to reach required alignment boundary or at mininum
- * one word if debugging is on to be able to detect writes
- * before the word boundary.
- *
-@@ -844,6 +878,9 @@ static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
- {
- unsigned long off = get_info_end(s); /* The end of info */
-
-+ if (IS_ENABLED(CONFIG_SLAB_CANARY))
-+ off += sizeof(void *);
-+
- if (s->flags & SLAB_STORE_USER)
- /* We also have user information there */
- off += 2 * sizeof(struct track);
-@@ -1567,6 +1604,8 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- object = next;
- next = get_freepointer(s, object);
-
-+ check_canary(s, object, s->random_active);
-+
- if (slab_want_init_on_free(s)) {
- /*
- * Clear the object and the metadata, but don't touch
-@@ -1580,6 +1619,9 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- if (!IS_ENABLED(CONFIG_SLAB_SANITIZE_VERIFY) && s->ctor)
- s->ctor(object);
- }
-+
-+ set_canary(s, object, s->random_inactive);
-+
- /* If object's reuse doesn't have to be delayed */
- if (!slab_free_hook(s, object)) {
- /* Move object to the new freelist */
-@@ -1611,6 +1653,7 @@ static void *setup_object(struct kmem_cache *s, struct page *page,
- void *object)
- {
- setup_object_debug(s, page, object);
-+ set_canary(s, object, s->random_inactive);
- object = kasan_init_slab_obj(s, object);
- if (unlikely(s->ctor) && !has_sanitize_verify(s)) {
- kasan_unpoison_object_data(s, object);
-@@ -2915,6 +2958,11 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
- } else if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
- memset(object, 0, s->object_size);
-
-+ if (object) {
-+ check_canary(s, object, s->random_inactive);
-+ set_canary(s, object, s->random_active);
-+ }
-+
- slab_post_alloc_hook(s, objcg, gfpflags, 1, &object);
-
- return object;
-@@ -3302,7 +3350,7 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
- void **p)
- {
- struct kmem_cache_cpu *c;
-- int i;
-+ int i, k;
- struct obj_cgroup *objcg = NULL;
-
- /* memcg and kmem_cache debug support */
-@@ -3372,6 +3420,11 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
- memset(p[j], 0, s->object_size);
- }
-
-+ for (k = 0; k < i; k++) {
-+ check_canary(s, p[k], s->random_inactive);
-+ set_canary(s, p[k], s->random_active);
-+ }
-+
- /* memcg and kmem_cache debug support */
- slab_post_alloc_hook(s, objcg, flags, size, p);
- return i;
-@@ -3573,6 +3626,7 @@ static void early_kmem_cache_node_alloc(int node)
- init_object(kmem_cache_node, n, SLUB_RED_ACTIVE);
- init_tracking(kmem_cache_node, n);
- #endif
-+ set_canary(kmem_cache_node, n, kmem_cache_node->random_active);
- n = kasan_kmalloc(kmem_cache_node, n, sizeof(struct kmem_cache_node),
- GFP_KERNEL);
- page->freelist = get_freepointer(kmem_cache_node, n);
-@@ -3753,6 +3807,9 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
- s->offset = ALIGN(freepointer_area / 2, sizeof(void *));
- }
-
-+ if (IS_ENABLED(CONFIG_SLAB_CANARY))
-+ size += sizeof(void *);
-+
- #ifdef CONFIG_SLUB_DEBUG
- if (flags & SLAB_STORE_USER)
- /*
-@@ -3826,6 +3883,10 @@ static int kmem_cache_open(struct kmem_cache *s, slab_flags_t flags)
- #ifdef CONFIG_SLAB_FREELIST_HARDENED
- s->random = get_random_long();
- #endif
-+#ifdef CONFIG_SLAB_CANARY
-+ s->random_active = get_random_long();
-+ s->random_inactive = get_random_long();
-+#endif
-
- if (!calculate_sizes(s, -1))
- goto error;
-@@ -4099,6 +4160,8 @@ void __check_heap_object(const void *ptr, unsigned long n, struct page *page,
- offset -= s->red_left_pad;
- }
-
-+ check_canary(s, (void *)ptr - offset, s->random_active);
-+
- /* Allow address range falling entirely within usercopy region. */
- if (offset >= s->useroffset &&
- offset - s->useroffset <= s->usersize &&
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0066-security-perf-Allow-further-restriction-of-perf_even.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0066-security-perf-Allow-further-restriction-of-perf_even.patch
deleted file mode 100644
index 7190b5b3633a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0066-security-perf-Allow-further-restriction-of-perf_even.patch
+++ /dev/null
@@ -1,122 +0,0 @@
-From e5033a4e93fe0ac2545f62f0128cd73fcc31d881 Mon Sep 17 00:00:00 2001
-From: Ben Hutchings <ben@decadent.org.uk>
-Date: Mon, 11 Jan 2016 15:23:55 +0000
-Subject: [PATCH 066/113] security,perf: Allow further restriction of
- perf_event_open
-
-When kernel.perf_event_open is set to 3 (or greater), disallow all
-access to performance events by users without CAP_SYS_ADMIN.
-Add a Kconfig symbol CONFIG_SECURITY_PERF_EVENTS_RESTRICT that
-makes this value the default.
-
-This is based on a similar feature in grsecurity
-(CONFIG_GRKERNSEC_PERF_HARDEN). This version doesn't include making
-the variable read-only. It also allows enabling further restriction
-at run-time regardless of whether the default is changed.
-
-Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
-[thibaut.sautereau@ssi.gouv.fr: Adapt to work with the new CAP_PERFMON capability]
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
----
- Documentation/admin-guide/sysctl/kernel.rst | 2 ++
- include/linux/perf_event.h | 8 ++++++++
- kernel/events/core.c | 7 ++++++-
- security/Kconfig | 9 +++++++++
- tools/perf/Documentation/security.txt | 1 +
- 5 files changed, 26 insertions(+), 1 deletion(-)
-
-diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
-index d4b32cc32bb7..4c20e6ded0af 100644
---- a/Documentation/admin-guide/sysctl/kernel.rst
-+++ b/Documentation/admin-guide/sysctl/kernel.rst
-@@ -860,6 +860,8 @@ with respect to CAP_PERFMON use cases.
- >=1 Disallow CPU event access by users without ``CAP_PERFMON``.
-
- >=2 Disallow kernel profiling by users without ``CAP_PERFMON``.
-+
-+>=3 Disallow use of any event by users without ``CAP_PERFMON``.
- === ==================================================================
-
-
-diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
-index 96450f6fb1de..d020c26b612a 100644
---- a/include/linux/perf_event.h
-+++ b/include/linux/perf_event.h
-@@ -1312,6 +1312,14 @@ static inline int perf_is_paranoid(void)
- return sysctl_perf_event_paranoid > -1;
- }
-
-+static inline int perf_allow_open(struct perf_event_attr *attr)
-+{
-+ if (sysctl_perf_event_paranoid > 2 && !perfmon_capable())
-+ return -EACCES;
-+
-+ return security_perf_event_open(attr, PERF_SECURITY_OPEN);
-+}
-+
- static inline int perf_allow_kernel(struct perf_event_attr *attr)
- {
- if (sysctl_perf_event_paranoid > 1 && !perfmon_capable())
-diff --git a/kernel/events/core.c b/kernel/events/core.c
-index c3ba29d058b7..6efbf92763b1 100644
---- a/kernel/events/core.c
-+++ b/kernel/events/core.c
-@@ -407,8 +407,13 @@ static cpumask_var_t perf_online_mask;
- * 0 - disallow raw tracepoint access for unpriv
- * 1 - disallow cpu events for unpriv
- * 2 - disallow kernel profiling for unpriv
-+ * 3 - disallow all unpriv perf event use
- */
-+#ifdef CONFIG_SECURITY_PERF_EVENTS_RESTRICT
-+int sysctl_perf_event_paranoid __read_mostly = 3;
-+#else
- int sysctl_perf_event_paranoid __read_mostly = 2;
-+#endif
-
- /* Minimum for 512 kiB + 1 user control page */
- int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */
-@@ -11638,7 +11643,7 @@ SYSCALL_DEFINE5(perf_event_open,
- return -EINVAL;
-
- /* Do we allow access to perf_event_open(2) ? */
-- err = security_perf_event_open(&attr, PERF_SECURITY_OPEN);
-+ err = perf_allow_open(&attr);
- if (err)
- return err;
-
-diff --git a/security/Kconfig b/security/Kconfig
-index 81d0a08736aa..c797326308f1 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -19,6 +19,15 @@ config SECURITY_DMESG_RESTRICT
-
- If you are unsure how to answer this question, answer N.
-
-+config SECURITY_PERF_EVENTS_RESTRICT
-+ bool "Restrict unprivileged use of performance events"
-+ depends on PERF_EVENTS
-+ help
-+ If you say Y here, the kernel.perf_event_paranoid sysctl
-+ will be set to 3 by default, and no unprivileged use of the
-+ perf_event_open syscall will be permitted unless it is
-+ changed.
-+
- config SECURITY
- bool "Enable different security models"
- depends on SYSFS
-diff --git a/tools/perf/Documentation/security.txt b/tools/perf/Documentation/security.txt
-index 4fe3b8b1958f..a7d88cc23a70 100644
---- a/tools/perf/Documentation/security.txt
-+++ b/tools/perf/Documentation/security.txt
-@@ -148,6 +148,7 @@ Perf tool provides a message similar to the one below:
- >= 0: Disallow raw and ftrace function tracepoint access
- >= 1: Disallow CPU event access
- >= 2: Disallow kernel profiling
-+ >= 3: Disallow use of any event
- To make the adjusted perf_event_paranoid setting permanent preserve it
- in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch
deleted file mode 100644
index 8c8164d310b4..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0067-enable-SECURITY_PERF_EVENTS_RESTRICT-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 14e62a087b59ccd0dcfd1ad1cb2c5457293be04b Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 4 May 2017 14:45:59 -0400
-Subject: [PATCH 067/113] enable SECURITY_PERF_EVENTS_RESTRICT by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- security/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index c797326308f1..2348ff7d4e1d 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -22,6 +22,7 @@ config SECURITY_DMESG_RESTRICT
- config SECURITY_PERF_EVENTS_RESTRICT
- bool "Restrict unprivileged use of performance events"
- depends on PERF_EVENTS
-+ default y
- help
- If you say Y here, the kernel.perf_event_paranoid sysctl
- will be set to 3 by default, and no unprivileged use of the
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch
deleted file mode 100644
index 3eb0b769394b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0068-add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by.patch
+++ /dev/null
@@ -1,124 +0,0 @@
-From bc3a02af3affde290739e6cd6a41f7a15f1e2368 Mon Sep 17 00:00:00 2001
-From: Serge Hallyn <serge.hallyn@canonical.com>
-Date: Fri, 31 May 2013 19:12:12 +0100
-Subject: [PATCH 068/113] add sysctl to disallow unprivileged CLONE_NEWUSER by
- default
-
-Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
-[bwh: Remove unneeded binary sysctl bits]
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-[thibaut.sautereau@ssi.gouv.fr: Adapt to sysctl code refactoring]
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- include/linux/user_namespace.h | 4 ++++
- kernel/fork.c | 11 +++++++++++
- kernel/sysctl.c | 12 ++++++++++++
- kernel/user_namespace.c | 3 +++
- 4 files changed, 30 insertions(+)
-
-diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
-index 6ef1c7109fc4..2140091b0b8d 100644
---- a/include/linux/user_namespace.h
-+++ b/include/linux/user_namespace.h
-@@ -106,6 +106,8 @@ void dec_ucount(struct ucounts *ucounts, enum ucount_type type);
-
- #ifdef CONFIG_USER_NS
-
-+extern int unprivileged_userns_clone;
-+
- static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
- {
- if (ns)
-@@ -139,6 +141,8 @@ extern bool current_in_userns(const struct user_namespace *target_ns);
- struct ns_common *ns_get_owner(struct ns_common *ns);
- #else
-
-+#define unprivileged_userns_clone 0
-+
- static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
- {
- return &init_user_ns;
-diff --git a/kernel/fork.c b/kernel/fork.c
-index c675fdbd3dce..cba344194fba 100644
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -82,6 +82,7 @@
- #include <linux/perf_event.h>
- #include <linux/posix-timers.h>
- #include <linux/user-return-notifier.h>
-+#include <linux/user_namespace.h>
- #include <linux/oom.h>
- #include <linux/khugepaged.h>
- #include <linux/signalfd.h>
-@@ -1863,6 +1864,10 @@ static __latent_entropy struct task_struct *copy_process(
- if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
- return ERR_PTR(-EINVAL);
-
-+ if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone)
-+ if (!capable(CAP_SYS_ADMIN))
-+ return ERR_PTR(-EPERM);
-+
- /*
- * Thread groups must share signals as well, and detached threads
- * can only be started up within the thread group.
-@@ -2928,6 +2933,12 @@ int ksys_unshare(unsigned long unshare_flags)
- if (unshare_flags & CLONE_NEWNS)
- unshare_flags |= CLONE_FS;
-
-+ if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
-+ err = -EPERM;
-+ if (!capable(CAP_SYS_ADMIN))
-+ goto bad_unshare_out;
-+ }
-+
- err = check_unshare_flags(unshare_flags);
- if (err)
- goto bad_unshare_out;
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index b2cd3dbbb17a..fccf24a08c8a 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -103,6 +103,9 @@
- #ifdef CONFIG_LOCKUP_DETECTOR
- #include <linux/nmi.h>
- #endif
-+#ifdef CONFIG_USER_NS
-+#include <linux/user_namespace.h>
-+#endif
-
- #if defined(CONFIG_SYSCTL)
-
-@@ -1902,6 +1905,15 @@ static struct ctl_table kern_table[] = {
- .proc_handler = proc_dointvec,
- },
- #endif
-+#ifdef CONFIG_USER_NS
-+ {
-+ .procname = "unprivileged_userns_clone",
-+ .data = &unprivileged_userns_clone,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec,
-+ },
-+#endif
- #ifdef CONFIG_PROC_SYSCTL
- {
- .procname = "tainted",
-diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
-index e703d5d9cbe8..29a30cff5e60 100644
---- a/kernel/user_namespace.c
-+++ b/kernel/user_namespace.c
-@@ -21,6 +21,9 @@
- #include <linux/bsearch.h>
- #include <linux/sort.h>
-
-+/* sysctl */
-+int unprivileged_userns_clone;
-+
- static struct kmem_cache *user_ns_cachep __read_mostly;
- static DEFINE_MUTEX(userns_state_mutex);
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0069-add-CONFIG-for-unprivileged_userns_clone.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0069-add-CONFIG-for-unprivileged_userns_clone.patch
deleted file mode 100644
index 50986719a95d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0069-add-CONFIG-for-unprivileged_userns_clone.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-From 3c3622cd06c8e430aa1aed6b1dd6cb763b3e2e44 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Wed, 31 Jul 2019 20:50:48 +0100
-Subject: [PATCH 069/113] add CONFIG for unprivileged_userns_clone
-
-When disabled, unprivileged users will not be able to create
-new namespaces. Allowing users to create their own namespaces
-has been part of several recent local privilege escalation
-exploits, so if you need user namespaces but are
-paranoid^Wsecurity-conscious you want to disable this.
-
-By default unprivileged user namespaces are disabled.
-
-Authored-by: Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
-Edited-by: Levente Polyak (anthraxx) <levente@leventepolyak.net>
----
- init/Kconfig | 16 ++++++++++++++++
- kernel/user_namespace.c | 4 ++++
- 2 files changed, 20 insertions(+)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 2af6689d9e71..a7b5a4cb7939 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1174,6 +1174,22 @@ config USER_NS
-
- If unsure, say N.
-
-+config USER_NS_UNPRIVILEGED
-+ bool "Allow unprivileged users to create namespaces"
-+ depends on USER_NS
-+ default n
-+ help
-+ When disabled, unprivileged users will not be able to create
-+ new namespaces. Allowing users to create their own namespaces
-+ has been part of several recent local privilege escalation
-+ exploits, so if you need user namespaces but are
-+ paranoid^Wsecurity-conscious you want to disable this.
-+
-+ This setting can be overridden at runtime via the
-+ kernel.unprivileged_userns_clone sysctl.
-+
-+ If unsure, say N.
-+
- config PID_NS
- bool "PID Namespaces"
- default y
-diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
-index 29a30cff5e60..5758274feaee 100644
---- a/kernel/user_namespace.c
-+++ b/kernel/user_namespace.c
-@@ -22,7 +22,11 @@
- #include <linux/sort.h>
-
- /* sysctl */
-+#ifdef CONFIG_USER_NS_UNPRIVILEGED
-+int unprivileged_userns_clone = 1;
-+#else
- int unprivileged_userns_clone;
-+#endif
-
- static struct kmem_cache *user_ns_cachep __read_mostly;
- static DEFINE_MUTEX(userns_state_mutex);
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0070-add-kmalloc-krealloc-alloc_size-attributes.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0070-add-kmalloc-krealloc-alloc_size-attributes.patch
deleted file mode 100644
index 89456f360c34..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0070-add-kmalloc-krealloc-alloc_size-attributes.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From 941b4478a3e32204eec70e073a1a00fe3a8ef266 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:02:56 -0400
-Subject: [PATCH 070/113] add kmalloc/krealloc alloc_size attributes
-
-Note that this is overly strict when combined with ksize users accessing
-beyond the requested data size.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/slab.h | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/include/linux/slab.h b/include/linux/slab.h
-index dd6897f62010..78f99835b91b 100644
---- a/include/linux/slab.h
-+++ b/include/linux/slab.h
-@@ -181,7 +181,7 @@ int kmem_cache_shrink(struct kmem_cache *);
- /*
- * Common kmalloc functions provided by all allocators
- */
--void * __must_check krealloc(const void *, size_t, gfp_t);
-+void * __must_check krealloc(const void *, size_t, gfp_t) __attribute((alloc_size(2)));
- void kfree(const void *);
- void kfree_sensitive(const void *);
- size_t __ksize(const void *);
-@@ -386,7 +386,7 @@ static __always_inline unsigned int kmalloc_index(size_t size)
- }
- #endif /* !CONFIG_SLOB */
-
--void *__kmalloc(size_t size, gfp_t flags) __assume_kmalloc_alignment __malloc;
-+void *__kmalloc(size_t size, gfp_t flags) __assume_kmalloc_alignment __malloc __attribute__((alloc_size(1)));
- void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __assume_slab_alignment __malloc;
- void kmem_cache_free(struct kmem_cache *, void *);
-
-@@ -410,7 +410,7 @@ static __always_inline void kfree_bulk(size_t size, void **p)
- }
-
- #ifdef CONFIG_NUMA
--void *__kmalloc_node(size_t size, gfp_t flags, int node) __assume_kmalloc_alignment __malloc;
-+void *__kmalloc_node(size_t size, gfp_t flags, int node) __assume_kmalloc_alignment __malloc __attribute__((alloc_size(1)));
- void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node) __assume_slab_alignment __malloc;
- #else
- static __always_inline void *__kmalloc_node(size_t size, gfp_t flags, int node)
-@@ -535,7 +535,7 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
- * Try really hard to succeed the allocation but fail
- * eventually.
- */
--static __always_inline void *kmalloc(size_t size, gfp_t flags)
-+static __always_inline __attribute__((alloc_size(1))) void *kmalloc(size_t size, gfp_t flags)
- {
- if (__builtin_constant_p(size)) {
- #ifndef CONFIG_SLOB
-@@ -557,7 +557,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
- return __kmalloc(size, flags);
- }
-
--static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
-+static __always_inline __attribute__((alloc_size(1))) void *kmalloc_node(size_t size, gfp_t flags, int node)
- {
- #ifndef CONFIG_SLOB
- if (__builtin_constant_p(size) &&
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0071-add-vmalloc-alloc_size-attributes.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0071-add-vmalloc-alloc_size-attributes.patch
deleted file mode 100644
index 4fe354ad08cd..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0071-add-vmalloc-alloc_size-attributes.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 7b72861a9f6de49ad511e2619fa7aaa92f9cda93 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 12:04:03 -0400
-Subject: [PATCH 071/113] add vmalloc alloc_size attributes
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- include/linux/vmalloc.h | 18 +++++++++---------
- 1 file changed, 9 insertions(+), 9 deletions(-)
-
-diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
-index 938eaf9517e2..7c069063c20d 100644
---- a/include/linux/vmalloc.h
-+++ b/include/linux/vmalloc.h
-@@ -102,18 +102,18 @@ static inline void vmalloc_init(void)
- static inline unsigned long vmalloc_nr_pages(void) { return 0; }
- #endif
-
--extern void *vmalloc(unsigned long size);
--extern void *vzalloc(unsigned long size);
--extern void *vmalloc_user(unsigned long size);
--extern void *vmalloc_node(unsigned long size, int node);
--extern void *vzalloc_node(unsigned long size, int node);
--extern void *vmalloc_32(unsigned long size);
--extern void *vmalloc_32_user(unsigned long size);
--extern void *__vmalloc(unsigned long size, gfp_t gfp_mask);
-+extern void *vmalloc(unsigned long size) __attribute__((alloc_size(1)));
-+extern void *vzalloc(unsigned long size) __attribute__((alloc_size(1)));
-+extern void *vmalloc_user(unsigned long size) __attribute__((alloc_size(1)));
-+extern void *vmalloc_node(unsigned long size, int node) __attribute__((alloc_size(1)));
-+extern void *vzalloc_node(unsigned long size, int node) __attribute__((alloc_size(1)));
-+extern void *vmalloc_32(unsigned long size) __attribute__((alloc_size(1)));
-+extern void *vmalloc_32_user(unsigned long size) __attribute__((alloc_size(1)));
-+extern void *__vmalloc(unsigned long size, gfp_t gfp_mask) __attribute__((alloc_size(1)));
- extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
- unsigned long start, unsigned long end, gfp_t gfp_mask,
- pgprot_t prot, unsigned long vm_flags, int node,
-- const void *caller);
-+ const void *caller) __attribute__((alloc_size(1)));
- void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask,
- int node, const void *caller);
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0072-add-kvmalloc-alloc_size-attribute.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0072-add-kvmalloc-alloc_size-attribute.patch
deleted file mode 100644
index df711dded1d5..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0072-add-kvmalloc-alloc_size-attribute.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 2deb1d273cf03c7c4327ced90feb26414e0d0f13 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 00:51:33 -0400
-Subject: [PATCH 072/113] add kvmalloc alloc_size attribute
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/mm.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/include/linux/mm.h b/include/linux/mm.h
-index cd5c313729ea..746f6d05bd81 100644
---- a/include/linux/mm.h
-+++ b/include/linux/mm.h
-@@ -759,7 +759,7 @@ static inline int is_vmalloc_or_module_addr(const void *x)
- }
- #endif
-
--extern void *kvmalloc_node(size_t size, gfp_t flags, int node);
-+extern void *kvmalloc_node(size_t size, gfp_t flags, int node) __attribute__((alloc_size(1)));
- static inline void *kvmalloc(size_t size, gfp_t flags)
- {
- return kvmalloc_node(size, flags, NUMA_NO_NODE);
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0073-add-percpu-alloc_size-attributes.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0073-add-percpu-alloc_size-attributes.patch
deleted file mode 100644
index 03ded158dc09..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0073-add-percpu-alloc_size-attributes.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From d3ccee2b1a9f4cbb8c05a17218473517198bb36b Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 14 May 2017 16:39:36 -0400
-Subject: [PATCH 073/113] add percpu alloc_size attributes
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/percpu.h | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/include/linux/percpu.h b/include/linux/percpu.h
-index 5e76af742c80..9a6c682ec127 100644
---- a/include/linux/percpu.h
-+++ b/include/linux/percpu.h
-@@ -123,7 +123,7 @@ extern int __init pcpu_page_first_chunk(size_t reserved_size,
- pcpu_fc_populate_pte_fn_t populate_pte_fn);
- #endif
-
--extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align);
-+extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align) __attribute__((alloc_size(1)));
- extern bool __is_kernel_percpu_address(unsigned long addr, unsigned long *can_addr);
- extern bool is_kernel_percpu_address(unsigned long addr);
-
-@@ -131,8 +131,8 @@ extern bool is_kernel_percpu_address(unsigned long addr);
- extern void __init setup_per_cpu_areas(void);
- #endif
-
--extern void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp);
--extern void __percpu *__alloc_percpu(size_t size, size_t align);
-+extern void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp) __attribute__((alloc_size(1)));
-+extern void __percpu *__alloc_percpu(size_t size, size_t align) __attribute__((alloc_size(1)));
- extern void free_percpu(void __percpu *__pdata);
- extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0074-add-alloc_pages_exact-alloc_size-attributes.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0074-add-alloc_pages_exact-alloc_size-attributes.patch
deleted file mode 100644
index f6328965bc7d..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0074-add-alloc_pages_exact-alloc_size-attributes.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 87ee060c78b634403773380d8046842edf106c22 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 14 May 2017 16:53:59 -0400
-Subject: [PATCH 074/113] add alloc_pages_exact alloc_size attributes
-
-Edited-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/gfp.h | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/include/linux/gfp.h b/include/linux/gfp.h
-index c603237e006c..893378b0262e 100644
---- a/include/linux/gfp.h
-+++ b/include/linux/gfp.h
-@@ -568,9 +568,9 @@ static inline struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
- extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
- extern unsigned long get_zeroed_page(gfp_t gfp_mask);
-
--void *alloc_pages_exact(size_t size, gfp_t gfp_mask);
-+void *alloc_pages_exact(size_t size, gfp_t gfp_mask) __attribute__((alloc_size(1)));
- void free_pages_exact(void *virt, size_t size);
--void * __meminit alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask);
-+void * __meminit alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask) __attribute__((alloc_size(2)));
-
- #define __get_free_page(gfp_mask) \
- __get_free_pages((gfp_mask), 0)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0075-Add-the-extra_latent_entropy-kernel-parameter.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0075-Add-the-extra_latent_entropy-kernel-parameter.patch
deleted file mode 100644
index 4fb5343298c9..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0075-Add-the-extra_latent_entropy-kernel-parameter.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-From 55ba39ba2604617b16b015105f69c180944acb35 Mon Sep 17 00:00:00 2001
-From: Emese Revfy <re.emese@gmail.com>
-Date: Tue, 31 May 2016 01:34:02 +0200
-Subject: [PATCH 075/113] Add the extra_latent_entropy kernel parameter
-
-When extra_latent_entropy is passed on the kernel command line,
-entropy will be extracted from up to the first 4GB of RAM while the
-runtime memory allocator is being initialized.
-
-Based on work created by the PaX Team.
-
-Signed-off-by: Emese Revfy <re.emese@gmail.com>
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- .../admin-guide/kernel-parameters.txt | 5 ++++
- mm/page_alloc.c | 25 +++++++++++++++++++
- scripts/gcc-plugins/Kconfig | 5 ++++
- 3 files changed, 35 insertions(+)
-
-diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
-index 26bfe7ae711b..e7ea794320e8 100644
---- a/Documentation/admin-guide/kernel-parameters.txt
-+++ b/Documentation/admin-guide/kernel-parameters.txt
-@@ -3566,6 +3566,11 @@
- the specified number of seconds. This is to be used if
- your oopses keep scrolling off the screen.
-
-+ extra_latent_entropy
-+ Enable a very simple form of latent entropy extraction
-+ from the first 4GB of memory as the bootmem allocator
-+ passes the memory pages to the buddy allocator.
-+
- pcbit= [HW,ISDN]
-
- pcd. [PARIDE]
-diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index e014e6df1f39..965d49be78ed 100644
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -70,6 +70,7 @@
- #include <linux/psi.h>
- #include <linux/padata.h>
- #include <linux/khugepaged.h>
-+#include <linux/random.h>
-
- #include <asm/sections.h>
- #include <asm/tlbflush.h>
-@@ -136,6 +137,15 @@ struct pcpu_drain {
- static DEFINE_MUTEX(pcpu_drain_mutex);
- static DEFINE_PER_CPU(struct pcpu_drain, pcpu_drain);
-
-+bool __meminitdata extra_latent_entropy;
-+
-+static int __init setup_extra_latent_entropy(char *str)
-+{
-+ extra_latent_entropy = true;
-+ return 0;
-+}
-+early_param("extra_latent_entropy", setup_extra_latent_entropy);
-+
- #ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
- volatile unsigned long latent_entropy __latent_entropy;
- EXPORT_SYMBOL(latent_entropy);
-@@ -1549,6 +1559,21 @@ void __free_pages_core(struct page *page, unsigned int order)
- __ClearPageReserved(p);
- set_page_count(p, 0);
-
-+ if (extra_latent_entropy && !PageHighMem(page) && page_to_pfn(page) < 0x100000) {
-+ unsigned long hash = 0;
-+ size_t index, end = PAGE_SIZE * nr_pages / sizeof hash;
-+ const unsigned long *data = lowmem_page_address(page);
-+
-+ for (index = 0; index < end; index++)
-+ hash ^= hash + data[index];
-+#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
-+ latent_entropy ^= hash;
-+ add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy));
-+#else
-+ add_device_randomness((const void *)&hash, sizeof(hash));
-+#endif
-+ }
-+
- atomic_long_add(nr_pages, &page_zone(page)->managed_pages);
-
- /*
-diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig
-index ae19fb0243b9..ad78375ece5e 100644
---- a/scripts/gcc-plugins/Kconfig
-+++ b/scripts/gcc-plugins/Kconfig
-@@ -53,6 +53,11 @@ config GCC_PLUGIN_LATENT_ENTROPY
- is some slowdown of the boot process (about 0.5%) and fork and
- irq processing.
-
-+ When extra_latent_entropy is passed on the kernel command line,
-+ entropy will be extracted from up to the first 4GB of RAM while the
-+ runtime memory allocator is being initialized. This costs even more
-+ slowdown of the boot process.
-+
- Note that entropy extracted this way is not cryptographically
- secure!
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0076-ata-avoid-null-pointer-dereference-on-bug.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0076-ata-avoid-null-pointer-dereference-on-bug.patch
deleted file mode 100644
index 61b25cf9b68a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0076-ata-avoid-null-pointer-dereference-on-bug.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From dc48fdd6bef9d5b8a4c38dd94d800f2df33c4f36 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 15 May 2017 23:45:34 -0400
-Subject: [PATCH 076/113] ata: avoid null pointer dereference on bug
-
-Extracted from PaX.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- drivers/ata/libata-core.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
-index 61c762961ca8..02a83039c25b 100644
---- a/drivers/ata/libata-core.c
-+++ b/drivers/ata/libata-core.c
-@@ -4540,7 +4540,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
- struct ata_port *ap;
- unsigned int tag;
-
-- WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
-+ BUG_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
- ap = qc->ap;
-
- qc->flags = 0;
-@@ -4557,7 +4557,7 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
- struct ata_port *ap;
- struct ata_link *link;
-
-- WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
-+ BUG_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
- WARN_ON_ONCE(!(qc->flags & ATA_QCFLAG_ACTIVE));
- ap = qc->ap;
- link = qc->dev->link;
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0077-sanity-check-for-negative-length-in-nla_memcpy.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0077-sanity-check-for-negative-length-in-nla_memcpy.patch
deleted file mode 100644
index cc497e839d5f..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0077-sanity-check-for-negative-length-in-nla_memcpy.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From cc3ef16a957ba9036fa4c0e1efb8ce643b5b2dec Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 15 May 2017 23:51:12 -0400
-Subject: [PATCH 077/113] sanity check for negative length in nla_memcpy
-
-Extracted from PaX.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- lib/nlattr.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/lib/nlattr.c b/lib/nlattr.c
-index 74019c8ebf6b..c480b4e7ffef 100644
---- a/lib/nlattr.c
-+++ b/lib/nlattr.c
-@@ -778,6 +778,8 @@ int nla_memcpy(void *dest, const struct nlattr *src, int count)
- {
- int minlen = min_t(int, count, nla_len(src));
-
-+ BUG_ON(minlen < 0);
-+
- memcpy(dest, nla_data(src), minlen);
- if (count > minlen)
- memset(dest + minlen, 0, count - minlen);
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0078-add-page-destructor-sanity-check.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0078-add-page-destructor-sanity-check.patch
deleted file mode 100644
index 4b3c0cdb0439..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0078-add-page-destructor-sanity-check.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 09c9b039e5be1eab1a5930f5b8fcc2468f700cdb Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 15 May 2017 23:59:18 -0400
-Subject: [PATCH 078/113] add page destructor sanity check
-
-Taken from the public PaX patches.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-[thibaut.sautereau@ssi.gouv.fr: Restore get_compound_page_dtor()]
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Reviewd-by: Levente Polyak <levente@leventepolyak.net>
----
- include/linux/mm.h | 9 +++++++--
- mm/swap.c | 12 +++++++++++-
- 2 files changed, 18 insertions(+), 3 deletions(-)
-
-diff --git a/include/linux/mm.h b/include/linux/mm.h
-index 746f6d05bd81..a463ffe84eb4 100644
---- a/include/linux/mm.h
-+++ b/include/linux/mm.h
-@@ -894,10 +894,15 @@ static inline void set_compound_page_dtor(struct page *page,
- page[1].compound_dtor = compound_dtor;
- }
-
--static inline void destroy_compound_page(struct page *page)
-+static inline compound_page_dtor *get_compound_page_dtor(struct page *page)
- {
- VM_BUG_ON_PAGE(page[1].compound_dtor >= NR_COMPOUND_DTORS, page);
-- compound_page_dtors[page[1].compound_dtor](page);
-+ return compound_page_dtors[page[1].compound_dtor];
-+}
-+
-+static inline void destroy_compound_page(struct page *page)
-+{
-+ (*get_compound_page_dtor(page))(page);
- }
-
- static inline unsigned int compound_order(struct page *page)
-diff --git a/mm/swap.c b/mm/swap.c
-index 47a47681c86b..762095d95092 100644
---- a/mm/swap.c
-+++ b/mm/swap.c
-@@ -102,6 +102,8 @@ static void __put_single_page(struct page *page)
-
- static void __put_compound_page(struct page *page)
- {
-+ compound_page_dtor *dtor;
-+
- /*
- * __page_cache_release() is supposed to be called for thp, not for
- * hugetlb. This is because hugetlb page does never have PageLRU set
-@@ -110,7 +112,15 @@ static void __put_compound_page(struct page *page)
- */
- if (!PageHuge(page))
- __page_cache_release(page);
-- destroy_compound_page(page);
-+ dtor = get_compound_page_dtor(page);
-+ if (!PageHuge(page))
-+ BUG_ON(dtor != free_compound_page
-+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-+ && dtor != free_transhuge_page
-+#endif
-+ );
-+
-+ (*dtor)(page);
- }
-
- void __put_page(struct page *page)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch
deleted file mode 100644
index f6ea840c797a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0079-PaX-shadow-cr4-sanity-check-essentially-a-revert.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From 0a40e217049884e911b510d7529062716936e561 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 16 May 2017 00:59:48 -0400
-Subject: [PATCH 079/113] PaX shadow cr4 sanity check (essentially a revert)
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- arch/x86/kernel/cpu/common.c | 1 +
- arch/x86/kernel/process.c | 1 +
- arch/x86/mm/tlb.c | 1 +
- 3 files changed, 3 insertions(+)
-
-diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
-index 35ad8480c464..edaeeab9df4b 100644
---- a/arch/x86/kernel/cpu/common.c
-+++ b/arch/x86/kernel/cpu/common.c
-@@ -399,6 +399,7 @@ EXPORT_SYMBOL_GPL(native_write_cr4);
- void cr4_update_irqsoff(unsigned long set, unsigned long clear)
- {
- unsigned long newval, cr4 = this_cpu_read(cpu_tlbstate.cr4);
-+ BUG_ON(cr4 != __read_cr4());
-
- lockdep_assert_irqs_disabled();
-
-diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
-index 145a7ac0c19a..058941e9ae40 100644
---- a/arch/x86/kernel/process.c
-+++ b/arch/x86/kernel/process.c
-@@ -596,6 +596,7 @@ void speculation_ctrl_update_current(void)
- static inline void cr4_toggle_bits_irqsoff(unsigned long mask)
- {
- unsigned long newval, cr4 = this_cpu_read(cpu_tlbstate.cr4);
-+ BUG_ON(cr4 != __read_cr4());
-
- newval = cr4 ^ mask;
- if (newval != cr4) {
-diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
-index 569ac1d57f55..044d88da4aee 100644
---- a/arch/x86/mm/tlb.c
-+++ b/arch/x86/mm/tlb.c
-@@ -1066,6 +1066,7 @@ STATIC_NOPV void native_flush_tlb_global(void)
- raw_local_irq_save(flags);
-
- cr4 = this_cpu_read(cpu_tlbstate.cr4);
-+ BUG_ON(cr4 != __read_cr4());
- /* toggle PGE */
- native_write_cr4(cr4 ^ X86_CR4_PGE);
- /* write old PGE again and flush TLBs */
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0080-add-writable-function-pointer-detection.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0080-add-writable-function-pointer-detection.patch
deleted file mode 100644
index 7bc04533e9fb..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0080-add-writable-function-pointer-detection.patch
+++ /dev/null
@@ -1,98 +0,0 @@
-From 3b29d50f0ec3aa25fd5291acc7a87d8fccfa5731 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 9 Jul 2017 17:53:23 -0400
-Subject: [PATCH 080/113] add writable function pointer detection
-
-Taken from the public PaX patches.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- scripts/mod/modpost.c | 28 +++++++++++++++++++++++++---
- 1 file changed, 25 insertions(+), 3 deletions(-)
-
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index f882ce0d9327..50e9baefc4e7 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -34,6 +34,7 @@ static int external_module = 0;
- static int warn_unresolved = 0;
- /* How a symbol is exported */
- static int sec_mismatch_count = 0;
-+static int writable_fptr_count = 0;
- static int sec_mismatch_fatal = 0;
- /* ignore missing files */
- static int ignore_missing_files;
-@@ -1007,6 +1008,7 @@ enum mismatch {
- ANY_EXIT_TO_ANY_INIT,
- EXPORT_TO_INIT_EXIT,
- EXTABLE_TO_NON_TEXT,
-+ DATA_TO_TEXT
- };
-
- /**
-@@ -1133,6 +1135,12 @@ static const struct sectioncheck sectioncheck[] = {
- .good_tosec = {ALL_TEXT_SECTIONS , NULL},
- .mismatch = EXTABLE_TO_NON_TEXT,
- .handler = extable_mismatch_handler,
-+},
-+/* Do not reference code from writable data */
-+{
-+ .fromsec = { DATA_SECTIONS, NULL },
-+ .bad_tosec = { ALL_TEXT_SECTIONS, NULL },
-+ .mismatch = DATA_TO_TEXT
- }
- };
-
-@@ -1320,10 +1328,10 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
- continue;
- if (!is_valid_name(elf, sym))
- continue;
-- if (sym->st_value == addr)
-- return sym;
- /* Find a symbol nearby - addr are maybe negative */
- d = sym->st_value - addr;
-+ if (d == 0)
-+ return sym;
- if (d < 0)
- d = addr - sym->st_value;
- if (d < distance) {
-@@ -1458,7 +1466,10 @@ static void report_sec_mismatch(const char *modname,
- char *prl_from;
- char *prl_to;
-
-- sec_mismatch_count++;
-+ if (mismatch->mismatch == DATA_TO_TEXT)
-+ writable_fptr_count++;
-+ else
-+ sec_mismatch_count++;
-
- get_pretty_name(from_is_func, &from, &from_p);
- get_pretty_name(to_is_func, &to, &to_p);
-@@ -1580,6 +1591,14 @@ static void report_sec_mismatch(const char *modname,
- fatal("There's a special handler for this mismatch type, "
- "we should never get here.");
- break;
-+ case DATA_TO_TEXT:
-+#if 0
-+ fprintf(stderr,
-+ "The %s %s:%s references\n"
-+ "the %s %s:%s%s\n",
-+ from, fromsec, fromsym, to, tosec, tosym, to_p);
-+#endif
-+ break;
- }
- fprintf(stderr, "\n");
- }
-@@ -2670,6 +2689,9 @@ int main(int argc, char **argv)
- }
-
- free(buf.p);
-+ if (writable_fptr_count)
-+ warn("modpost: Found %d writable function pointer(s).\n",
-+ writable_fptr_count);
-
- return err;
- }
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0081-support-overriding-early-audit-kernel-cmdline.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0081-support-overriding-early-audit-kernel-cmdline.patch
deleted file mode 100644
index 5f5bc2e74d34..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0081-support-overriding-early-audit-kernel-cmdline.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From ee257a5d7142058fad519c3e0c1347641956e49c Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 9 Jul 2017 17:20:29 -0400
-Subject: [PATCH 081/113] support overriding early audit kernel cmdline
-
----
- kernel/audit.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/kernel/audit.c b/kernel/audit.c
-index 68cee3bc8cfe..2059c66f7c9b 100644
---- a/kernel/audit.c
-+++ b/kernel/audit.c
-@@ -1693,6 +1693,9 @@ static int __init audit_enable(char *str)
-
- if (audit_default == AUDIT_OFF)
- audit_initialized = AUDIT_DISABLED;
-+ else if (!audit_ever_enabled)
-+ audit_initialized = AUDIT_UNINITIALIZED;
-+
- if (audit_set_enabled(audit_default))
- pr_err("audit: error setting audit state (%d)\n",
- audit_default);
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch
deleted file mode 100644
index ec7a284f0f06..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0082-FORTIFY_SOURCE-intra-object-overflow-checking.patch
+++ /dev/null
@@ -1,135 +0,0 @@
-From c37790fe2fe6b91ba235235eb730a12f0f97303d Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 3 Jun 2017 17:34:13 -0400
-Subject: [PATCH 082/113] FORTIFY_SOURCE intra-object overflow checking
-
-This adds supporting for detecting buffer overflows from inner objects
-for the fortified string family functions. It's comparable to the
-_FORTIFY_SOURCE=2 feature in glibc with the additional coverage of
-intra-object read overflows for supported functions.
-
-The mem* family functions are left with only the inter-object overflow
-checks as is the case with glibc _FORTIFY_SOURCE=2.
-
-This feature is currently hidden behind CONFIG_EXPERT because it's a lot
-more likely to uncover benign / intended issues and will need a lot of
-runtime testing. It's already useful for finding bugs but it may not yet
-be a good idea to use it for hardening unless panics for benign issues
-are seen as a lesser evil than the vulnerabilities it can catch.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- include/linux/string.h | 26 ++++++++++++++++----------
- security/Kconfig | 10 ++++++++++
- 2 files changed, 26 insertions(+), 10 deletions(-)
-
-diff --git a/include/linux/string.h b/include/linux/string.h
-index b1f3894a0a3e..4c5564a6ad80 100644
---- a/include/linux/string.h
-+++ b/include/linux/string.h
-@@ -264,6 +264,12 @@ void __read_overflow2(void) __compiletime_error("detected read beyond size of ob
- void __read_overflow3(void) __compiletime_error("detected read beyond size of object passed as 3rd parameter");
- void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
-
-+#ifdef CONFIG_FORTIFY_SOURCE_STRICT_STRING
-+#define __string_size(p) __builtin_object_size(p, 1)
-+#else
-+#define __string_size(p) __builtin_object_size(p, 0)
-+#endif
-+
- #if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE)
-
- #ifdef CONFIG_KASAN
-@@ -292,7 +298,7 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size)
-
- __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
- {
-- size_t p_size = __builtin_object_size(p, 0);
-+ size_t p_size = __string_size(p);
- if (__builtin_constant_p(size) && p_size < size)
- __write_overflow();
- if (p_size < size)
-@@ -302,7 +308,7 @@ __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
-
- __FORTIFY_INLINE char *strcat(char *p, const char *q)
- {
-- size_t p_size = __builtin_object_size(p, 0);
-+ size_t p_size = __string_size(p);
- if (p_size == (size_t)-1)
- return __underlying_strcat(p, q);
- if (strlcat(p, q, p_size) >= p_size)
-@@ -313,7 +319,7 @@ __FORTIFY_INLINE char *strcat(char *p, const char *q)
- __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
- {
- __kernel_size_t ret;
-- size_t p_size = __builtin_object_size(p, 0);
-+ size_t p_size = __string_size(p);
-
- /* Work around gcc excess stack consumption issue */
- if (p_size == (size_t)-1 ||
-@@ -328,7 +334,7 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
- extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
- __FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen)
- {
-- size_t p_size = __builtin_object_size(p, 0);
-+ size_t p_size = __string_size(p);
- __kernel_size_t ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
- if (p_size <= ret && maxlen != ret)
- fortify_panic(__func__);
-@@ -340,8 +346,8 @@ extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
- __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
- {
- size_t ret;
-- size_t p_size = __builtin_object_size(p, 0);
-- size_t q_size = __builtin_object_size(q, 0);
-+ size_t p_size = __string_size(p);
-+ size_t q_size = __string_size(q);
- if (p_size == (size_t)-1 && q_size == (size_t)-1)
- return __real_strlcpy(p, q, size);
- ret = strlen(q);
-@@ -361,8 +367,8 @@ __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
- __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
- {
- size_t p_len, copy_len;
-- size_t p_size = __builtin_object_size(p, 0);
-- size_t q_size = __builtin_object_size(q, 0);
-+ size_t p_size = __string_size(p);
-+ size_t q_size = __string_size(q);
- if (p_size == (size_t)-1 && q_size == (size_t)-1)
- return __underlying_strncat(p, q, count);
- p_len = strlen(p);
-@@ -475,8 +481,8 @@ __FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp)
- /* defined after fortified strlen and memcpy to reuse them */
- __FORTIFY_INLINE char *strcpy(char *p, const char *q)
- {
-- size_t p_size = __builtin_object_size(p, 0);
-- size_t q_size = __builtin_object_size(q, 0);
-+ size_t p_size = __string_size(p);
-+ size_t q_size = __string_size(q);
- if (p_size == (size_t)-1 && q_size == (size_t)-1)
- return __underlying_strcpy(p, q);
- memcpy(p, q, strlen(q) + 1);
-diff --git a/security/Kconfig b/security/Kconfig
-index 2348ff7d4e1d..f3c995bd79cf 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -208,6 +208,16 @@ config FORTIFY_SOURCE
- Detect overflows of buffers in common string and memory functions
- where the compiler can determine and validate the buffer sizes.
-
-+config FORTIFY_SOURCE_STRICT_STRING
-+ bool "Harden common functions against buffer overflows"
-+ depends on FORTIFY_SOURCE
-+ depends on EXPERT
-+ help
-+ Perform stricter overflow checks catching overflows within objects
-+ for common C string functions rather than only between objects.
-+
-+ This is not yet intended for production use, only bug finding.
-+
- config STATIC_USERMODEHELPER
- bool "Force all usermode helper calls through a single binary"
- help
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch
deleted file mode 100644
index a257b1d1ffb6..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0083-Revert-mm-revert-x86_64-and-arm64-ELF_ET_DYN_BASE-ba.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From 4da4039518f44bc90e4974e4651126c8b05e780e Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sat, 26 Aug 2017 20:16:03 -0400
-Subject: [PATCH 083/113] Revert "mm: revert x86_64 and arm64 ELF_ET_DYN_BASE
- base changes"
-
-This reverts commit aab425db4279aeb83b7911693f0cccbd3644c9fd.
----
- arch/arm64/include/asm/elf.h | 8 ++------
- arch/x86/include/asm/elf.h | 4 ++--
- 2 files changed, 4 insertions(+), 8 deletions(-)
-
-diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
-index 8d1c8dcb87fd..26d27c7a2c2e 100644
---- a/arch/arm64/include/asm/elf.h
-+++ b/arch/arm64/include/asm/elf.h
-@@ -124,14 +124,10 @@
-
- /*
- * This is the base location for PIE (ET_DYN with INTERP) loads. On
-- * 64-bit, this is above 4GB to leave the entire 32-bit address
-+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
- * space open for things that want to use the area for 32-bit pointers.
- */
--#ifdef CONFIG_ARM64_FORCE_52BIT
--#define ELF_ET_DYN_BASE (2 * TASK_SIZE_64 / 3)
--#else
--#define ELF_ET_DYN_BASE (2 * DEFAULT_MAP_WINDOW_64 / 3)
--#endif /* CONFIG_ARM64_FORCE_52BIT */
-+#define ELF_ET_DYN_BASE 0x100000000UL
-
- #ifndef __ASSEMBLY__
-
-diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
-index b9a5d488f1a5..b55054566ece 100644
---- a/arch/x86/include/asm/elf.h
-+++ b/arch/x86/include/asm/elf.h
-@@ -246,11 +246,11 @@ extern int force_personality32;
-
- /*
- * This is the base location for PIE (ET_DYN with INTERP) loads. On
-- * 64-bit, this is above 4GB to leave the entire 32-bit address
-+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
- * space open for things that want to use the area for 32-bit pointers.
- */
- #define ELF_ET_DYN_BASE (mmap_is_ia32() ? 0x000400000UL : \
-- (DEFAULT_MAP_WINDOW / 3 * 2))
-+ 0x100000000UL)
-
- /* This yields a mask that user programs can use to figure out what
- instruction set this CPU supports. This could be done in user space,
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch
deleted file mode 100644
index c37dab0bb349..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0084-x86_64-move-vdso-to-mmap-region-from-stack-region.patch
+++ /dev/null
@@ -1,118 +0,0 @@
-From 1f403103506f1a23a60a3325552a457493ee8de2 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 11 May 2017 16:52:00 -0400
-Subject: [PATCH 084/113] x86_64: move vdso to mmap region from stack region
-
-This removes the only executable code from the stack region and gives
-the vdso the same randomized base as other mmap mappings including the
-linker and other shared objects. It results in a sane amount of entropy
-being provided and there's little to no advantage in separating this
-from the existing executable code there.
-
-It's sensible for userspace to reserve the initial mmap base as a region
-for executable code with a random gap for other mmap allocations, along
-with providing randomization within that region. However, there isn't
-much the kernel can do to help due to how dynamic linkers load the
-shared objects.
-
-This was extracted from the PaX RANDMMAP feature.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/entry/vdso/vma.c | 48 +-----------------------------------
- arch/x86/include/asm/elf.h | 1 -
- arch/x86/kernel/sys_x86_64.c | 7 ------
- 3 files changed, 1 insertion(+), 55 deletions(-)
-
-diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
-index 9185cb1d13b9..543912071557 100644
---- a/arch/x86/entry/vdso/vma.c
-+++ b/arch/x86/entry/vdso/vma.c
-@@ -315,55 +315,9 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr)
- }
-
- #ifdef CONFIG_X86_64
--/*
-- * Put the vdso above the (randomized) stack with another randomized
-- * offset. This way there is no hole in the middle of address space.
-- * To save memory make sure it is still in the same PTE as the stack
-- * top. This doesn't give that many random bits.
-- *
-- * Note that this algorithm is imperfect: the distribution of the vdso
-- * start address within a PMD is biased toward the end.
-- *
-- * Only used for the 64-bit and x32 vdsos.
-- */
--static unsigned long vdso_addr(unsigned long start, unsigned len)
--{
-- unsigned long addr, end;
-- unsigned offset;
--
-- /*
-- * Round up the start address. It can start out unaligned as a result
-- * of stack start randomization.
-- */
-- start = PAGE_ALIGN(start);
--
-- /* Round the lowest possible end address up to a PMD boundary. */
-- end = (start + len + PMD_SIZE - 1) & PMD_MASK;
-- if (end >= TASK_SIZE_MAX)
-- end = TASK_SIZE_MAX;
-- end -= len;
--
-- if (end > start) {
-- offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
-- addr = start + (offset << PAGE_SHIFT);
-- } else {
-- addr = start;
-- }
--
-- /*
-- * Forcibly align the final address in case we have a hardware
-- * issue that requires alignment for performance reasons.
-- */
-- addr = align_vdso_addr(addr);
--
-- return addr;
--}
--
- static int map_vdso_randomized(const struct vdso_image *image)
- {
-- unsigned long addr = vdso_addr(current->mm->start_stack, image->size-image->sym_vvar_start);
--
-- return map_vdso(image, addr);
-+ return map_vdso(image, 0);
- }
- #endif
-
-diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
-index b55054566ece..58292600112d 100644
---- a/arch/x86/include/asm/elf.h
-+++ b/arch/x86/include/asm/elf.h
-@@ -398,5 +398,4 @@ struct va_alignment {
- } ____cacheline_aligned;
-
- extern struct va_alignment va_align;
--extern unsigned long align_vdso_addr(unsigned long);
- #endif /* _ASM_X86_ELF_H */
-diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
-index 504fa5425bce..c4e35a3b3733 100644
---- a/arch/x86/kernel/sys_x86_64.c
-+++ b/arch/x86/kernel/sys_x86_64.c
-@@ -52,13 +52,6 @@ static unsigned long get_align_bits(void)
- return va_align.bits & get_align_mask();
- }
-
--unsigned long align_vdso_addr(unsigned long addr)
--{
-- unsigned long align_mask = get_align_mask();
-- addr = (addr + align_mask) & ~align_mask;
-- return addr | get_align_bits();
--}
--
- static int __init control_va_addr_alignment(char *str)
- {
- /* guard against enabling this on other CPU families */
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch
deleted file mode 100644
index 652e6a2eaef1..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0085-x86-determine-stack-entropy-based-on-mmap-entropy.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 7886dd7cdefed4f32ab1c17df880462622f04a70 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 21 May 2017 20:30:44 -0400
-Subject: [PATCH 085/113] x86: determine stack entropy based on mmap entropy
-
-Stack mapping entropy is currently hard-wired to 11 bits of entropy on
-32-bit and 22 bits of entropy on 64-bit. The stack itself gains an extra
-8 bits of entropy from lower bit randomization within 16 byte alignment
-constraints. The argument block could have all lower bits randomized but
-it currently only gets the mapping randomization.
-
-Rather than hard-wiring values this switches to using the mmap entropy
-configuration like the mmap base and executable base, resulting in a
-range of 8 to 16 bits on 32-bit and 28 to 32 bits on 64-bit depending on
-kernel configuration and overridable via the sysctl entries.
-
-It's worth noting that since these kernel configuration options default
-to the minimum supported entropy value, the entropy on 32-bit will drop
-from 11 to 8 bits for builds using the defaults. However, following the
-configuration seems like the right thing to do regardless. At the very
-least, changing the defaults for COMPAT (32-bit processes on 64-bit)
-should be considered due to the larger address space compared to real
-32-bit.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/include/asm/elf.h | 10 +++++++---
- 1 file changed, 7 insertions(+), 3 deletions(-)
-
-diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
-index 58292600112d..608cca19cf8c 100644
---- a/arch/x86/include/asm/elf.h
-+++ b/arch/x86/include/asm/elf.h
-@@ -330,8 +330,8 @@ extern bool mmap_address_hint_valid(unsigned long addr, unsigned long len);
-
- #ifdef CONFIG_X86_32
-
--#define __STACK_RND_MASK(is32bit) (0x7ff)
--#define STACK_RND_MASK (0x7ff)
-+#define __STACK_RND_MASK(is32bit) ((1UL << mmap_rnd_bits) - 1)
-+#define STACK_RND_MASK ((1UL << mmap_rnd_bits) - 1)
-
- #define ARCH_DLINFO ARCH_DLINFO_IA32
-
-@@ -340,7 +340,11 @@ extern bool mmap_address_hint_valid(unsigned long addr, unsigned long len);
- #else /* CONFIG_X86_32 */
-
- /* 1GB for 64bit, 8MB for 32bit */
--#define __STACK_RND_MASK(is32bit) ((is32bit) ? 0x7ff : 0x3fffff)
-+#ifdef CONFIG_COMPAT
-+#define __STACK_RND_MASK(is32bit) ((is32bit) ? (1UL << mmap_rnd_compat_bits) - 1 : (1UL << mmap_rnd_bits) - 1)
-+#else
-+#define __STACK_RND_MASK(is32bit) ((1UL << mmap_rnd_bits) - 1)
-+#endif
- #define STACK_RND_MASK __STACK_RND_MASK(mmap_is_ia32())
-
- #define ARCH_DLINFO \
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch
deleted file mode 100644
index f814b346de7c..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0086-arm64-determine-stack-entropy-based-on-mmap-entropy.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 7a9997243a77003f2741faa992b0889969915337 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Mon, 22 May 2017 05:06:20 -0400
-Subject: [PATCH 086/113] arm64: determine stack entropy based on mmap entropy
-
-Stack mapping entropy is currently hard-wired to 11 bits of entropy on
-32-bit and 18 bits of entropy on 64-bit. The stack itself gains an extra
-8 bits of entropy from lower bit randomization within 16 byte alignment
-constraints. The argument block could have all lower bits randomized but
-it currently only gets the mapping randomization.
-
-Rather than hard-wiring values this switches to using the mmap entropy
-configuration like the mmap base and executable base, resulting in a
-range of 8 to 16 bits on 32-bit and 18 to 24 bits on 64-bit (with 4k
-pages and 3 level page tables) depending on kernel configuration and
-overridable via the sysctl entries.
-
-It's worth noting that since these kernel configuration options default
-to the minimum supported entropy value, the entropy on 32-bit will drop
-from 11 to 8 bits for builds using the defaults. However, following the
-configuration seems like the right thing to do regardless. At the very
-least, changing the defaults for COMPAT (32-bit processes on 64-bit)
-should be considered due to the larger address space compared to real
-32-bit.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/arm64/include/asm/elf.h | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
-index 26d27c7a2c2e..32c1609a1158 100644
---- a/arch/arm64/include/asm/elf.h
-+++ b/arch/arm64/include/asm/elf.h
-@@ -185,10 +185,10 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
- /* 1GB of VA */
- #ifdef CONFIG_COMPAT
- #define STACK_RND_MASK (test_thread_flag(TIF_32BIT) ? \
-- 0x7ff >> (PAGE_SHIFT - 12) : \
-- 0x3ffff >> (PAGE_SHIFT - 12))
-+ ((1UL << mmap_rnd_compat_bits) - 1) >> (PAGE_SHIFT - 12) : \
-+ ((1UL << mmap_rnd_bits) - 1) >> (PAGE_SHIFT - 12))
- #else
--#define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12))
-+#define STACK_RND_MASK (((1UL << mmap_rnd_bits) - 1) >> (PAGE_SHIFT - 12))
- #endif
-
- #ifdef __AARCH64EB__
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0087-randomize-lower-bits-of-the-argument-block.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0087-randomize-lower-bits-of-the-argument-block.patch
deleted file mode 100644
index dc6a007b7a22..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0087-randomize-lower-bits-of-the-argument-block.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From ec8a6342397f4d75cea932e163a02d913d350b57 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 11 May 2017 16:02:49 -0400
-Subject: [PATCH 087/113] randomize lower bits of the argument block
-
-This was based on the PaX RANDUSTACK feature in grsecurity, where all of
-the lower bits are randomized. PaX keeps 16-byte alignment.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
-[levente@leventepolyak.net: do not randomize with ADDR_NO_RANDOMIZE personality]
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- fs/exec.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/fs/exec.c b/fs/exec.c
-index ca89e0e3ef10..d2a03d32e195 100644
---- a/fs/exec.c
-+++ b/fs/exec.c
-@@ -34,6 +34,7 @@
- #include <linux/swap.h>
- #include <linux/string.h>
- #include <linux/init.h>
-+#include <linux/sched.h>
- #include <linux/sched/mm.h>
- #include <linux/sched/coredump.h>
- #include <linux/sched/signal.h>
-@@ -64,6 +65,7 @@
- #include <linux/compat.h>
- #include <linux/vmalloc.h>
- #include <linux/io_uring.h>
-+#include <linux/random.h>
-
- #include <linux/uaccess.h>
- #include <asm/mmu_context.h>
-@@ -280,6 +282,8 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
- mm->stack_vm = mm->total_vm = 1;
- mmap_write_unlock(mm);
- bprm->p = vma->vm_end - sizeof(void *);
-+ if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-+ bprm->p ^= get_random_int() & ~PAGE_MASK;
- return 0;
- err:
- mmap_write_unlock(mm);
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0088-x86_64-match-arm64-brk-randomization-entropy.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0088-x86_64-match-arm64-brk-randomization-entropy.patch
deleted file mode 100644
index 4dd084e86825..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0088-x86_64-match-arm64-brk-randomization-entropy.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 7c462ca9c247669cf7001b339537714537ab99c6 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 30 May 2017 07:19:48 -0400
-Subject: [PATCH 088/113] x86_64: match arm64 brk randomization entropy
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/kernel/process.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
-index 058941e9ae40..61460d55dd72 100644
---- a/arch/x86/kernel/process.c
-+++ b/arch/x86/kernel/process.c
-@@ -43,6 +43,8 @@
- #include <asm/io_bitmap.h>
- #include <asm/proto.h>
- #include <asm/frame.h>
-+#include <asm/elf.h>
-+#include <linux/sizes.h>
-
- #include "process.h"
-
-@@ -906,7 +908,10 @@ unsigned long arch_align_stack(unsigned long sp)
-
- unsigned long arch_randomize_brk(struct mm_struct *mm)
- {
-- return randomize_page(mm->brk, 0x02000000);
-+ if (mmap_is_ia32())
-+ return randomize_page(mm->brk, SZ_32M);
-+ else
-+ return randomize_page(mm->brk, SZ_1G);
- }
-
- /*
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0089-support-randomizing-the-lower-bits-of-brk.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0089-support-randomizing-the-lower-bits-of-brk.patch
deleted file mode 100644
index 74521ae0abfc..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0089-support-randomizing-the-lower-bits-of-brk.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 3a786b13d3d3eaca44a116a539f8a465bae0a169 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 30 May 2017 18:03:30 -0400
-Subject: [PATCH 089/113] support randomizing the lower bits of brk
-
-This adds support for arch_randomize_brk implementations not performing
-page alignment in order to randomize the lower bits of the brk heap.
-
-This idea is taken from PaX but the approach is different. This reuses
-the existing code and avoids forcing early creation of the heap mapping,
-avoiding mapping it if it's not used which is the case with many modern
-allocators based solely on mmap.
-
-The malloc implementation can be relied upon to align this as needed to
-the requirements it has, so using 16 byte alignment here is unnecessary.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/mmap.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/mm/mmap.c b/mm/mmap.c
-index 5c8b4485860d..0e26c225bb53 100644
---- a/mm/mmap.c
-+++ b/mm/mmap.c
-@@ -231,6 +231,13 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
-
- newbrk = PAGE_ALIGN(brk);
- oldbrk = PAGE_ALIGN(mm->brk);
-+ /* properly handle unaligned min_brk as an empty heap */
-+ if (min_brk & ~PAGE_MASK) {
-+ if (brk == min_brk)
-+ newbrk -= PAGE_SIZE;
-+ if (mm->brk == min_brk)
-+ oldbrk -= PAGE_SIZE;
-+ }
- if (oldbrk == newbrk) {
- mm->brk = brk;
- goto success;
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0090-mm-randomize-lower-bits-of-brk.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0090-mm-randomize-lower-bits-of-brk.patch
deleted file mode 100644
index 87d68eff987b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0090-mm-randomize-lower-bits-of-brk.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 4b1f2c7238a4b5c6c6fbb4cdd43686f23e5c0672 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 1 Jun 2017 03:22:38 -0400
-Subject: [PATCH 090/113] mm: randomize lower bits of brk
-
-Per PaX, but for this alternate brk randomization approach.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/util.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/mm/util.c b/mm/util.c
-index 4ddb6e186dd5..4ca72f952329 100644
---- a/mm/util.c
-+++ b/mm/util.c
-@@ -336,9 +336,9 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
- {
- /* Is the current task 32bit ? */
- if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task())
-- return randomize_page(mm->brk, SZ_32M);
-+ return mm->brk + get_random_long() % SZ_32M;
-
-- return randomize_page(mm->brk, SZ_1G);
-+ return mm->brk + get_random_long() % SZ_1G;
- }
-
- unsigned long arch_mmap_rnd(void)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0091-x86-randomize-lower-bits-of-brk.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0091-x86-randomize-lower-bits-of-brk.patch
deleted file mode 100644
index e298285bef98..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0091-x86-randomize-lower-bits-of-brk.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From ee36f8847014ce9c6f8b2ae7ecf582fa7e9212f1 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 1 Jun 2017 03:23:06 -0400
-Subject: [PATCH 091/113] x86: randomize lower bits of brk
-
-Per PaX, but for this alternate brk randomization approach.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/kernel/process.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
-index 61460d55dd72..0d4c3887229d 100644
---- a/arch/x86/kernel/process.c
-+++ b/arch/x86/kernel/process.c
-@@ -909,9 +909,9 @@ unsigned long arch_align_stack(unsigned long sp)
- unsigned long arch_randomize_brk(struct mm_struct *mm)
- {
- if (mmap_is_ia32())
-- return randomize_page(mm->brk, SZ_32M);
-+ return mm->brk + get_random_long() % SZ_32M;
- else
-- return randomize_page(mm->brk, SZ_1G);
-+ return mm->brk + get_random_long() % SZ_1G;
- }
-
- /*
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0092-mm-guarantee-brk-gap-is-at-least-one-page.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0092-mm-guarantee-brk-gap-is-at-least-one-page.patch
deleted file mode 100644
index b0c754847efd..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0092-mm-guarantee-brk-gap-is-at-least-one-page.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From c8d91234889dc8f16c7b65ad5c82006705f1639f Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 1 Jun 2017 03:23:39 -0400
-Subject: [PATCH 092/113] mm: guarantee brk gap is at least one page
-
-Per PaX, but for this alternate brk randomization approach.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- mm/util.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/mm/util.c b/mm/util.c
-index 4ca72f952329..62ed34dfceb7 100644
---- a/mm/util.c
-+++ b/mm/util.c
-@@ -336,9 +336,9 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
- {
- /* Is the current task 32bit ? */
- if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task())
-- return mm->brk + get_random_long() % SZ_32M;
-+ return mm->brk + get_random_long() % SZ_32M + PAGE_SIZE;
-
-- return mm->brk + get_random_long() % SZ_1G;
-+ return mm->brk + get_random_long() % SZ_1G + PAGE_SIZE;
- }
-
- unsigned long arch_mmap_rnd(void)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0093-x86-guarantee-brk-gap-is-at-least-one-page.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0093-x86-guarantee-brk-gap-is-at-least-one-page.patch
deleted file mode 100644
index bfa1ee7ebd01..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0093-x86-guarantee-brk-gap-is-at-least-one-page.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 917039f2905ed6432e56b444b36803d853de1b47 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Thu, 1 Jun 2017 03:23:48 -0400
-Subject: [PATCH 093/113] x86: guarantee brk gap is at least one page
-
-Per PaX, but for this alternate brk randomization approach.
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- arch/x86/kernel/process.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
-index 0d4c3887229d..161e25d02fd5 100644
---- a/arch/x86/kernel/process.c
-+++ b/arch/x86/kernel/process.c
-@@ -909,9 +909,9 @@ unsigned long arch_align_stack(unsigned long sp)
- unsigned long arch_randomize_brk(struct mm_struct *mm)
- {
- if (mmap_is_ia32())
-- return mm->brk + get_random_long() % SZ_32M;
-+ return mm->brk + get_random_long() % SZ_32M + PAGE_SIZE;
- else
-- return mm->brk + get_random_long() % SZ_1G;
-+ return mm->brk + get_random_long() % SZ_1G + PAGE_SIZE;
- }
-
- /*
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0094-x86_64-bound-mmap-between-legacy-modern-bases.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0094-x86_64-bound-mmap-between-legacy-modern-bases.patch
deleted file mode 100644
index efa4e279dc40..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0094-x86_64-bound-mmap-between-legacy-modern-bases.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 561c6c6469dd335b4e7de5932a115dd2cb77ad34 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 4 Jul 2017 14:50:54 -0400
-Subject: [PATCH 094/113] x86_64: bound mmap between legacy/modern bases
-
----
- arch/x86/kernel/sys_x86_64.c | 7 ++-----
- 1 file changed, 2 insertions(+), 5 deletions(-)
-
-diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
-index c4e35a3b3733..e30ec4c750d1 100644
---- a/arch/x86/kernel/sys_x86_64.c
-+++ b/arch/x86/kernel/sys_x86_64.c
-@@ -113,10 +113,7 @@ static void find_start_end(unsigned long addr, unsigned long flags,
- }
-
- *begin = get_mmap_base(1);
-- if (in_32bit_syscall())
-- *end = task_size_32bit();
-- else
-- *end = task_size_64bit(addr > DEFAULT_MAP_WINDOW);
-+ *end = get_mmap_base(0);
- }
-
- unsigned long
-@@ -193,7 +190,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
-
- info.flags = VM_UNMAPPED_AREA_TOPDOWN;
- info.length = len;
-- info.low_limit = PAGE_SIZE;
-+ info.low_limit = get_mmap_base(1);
- info.high_limit = get_mmap_base(0);
-
- /*
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0095-restrict-device-timing-side-channels.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0095-restrict-device-timing-side-channels.patch
deleted file mode 100644
index f2f4563b237e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0095-restrict-device-timing-side-channels.patch
+++ /dev/null
@@ -1,174 +0,0 @@
-From 776a04a1a0d87c4dfb815d4a272617ed9109ecd7 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 16 May 2017 18:26:10 -0400
-Subject: [PATCH 095/113] restrict device timing side channels
-
-Based on the public grsecurity patches.
-
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- fs/inode.c | 4 ++++
- fs/stat.c | 20 +++++++++++++++-----
- include/linux/capability.h | 5 +++++
- include/linux/fs.h | 11 +++++++++++
- include/linux/fsnotify.h | 4 ++++
- kernel/capability.c | 6 ++++++
- kernel/sysctl.c | 9 +++++++++
- 7 files changed, 54 insertions(+), 5 deletions(-)
-
-diff --git a/fs/inode.c b/fs/inode.c
-index 5eea9912a0b9..f86f383a3e1d 100644
---- a/fs/inode.c
-+++ b/fs/inode.c
-@@ -116,6 +116,10 @@ int proc_nr_inodes(struct ctl_table *table, int write,
- }
- #endif
-
-+/* sysctl */
-+int device_sidechannel_restrict __read_mostly = 1;
-+EXPORT_SYMBOL(device_sidechannel_restrict);
-+
- static int no_open(struct inode *inode, struct file *file)
- {
- return -ENXIO;
-diff --git a/fs/stat.c b/fs/stat.c
-index dacecdda2e79..14173d0f777d 100644
---- a/fs/stat.c
-+++ b/fs/stat.c
-@@ -43,8 +43,13 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
- stat->gid = inode->i_gid;
- stat->rdev = inode->i_rdev;
- stat->size = i_size_read(inode);
-- stat->atime = inode->i_atime;
-- stat->mtime = inode->i_mtime;
-+ if (is_sidechannel_device(inode) && !capable_noaudit(CAP_MKNOD)) {
-+ stat->atime = inode->i_ctime;
-+ stat->mtime = inode->i_ctime;
-+ } else {
-+ stat->atime = inode->i_atime;
-+ stat->mtime = inode->i_mtime;
-+ }
- stat->ctime = inode->i_ctime;
- stat->blksize = i_blocksize(inode);
- stat->blocks = inode->i_blocks;
-@@ -83,9 +88,14 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
- if (IS_DAX(inode))
- stat->attributes |= STATX_ATTR_DAX;
-
-- if (inode->i_op->getattr)
-- return inode->i_op->getattr(path, stat, request_mask,
-- query_flags);
-+ if (inode->i_op->getattr) {
-+ int retval = inode->i_op->getattr(path, stat, request_mask, query_flags);
-+ if (!retval && is_sidechannel_device(inode) && !capable_noaudit(CAP_MKNOD)) {
-+ stat->atime = stat->ctime;
-+ stat->mtime = stat->ctime;
-+ }
-+ return retval;
-+ }
-
- generic_fillattr(inode, stat);
- return 0;
-diff --git a/include/linux/capability.h b/include/linux/capability.h
-index 1e7fe311cabe..a5b6d4c9acf5 100644
---- a/include/linux/capability.h
-+++ b/include/linux/capability.h
-@@ -208,6 +208,7 @@ extern bool has_capability_noaudit(struct task_struct *t, int cap);
- extern bool has_ns_capability_noaudit(struct task_struct *t,
- struct user_namespace *ns, int cap);
- extern bool capable(int cap);
-+extern bool capable_noaudit(int cap);
- extern bool ns_capable(struct user_namespace *ns, int cap);
- extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
- extern bool ns_capable_setid(struct user_namespace *ns, int cap);
-@@ -234,6 +235,10 @@ static inline bool capable(int cap)
- {
- return true;
- }
-+static inline bool capable_noaudit(int cap)
-+{
-+ return true;
-+}
- static inline bool ns_capable(struct user_namespace *ns, int cap)
- {
- return true;
-diff --git a/include/linux/fs.h b/include/linux/fs.h
-index 8bde32cf9711..83d50b0a2a18 100644
---- a/include/linux/fs.h
-+++ b/include/linux/fs.h
-@@ -3475,4 +3475,15 @@ static inline int inode_drain_writes(struct inode *inode)
- return filemap_write_and_wait(inode->i_mapping);
- }
-
-+extern int device_sidechannel_restrict;
-+
-+static inline bool is_sidechannel_device(const struct inode *inode)
-+{
-+ umode_t mode;
-+ if (!device_sidechannel_restrict)
-+ return false;
-+ mode = inode->i_mode;
-+ return ((S_ISCHR(mode) || S_ISBLK(mode)) && (mode & (S_IROTH | S_IWOTH)));
-+}
-+
- #endif /* _LINUX_FS_H */
-diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
-index f8acddcf54fb..7b109980327f 100644
---- a/include/linux/fsnotify.h
-+++ b/include/linux/fsnotify.h
-@@ -83,10 +83,14 @@ static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask)
- static inline int fsnotify_file(struct file *file, __u32 mask)
- {
- const struct path *path = &file->f_path;
-+ struct inode *inode = file_inode(file);
-
- if (file->f_mode & FMODE_NONOTIFY)
- return 0;
-
-+ if (mask & (FS_ACCESS | FS_MODIFY) && is_sidechannel_device(inode))
-+ return 0;
-+
- return fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH);
- }
-
-diff --git a/kernel/capability.c b/kernel/capability.c
-index de7eac903a2a..5602178f3d21 100644
---- a/kernel/capability.c
-+++ b/kernel/capability.c
-@@ -449,6 +449,12 @@ bool capable(int cap)
- return ns_capable(&init_user_ns, cap);
- }
- EXPORT_SYMBOL(capable);
-+
-+bool capable_noaudit(int cap)
-+{
-+ return ns_capable_noaudit(&init_user_ns, cap);
-+}
-+EXPORT_SYMBOL(capable_noaudit);
- #endif /* CONFIG_MULTIUSER */
-
- /**
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index fccf24a08c8a..7fda9f61ea1a 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -2272,6 +2272,15 @@ static struct ctl_table kern_table[] = {
- .extra2 = &two,
- },
- #endif
-+ {
-+ .procname = "device_sidechannel_restrict",
-+ .data = &device_sidechannel_restrict,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax_sysadmin,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
- {
- .procname = "ngroups_max",
- .data = &ngroups_max,
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch
deleted file mode 100644
index 5db5a7e5ea97..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0096-sysctl-expose-proc_dointvec_minmax_sysadmin-as-API-f.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From 245008adfd6a5dec75ee9dc30eab0f0b6fc3cfab Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Sun, 6 Sep 2020 20:28:32 +0200
-Subject: [PATCH 096/113] sysctl: expose proc_dointvec_minmax_sysadmin as API
- function
-
-Orthogonal to the other sysctl proc functions expose the variant that is
-checking CAP_SYS_ADMIN on write for consumption in external subsystem's
-sysctl tables.
-
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- include/linux/sysctl.h | 2 ++
- kernel/sysctl.c | 31 ++++++++++++++++++++++++++++---
- 2 files changed, 30 insertions(+), 3 deletions(-)
-
-diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
-index 51298a4f4623..b835c57330f2 100644
---- a/include/linux/sysctl.h
-+++ b/include/linux/sysctl.h
-@@ -53,6 +53,8 @@ int proc_douintvec(struct ctl_table *, int, void *, size_t *, loff_t *);
- int proc_dointvec_minmax(struct ctl_table *, int, void *, size_t *, loff_t *);
- int proc_douintvec_minmax(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos);
-+int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
-+ void *buffer, size_t *lenp, loff_t *ppos);
- int proc_dointvec_jiffies(struct ctl_table *, int, void *, size_t *, loff_t *);
- int proc_dointvec_userhz_jiffies(struct ctl_table *, int, void *, size_t *,
- loff_t *);
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index 7fda9f61ea1a..13b619e46ade 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -890,8 +890,27 @@ static int proc_taint(struct ctl_table *table, int write,
- return err;
- }
-
--#ifdef CONFIG_PRINTK
--static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
-+/**
-+ * proc_dointvec_minmax_sysadmin - read a vector of integers with min/max values
-+ * checking CAP_SYS_ADMIN on write
-+ * @table: the sysctl table
-+ * @write: %TRUE if this is a write to the sysctl file
-+ * @buffer: the user buffer
-+ * @lenp: the size of the user buffer
-+ * @ppos: file position
-+ *
-+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
-+ * values from/to the user buffer, treated as an ASCII string.
-+ *
-+ * This routine will ensure the values are within the range specified by
-+ * table->extra1 (min) and table->extra2 (max).
-+ *
-+ * Writing is only allowed when root has CAP_SYS_ADMIN.
-+ *
-+ * Returns 0 on success, -EPERM on permission failure or -EINVAL on write
-+ * when the range check fails.
-+ */
-+int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
- {
- if (write && !capable(CAP_SYS_ADMIN))
-@@ -899,7 +918,6 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
-
- return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
- }
--#endif
-
- /**
- * struct do_proc_dointvec_minmax_conv_param - proc_dointvec_minmax() range checking structure
-@@ -1585,6 +1603,12 @@ int proc_douintvec_minmax(struct ctl_table *table, int write,
- return -ENOSYS;
- }
-
-+int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
-+ void *buffer, size_t *lenp, loff_t *ppos)
-+{
-+ return -ENOSYS;
-+}
-+
- int proc_dointvec_jiffies(struct ctl_table *table, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
- {
-@@ -3436,6 +3460,7 @@ EXPORT_SYMBOL(proc_douintvec);
- EXPORT_SYMBOL(proc_dointvec_jiffies);
- EXPORT_SYMBOL(proc_dointvec_minmax);
- EXPORT_SYMBOL_GPL(proc_douintvec_minmax);
-+EXPORT_SYMBOL(proc_dointvec_minmax_sysadmin);
- EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
- EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
- EXPORT_SYMBOL(proc_dostring);
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch
deleted file mode 100644
index d6b50c588c33..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0097-usb-add-toggle-for-disabling-newly-added-USB-devices.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-From 474acec9ac886a45771b335fe0a1becc5a7901f1 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Tue, 16 May 2017 17:51:48 -0400
-Subject: [PATCH 097/113] usb: add toggle for disabling newly added USB devices
-
-Based on the public grsecurity patches.
-
-[thibaut.sautereau@ssi.gouv.fr: Adapt to sysctl code refactoring]
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- drivers/usb/core/hub.c | 9 +++++++++
- include/linux/usb.h | 3 +++
- kernel/sysctl.c | 14 ++++++++++++++
- 3 files changed, 26 insertions(+)
-
-diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index 17202b2ee063..9385c745d55e 100644
---- a/drivers/usb/core/hub.c
-+++ b/drivers/usb/core/hub.c
-@@ -5054,6 +5054,9 @@ static int descriptors_changed(struct usb_device *udev,
- return changed;
- }
-
-+/* sysctl */
-+int deny_new_usb __read_mostly = 0;
-+
- static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
- u16 portchange)
- {
-@@ -5114,6 +5117,12 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
- goto done;
- return;
- }
-+
-+ if (deny_new_usb) {
-+ dev_err(&port_dev->dev, "denied insert of USB device on port %d\n", port1);
-+ goto done;
-+ }
-+
- if (hub_is_superspeed(hub->hdev))
- unit_load = 150;
- else
-diff --git a/include/linux/usb.h b/include/linux/usb.h
-index 7d72c4e0713c..8e7549e3012a 100644
---- a/include/linux/usb.h
-+++ b/include/linux/usb.h
-@@ -2035,6 +2035,9 @@ extern void usb_led_activity(enum usb_led_event ev);
- static inline void usb_led_activity(enum usb_led_event ev) {}
- #endif
-
-+/* sysctl */
-+extern int deny_new_usb;
-+
- #endif /* __KERNEL__ */
-
- #endif
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index 13b619e46ade..f867606fbd80 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -106,6 +106,9 @@
- #ifdef CONFIG_USER_NS
- #include <linux/user_namespace.h>
- #endif
-+#if IS_ENABLED(CONFIG_USB)
-+#include <linux/usb.h>
-+#endif
-
- #if defined(CONFIG_SYSCTL)
-
-@@ -2305,6 +2308,17 @@ static struct ctl_table kern_table[] = {
- .extra1 = SYSCTL_ZERO,
- .extra2 = SYSCTL_ONE,
- },
-+#if IS_ENABLED(CONFIG_USB)
-+ {
-+ .procname = "deny_new_usb",
-+ .data = &deny_new_usb,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax_sysadmin,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
-+#endif
- {
- .procname = "ngroups_max",
- .data = &ngroups_max,
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0098-usb-implement-dedicated-subsystem-sysctl-tables.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0098-usb-implement-dedicated-subsystem-sysctl-tables.patch
deleted file mode 100644
index c4cedc8b9bff..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0098-usb-implement-dedicated-subsystem-sysctl-tables.patch
+++ /dev/null
@@ -1,195 +0,0 @@
-From 0772d6cfa20bdf02f474623428e68f9bef338655 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Sun, 6 Sep 2020 21:08:16 +0200
-Subject: [PATCH 098/113] usb: implement dedicated subsystem sysctl tables
-
-This moves the usb related sysctl knobs to an own usb local sysctl table
-in order to clean up the global sysctl as well as allow the knob to be
-exported and referenced appropriately when building the usb components
-as dedicated modules.
-
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- drivers/usb/core/Makefile | 1 +
- drivers/usb/core/hub.c | 3 ---
- drivers/usb/core/sysctl.c | 44 +++++++++++++++++++++++++++++++++++++++
- drivers/usb/core/usb.c | 9 ++++++++
- include/linux/usb.h | 10 ++++++++-
- kernel/sysctl.c | 14 -------------
- 6 files changed, 63 insertions(+), 18 deletions(-)
- create mode 100644 drivers/usb/core/sysctl.c
-
-diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
-index 18e874b0441e..fc7a3a9aa72a 100644
---- a/drivers/usb/core/Makefile
-+++ b/drivers/usb/core/Makefile
-@@ -11,6 +11,7 @@ usbcore-y += phy.o port.o
- usbcore-$(CONFIG_OF) += of.o
- usbcore-$(CONFIG_USB_PCI) += hcd-pci.o
- usbcore-$(CONFIG_ACPI) += usb-acpi.o
-+usbcore-$(CONFIG_SYSCTL) += sysctl.o
-
- obj-$(CONFIG_USB) += usbcore.o
-
-diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index 9385c745d55e..b62b3da81ac4 100644
---- a/drivers/usb/core/hub.c
-+++ b/drivers/usb/core/hub.c
-@@ -5054,9 +5054,6 @@ static int descriptors_changed(struct usb_device *udev,
- return changed;
- }
-
--/* sysctl */
--int deny_new_usb __read_mostly = 0;
--
- static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
- u16 portchange)
- {
-diff --git a/drivers/usb/core/sysctl.c b/drivers/usb/core/sysctl.c
-new file mode 100644
-index 000000000000..3fa188ac8f67
---- /dev/null
-+++ b/drivers/usb/core/sysctl.c
-@@ -0,0 +1,44 @@
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/kmemleak.h>
-+#include <linux/sysctl.h>
-+#include <linux/usb.h>
-+
-+static struct ctl_table usb_table[] = {
-+ {
-+ .procname = "deny_new_usb",
-+ .data = &deny_new_usb,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax_sysadmin,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
-+ { }
-+};
-+
-+static struct ctl_table usb_root_table[] = {
-+ { .procname = "kernel",
-+ .mode = 0555,
-+ .child = usb_table },
-+ { }
-+};
-+
-+static struct ctl_table_header *usb_table_header;
-+
-+int __init usb_init_sysctl(void)
-+{
-+ usb_table_header = register_sysctl_table(usb_root_table);
-+ if (!usb_table_header) {
-+ pr_warn("usb: sysctl registration failed\n");
-+ return -ENOMEM;
-+ }
-+
-+ kmemleak_not_leak(usb_table_header);
-+ return 0;
-+}
-+
-+void usb_exit_sysctl(void)
-+{
-+ unregister_sysctl_table(usb_table_header);
-+}
-diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
-index 9b4ac4415f1a..93b4b798bdcc 100644
---- a/drivers/usb/core/usb.c
-+++ b/drivers/usb/core/usb.c
-@@ -72,6 +72,9 @@ MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
- #define usb_autosuspend_delay 0
- #endif
-
-+int deny_new_usb __read_mostly = 0;
-+EXPORT_SYMBOL(deny_new_usb);
-+
- static bool match_endpoint(struct usb_endpoint_descriptor *epd,
- struct usb_endpoint_descriptor **bulk_in,
- struct usb_endpoint_descriptor **bulk_out,
-@@ -978,6 +981,9 @@ static int __init usb_init(void)
- usb_debugfs_init();
-
- usb_acpi_register();
-+ retval = usb_init_sysctl();
-+ if (retval)
-+ goto sysctl_init_failed;
- retval = bus_register(&usb_bus_type);
- if (retval)
- goto bus_register_failed;
-@@ -1012,6 +1018,8 @@ static int __init usb_init(void)
- bus_notifier_failed:
- bus_unregister(&usb_bus_type);
- bus_register_failed:
-+ usb_exit_sysctl();
-+sysctl_init_failed:
- usb_acpi_unregister();
- usb_debugfs_cleanup();
- out:
-@@ -1035,6 +1043,7 @@ static void __exit usb_exit(void)
- usb_hub_cleanup();
- bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
- bus_unregister(&usb_bus_type);
-+ usb_exit_sysctl();
- usb_acpi_unregister();
- usb_debugfs_cleanup();
- idr_destroy(&usb_bus_idr);
-diff --git a/include/linux/usb.h b/include/linux/usb.h
-index 8e7549e3012a..653265115e56 100644
---- a/include/linux/usb.h
-+++ b/include/linux/usb.h
-@@ -2035,8 +2035,16 @@ extern void usb_led_activity(enum usb_led_event ev);
- static inline void usb_led_activity(enum usb_led_event ev) {}
- #endif
-
--/* sysctl */
-+/* sysctl.c */
- extern int deny_new_usb;
-+#ifdef CONFIG_SYSCTL
-+extern int usb_init_sysctl(void);
-+extern void usb_exit_sysctl(void);
-+#else
-+static inline int usb_init_sysctl(void) { return 0; }
-+static inline void usb_exit_sysctl(void) { }
-+#endif /* CONFIG_SYSCTL */
-+
-
- #endif /* __KERNEL__ */
-
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index f867606fbd80..13b619e46ade 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -106,9 +106,6 @@
- #ifdef CONFIG_USER_NS
- #include <linux/user_namespace.h>
- #endif
--#if IS_ENABLED(CONFIG_USB)
--#include <linux/usb.h>
--#endif
-
- #if defined(CONFIG_SYSCTL)
-
-@@ -2308,17 +2305,6 @@ static struct ctl_table kern_table[] = {
- .extra1 = SYSCTL_ZERO,
- .extra2 = SYSCTL_ONE,
- },
--#if IS_ENABLED(CONFIG_USB)
-- {
-- .procname = "deny_new_usb",
-- .data = &deny_new_usb,
-- .maxlen = sizeof(int),
-- .mode = 0644,
-- .proc_handler = proc_dointvec_minmax_sysadmin,
-- .extra1 = SYSCTL_ZERO,
-- .extra2 = SYSCTL_ONE,
-- },
--#endif
- {
- .procname = "ngroups_max",
- .data = &ngroups_max,
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0099-hard-wire-legacy-checkreqprot-option-to-0.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0099-hard-wire-legacy-checkreqprot-option-to-0.patch
deleted file mode 100644
index 7951f0b2f06e..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0099-hard-wire-legacy-checkreqprot-option-to-0.patch
+++ /dev/null
@@ -1,133 +0,0 @@
-From e98a7d178cfa3c57efb9a642cca152a1ad9c1875 Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Sun, 25 Feb 2018 03:26:45 -0500
-Subject: [PATCH 099/113] hard-wire legacy checkreqprot option to 0
-
-The userspace API is left intact for compatibility.
-
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- .../admin-guide/kernel-parameters.txt | 11 ---------
- security/selinux/Kconfig | 23 -------------------
- security/selinux/hooks.c | 16 +------------
- security/selinux/selinuxfs.c | 12 +---------
- 4 files changed, 2 insertions(+), 60 deletions(-)
-
-diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
-index e7ea794320e8..0e8e3fdd7005 100644
---- a/Documentation/admin-guide/kernel-parameters.txt
-+++ b/Documentation/admin-guide/kernel-parameters.txt
-@@ -518,17 +518,6 @@
- nosocket -- Disable socket memory accounting.
- nokmem -- Disable kernel memory accounting.
-
-- checkreqprot [SELINUX] Set initial checkreqprot flag value.
-- Format: { "0" | "1" }
-- See security/selinux/Kconfig help text.
-- 0 -- check protection applied by kernel (includes
-- any implied execute protection).
-- 1 -- check protection requested by application.
-- Default value is set via a kernel config option.
-- Value can be changed at runtime via
-- /sys/fs/selinux/checkreqprot.
-- Setting checkreqprot to 1 is deprecated.
--
- cio_ignore= [S390]
- See Documentation/s390/common_io.rst for details.
- clk_ignore_unused
-diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
-index 76d7ed11513c..ae851a826c26 100644
---- a/security/selinux/Kconfig
-+++ b/security/selinux/Kconfig
-@@ -70,29 +70,6 @@ config SECURITY_SELINUX_AVC_STATS
- /sys/fs/selinux/avc/cache_stats, which may be monitored via
- tools such as avcstat.
-
--config SECURITY_SELINUX_CHECKREQPROT_VALUE
-- int "NSA SELinux checkreqprot default value"
-- depends on SECURITY_SELINUX
-- range 0 1
-- default 0
-- help
-- This option sets the default value for the 'checkreqprot' flag
-- that determines whether SELinux checks the protection requested
-- by the application or the protection that will be applied by the
-- kernel (including any implied execute for read-implies-exec) for
-- mmap and mprotect calls. If this option is set to 0 (zero),
-- SELinux will default to checking the protection that will be applied
-- by the kernel. If this option is set to 1 (one), SELinux will
-- default to checking the protection requested by the application.
-- The checkreqprot flag may be changed from the default via the
-- 'checkreqprot=' boot parameter. It may also be changed at runtime
-- via /sys/fs/selinux/checkreqprot if authorized by policy.
--
-- WARNING: this option is deprecated and will be removed in a future
-- kernel release.
--
-- If you are unsure how to answer this question, answer 0.
--
- config SECURITY_SELINUX_SIDTAB_HASH_BITS
- int "NSA SELinux sidtab hashtable size"
- depends on SECURITY_SELINUX
-diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
-index c46312710e73..541c65650c5e 100644
---- a/security/selinux/hooks.c
-+++ b/security/selinux/hooks.c
-@@ -136,21 +136,7 @@ static int __init selinux_enabled_setup(char *str)
- __setup("selinux=", selinux_enabled_setup);
- #endif
-
--static unsigned int selinux_checkreqprot_boot =
-- CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
--
--static int __init checkreqprot_setup(char *str)
--{
-- unsigned long checkreqprot;
--
-- if (!kstrtoul(str, 0, &checkreqprot)) {
-- selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
-- if (checkreqprot)
-- pr_warn("SELinux: checkreqprot set to 1 via kernel parameter. This is deprecated and will be rejected in a future kernel release.\n");
-- }
-- return 1;
--}
--__setup("checkreqprot=", checkreqprot_setup);
-+static const unsigned int selinux_checkreqprot_boot;
-
- /**
- * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
-diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
-index 4bde570d56a2..cc5caffc07fa 100644
---- a/security/selinux/selinuxfs.c
-+++ b/security/selinux/selinuxfs.c
-@@ -725,7 +725,6 @@ static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
- static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
- {
-- struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
- char *page;
- ssize_t length;
- unsigned int new_value;
-@@ -749,18 +748,9 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
- return PTR_ERR(page);
-
- length = -EINVAL;
-- if (sscanf(page, "%u", &new_value) != 1)
-+ if (sscanf(page, "%u", &new_value) != 1 || new_value)
- goto out;
-
-- if (new_value) {
-- char comm[sizeof(current->comm)];
--
-- memcpy(comm, current->comm, sizeof(comm));
-- pr_warn_once("SELinux: %s (%d) set checkreqprot to 1. This is deprecated and will be rejected in a future kernel release.\n",
-- comm, current->pid);
-- }
--
-- checkreqprot_set(fsi->state, (new_value ? 1 : 0));
- length = count;
- out:
- kfree(page);
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch
deleted file mode 100644
index 13963c0fc39b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0100-security-tty-Add-owner-user-namespace-to-tty_struct.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From 48228b49d9243d026b6c3eee1a8a8547e88c6624 Mon Sep 17 00:00:00 2001
-From: Matt Brown <matt@nmatt.com>
-Date: Mon, 29 May 2017 17:37:59 -0400
-Subject: [PATCH 100/113] security: tty: Add owner user namespace to tty_struct
-
-This patch adds struct user_namespace *owner_user_ns to the tty_struct.
-Then it is set to current_user_ns() in the alloc_tty_struct function.
-
-This is done to facilitate capability checks against the original user
-namespace that allocated the tty.
-
-E.g. ns_capable(tty->owner_user_ns,CAP_SYS_ADMIN)
-
-This combined with the use of user namespace's will allow hardening
-protections to be built to mitigate container escapes that utilize TTY
-ioctls such as TIOCSTI.
-
-See: https://bugzilla.redhat.com/show_bug.cgi?id=1411256
-
-Acked-by: Serge Hallyn <serge@hallyn.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Signed-off-by: Matt Brown <matt@nmatt.com>
----
- drivers/tty/tty_io.c | 2 ++
- include/linux/tty.h | 2 ++
- 2 files changed, 4 insertions(+)
-
-diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
-index ff87cb51747d..a3b0d0c68c34 100644
---- a/drivers/tty/tty_io.c
-+++ b/drivers/tty/tty_io.c
-@@ -171,6 +171,7 @@ static void free_tty_struct(struct tty_struct *tty)
- put_device(tty->dev);
- kfree(tty->write_buf);
- tty->magic = 0xDEADDEAD;
-+ put_user_ns(tty->owner_user_ns);
- kfree(tty);
- }
-
-@@ -3031,6 +3032,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
- tty->index = idx;
- tty_line_name(driver, idx, tty->name);
- tty->dev = tty_get_device(tty);
-+ tty->owner_user_ns = get_user_ns(current_user_ns());
-
- return tty;
- }
-diff --git a/include/linux/tty.h b/include/linux/tty.h
-index bc8caac390fc..29fd018fc255 100644
---- a/include/linux/tty.h
-+++ b/include/linux/tty.h
-@@ -14,6 +14,7 @@
- #include <uapi/linux/tty.h>
- #include <linux/rwsem.h>
- #include <linux/llist.h>
-+#include <linux/user_namespace.h>
-
-
- /*
-@@ -342,6 +343,7 @@ struct tty_struct {
- /* If the tty has a pending do_SAK, queue it here - akpm */
- struct work_struct SAK_work;
- struct tty_port *port;
-+ struct user_namespace *owner_user_ns;
- } __randomize_layout;
-
- /* Each of a tty's open files has private_data pointing to tty_file_private */
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch
deleted file mode 100644
index 1db8a94a0308..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0101-security-tty-make-TIOCSTI-ioctl-require-CAP_SYS_ADMI.patch
+++ /dev/null
@@ -1,197 +0,0 @@
-From 04fc45d4854878826c1e2738c0b5528b7f9ee637 Mon Sep 17 00:00:00 2001
-From: Matt Brown <matt@nmatt.com>
-Date: Mon, 29 May 2017 17:38:00 -0400
-Subject: [PATCH 101/113] security: tty: make TIOCSTI ioctl require
- CAP_SYS_ADMIN
-
-This introduces the tiocsti_restrict sysctl, whose default is controlled
-via CONFIG_SECURITY_TIOCSTI_RESTRICT. When activated, this control
-restricts all TIOCSTI ioctl calls from non CAP_SYS_ADMIN users.
-
-This patch depends on patch 1/2
-
-This patch was inspired from GRKERNSEC_HARDEN_TTY.
-
-This patch would have prevented
-https://bugzilla.redhat.com/show_bug.cgi?id=1411256 under the following
-conditions:
-* non-privileged container
-* container run inside new user namespace
-
-Possible effects on userland:
-
-There could be a few user programs that would be effected by this
-change.
-See: <https://codesearch.debian.net/search?q=ioctl%5C%28.*TIOCSTI>
-notable programs are: agetty, csh, xemacs and tcsh
-
-However, I still believe that this change is worth it given that the
-Kconfig defaults to n. This will be a feature that is turned on for the
-same reason that people activate it when using grsecurity. Users of this
-opt-in feature will realize that they are choosing security over some OS
-features like unprivileged TIOCSTI ioctls, as should be clear in the
-Kconfig help message.
-
-Threat Model/Patch Rational:
-
->From grsecurity's config for GRKERNSEC_HARDEN_TTY.
-
- | There are very few legitimate uses for this functionality and it
- | has made vulnerabilities in several 'su'-like programs possible in
- | the past. Even without these vulnerabilities, it provides an
- | attacker with an easy mechanism to move laterally among other
- | processes within the same user's compromised session.
-
-So if one process within a tty session becomes compromised it can follow
-that additional processes, that are thought to be in different security
-boundaries, can be compromised as a result. When using a program like su
-or sudo, these additional processes could be in a tty session where TTY
-file descriptors are indeed shared over privilege boundaries.
-
-This is also an excellent writeup about the issue:
-<http://www.halfdog.net/Security/2012/TtyPushbackPrivilegeEscalation/>
-
-When user namespaces are in use, the check for the capability
-CAP_SYS_ADMIN is done against the user namespace that originally opened
-the tty.
-
-Acked-by: Serge Hallyn <serge@hallyn.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Signed-off-by: Matt Brown <matt@nmatt.com>
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- Documentation/admin-guide/sysctl/kernel.rst | 20 ++++++++++++++++++++
- drivers/tty/tty_io.c | 8 ++++++++
- include/linux/tty.h | 2 ++
- kernel/sysctl.c | 14 ++++++++++++++
- security/Kconfig | 13 +++++++++++++
- 5 files changed, 57 insertions(+)
-
-diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
-index 4c20e6ded0af..3cd263f8ac46 100644
---- a/Documentation/admin-guide/sysctl/kernel.rst
-+++ b/Documentation/admin-guide/sysctl/kernel.rst
-@@ -1385,6 +1385,26 @@ If a value outside of this range is written to ``threads-max`` an
- ``EINVAL`` error occurs.
-
-
-+tiocsti_restrict
-+================
-+
-+This toggle indicates whether unprivileged users are prevented from using the
-+``TIOCSTI`` ioctl to inject commands into other processes which share a tty
-+session.
-+
-+= ============================================================================
-+0 No restriction, except the default one of only being able to inject commands
-+ into one's own tty.
-+1 Users must have ``CAP_SYS_ADMIN`` to use the ``TIOCSTI`` ioctl.
-+= ============================================================================
-+
-+When user namespaces are in use, the check for ``CAP_SYS_ADMIN`` is done
-+against the user namespace that originally opened the tty.
-+
-+The kernel config option ``CONFIG_SECURITY_TIOCSTI_RESTRICT`` sets the default
-+value of ``tiocsti_restrict``.
-+
-+
- traceoff_on_warning
- ===================
-
-diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
-index a3b0d0c68c34..b0acd66e0878 100644
---- a/drivers/tty/tty_io.c
-+++ b/drivers/tty/tty_io.c
-@@ -2193,11 +2193,19 @@ static int tty_fasync(int fd, struct file *filp, int on)
- * FIXME: may race normal receive processing
- */
-
-+int tiocsti_restrict = IS_ENABLED(CONFIG_SECURITY_TIOCSTI_RESTRICT);
-+
- static int tiocsti(struct tty_struct *tty, char __user *p)
- {
- char ch, mbz = 0;
- struct tty_ldisc *ld;
-
-+ if (tiocsti_restrict &&
-+ !ns_capable(tty->owner_user_ns, CAP_SYS_ADMIN)) {
-+ dev_warn_ratelimited(tty->dev,
-+ "Denied TIOCSTI ioctl for non-privileged process\n");
-+ return -EPERM;
-+ }
- if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (get_user(ch, p))
-diff --git a/include/linux/tty.h b/include/linux/tty.h
-index 29fd018fc255..743e3964a03a 100644
---- a/include/linux/tty.h
-+++ b/include/linux/tty.h
-@@ -353,6 +353,8 @@ struct tty_file_private {
- struct list_head list;
- };
-
-+extern int tiocsti_restrict;
-+
- /* tty magic number */
- #define TTY_MAGIC 0x5401
-
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index 13b619e46ade..8fd007fbec4c 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -106,6 +106,9 @@
- #ifdef CONFIG_USER_NS
- #include <linux/user_namespace.h>
- #endif
-+#if defined CONFIG_TTY
-+#include <linux/tty.h>
-+#endif
-
- #if defined(CONFIG_SYSCTL)
-
-@@ -2295,6 +2298,17 @@ static struct ctl_table kern_table[] = {
- .extra1 = SYSCTL_ZERO,
- .extra2 = &two,
- },
-+#endif
-+#if defined CONFIG_TTY
-+ {
-+ .procname = "tiocsti_restrict",
-+ .data = &tiocsti_restrict,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax_sysadmin,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
- #endif
- {
- .procname = "device_sidechannel_restrict",
-diff --git a/security/Kconfig b/security/Kconfig
-index f3c995bd79cf..c8ea5a6ecce0 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -29,6 +29,19 @@ config SECURITY_PERF_EVENTS_RESTRICT
- perf_event_open syscall will be permitted unless it is
- changed.
-
-+config SECURITY_TIOCSTI_RESTRICT
-+ bool "Restrict unprivileged use of tiocsti command injection"
-+ default n
-+ help
-+ This enforces restrictions on unprivileged users injecting commands
-+ into other processes which share a tty session using the TIOCSTI
-+ ioctl. This option makes TIOCSTI use require CAP_SYS_ADMIN.
-+
-+ If this option is not selected, no restrictions will be enforced
-+ unless the tiocsti_restrict sysctl is explicitly set to (1).
-+
-+ If you are unsure how to answer this question, answer N.
-+
- config SECURITY
- bool "Enable different security models"
- depends on SYSFS
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch
deleted file mode 100644
index 6455a10a5129..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0102-enable-SECURITY_TIOCSTI_RESTRICT-by-default.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 714cff25e38b9cc3e069a2cd06b480227769c7ec Mon Sep 17 00:00:00 2001
-From: Daniel Micay <danielmicay@gmail.com>
-Date: Wed, 3 May 2017 23:36:14 -0400
-Subject: [PATCH 102/113] enable SECURITY_TIOCSTI_RESTRICT by default
-
-Signed-off-by: Daniel Micay <danielmicay@gmail.com>
----
- security/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/security/Kconfig b/security/Kconfig
-index c8ea5a6ecce0..615205c0113b 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -31,7 +31,7 @@ config SECURITY_PERF_EVENTS_RESTRICT
-
- config SECURITY_TIOCSTI_RESTRICT
- bool "Restrict unprivileged use of tiocsti command injection"
-- default n
-+ default y
- help
- This enforces restrictions on unprivileged users injecting commands
- into other processes which share a tty session using the TIOCSTI
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0103-disable-unprivileged-eBPF-access-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0103-disable-unprivileged-eBPF-access-by-default.patch
deleted file mode 100644
index 4d960371cc97..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0103-disable-unprivileged-eBPF-access-by-default.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 6e0e1a78fea78d53a893446f4c98018624ef1a72 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Mon, 7 May 2018 20:37:07 +0200
-Subject: [PATCH 103/113] disable unprivileged eBPF access by default
-
----
- kernel/bpf/syscall.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
-index 9433ab9995cd..348c36273f1a 100644
---- a/kernel/bpf/syscall.c
-+++ b/kernel/bpf/syscall.c
-@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(map_idr_lock);
- static DEFINE_IDR(link_idr);
- static DEFINE_SPINLOCK(link_idr_lock);
-
--int sysctl_unprivileged_bpf_disabled __read_mostly;
-+int sysctl_unprivileged_bpf_disabled __read_mostly = 1;
-
- static const struct bpf_map_ops * const bpf_map_types[] = {
- #define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0104-enable-BPF-JIT-hardening-by-default-if-available.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0104-enable-BPF-JIT-hardening-by-default-if-available.patch
deleted file mode 100644
index a9dc01c78239..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0104-enable-BPF-JIT-hardening-by-default-if-available.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 1cbafc2eaedb28b5b4d7ed12e452c77b0ef89385 Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Mon, 7 May 2018 20:37:55 +0200
-Subject: [PATCH 104/113] enable BPF JIT hardening by default (if available)
-
----
- kernel/bpf/core.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
-index 55454d2278b1..de02792dc2fc 100644
---- a/kernel/bpf/core.c
-+++ b/kernel/bpf/core.c
-@@ -524,7 +524,7 @@ void bpf_prog_kallsyms_del_all(struct bpf_prog *fp)
- /* All BPF JIT sysctl knobs here. */
- int bpf_jit_enable __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_DEFAULT_ON);
- int bpf_jit_kallsyms __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_DEFAULT_ON);
--int bpf_jit_harden __read_mostly;
-+int bpf_jit_harden __read_mostly = 2;
- long bpf_jit_limit __read_mostly;
-
- static void
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0105-enable-protected_-fifos-regular-by-default.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0105-enable-protected_-fifos-regular-by-default.patch
deleted file mode 100644
index b34d802b3138..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0105-enable-protected_-fifos-regular-by-default.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 10eb8949c298512a3cfc98d40a87090a06c1a09b Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Sun, 4 Nov 2018 18:48:53 +0100
-Subject: [PATCH 105/113] enable protected_{fifos,regular} by default
-
----
- fs/namei.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/fs/namei.c b/fs/namei.c
-index 59ff3ce21026..72f912c68975 100644
---- a/fs/namei.c
-+++ b/fs/namei.c
-@@ -934,8 +934,8 @@ static inline void put_link(struct nameidata *nd)
-
- int sysctl_protected_symlinks __read_mostly = 1;
- int sysctl_protected_hardlinks __read_mostly = 1;
--int sysctl_protected_fifos __read_mostly;
--int sysctl_protected_regular __read_mostly;
-+int sysctl_protected_fifos __read_mostly = 2;
-+int sysctl_protected_regular __read_mostly = 2;
-
- /**
- * may_follow_link - Check symlink following for unsafe situations
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch
deleted file mode 100644
index aaa5f09dbe16..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0106-modpost-Add-CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_.patch
+++ /dev/null
@@ -1,129 +0,0 @@
-From 814f4aea891f6c09e11ea22029ce6531c7d40cd2 Mon Sep 17 00:00:00 2001
-From: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Date: Mon, 6 May 2019 17:07:11 +0200
-Subject: [PATCH 106/113] modpost: Add
- CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_VERBOSE
-
-With 46c7dd56d541 ("modpost: always show verbose warning for section
-mismatch"), sec_mismatch_verbose was removed which would have printed
-errors for all writable function pointers during compilation if it
-hadn't been "#if 0"ed out for quite some time now.
-
-Let's introduce a new DEBUG_WRITABLE_FUNCTION_POINTERS_VERBOSE Kconfig
-option to cleanly control this linux-hardened functionality.
-
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- lib/Kconfig.debug | 3 +++
- scripts/Makefile.modpost | 1 +
- scripts/mod/modpost.c | 25 ++++++++++++++++---------
- 3 files changed, 20 insertions(+), 9 deletions(-)
-
-diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index 4a1a32a059f4..5fce84adc315 100644
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -374,6 +374,9 @@ config DEBUG_FORCE_FUNCTION_ALIGN_32B
-
- It is mainly for debug and performance tuning use.
-
-+config DEBUG_WRITABLE_FUNCTION_POINTERS_VERBOSE
-+ bool "Enable verbose reporting of writable function pointers"
-+
- #
- # Select this config option from the architecture Kconfig, if it
- # is preferred to always offer frame pointers as a config
-diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
-index f54b6ac37ac2..e53b3057d4cb 100644
---- a/scripts/Makefile.modpost
-+++ b/scripts/Makefile.modpost
-@@ -47,6 +47,7 @@ MODPOST = scripts/mod/modpost \
- $(if $(CONFIG_MODVERSIONS),-m) \
- $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
- $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
-+ $(if $(CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_VERBOSE),-f) \
- $(if $(KBUILD_MODPOST_WARN),-w) \
- -o $@
-
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index 50e9baefc4e7..2cbc4e8a6295 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -34,8 +34,9 @@ static int external_module = 0;
- static int warn_unresolved = 0;
- /* How a symbol is exported */
- static int sec_mismatch_count = 0;
--static int writable_fptr_count = 0;
- static int sec_mismatch_fatal = 0;
-+static int writable_fptr_count = 0;
-+static int writable_fptr_verbose = 0;
- /* ignore missing files */
- static int ignore_missing_files;
- /* If set to 1, only warn (instead of error) about missing ns imports */
-@@ -1466,10 +1467,13 @@ static void report_sec_mismatch(const char *modname,
- char *prl_from;
- char *prl_to;
-
-- if (mismatch->mismatch == DATA_TO_TEXT)
-+ if (mismatch->mismatch == DATA_TO_TEXT) {
- writable_fptr_count++;
-- else
-+ if (!writable_fptr_verbose)
-+ return;
-+ } else {
- sec_mismatch_count++;
-+ }
-
- get_pretty_name(from_is_func, &from, &from_p);
- get_pretty_name(to_is_func, &to, &to_p);
-@@ -1592,12 +1596,10 @@ static void report_sec_mismatch(const char *modname,
- "we should never get here.");
- break;
- case DATA_TO_TEXT:
--#if 0
- fprintf(stderr,
- "The %s %s:%s references\n"
- "the %s %s:%s%s\n",
- from, fromsec, fromsym, to, tosec, tosym, to_p);
--#endif
- break;
- }
- fprintf(stderr, "\n");
-@@ -2578,7 +2580,7 @@ int main(int argc, char **argv)
- struct dump_list *dump_read_start = NULL;
- struct dump_list **dump_read_iter = &dump_read_start;
-
-- while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) {
-+ while ((opt = getopt(argc, argv, "ei:fmnT:o:awENd:")) != -1) {
- switch (opt) {
- case 'e':
- external_module = 1;
-@@ -2589,6 +2591,9 @@ int main(int argc, char **argv)
- (*dump_read_iter)->file = optarg;
- dump_read_iter = &(*dump_read_iter)->next;
- break;
-+ case 'f':
-+ writable_fptr_verbose = 1;
-+ break;
- case 'm':
- modversions = 1;
- break;
-@@ -2689,9 +2694,11 @@ int main(int argc, char **argv)
- }
-
- free(buf.p);
-- if (writable_fptr_count)
-- warn("modpost: Found %d writable function pointer(s).\n",
-- writable_fptr_count);
-+ if (writable_fptr_count && !writable_fptr_verbose)
-+ warn("modpost: Found %d writable function pointer%s.\n"
-+ "To see full details build your kernel with:\n"
-+ "'make CONFIG_DEBUG_WRITABLE_FUNCTION_POINTERS_VERBOSE=y'\n",
-+ writable_fptr_count, (writable_fptr_count == 1 ? "" : "s"));
-
- return err;
- }
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0107-mm-Fix-extra_latent_entropy.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0107-mm-Fix-extra_latent_entropy.patch
deleted file mode 100644
index c02ede21220b..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0107-mm-Fix-extra_latent_entropy.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-From 5922d5d781f7f95ffbd4dc08be6236c84b2a8c82 Mon Sep 17 00:00:00 2001
-From: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Date: Tue, 7 May 2019 11:46:21 +0200
-Subject: [PATCH 107/113] mm: Fix extra_latent_entropy
-
-Commit a9cd410a3d29 ("mm/page_alloc.c: memory hotplug: free pages as
-higher order") changed `static void __init __free_pages_boot_core()`
-into `void __free_pages_core()`, causing the following section mismatch
-warning at compile time:
-
- WARNING: vmlinux.o(.text+0x180fe4): Section mismatch in reference from the function __free_pages_core() to the variable .meminit.data:extra_latent_entropy
- The function __free_pages_core() references the variable __meminitdata extra_latent_entropy.
- This is often because __free_pages_core lacks a __meminitdata annotation or the annotation of extra_latent_entropy is wrong.
-
-This commit is an attempt at fixing this issue. I'm not sure it's OK as
-we are accessing pages that are still managed by the bootmem allocator.
-The prefetching part is not an issue as it only affects struct pages.
-
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
----
- mm/page_alloc.c | 38 ++++++++++++++++++++++----------------
- 1 file changed, 22 insertions(+), 16 deletions(-)
-
-diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index 965d49be78ed..cb7501769331 100644
---- a/mm/page_alloc.c
-+++ b/mm/page_alloc.c
-@@ -1539,6 +1539,25 @@ static void __free_pages_ok(struct page *page, unsigned int order,
- local_irq_restore(flags);
- }
-
-+static void __init __gather_extra_latent_entropy(struct page *page,
-+ unsigned int nr_pages)
-+{
-+ if (extra_latent_entropy && !PageHighMem(page) && page_to_pfn(page) < 0x100000) {
-+ unsigned long hash = 0;
-+ size_t index, end = PAGE_SIZE * nr_pages / sizeof hash;
-+ const unsigned long *data = lowmem_page_address(page);
-+
-+ for (index = 0; index < end; index++)
-+ hash ^= hash + data[index];
-+#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
-+ latent_entropy ^= hash;
-+ add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy));
-+#else
-+ add_device_randomness((const void *)&hash, sizeof(hash));
-+#endif
-+ }
-+}
-+
- void __free_pages_core(struct page *page, unsigned int order)
- {
- unsigned int nr_pages = 1 << order;
-@@ -1558,22 +1577,6 @@ void __free_pages_core(struct page *page, unsigned int order)
- }
- __ClearPageReserved(p);
- set_page_count(p, 0);
--
-- if (extra_latent_entropy && !PageHighMem(page) && page_to_pfn(page) < 0x100000) {
-- unsigned long hash = 0;
-- size_t index, end = PAGE_SIZE * nr_pages / sizeof hash;
-- const unsigned long *data = lowmem_page_address(page);
--
-- for (index = 0; index < end; index++)
-- hash ^= hash + data[index];
--#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
-- latent_entropy ^= hash;
-- add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy));
--#else
-- add_device_randomness((const void *)&hash, sizeof(hash));
--#endif
-- }
--
- atomic_long_add(nr_pages, &page_zone(page)->managed_pages);
-
- /*
-@@ -1632,6 +1635,7 @@ void __init memblock_free_pages(struct page *page, unsigned long pfn,
- {
- if (early_page_uninitialised(pfn))
- return;
-+ __gather_extra_latent_entropy(page, 1 << order);
- __free_pages_core(page, order);
- }
-
-@@ -1723,6 +1727,7 @@ static void __init deferred_free_range(unsigned long pfn,
- if (nr_pages == pageblock_nr_pages &&
- (pfn & (pageblock_nr_pages - 1)) == 0) {
- set_pageblock_migratetype(page, MIGRATE_MOVABLE);
-+ __gather_extra_latent_entropy(page, 1 << pageblock_order);
- __free_pages_core(page, pageblock_order);
- return;
- }
-@@ -1730,6 +1735,7 @@ static void __init deferred_free_range(unsigned long pfn,
- for (i = 0; i < nr_pages; i++, page++, pfn++) {
- if ((pfn & (pageblock_nr_pages - 1)) == 0)
- set_pageblock_migratetype(page, MIGRATE_MOVABLE);
-+ __gather_extra_latent_entropy(page, 1);
- __free_pages_core(page, 0);
- }
- }
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0108-add-CONFIG-for-unprivileged_userfaultfd.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0108-add-CONFIG-for-unprivileged_userfaultfd.patch
deleted file mode 100644
index 30dafb7cef67..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0108-add-CONFIG-for-unprivileged_userfaultfd.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From 4a95200b96f6433aabae2f224a306f89c67344be Mon Sep 17 00:00:00 2001
-From: Levente Polyak <levente@leventepolyak.net>
-Date: Wed, 2 Oct 2019 01:22:17 +0200
-Subject: [PATCH 108/113] add CONFIG for unprivileged_userfaultfd
-
-When disabled, unprivileged users will not be able to use the userfaultfd
-syscall. Userfaultfd provide attackers with a way to stall a kernel
-thread in the middle of memory accesses from userspace by initiating an
-access on an unmapped page. To avoid various heap grooming and heap
-spraying techniques for exploiting use-after-free flaws this should be
-disabled by default.
-
-This setting can be overridden at runtime via the
-vm.unprivileged_userfaultfd sysctl.
-
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- fs/userfaultfd.c | 4 ++++
- init/Kconfig | 17 +++++++++++++++++
- 2 files changed, 21 insertions(+)
-
-diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
-index 000b457ad087..06d35ecdcbc8 100644
---- a/fs/userfaultfd.c
-+++ b/fs/userfaultfd.c
-@@ -28,7 +28,11 @@
- #include <linux/security.h>
- #include <linux/hugetlb.h>
-
-+#ifdef CONFIG_USERFAULTFD_UNPRIVILEGED
- int sysctl_unprivileged_userfaultfd __read_mostly = 1;
-+#else
-+int sysctl_unprivileged_userfaultfd __read_mostly;
-+#endif
-
- static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
-
-diff --git a/init/Kconfig b/init/Kconfig
-index a7b5a4cb7939..2feea719cc25 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1745,6 +1745,23 @@ config USERFAULTFD
- Enable the userfaultfd() system call that allows to intercept and
- handle page faults in userland.
-
-+config USERFAULTFD_UNPRIVILEGED
-+ bool "Allow unprivileged users to use the userfaultfd syscall"
-+ depends on USERFAULTFD
-+ default n
-+ help
-+ When disabled, unprivileged users will not be able to use the userfaultfd
-+ syscall. Userfaultfd provide attackers with a way to stall a kernel
-+ thread in the middle of memory accesses from userspace by initiating an
-+ access on an unmapped page. To avoid various heap grooming and heap
-+ spraying techniques for exploiting use-after-free flaws this should be
-+ disabled by default.
-+
-+ This setting can be overridden at runtime via the
-+ vm.unprivileged_userfaultfd sysctl.
-+
-+ If unsure, say N.
-+
- config ARCH_HAS_MEMBARRIER_CALLBACKS
- bool
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch
deleted file mode 100644
index 56909fb40613..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0109-slub-Extend-init_on_alloc-to-slab-caches-with-constr.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From 9c7d5fd0b1087cb52989ccc025a073b4a143c7a6 Mon Sep 17 00:00:00 2001
-From: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Date: Fri, 29 Nov 2019 16:27:14 +0100
-Subject: [PATCH 109/113] slub: Extend init_on_alloc to slab caches with
- constructors
-
-Signed-off-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- mm/slab.h | 2 ++
- mm/slub.c | 23 ++++++++++++++++++-----
- 2 files changed, 20 insertions(+), 5 deletions(-)
-
-diff --git a/mm/slab.h b/mm/slab.h
-index 105dba485a7e..2138deacf719 100644
---- a/mm/slab.h
-+++ b/mm/slab.h
-@@ -630,8 +630,10 @@ static inline void cache_random_seq_destroy(struct kmem_cache *cachep) { }
- static inline bool slab_want_init_on_alloc(gfp_t flags, struct kmem_cache *c)
- {
- if (static_branch_unlikely(&init_on_alloc)) {
-+#ifndef CONFIG_SLUB
- if (c->ctor)
- return false;
-+#endif
- if (c->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON))
- return flags & __GFP_ZERO;
- return true;
-diff --git a/mm/slub.c b/mm/slub.c
-index dd68308c94a9..802f9051bc1a 100644
---- a/mm/slub.c
-+++ b/mm/slub.c
-@@ -1635,9 +1635,10 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
- * need to show a valid freepointer to check_object().
- *
- * Note that doing this for all caches (not just ctor
-- * ones, which have s->offset != NULL)) causes a GPF,
-- * due to KASAN poisoning and the way set_freepointer()
-- * eventually dereferences the freepointer.
-+ * ones, which have s->offset >= object_size)) causes a
-+ * GPF, due to KASAN poisoning and the way
-+ * set_freepointer() eventually dereferences the
-+ * freepointer.
- */
- set_freepointer(s, object, NULL);
- }
-@@ -2955,8 +2956,14 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
- if (s->ctor)
- s->ctor(object);
- kasan_poison_object_data(s, object);
-- } else if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
-+ } else if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object) {
- memset(object, 0, s->object_size);
-+ if (s->ctor) {
-+ kasan_unpoison_object_data(s, object);
-+ s->ctor(object);
-+ kasan_poison_object_data(s, object);
-+ }
-+ }
-
- if (object) {
- check_canary(s, object, s->random_inactive);
-@@ -3416,8 +3423,14 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
- } else if (unlikely(slab_want_init_on_alloc(flags, s))) {
- int j;
-
-- for (j = 0; j < i; j++)
-+ for (j = 0; j < i; j++) {
- memset(p[j], 0, s->object_size);
-+ if (s->ctor) {
-+ kasan_unpoison_object_data(s, p[j]);
-+ s->ctor(p[j]);
-+ kasan_poison_object_data(s, p[j]);
-+ }
-+ }
- }
-
- for (k = 0; k < i; k++) {
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch
deleted file mode 100644
index 9e7cfcfc32f3..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0110-net-tcp-add-option-to-disable-TCP-simultaneous-conne.patch
+++ /dev/null
@@ -1,151 +0,0 @@
-From b39a5838a263e450e0871054a7832cd5149a8f0a Mon Sep 17 00:00:00 2001
-From: madaidan <50278627+madaidan@users.noreply.github.com>
-Date: Sun, 9 Feb 2020 00:03:41 +0000
-Subject: [PATCH 110/113] net: tcp: add option to disable TCP simultaneous
- connect
-
-This is modified from Brad Spengler/PaX Team's code in the last public
-patch of grsecurity/PaX based on my understanding of the code. Changes
-or omissions from the original code are mine and don't reflect the
-original grsecurity/PaX code.
-
-TCP simultaneous connect adds a weakness in Linux's implementation of
-TCP that allows two clients to connect to each other without either
-entering a listening state. The weakness allows an attacker to easily
-prevent a client from connecting to a known server provided the source
-port for the connection is guessed correctly.
-
-As the weakness could be used to prevent an antivirus or IPS from
-fetching updates, or prevent an SSL gateway from fetching a CRL, it
-should be eliminated.
-
-This creates a net.ipv4.tcp_simult_connect sysctl that when disabled,
-disables TCP simultaneous connect.
-
-Reviewd-by: Thibaut Sautereau <thibaut.sautereau@ssi.gouv.fr>
-Reviewd-by: Levente Polyak <levente@leventepolyak.net>
-Signed-off-by: Levente Polyak <levente@leventepolyak.net>
----
- Documentation/networking/ip-sysctl.rst | 18 ++++++++++++++++++
- include/net/tcp.h | 1 +
- net/ipv4/Kconfig | 23 +++++++++++++++++++++++
- net/ipv4/sysctl_net_ipv4.c | 9 +++++++++
- net/ipv4/tcp_input.c | 3 ++-
- 5 files changed, 53 insertions(+), 1 deletion(-)
-
-diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
-index 25e6673a085a..76f1892d65ed 100644
---- a/Documentation/networking/ip-sysctl.rst
-+++ b/Documentation/networking/ip-sysctl.rst
-@@ -665,6 +665,24 @@ tcp_comp_sack_nr - INTEGER
-
- Default : 44
-
-+tcp_simult_connect - BOOLEAN
-+ Enable TCP simultaneous connect that adds a weakness in Linux's strict
-+ implementation of TCP that allows two clients to connect to each other
-+ without either entering a listening state. The weakness allows an attacker
-+ to easily prevent a client from connecting to a known server provided the
-+ source port for the connection is guessed correctly.
-+
-+ As the weakness could be used to prevent an antivirus or IPS from fetching
-+ updates, or prevent an SSL gateway from fetching a CRL, it should be
-+ eliminated by disabling this option. Though Linux is one of few operating
-+ systems supporting simultaneous connect, it has no legitimate use in
-+ practice and is rarely supported by firewalls.
-+
-+ Disabling this may break TCP STUNT which is used by some applications for
-+ NAT traversal.
-+
-+ Default: Value of CONFIG_TCP_SIMULT_CONNECT_DEFAULT_ON
-+
- tcp_slow_start_after_idle - BOOLEAN
- If set, provide RFC2861 behavior and time out the congestion
- window after an idle period. An idle period is defined at
-diff --git a/include/net/tcp.h b/include/net/tcp.h
-index fe9747ee70a6..116c227bb292 100644
---- a/include/net/tcp.h
-+++ b/include/net/tcp.h
-@@ -245,6 +245,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
- /* sysctl variables for tcp */
- extern int sysctl_tcp_max_orphans;
- extern long sysctl_tcp_mem[3];
-+extern int sysctl_tcp_simult_connect;
-
- #define TCP_RACK_LOSS_DETECTION 0x1 /* Use RACK to detect losses */
- #define TCP_RACK_STATIC_REO_WND 0x2 /* Use static RACK reo wnd */
-diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
-index 989e005bf698..d1584b4b39f9 100644
---- a/net/ipv4/Kconfig
-+++ b/net/ipv4/Kconfig
-@@ -743,3 +743,26 @@ config TCP_MD5SIG
- on the Internet.
-
- If unsure, say N.
-+
-+config TCP_SIMULT_CONNECT_DEFAULT_ON
-+ bool "Enable TCP simultaneous connect"
-+ help
-+ Enable TCP simultaneous connect that adds a weakness in Linux's strict
-+ implementation of TCP that allows two clients to connect to each other
-+ without either entering a listening state. The weakness allows an
-+ attacker to easily prevent a client from connecting to a known server
-+ provided the source port for the connection is guessed correctly.
-+
-+ As the weakness could be used to prevent an antivirus or IPS from
-+ fetching updates, or prevent an SSL gateway from fetching a CRL, it
-+ should be eliminated by disabling this option. Though Linux is one of
-+ few operating systems supporting simultaneous connect, it has no
-+ legitimate use in practice and is rarely supported by firewalls.
-+
-+ Disabling this may break TCP STUNT which is used by some applications
-+ for NAT traversal.
-+
-+ This setting can be overridden at runtime via the
-+ net.ipv4.tcp_simult_connect sysctl.
-+
-+ If unsure, say N.
-diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
-index 3e5f4f2e705e..791329c77dea 100644
---- a/net/ipv4/sysctl_net_ipv4.c
-+++ b/net/ipv4/sysctl_net_ipv4.c
-@@ -588,6 +588,15 @@ static struct ctl_table ipv4_table[] = {
- .mode = 0644,
- .proc_handler = proc_do_static_key,
- },
-+ {
-+ .procname = "tcp_simult_connect",
-+ .data = &sysctl_tcp_simult_connect,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
- { }
- };
-
-diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
-index fac5c1469cee..7c3ffb3f4002 100644
---- a/net/ipv4/tcp_input.c
-+++ b/net/ipv4/tcp_input.c
-@@ -82,6 +82,7 @@
- #include <net/mptcp.h>
-
- int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
-+int sysctl_tcp_simult_connect __read_mostly = IS_ENABLED(CONFIG_TCP_SIMULT_CONNECT_DEFAULT_ON);
-
- #define FLAG_DATA 0x01 /* Incoming frame contained data. */
- #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
-@@ -6197,7 +6198,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
- tcp_paws_reject(&tp->rx_opt, 0))
- goto discard_and_undo;
-
-- if (th->syn) {
-+ if (th->syn && sysctl_tcp_simult_connect) {
- /* We see SYN without ACK. It is attempt of
- * simultaneous connect with crossed SYNs.
- * Particularly, it can be connect to self.
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch
deleted file mode 100644
index 686a2d2b7a57..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0111-dccp-ccid-move-timers-to-struct-dccp_sock.patch
+++ /dev/null
@@ -1,238 +0,0 @@
-From 1f98b5c4225878e41a89a94328c3c6368a97c81a Mon Sep 17 00:00:00 2001
-From: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
-Date: Tue, 13 Oct 2020 19:18:48 +0200
-Subject: [PATCH 111/113] dccp: ccid: move timers to struct dccp_sock
-
-When dccps_hc_tx_ccid is freed, ccid timers may still trigger. The reason
-del_timer_sync can't be used is because this relies on keeping a reference
-to struct sock. But as we keep a pointer to dccps_hc_tx_ccid and free that
-during disconnect, the timer should really belong to struct dccp_sock.
-
-This addresses CVE-2020-16119.
-
-Fixes: 839a6094140a (net: dccp: Convert timers to use timer_setup())
-Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
-Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
----
- include/linux/dccp.h | 2 ++
- net/dccp/ccids/ccid2.c | 32 +++++++++++++++++++-------------
- net/dccp/ccids/ccid3.c | 30 ++++++++++++++++++++----------
- 3 files changed, 41 insertions(+), 23 deletions(-)
-
-diff --git a/include/linux/dccp.h b/include/linux/dccp.h
-index 07e547c02fd8..504afa1a4be6 100644
---- a/include/linux/dccp.h
-+++ b/include/linux/dccp.h
-@@ -259,6 +259,7 @@ struct dccp_ackvec;
- * @dccps_sync_scheduled - flag which signals "send out-of-band message soon"
- * @dccps_xmitlet - tasklet scheduled by the TX CCID to dequeue data packets
- * @dccps_xmit_timer - used by the TX CCID to delay sending (rate-based pacing)
-+ * @dccps_ccid_timer - used by the CCIDs
- * @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs)
- */
- struct dccp_sock {
-@@ -303,6 +304,7 @@ struct dccp_sock {
- __u8 dccps_sync_scheduled:1;
- struct tasklet_struct dccps_xmitlet;
- struct timer_list dccps_xmit_timer;
-+ struct timer_list dccps_ccid_timer;
- };
-
- static inline struct dccp_sock *dccp_sk(const struct sock *sk)
-diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
-index 3da1f77bd039..dbca1f1e2449 100644
---- a/net/dccp/ccids/ccid2.c
-+++ b/net/dccp/ccids/ccid2.c
-@@ -126,21 +126,26 @@ static void dccp_tasklet_schedule(struct sock *sk)
-
- static void ccid2_hc_tx_rto_expire(struct timer_list *t)
- {
-- struct ccid2_hc_tx_sock *hc = from_timer(hc, t, tx_rtotimer);
-- struct sock *sk = hc->sk;
-- const bool sender_was_blocked = ccid2_cwnd_network_limited(hc);
-+ struct dccp_sock *dp = from_timer(dp, t, dccps_ccid_timer);
-+ struct sock *sk = (struct sock *)dp;
-+ struct ccid2_hc_tx_sock *hc;
-+ bool sender_was_blocked;
-
- bh_lock_sock(sk);
-+
-+ if (inet_sk_state_load(sk) == DCCP_CLOSED)
-+ goto out;
-+
-+ hc = ccid_priv(dp->dccps_hc_tx_ccid);
-+ sender_was_blocked = ccid2_cwnd_network_limited(hc);
-+
- if (sock_owned_by_user(sk)) {
-- sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + HZ / 5);
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer, jiffies + HZ / 5);
- goto out;
- }
-
- ccid2_pr_debug("RTO_EXPIRE\n");
-
-- if (sk->sk_state == DCCP_CLOSED)
-- goto out;
--
- /* back-off timer */
- hc->tx_rto <<= 1;
- if (hc->tx_rto > DCCP_RTO_MAX)
-@@ -166,7 +171,7 @@ static void ccid2_hc_tx_rto_expire(struct timer_list *t)
- if (sender_was_blocked)
- dccp_tasklet_schedule(sk);
- /* restart backed-off timer */
-- sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer, jiffies + hc->tx_rto);
- out:
- bh_unlock_sock(sk);
- sock_put(sk);
-@@ -330,7 +335,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
- }
- #endif
-
-- sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer, jiffies + hc->tx_rto);
-
- #ifdef CONFIG_IP_DCCP_CCID2_DEBUG
- do {
-@@ -700,9 +705,9 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
-
- /* restart RTO timer if not all outstanding data has been acked */
- if (hc->tx_pipe == 0)
-- sk_stop_timer(sk, &hc->tx_rtotimer);
-+ sk_stop_timer(sk, &dp->dccps_ccid_timer);
- else
-- sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer, jiffies + hc->tx_rto);
- done:
- /* check if incoming Acks allow pending packets to be sent */
- if (sender_was_blocked && !ccid2_cwnd_network_limited(hc))
-@@ -737,17 +742,18 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
- hc->tx_last_cong = hc->tx_lsndtime = hc->tx_cwnd_stamp = ccid2_jiffies32;
- hc->tx_cwnd_used = 0;
- hc->sk = sk;
-- timer_setup(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire, 0);
-+ timer_setup(&dp->dccps_ccid_timer, ccid2_hc_tx_rto_expire, 0);
- INIT_LIST_HEAD(&hc->tx_av_chunks);
- return 0;
- }
-
- static void ccid2_hc_tx_exit(struct sock *sk)
- {
-+ struct dccp_sock *dp = dccp_sk(sk);
- struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
- int i;
-
-- sk_stop_timer(sk, &hc->tx_rtotimer);
-+ sk_stop_timer(sk, &dp->dccps_ccid_timer);
-
- for (i = 0; i < hc->tx_seqbufc; i++)
- kfree(hc->tx_seqbuf[i]);
-diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
-index b9ee1a4a8955..685f4d046c0d 100644
---- a/net/dccp/ccids/ccid3.c
-+++ b/net/dccp/ccids/ccid3.c
-@@ -184,17 +184,24 @@ static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hc,
-
- static void ccid3_hc_tx_no_feedback_timer(struct timer_list *t)
- {
-- struct ccid3_hc_tx_sock *hc = from_timer(hc, t, tx_no_feedback_timer);
-- struct sock *sk = hc->sk;
-+ struct dccp_sock *dp = from_timer(dp, t, dccps_ccid_timer);
-+ struct ccid3_hc_tx_sock *hc;
-+ struct sock *sk = (struct sock *)dp;
- unsigned long t_nfb = USEC_PER_SEC / 5;
-
- bh_lock_sock(sk);
-+
-+ if (inet_sk_state_load(sk) == DCCP_CLOSED)
-+ goto out;
-+
- if (sock_owned_by_user(sk)) {
- /* Try again later. */
- /* XXX: set some sensible MIB */
- goto restart_timer;
- }
-
-+ hc = ccid_priv(dp->dccps_hc_tx_ccid);
-+
- ccid3_pr_debug("%s(%p, state=%s) - entry\n", dccp_role(sk), sk,
- ccid3_tx_state_name(hc->tx_state));
-
-@@ -250,8 +257,8 @@ static void ccid3_hc_tx_no_feedback_timer(struct timer_list *t)
- t_nfb = max(hc->tx_t_rto, 2 * hc->tx_t_ipi);
-
- restart_timer:
-- sk_reset_timer(sk, &hc->tx_no_feedback_timer,
-- jiffies + usecs_to_jiffies(t_nfb));
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer,
-+ jiffies + usecs_to_jiffies(t_nfb));
- out:
- bh_unlock_sock(sk);
- sock_put(sk);
-@@ -280,7 +287,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
- return -EBADMSG;
-
- if (hc->tx_state == TFRC_SSTATE_NO_SENT) {
-- sk_reset_timer(sk, &hc->tx_no_feedback_timer, (jiffies +
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer, (jiffies +
- usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
- hc->tx_last_win_count = 0;
- hc->tx_t_last_win_count = now;
-@@ -354,6 +361,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, unsigned int len)
- static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
- {
- struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
-+ struct dccp_sock *dp = dccp_sk(sk);
- struct tfrc_tx_hist_entry *acked;
- ktime_t now;
- unsigned long t_nfb;
-@@ -420,7 +428,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
- (unsigned int)(hc->tx_x >> 6));
-
- /* unschedule no feedback timer */
-- sk_stop_timer(sk, &hc->tx_no_feedback_timer);
-+ sk_stop_timer(sk, &dp->dccps_ccid_timer);
-
- /*
- * As we have calculated new ipi, delta, t_nom it is possible
-@@ -445,8 +453,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
- "expire in %lu jiffies (%luus)\n",
- dccp_role(sk), sk, usecs_to_jiffies(t_nfb), t_nfb);
-
-- sk_reset_timer(sk, &hc->tx_no_feedback_timer,
-- jiffies + usecs_to_jiffies(t_nfb));
-+ sk_reset_timer(sk, &dp->dccps_ccid_timer,
-+ jiffies + usecs_to_jiffies(t_nfb));
- }
-
- static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type,
-@@ -488,21 +496,23 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type,
-
- static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
- {
-+ struct dccp_sock *dp = dccp_sk(sk);
- struct ccid3_hc_tx_sock *hc = ccid_priv(ccid);
-
- hc->tx_state = TFRC_SSTATE_NO_SENT;
- hc->tx_hist = NULL;
- hc->sk = sk;
-- timer_setup(&hc->tx_no_feedback_timer,
-+ timer_setup(&dp->dccps_ccid_timer,
- ccid3_hc_tx_no_feedback_timer, 0);
- return 0;
- }
-
- static void ccid3_hc_tx_exit(struct sock *sk)
- {
-+ struct dccp_sock *dp = dccp_sk(sk);
- struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
-
-- sk_stop_timer(sk, &hc->tx_no_feedback_timer);
-+ sk_stop_timer(sk, &dp->dccps_ccid_timer);
- tfrc_tx_hist_purge(&hc->tx_hist);
- }
-
---
-2.30.1
-
diff --git a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch b/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch
deleted file mode 100644
index 92c40ed81a6a..000000000000
--- a/sys-kernel/cairn-sources/files/5.10.14/hardened-patches/0112-Revert-dccp-don-t-free-ccid2_hc_tx_sock-struct-in-dc.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 4b8f9f14b8e6e099f53fd14a4f00638701dc0fc5 Mon Sep 17 00:00:00 2001
-From: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
-Date: Tue, 13 Oct 2020 19:18:49 +0200
-Subject: [PATCH 112/113] Revert "dccp: don't free ccid2_hc_tx_sock struct in
- dccp_disconnect()"
-
-This reverts commit 2677d20677314101293e6da0094ede7b5526d2b1.
-
-This fixes an issue that after disconnect, dccps_hc_tx_ccid will still be
-kept, allowing the socket to be reused as a listener socket, and the cloned
-socket will free its dccps_hc_tx_ccid, leading to a later use after free,
-when the listener socket is closed.
-
-This addresses CVE-2020-16119.
-
-Fixes: 2677d2067731 (dccp: don't free ccid2_hc_tx_sock struct in dccp_disconnect())
-Reported-by: Hadar Manor
-Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
-Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
----
- net/dccp/proto.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/net/dccp/proto.c b/net/dccp/proto.c
-index 6d705d90c614..359e848dba6c 100644
---- a/net/dccp/proto.c
-+++ b/net/dccp/proto.c
-@@ -279,7 +279,9 @@ int dccp_disconnect(struct sock *sk, int flags)
-
- dccp_clear_xmit_timers(sk);
- ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
-+ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
- dp->dccps_hc_rx_ccid = NULL;
-+ dp->dccps_hc_tx_ccid = NULL;
-
- __skb_queue_purge(&sk->sk_receive_queue);
- __skb_queue_purge(&sk->sk_write_queue);
---
-2.30.1
-
diff --git a/sys-kernel/cryptodev/metadata.xml b/sys-kernel/cryptodev/metadata.xml
index c7bb627138ce..c2846d62ec6a 100644
--- a/sys-kernel/cryptodev/metadata.xml
+++ b/sys-kernel/cryptodev/metadata.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>swegener@gentoo.org</email>
- <name>Sven Wegener</name>
- </maintainer>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>swegener@gentoo.org</email>
+ <name>Sven Wegener</name>
+ </maintainer>
+
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/debian-sources/Manifest b/sys-kernel/debian-sources/Manifest
index 0e6b290e8890..d6140143eeca 100644
--- a/sys-kernel/debian-sources/Manifest
+++ b/sys-kernel/debian-sources/Manifest
@@ -1,4 +1,4 @@
DIST linux_4.19.171-2.debian.tar.xz 1480804 BLAKE2B 5a26948990dbe34443a2af38683dd215739add79c420960d39bbc97d6e3652932250f81fa7217b6107e1327c8c70d394f2ba99342d1074db6c3de3d0682328c1 SHA512 24518c688403d0355bfe183c450e462310d69852a865331ac5fd6766ab9c01e0d416d3c545940d864426cb013bd5db504becdef938095c51a8086375aa07f821
DIST linux_4.19.171.orig.tar.xz 107575880 BLAKE2B 5b084939b192e816cf4c9b829bac364decee60176ec0cd274f03ed2f17d712573f28c54005a9ecf20d0e0ab388d9345766cacdbe3e4f7c9df836248d2368ecb3 SHA512 ff8eb0207476feef390f656681e8618b65fa1154a7bb2d0994e88e19b946ea8e77b2cd39c1586f16c3c5c775bed0d0097e13cd175f44fe4f531aab586f95e511
-DIST linux_5.10.12-1.debian.tar.xz 1305284 BLAKE2B d9df179c4ef639c27e7f237c59beaacd149a8484aaf30874d37d6d23c64428f64db56b5d48f3e6c1b230ca748086b8ebafee6fe540ad53d812781946901e964b SHA512 92f24ce3f44d0ad4b294a2610c9c355ecfbd803c22bd5293b708b17aa7a146138063884aae31ad5f80f30ae762458ff834977ff3203b46afc03f14aabf67136b
-DIST linux_5.10.12.orig.tar.xz 121447500 BLAKE2B 586ac53037c933c2e15d1a11f33ecafbe02c5bccc71e3612f8ef01ab7be6f03e7a03a22b98439f1fda964da23680dd8dcbeb5a0840a60d4497560b1980d19c2e SHA512 7aeebba8639ddfd33d3f731098eb087102a5bf98e112a288c5faf2c4a265518814ef72312f5a1263c60eb030753dcdd4cef7e1de53113e3e256a47d96b7bdef4
+DIST linux_5.10.13-1.debian.tar.xz 4005688 BLAKE2B c037a10dc97db68e88cae22bbb6159fdddf122afc5e1fe76e73768aba706182c2e6129a7ebac22074f74162142c7b7b41e4945e481e0cede2d766fca06dc3e8c SHA512 5e8342c84b6c8fbc58fabf2d485487fe8dcc590c2ad2241300721381fcf8ee5db39aa98a2308c96b6da61be72dd249404a9c70ab3cd7a8f1c0e2cfa8e0484713
+DIST linux_5.10.13.orig.tar.xz 121445856 BLAKE2B 68f1eb2a08c7eed558a69810fba476f408617a004364fefc6851435b40f0cf57883bc3735f3329adba421ef214dd9754b1c754fd5f078af07a8075875dbb9b08 SHA512 02ce47475511d082d19b9d9d14c5d0af97e331db058d276b357d35a737a7b6b4620d6fdf83f388f588b559d1d4f07ff9280c5221b1f25df89f9f3954e18e55b4
diff --git a/sys-kernel/debian-sources/debian-sources-5.10.12_p1.ebuild b/sys-kernel/debian-sources/debian-sources-5.10.13_p1.ebuild
index 265bc8cca223..265bc8cca223 100644
--- a/sys-kernel/debian-sources/debian-sources-5.10.12_p1.ebuild
+++ b/sys-kernel/debian-sources/debian-sources-5.10.13_p1.ebuild
diff --git a/sys-kernel/debian-sources/metadata.xml b/sys-kernel/debian-sources/metadata.xml
index 1fd2999852ac..35b97c0ead43 100644
--- a/sys-kernel/debian-sources/metadata.xml
+++ b/sys-kernel/debian-sources/metadata.xml
@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="project">
- <email>dev@liguros.net</email>
- <name>Development</name>
- </maintainer>
- <use>
- <flag name='binary'>Builds and installs kernel automatically</flag>
- <flag name='rt'>Applies the CONFIG_PREEMPT_RT patch series</flag>
- </use>
- <origin>ports</origin>
-</pkgmetadata>
+ <maintainer type="project">
+ <email>dev@liguros.net</email>
+ <name>Development</name>
+ </maintainer>
+
+ <use>
+ <flag name="binary">Builds and installs kernel automatically</flag>
+ <flag name="rt">Applies the CONFIG_PREEMPT_RT patch series</flag>
+ </use>
+ <origin>ports</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/dracut-crypt-ssh/metadata.xml b/sys-kernel/dracut-crypt-ssh/metadata.xml
index b5a52fe7a222..a177103c3ee5 100644
--- a/sys-kernel/dracut-crypt-ssh/metadata.xml
+++ b/sys-kernel/dracut-crypt-ssh/metadata.xml
@@ -1,15 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>jakov.smolic@sartura.hr</email>
- <name>Jakov Smolic</name>
- </maintainer>
- <maintainer type="project">
- <email>proxy-maint@gentoo.org</email>
- <name>Proxy Maintainers</name>
- </maintainer>
- <longdescription lang="en">
+ <maintainer type="person">
+ <email>jakov.smolic@sartura.hr</email>
+ <name>Jakov Smolic</name>
+ </maintainer>
+ <maintainer type="project">
+ <email>proxy-maint@gentoo.org</email>
+ <name>Proxy Maintainers</name>
+ </maintainer>
+ <longdescription lang="en">
crypt-ssh is a dracut module which allows remote unlocking of block devices encrypted with LUKS via ssh, during the initramfs stage of the boot.
</longdescription>
-</pkgmetadata>
+
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/dracut/metadata.xml b/sys-kernel/dracut/metadata.xml
index 39e56c08ac47..c924377f0ff8 100644
--- a/sys-kernel/dracut/metadata.xml
+++ b/sys-kernel/dracut/metadata.xml
@@ -1,16 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>chutzpah@gentoo.org</email>
- <name>Patrick McLean</name>
- </maintainer>
- <maintainer type="person">
- <email>alexander@tsoy.me</email>
- <name>Alexander Tsoy</name>
- </maintainer>
- <maintainer type="person">
- <email>floppym@gentoo.org</email>
- <name>Mike Gilbert</name>
- </maintainer>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>chutzpah@gentoo.org</email>
+ <name>Patrick McLean</name>
+ </maintainer>
+ <maintainer type="person">
+ <email>alexander@tsoy.me</email>
+ <name>Alexander Tsoy</name>
+ </maintainer>
+ <maintainer type="person">
+ <email>floppym@gentoo.org</email>
+ <name>Mike Gilbert</name>
+ </maintainer>
+
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/dummy-sources/metadata.xml b/sys-kernel/dummy-sources/metadata.xml
new file mode 100644
index 000000000000..93bdefc36981
--- /dev/null
+++ b/sys-kernel/dummy-sources/metadata.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
+<pkgmetadata>
+ <maintainer type="project">
+ <email>core@liguros.net</email>
+ <name>Development</name>
+ </maintainer>
+
+ <origin>xor-overlay</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/genkernel/Manifest b/sys-kernel/genkernel/Manifest
index a0b2eb3d2be4..eb04e898dfec 100644
--- a/sys-kernel/genkernel/Manifest
+++ b/sys-kernel/genkernel/Manifest
@@ -36,7 +36,7 @@ DIST kmod-27.tar.xz 548924 BLAKE2B 9f12bf5792d4c867e28e0776c279369c063e84269212e
DIST kmod-28.tar.xz 552448 BLAKE2B af41a0c5681fb94eb5264f46ed2ae666d171d4e2d0dc21419a3c2f4b12a783350a06b408fb02a7afb00fcea1cd994ee35864c1ec8b7a8cc58a8c9dcdeffaf1b3 SHA512 50646dc72675a5e17b01e327e3d41b972f18aaeac20c8b00983c4d099c6218f35c32c184a833a2d7f716755d6a86851c90913d2835874cef933bdc4a9722df9a
DIST libaio-0.3.112.tar.gz 46977 BLAKE2B 088f3b195a65bdc97ae2318e47af17c65259ed3208dca7bfef93c81a800602085e5b2078dbd436c740be316d0ebd923a1b3b7c0808257e2e7c7fb0f7ae1e0dba SHA512 5f984529c9f747a6c82f1e4457fc0832bb1fc299ae6e700f2ac5a8ea7b9bfc6ea1e75809728cc115a020cff6685ed1f4e38c6aeacc1ea98dfccce04dd19dafaa
DIST libgcrypt-1.8.6.tar.bz2 2997781 BLAKE2B 90ecacae75633dfff248b9c07a72126aaa4a5c285141f89c42237326ae3bfb99c937eef05d87b466c3d8f5cf022725ccee5c0dbc74d4eb57523a8a2892864b65 SHA512 28a26f665b7e327b79815849ee6e84ab384ee9105d81d4d06e4feeea07d986f940cbbb9faaae8712068cace45b4110a62965a93201da0e1ad008b65808b2b29b
-DIST libgcrypt-1.8.7.tar.bz2 2985660 BLAKE2B cb2132b826f3f3af240e6c9ac5fd992808aa17ce64144d17452591a5b1e402564af82c021b58f5fd620ebeb5894ac9654835f6d8376ec05ee41fc02189dd6825 SHA512 6309d17624d8029848990d225d5924886c951cef691266c8e010fbbb7f678972cee70cbb91d370ad0bcdc8c8761402a090c2c853c9427ec79293624a59da5060
+DIST libgcrypt-1.9.2.tar.bz2 3206187 BLAKE2B e0ceb02b0c26a7246c4146640a9dcea01429a365bd484532b9d85fdb0c8f4ac1308862e70899a1593f4665e4b2d16ceaa10029702f67720897975258a25d8ab0 SHA512 d2e3dc89788763229f554382b3cf0c3a2680f774258abc4c1fd9ef1ad44920d57d14422af9b6b405e42742e691d19ab2ee458fddf057e778964519eee090f016
DIST libgpg-error-1.38.tar.bz2 957637 BLAKE2B 9532402466748503805366b94c82c9adfe5b448f885c26b33ebf7ba9957161ca046b4057f5ca862224accb9f2af731652a55d20e7a4ab69107190a58c8e11ad6 SHA512 b936a4738c2cee111d855b1ba3ec433da8c77799a87d1f71275f974f871ebfa593c9db06ea53f0490b6cd6b94bef34f6052a587a4d13d839ec0128500c2dd9de
DIST libgpg-error-1.39.tar.bz2 961676 BLAKE2B 8753a9295ca57ba79142ffbc7fa01a986addcdd6a8860cf80c9e1bf9f6f9dfce874f804205a5cdd956e026eb006f2662110c63e7ed52c7a42ee0c45923ae52be SHA512 b28be183ac3d3920363558c4b5b2c24f9074a302799915cc076674bb349dcfb6f09160bec1d3fb62e04047c3ce432d345f36b0905100a88cc730b53d4eb78e42
DIST libgpg-error-1.41.tar.bz2 967117 BLAKE2B 9dc95bc09f55915d904e0f956ecf9281615028b8b8d876dbc786b752068fefea56adfb5dd5db65bad656ab664d567e56541e44a584c7f8672c30537ed05c4db0 SHA512 578d1d8090b9f6e6cbe59d9aeebec7df81aae492f75ec343f8df530950d30866fa0a7903ca050bf7bf721413f7b2708abe34f7467e2b208cc1447ffc9bd5b9a5
@@ -54,7 +54,7 @@ DIST thin-provisioning-tools-0.9.0.tar.gz 500998 BLAKE2B ac269fb6dfd1baf1572da27
DIST unionfs-fuse-0.24.tar.bz2 30381 BLAKE2B c3886d7b0cbd4ac62712d7d94bf9544481200e4354539b29770a88974ea3298b0f594cecfc6f7accff3595004ad1453075b947a2633b5300a3684fedba4995e5 SHA512 e0e414f4edbf641ec9d0135a8723e43fc75412359b482f7aedd66fe8245e4df03943c5ecb6f8de4fdbd97f0346033c691e766cc4f4a755f5b43748e1441d3fbd
DIST unionfs-fuse-2.0.tar.gz 46537 BLAKE2B 2f5a0da5adb15c408e7b9d0c3658e389a1aea4a9a5f2f3809fc724af43cf2a4b309e4220e46647e3f3fc9b19d48c8d62692e190cf8536182abfe551bfacfcc24 SHA512 5b60204632f498931fff7671cc9f40b1800d34cb8c0d0de0773626e2653eb0a36647566c92c1d0cf79543e01b934602ef5603a06508407f352e48ef27a7ee758
DIST util-linux-2.35.2.tar.xz 5150488 BLAKE2B 93eb90ab33db7795b46425ec4ec87f8a2d3d6e0dad671345375ea02efd654bf72041932d30b41bea494e4b62952e2fd14ea9f9e6c738d4eb4b050bd170b9bb0e SHA512 59e038ba71aa74c9af6f927b357483a965f675ab3ffcd25cf0c1b043656312d2d2d07c55659fd3da69ede165bec313e0ae7e1cd73758e49681ae610604b399a2
-DIST util-linux-2.36.1.tar.xz 5231880 BLAKE2B 52d867aa0b722a84828c37958d80b0bdcc1ceaae4e46fa6550ad0f2f152c52e4aaf2c8bc5fdf4f27b522037a870ff2554382abac0eaa50a6791d8b8016e3d74c SHA512 9dfd01ae4c16fa35015dafd222d555988b72e4d1d2fbadd140791b9ef78f84fa8254d4d08dc67cabf41e873338867f19e786b989d708ccfe5161c4f7679bba7a
+DIST util-linux-2.36.2.tar.xz 5348032 BLAKE2B 17e49515f8d0430f3ed26b80bf1d6e811d847141020d0dae1340dc92887549b7b711f3db6e3913120871fc912435def73586a7aef09d8d9cc6ff7ca331b2770f SHA512 6ab141f44ca4cb6b600081f10eae17e15d23abd122a37eb3ac6c845513a6a4396dc9dcff30b3032de80116ddde50e27dfbc86f92708c1051f84f0c919194664b
DIST util-linux-2.36.tar.xz 5242420 BLAKE2B a03b626a376815f37a17b3808d1d421c7ec27a133edf857116603de38f7e13f527687691d0c8aa68f4f6868be6f3bcc64573d759308d74731107e02067449ce6 SHA512 cbb4975da8d99a1edd45514171d59ea7b019ce0f77a81e88b447a733f725e91c53540d9dc78bc626dc011dca129b8b150aaf9e64ccf62a4202ae816581acf4fd
DIST xfsprogs-5.10.0.tar.xz 1273332 BLAKE2B 8caaa0ca8a94480f131d36b383afcf732b3a5a7a3c7927b4b4da4855fc5a0fb97a56fcebb98391a4dd0f02465868a4bd857e57eeba053a419df47d42f74bc958 SHA512 da09e687c87c4b133888dba7b4458017ec028020637ea5066be0232bf5c7da18239cc33eadd02d9b99d1c835aab38cab1ec9d45ae8b83897f9157cfcb0271fbd
DIST xfsprogs-5.6.0.tar.xz 1253112 BLAKE2B 7928b29458e3ad8251b48b6fb14a515e0128701c40cdfa63c05fc85173c70da3f34c948b7791f12ac5bb8d5f0c634016dac71c328a8917d1065aa7fb4cac3291 SHA512 a6bee55b0a23316c73f3921234d1dbaa4cbe91c12e79264e5f9bfe1356a24baa0ab25270405a46e4613a7e48443ef21997ff4f5962663777bed373f89ca29701
diff --git a/sys-kernel/genkernel/genkernel-9999.ebuild b/sys-kernel/genkernel/genkernel-9999.ebuild
index bfa1e039fc9e..97bf576750c7 100644
--- a/sys-kernel/genkernel/genkernel-9999.ebuild
+++ b/sys-kernel/genkernel/genkernel-9999.ebuild
@@ -28,7 +28,7 @@ VERSION_ISCSI="2.0.878"
VERSION_JSON_C="0.13.1"
VERSION_KMOD="28"
VERSION_LIBAIO="0.3.112"
-VERSION_LIBGCRYPT="1.8.7"
+VERSION_LIBGCRYPT="1.9.2"
VERSION_LIBGPGERROR="1.41"
VERSION_LVM="2.02.187"
VERSION_LZO="2.10"
@@ -37,7 +37,7 @@ VERSION_POPT="1.18"
VERSION_STRACE="5.10"
VERSION_THIN_PROVISIONING_TOOLS="0.9.0"
VERSION_UNIONFS_FUSE="2.0"
-VERSION_UTIL_LINUX="2.36.1"
+VERSION_UTIL_LINUX="2.36.2"
VERSION_XFSPROGS="5.10.0"
VERSION_XZ="5.2.5"
VERSION_ZLIB="1.2.11"
diff --git a/sys-kernel/genkernel/metadata.xml b/sys-kernel/genkernel/metadata.xml
index fca8c03fc36d..8d64bbf915fd 100644
--- a/sys-kernel/genkernel/metadata.xml
+++ b/sys-kernel/genkernel/metadata.xml
@@ -1,19 +1,15 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="project">
- <email>genkernel@gentoo.org</email>
- </maintainer>
- <use>
- <flag name="cryptsetup">Enable support for Luks disk encryption using <pkg>sys-fs/cryptsetup</pkg></flag>
- <flag name="firmware">Prefer system firmware <pkg>sys-kernel/linux-firmware</pkg> over local copy.</flag>
- </use>
- <!--
- <upstream>
- <remote-id type="gentoo">git://git.gentoo.org/proj/genkernel</remote-id>
- </upstream>
- -->
- <upstream>
- <remote-id type="sourceforge">fuse</remote-id>
- </upstream>
-</pkgmetadata>
+ <maintainer type="project">
+ <email>genkernel@gentoo.org</email>
+ </maintainer>
+ <upstream>
+ <remote-id type="sourceforge">fuse</remote-id>
+ </upstream>
+ <use>
+ <flag name="cryptsetup">Enable support for Luks disk encryption using <pkg>sys-fs/cryptsetup</pkg></flag>
+ <flag name="firmware">Prefer system firmware <pkg>sys-kernel/linux-firmware</pkg> over local copy.</flag>
+ </use>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/gentoo-kernel-bin/Manifest b/sys-kernel/gentoo-kernel-bin/Manifest
index 78b7492a65b3..1c0f24915fd1 100644
--- a/sys-kernel/gentoo-kernel-bin/Manifest
+++ b/sys-kernel/gentoo-kernel-bin/Manifest
@@ -1,44 +1,27 @@
-DIST gentoo-kernel-5.10.10-1.amd64.xpak 64334952 BLAKE2B 6dbfc8d8dffdd7d2b9cc7fa1bb60868c87a89a910d46323966cac9cc61e9cb387c29453042eb3f8d3e6f7113c0e72b31a02e1657678bc87f195a658591a85681 SHA512 f2593710e4727c730ddb8dac708ba12c9d8bad88cb8b65f6746ae14b522fc47638ffe019ace5a3c578bd52869bed2e2e6d993912690e96204a26b93c12a19d90
-DIST gentoo-kernel-5.10.10-1.arm64.xpak 59568061 BLAKE2B 4cfc3645d31ab062d9cf69cac9ca76a56ee7f57d4895d455c68e3cf24d7eeb01e120a98257ffca3ff000419497ef5fe3f0da1ef6f31c3ba32c77f8d280a50f53 SHA512 c9cfd6c20471413dd6430437b9a6cbfa7b57259ce822016388dd07c566e042f56155de22d8d06c177e73c16c21d04e247eff663df95aa533b089d05055bb1d3a
-DIST gentoo-kernel-5.10.10-1.x86.xpak 57274976 BLAKE2B c606a4df7cb2df25a5d1d2668860791788878c2353e4bafd08f22de105f985aa78c9e494e77d041396bcb88cfdc72f0b6a1bb3d0b1e670e00b17eac163bd001e SHA512 13d3dc2fbfa1526e4f365a9f454ceffd7424004bf98f5d3116877758067bb13991ea107371f63ea46520f909b536460343a2b8f024f73b7b01b228fbfd22733e
-DIST gentoo-kernel-5.10.11-1.amd64.xpak 64361874 BLAKE2B 81f33a992539d7cc8f7e35de50515d2bd71268cb4d9bf53236d6abcd49cf5e235032d58cdbaa1d1c670ab63b0af150895ccaf1e830df610179392ed114ab7f98 SHA512 639cd26a0bdb4bdcc6dc6ef36702f8aa37cd0747e93e3b2053e0e66139a3d538f019b795bd0bed48a8236ec3f5c768551a105e4f8396824c614b406cc450722d
-DIST gentoo-kernel-5.10.11-1.arm64.xpak 59510738 BLAKE2B f7bc2139a24b295f5be4ba9797001a5797c0d5e47a98b7c9e8f38a91733ae64da79610c4f8db67f8e53440a6f18dc44552ab05df528a067492a1bba6f30d1c96 SHA512 e65d51cfb3453d0c098ef484e29af113356739310e0ffd386d27d9933e18e7e1759a425e8a0416b8026176400fd3a69df6f38ba802771cd413a96af8f6d89282
-DIST gentoo-kernel-5.10.11-1.x86.xpak 57287495 BLAKE2B a23fc6067de63dc97c89e3de9310bca4705c21c407601874b9e8f0c68608eb0752fb1add9f351453882a24e1e89f4ab38635161aa177fb0f8f25bbd8d5ca00e8 SHA512 f522d97ef335dbcd3df0444f101add87e530f141d146f65f1c3e4b5776bb9f701557416263122c505d17510b66060f6f4e5d3c4fbd408f8c90c89f76c844c4e8
-DIST gentoo-kernel-5.10.12-1.amd64.xpak 64350144 BLAKE2B 2b20f43d0e0c64af3ef9918bfeeba4997983782cbb9ddda57f5da641f9cf25b57a24c24775048955931047b3b4b0117984818c8fc2981803dcdb93bfae28d58d SHA512 271399b7ac20fd9a10bc7078d31002a6e4f386d83d89b8035c6c494e78644e550e8a7775cf229676ba7ec5aac7803ce41e6f3f068699b06fb43b38bd322c172a
-DIST gentoo-kernel-5.10.12-1.arm64.xpak 59600745 BLAKE2B 37d1e3bff20fe9a97ff5b3e3ed003f5f425f45ed13f74f6e2e2dcc3fb28febb24c7a58019066e8dbb0b05b02aa41eb1bb07e357241f1a1ed40769619168e579d SHA512 4625f5758c315cc1b50efd0563a8a6579eec045ab5d88f24871bfe8260109eb51e7e843c65f8bac9c50258521a3922ac28338f9a8591b059c31467691db7f9df
-DIST gentoo-kernel-5.10.12-1.x86.xpak 57278945 BLAKE2B 3d97e4fafcaee7d6f9be1f05c3beb844eafac3a188d36db3c540add6c717f41373f2810ba7d9039a83685220e6d622cff35f588d2fa3682bfbbcc0d72edba547 SHA512 c13dddfb7280250e37576727bc4f12fd26aa8973608ca69cf94cd75ca5ab2dbcd89b17ff491634988b9944b53dcfc08bd4e48697834235aca320d580cc3838ef
-DIST gentoo-kernel-5.10.13-1.amd64.xpak 64342967 BLAKE2B 9f88a6f23d4403241aed7f2b44de769902eac86ec680abb2d29a0fa789b6dcb9ba68058b34672dca3a8ce8472e06ea5d019e1a13975b9f0b81a6e59bd5d5fea0 SHA512 56a5361134ba063835d4dde0da03c7776a24419a71c427be224ced5264b587b7c0883954bdeb57dea5e5615f0833704fe4e849ffdafd4cb69dd73734fef513bd
-DIST gentoo-kernel-5.10.13-1.x86.xpak 57282928 BLAKE2B 4db08e15a64c949f82be99b38801a3b4cdf053165ba3129904bf67627793390872a23fe4c8de4d20d2db527d10da324bf31a8ca5594d2cf17e230f79e85e8af2 SHA512 0cf78998d29b82fe9cca3ac83e1a013178396500f1fd2a870300e541309107eac185bdeb11814cc9b56e1bd00a8a2fe6f175f1814c231527766ab99ffeab8ef1
-DIST gentoo-kernel-5.10.14-1.amd64.xpak 64344950 BLAKE2B d51174b3b2fbb3c25bf2b6423cc1f65d1c40e6849aed60ac62eab7936b34c33fcd16395431aa5a9e49e347425bf6fbe44aea9e7d8a72f14d82b0024b47e488af SHA512 46ea0a591fc705fb6b6da3795f54b6538b710034f87df030e82789d6750d4cf1433be51d6e00fdad2be7e3b8fdf12485cb1b97ff269a4f00d13feec7a33c394d
-DIST gentoo-kernel-5.10.14-1.x86.xpak 57279381 BLAKE2B c6192e95414717841b0464eba0b0c037abd71b55ce0599d018ea5760c08d912c2604ea0f8ab6942976ba5c9b3bff5c739c414eeadfd462db52f73f70b00ee614 SHA512 310786e118cf140415009044912c15e2389c0d00078cf8896a91f5a697476ae972b77fcb7b0c3d5a0377023d7c0cce490b16886e04ffe006e9c7b29d6a4bc7a2
-DIST gentoo-kernel-5.10.15-1.amd64.xpak 64341722 BLAKE2B d2a6b3b4b53824a568e924517a3cb4930db5611154d93bf2e33629b6fa72c0da0a18fcfbfc9d09c4cd1ba927558d4180736b63e0b9a022da0f584936ec0f7fc4 SHA512 14f655eef1df2578c905d4273942429bc00f3800de042c48a63b8db0b68dc3ad3fb5ed4b25eec88879220a8ff7bdce23be580eb50b7bcc249e77b8a2bc6b1b4a
-DIST gentoo-kernel-5.10.15-1.x86.xpak 57292674 BLAKE2B c97cd518abb97c3511382630ed1ade91a75d7e4ef3520fe104b6b2407b0bc911de387fabd30d03f1a05a9e5154fb039928b7964c74cd53dfa3048ac72f0101d6 SHA512 4862fa1ef3e84d3247a57b3f1eb9bb7751d9fb74649aee537b152c744d12b29c3cd936d109bf7bc7096a5ec6168e0a8ade4edefcade8cc65af7c6b15c3e2e399
-DIST gentoo-kernel-5.10.9-1.amd64.xpak 64344838 BLAKE2B a43bee38c3d4ce1be11d99ee73489cf2d93c794fa06405f7597a7a2fa29c9ef3e64a0f9f34a20467fb730d25682062cba0ad73eb824b34918c5854010bc6cfc7 SHA512 b6c09eac07a3ada4e8ab6573d877ac62ac67858f4b5ad70364e7414fd4d269df88a57dd4fe2bd31a76537fd464b234fac513e898f07969f5d5c6857c8f0fbe65
-DIST gentoo-kernel-5.10.9-1.arm64.xpak 59837992 BLAKE2B 815b3f655ba9f8e8f7f0e000f41575fb752bc50cad2a61af71e83b824ac19f391feb28ae22da0233520629229aed3543ffd3a9f94794c741a8583aaad64d7d4e SHA512 bb1ecbcae01c1cd87bee0a07edb3daf20a9644b89fd3e588180d52e43e6eccc74511e9f74de56b0d729f304683b8ee30ceb1841ad944f9b83222682b2d977e94
-DIST gentoo-kernel-5.10.9-1.x86.xpak 57275255 BLAKE2B b577fbfbf9a470a4383f6d3cf91a26ecb8e41da62807595fded551d52b4629d2f532604e986900c9b8818a48dfbfc87b98deafbffa0c2a96bba8a252446e7675 SHA512 ce5d7bbe47d0c2ec31611580da10af7e4d0ef8979ca14a86c172b75658ef536c25b6336e57aad023de890f806e6e93658d9cf809d3a4f08bb5b2c22b002ae2c8
-DIST gentoo-kernel-5.4.80-r1-1.amd64.xpak 61053571 BLAKE2B 24eebf676e1824b01aa6b75963ff8afe25e797afe90440016f4675e8385e1d6b1a04aa662d7c92217af97d56d79f9631a84c2a271b005b5ea7ad71bb8637d941 SHA512 ea99729ee68a44f6b5081e0d81dd7d5abbb50482eda8c4e435d6ee997572362de09d7c813da2ecf1aac4ed299feb73205bcff7d4d359793889690ce07cfb057f
-DIST gentoo-kernel-5.4.80-r1-1.x86.xpak 52880910 BLAKE2B f94a7bbdcdbd383e919f2542251d2552e50e34264ab495a43d75e28dab881162f2549b48383b32a3b2a813a192b7d9f602eaa8210085733ac123e2246e6a285b SHA512 3b5dd91103461306f4a4ea4554792d4cdabedba6165de119523b927abb2009adc7d554f23110ddeac1a1add69b2d1674b7b87b93b1e1b186a2594174808dd9d2
-DIST gentoo-kernel-5.4.83-1.amd64.xpak 61015400 BLAKE2B 73527460e0c430a23c8221f8a736416ef6c3ff0ab93d017096456e72bd6c2c88e2a631bd18b2f995bc929f918e9b5a59aa033119a534a985ae1e33d39ff48790 SHA512 53dbb9fe6d940bd93eeb35c93bb869931f8f423f6c3997433030bede0b0c11dde478e391ff372ff252771a1bb32207cefbfb478f79715ba2ee3910016087bd87
-DIST gentoo-kernel-5.4.83-1.arm64.xpak 56245318 BLAKE2B 53e8e3e3bae66539622bf56c175fe2055905c8a39eb89ea084d0622fab366c0b0614a209d2063e7b44005d438c00759b2a5aca0147b83e9bc17b2a321f693d14 SHA512 657118b04169d9b2bf32fc11138573e0ecf16b27155b6f299e477b211885805bb6c9beab22a19d2d9f93c9a57f0d21759e6ff9b3747c9c7dd76a39867b04b1bc
-DIST gentoo-kernel-5.4.83-1.x86.xpak 52886754 BLAKE2B 2594b014c703f9f960d180bb6b2973027d238a2232ff8c358faf76a78d8ec8835e423fed19ad8afd30225c11e884a93411636407ca5a034c8abaa32635c21089 SHA512 70776892d7cd38d3bcd4cd797a14fb25f72bf0f29c2abd14a21b2361fac062c037b139588554b47727929ae60d331e6bd6ceec0c2f8e8f830adea4ed92279ba7
-DIST gentoo-kernel-5.4.88-1.amd64.xpak 61056095 BLAKE2B 67532c81c4c3ae036bcebb30bf08c5371d47ee94adb6d56afd31e3548a82a6e69e2fbf7cf5c4caee42a8a277d1faa609427e9962eba823e49ee82f926fc48f67 SHA512 444ec47f98e0d9344d8ee2083256ea1d83d78f319facee7959564da2d5132a0c26588a1575ac6ccddb15b68f066ebaceda5088c2fba716e6fca29d9e04bf0781
-DIST gentoo-kernel-5.4.88-1.arm64.xpak 56317914 BLAKE2B 3bf2420216a8a4f562d03c45010f3592399b2246dafb3dfd15ccea4327650fdd029284406ad6e49894ae3360a2d7ff0661b2be3d7915aac4e17263ae7e816fed SHA512 ddbfde061506388f8224459eb4f73d61dd43692b456556a5fdaf06b4ddb4dcfafb1fac097015ccc7c25640d1e3488a66a30312b26aa4dfaf565e885dd4f679bd
-DIST gentoo-kernel-5.4.88-1.x86.xpak 52893703 BLAKE2B dec54ce2650c69ef3a558b6ab63c622d4e7051fab003923b7f838fa54e247d712fd8c85dc9d00b3430ed02170f99e29b812777ccbf0b62bacca66f0b4e358e30 SHA512 0267b4bffc0c7f76e9fa72fab6d2d55a5e65e228f7eff7a11cf9dd8b731adba41e36ffc8b0efd33306767f5bd645a690fef40750dfa0b83bf427d3e250eba1e5
-DIST gentoo-kernel-5.4.91-1.amd64.xpak 61048020 BLAKE2B f2155b5e4cdf3f142eaa1b81bcef529840dd50c0eb7d6cc225216ce5965bd53f00fc7c6334c6c7e6332feac3a3432dcdbc35622d9015cf750fcbb08202bb9c40 SHA512 fecb178c72e37b12d940e924a320802e4bf1a27338a7f07c0f0cca9c45f65b72b9e03eb120da399aad4e9aebf2ca806134de4350b9b8c936665a2845fae88de6
-DIST gentoo-kernel-5.4.91-1.arm64.xpak 56311101 BLAKE2B 3c84a83b22f6449d9e83f81dfd325de0796d1ce7078fa0b61ac11e0d9e3d5e0535719bf4285f4283cd133e4165d3e3b2bd282a21eda881f4857548769124f65e SHA512 b41342608d65e94bc333e388c6b623df00ca6378d50b95d6b27b50be1374ed90196cf4ac6a118b37f3aacfaf0c0aef16399b3c6e6a25871a80d218dd187e404c
-DIST gentoo-kernel-5.4.91-1.x86.xpak 52889220 BLAKE2B d58145b5a092981f90f7699d1455a6f8e21bb5b8c15d4dba100aa0512782248d0017adb19edc7fb7a5348649aa76ea285e4f288c1f748d9de18453db505daa54 SHA512 5b1e5563181c1d5fa6593a5547f22670504edea0f9553e0b4e7d43d8a621f46ff4ebe369c95e1d7239c483ee31d99b9395384cb02e49c2eefecac26d475e9ede
-DIST gentoo-kernel-5.4.92-1.amd64.xpak 61046219 BLAKE2B 0e4b4db5eb4e15eb66739a7b756a11f194e420020c47eb89c73c7856865e09cda7d065d2b7a6f32cea925e29cc25b07b5cd0447ee17d41a47656d48f49d8828b SHA512 ec22ea8fa8e1de284f5d3408deb152e5de48ac85e197f29738998bb97aa556c910ba133c154e39ac4f50a7d64195b2b093864b3a171418bfabc2509c2c550665
-DIST gentoo-kernel-5.4.92-1.arm64.xpak 56356094 BLAKE2B 0472855af98713a38e1fed96eb64b72c74ba9b29c7713648c25f91fdab3f5a4f28322b1a37090f357417656af82173e3992a34ec1c5ebfc68c0401ab231c5fea SHA512 295808b8c9c00f803a3519a5ce9eaf6ec99979a58b276d988b9fcbf1f2433c5d45b1d223670b4977a921ee4da7176c2a29cc860e129d7b2e7a4b937b5365d98a
-DIST gentoo-kernel-5.4.92-1.x86.xpak 52893632 BLAKE2B 74187e0602932a720faa468c68fc215b8ed347b0364bc532dfcb9f34acc6e072a19b9ee2d82e61aaef2d3a67417c582038f967572b5fa264651e542c6ab00af7 SHA512 31606acd96f4b844ecd476f719ea0153d6b187a23c35a593ce9b70c2c9970b0be2a3a0c0eb57ae341d07231e7577a939ddae87d45dce79eb998fe90a13257d0c
-DIST gentoo-kernel-5.4.93-1.amd64.xpak 61051190 BLAKE2B 80cb1938d7ef498796df7008f1bb2a8d30d5d69b75d0b0fcb0c7af45867b5aae87860decd4eb41947ed4a7678cbd94f4f7f480a4d38a8050d4751d0c3058490b SHA512 0100f8d88d9ee798fcc9813b1b086c3551feadffa0ef06a08070614a52f5d4ef146e622017e590a5534c1d1c9d502a9f2c72d450724a60c3f77fcb925eb1d93a
-DIST gentoo-kernel-5.4.93-1.arm64.xpak 56339310 BLAKE2B 2b7edabc83e56bcefab8a332fec5c46b9d6fc0c27d38a66509b3964fbab1b3ea86130e1ba1e47a032599916dfc664cd86d62c64525934e1712b39d5c481d87f8 SHA512 619cf0c43b9afd3f37a1d069544db00d96ad6fb95995c731d0b9d1c868755f2af84601e8f7420bfb8c75bbd45de264acdc6d79e406406e72197c08720d8fc82b
-DIST gentoo-kernel-5.4.93-1.x86.xpak 52895797 BLAKE2B 069b8e797b479562033dffb19e0772787ee383a22dd4ee5ba2f8d464cba7ee07073198fd2d3b9ecbcfca1ee72900550ee03b2ae52c11eea4b9bec38c5ca5f2e8 SHA512 dd81aa89c9473cb555bca44965e01e39018a06ee6e7de3512b0ee721cf8a462abeb3503b61017b110e6a39167ceacc76e15f61112055ee7dc4645a29d43953a6
+DIST gentoo-kernel-5.10.17-1.amd64.xpak 64346939 BLAKE2B 3387154f735f5f6f50df4fd236c65a1f7c0b4c2257f637bca75d6569c5ac2f3d841828ee94b0072e3edfad947487157d9c42c3add280e97786947fbd305e851d SHA512 7572525cedbbce2d5a2478ab50afac686b01a213af110a570d514c6a7c439e5f5957fcd95c643db3ce1201c50944f64bbbb9a10a38f803cfcf7d3de1368847c2
+DIST gentoo-kernel-5.10.17-1.arm64.xpak 59606648 BLAKE2B 444e43a12a94310b00ed686d3225b61284207f93995bc75375d66435ba22cde42a1882fb1ff7479f1ed6ba369c509de11ba453a945f6608de83b1f121a5fb4e2 SHA512 998cc8342ab5e68f74a80ddf6f1fea68a618139492f5c078eb5c1619611f5635a0635ff362f9414c9518011868bd0f3bf12f110e5e5717e32c728e5f369a6b50
+DIST gentoo-kernel-5.10.17-1.x86.xpak 57292329 BLAKE2B 824b77875aa1336fff7b9f054f837904462c429b625a5085296dcaeee156c2d794242fb35d2d0fd20fb6e8230895bcb5a8b334f04b86034c0818bc0b740f8b66 SHA512 bde8d238b592f7aacf63f3b4464790d3df5901bc772850ec991957c849b634790665a2b9affd0484107017d909a45eb6634a0c345b73bd77274c3101432bacee
+DIST gentoo-kernel-5.10.18-1.amd64.xpak 64024674 BLAKE2B 456b0e7e35bf54ba06908212e1a8c98dd8dd99b3670dcf344fa9b4a829413eb2c38e98f52dea3af0df80a31e925c9349851049689f4270a3cd2e03882d66c636 SHA512 9ca89659dd020fae705c71813e276bf36ef874f74d1264b7b33420aa508f01cb018b0ccbcedf774a09d00c2b881f4798b7aa3c42aeaa8319175fc9318af02ba5
+DIST gentoo-kernel-5.10.18-1.arm64.xpak 59269183 BLAKE2B 3ebd1c3ffc96d761132ce899da374286ff800ad6e057fb758ba175b8b07464723df988ce3e2199214c2b4bb50508839ebf3a490966a87d85faf0f8f99cc88012 SHA512 f50a978e376a5ee438c9992ce7afb4cb91277b498a4e6678e91edb903ae4992af237ec2f13c4b737594003bd69ee4dd4e302d1fd3d722d009c121528dde18f46
+DIST gentoo-kernel-5.10.18-1.x86.xpak 56984732 BLAKE2B 8c764915907440e0840f345fa9c7f475f5a016f02d19956a36b00349356755428114629a47ae4a24d212cea2ae3694adbab0d4a5a367dc4992dc542855373ff0 SHA512 b59956497a7ae1f79325108857a6bc7c9abcaea6874ce857a8021e8e26204f860afc6b7e29a9a028b3e0f13409e50ebfc6ff747fe32c0789302296012a9c07b1
+DIST gentoo-kernel-5.10.19-1.amd64.xpak 64036559 BLAKE2B 8f71ea8599f8d26931e6f4314a16fad1d652397f87279af003d7a4f94a83e1f7cb0bb89f197347e0ef8008d3ac7dca3c3478335fa20c8f1ac52a1412468352d8 SHA512 65562dd5297b69a29eacf50d3967d1115ce716b20d40893bc58ac98e29b949b9986a983beef629cf40a6d419997a2f49afc5cf16df720804af0bc1afc6d92ae4
+DIST gentoo-kernel-5.10.19-1.arm64.xpak 59222742 BLAKE2B 0d5468611285d6153a74c597f92c5127322c668b88aa5e20c94c7ba5546a7b33077c769e722e1f1f94f8df907a7e12731b99cf3a926cb1222482248f4d9334a0 SHA512 51601d08269b564894e1d6b27a16e0a7f928c86c83e996efd7efa17caf1a0dcf9ada93eecce72dbb322a952c5261f0056612e1d496fdd122d1e5bb567300fcb2
+DIST gentoo-kernel-5.10.19-1.x86.xpak 56996359 BLAKE2B 58e9d8e9a3c28e95a25f91fa2b7a0e70103b976d52e44ab37ee1d69e59ed4b0ae85078208e5843a1c1d03672ca00b3b12382a4d22a969d34a895b6081123cf1d SHA512 c9d7b41a60032a2b5273c30df01a22300b1a95029c768cb89fa6f1b49d79bd4f0a965766735b418e24f679e534dd545841cbc4749a6f5ce455e91124c4428eee
+DIST gentoo-kernel-5.11.2-1.amd64.xpak 64830406 BLAKE2B f9c5d0591a175e497e3ff9f9c12e855e0c7db90aaf28fef5bbc695604c5745e13e3cd16001eb75216c55868497954a58738a7eca2314f077548650ae27b73620 SHA512 9a05cf8ce3218ac7e6b880624cbdc67d7fa221f0440f920de70f883a33978df08297184eeeb7a5b3c420da34ba7cb9ebc38f11c9a4979cf5d8a5c7a33e82b85a
+DIST gentoo-kernel-5.11.2-1.arm64.xpak 59866719 BLAKE2B 5c8e59242ac3512488afbc1335845294f6ed6b5f7cf0674c4655689b4e93284b110295da479c14f3bd70111c5f652a2c7c641bd34b06f9d7b21bacdb3965b746 SHA512 978891967b1b2c59ca1d4e77bd7d622585532e39cdaceae087a72c6f72d57764cd9dcdcad918ddb1c2d92a42ddc9859baf532971a280cbbe7c4811acb7cc3f5c
+DIST gentoo-kernel-5.11.2-1.x86.xpak 57784553 BLAKE2B 452b7e2bca5f9c83345b14f8a3e9ca54bd18e2b6f89e9d165ee3b59de8b8cd46411858a08d58546cde72180bf78c596f1ab3d595c2e5e818e2df9722101cf0b2 SHA512 9620e721c8c0e474db8861400b3109a2b26af68aafbe94975030a45f620e7f7ca5f9837d8dedfca6e97d5b4cf458ba76d34eee790268ddbcc4677d2b06e220df
+DIST gentoo-kernel-5.4.100-1.amd64.xpak 61080710 BLAKE2B 84b33a1aa252b0957eb90ddd792f001942589d7f65399a5b007a2c831d0a1fa3b879814a55e5cf8b1ad6166970d3ac89838f57a2c61cec6b7b136b55d5ea4c7b SHA512 98b3dfd31a2830ed49dfc7094e9f37a39e7fbef54b648b4840122f2b53b8e970fb9c75a653445753d8e4efbd723716b9c56b2f99214c79832f3e49de63b3efbe
+DIST gentoo-kernel-5.4.100-1.arm64.xpak 56394488 BLAKE2B b8ea7a56a087e98706099cc151b652dba2a40e2a39ae99670b0989ce2f11c133f07b53dda1a9749f946719ab8a5b97a57ee0a12fcf3d9a568b498859420eeef5 SHA512 549ada0acf8874d3254c8a586f5c4d0ed4f08a103aee74befae38fc47d10c716d86f3f133b8ee3c49e61fcacda2298b04b5fe96bf35917b0963f922fe424e96f
+DIST gentoo-kernel-5.4.100-1.x86.xpak 52912122 BLAKE2B 5f1a8f7ccf3f9df6a89650d62df903896cf0342b9cf6e0fc265e67a887aa9a0608d62b023d9641711a2d9196958ddfbddec4e19f5f731356f5bf3a74421145f9 SHA512 6d1e5089bb817cf9e7401bb1be0b1d1433caea884b8ba4208c973fc7bbd879b65b69ace8fe3cba05bcb6aae0607ff1be9a63da42642ec2c32fe5ff7adf6fef28
+DIST gentoo-kernel-5.4.101-1.amd64.xpak 61129676 BLAKE2B 87166f24485d888cf3a76904c38cca21135399f25c58524732e5b3d291c33cfab12b0ddac1450f4fe395ecf17de5b44d0f8e70d685f21c6b5c6b1b2707209149 SHA512 017ec51bf227817aab05a4ba958d8d3c645f9d0ec774c210c3ec3c2b7af7be18a3683e75ccdbf1dab2de7954bdb6bd1527b1d398adbb8ddae616543584e6db09
+DIST gentoo-kernel-5.4.101-1.arm64.xpak 56300423 BLAKE2B 45b69b3f406a4dbd297db8c7ace87c1c28fac2328d4e5c9f26168c61514a71ed861fd35303bdbcc4bac39f12c03e3e8c31f97f3a133606d6314b5b4a5f652059 SHA512 1d638b23f30d686face84a7026e7882c18891c50c107e467615ae7910beef17c48a7c42e7a4efbbc45bf5fdfb413da3cdecc718fbc3ac771a92f076e27793613
+DIST gentoo-kernel-5.4.101-1.x86.xpak 52909165 BLAKE2B 39a094693fe036d75fde0ee331492c8e859a0529e29c45ff7fe8a8f7bb87dd8a5fa8782ee34f297cc046e27701a491ae27c3386c6902f56b1c93bd88d1bc55ca SHA512 f58296401f06c029693639379115d6f94a5203e416e1eb1d75611d0660a1d81385958b2ce2cb66776e9766937bf6df746e3f835e3437bb0b7702143f5050d667
DIST gentoo-kernel-5.4.94-1.amd64.xpak 61075025 BLAKE2B 96f7d69735dacd618266d4220907d2e196d4a59f39fdb6c93e88299ecd26a503684bcfbe0a0dcc8c027c3e1b90fc7c066f0d0cb5e007efee859215c6a4b91807 SHA512 e786c30e4ac3e62f25cb6403105847c20b7673f0e9fee32f513854c6e739cce513409f136da9dfd8c366d74ffc4db00625dc5d6270623af56149e4dd05801c57
DIST gentoo-kernel-5.4.94-1.arm64.xpak 56309818 BLAKE2B 50f9f4d7bfaee560860899a0a16805c0a805a9cd0b915a0dec3f654180db73cc73f3247ccc808842103fefabe9cbc0aa963aff8c649c0fe2d314a6ddf22a02ce SHA512 36ee8c73e76ac00ea6c26a5530d6dab91df46fcf2b5f072bbcc44d8bf8b7df710fa601584ee2707cb1c1bbfad9342e369a00926224a0527f1fd4588d01085508
DIST gentoo-kernel-5.4.94-1.x86.xpak 52893412 BLAKE2B b694d25318a84dd4d458b3ad42193781a42853fef9bc21c7e0f3671b5d74b9358c3408bb478d669d57f3618bc433d29df02bed71d80abc7bb8e8814c6e08997d SHA512 c64d72334079b3650c37427ab38e72d9b0d946d93989a491224a936e59d4eb0e43046bf03d85487d41ae6dec43cf5c5dd8667d3e2c9cf7355ec9e95f61f096e2
-DIST gentoo-kernel-5.4.95-1.amd64.xpak 61046196 BLAKE2B 0473181cbf20219d9007f7f5d0e0fa8f1f9e50a65f21dbbca551a1b3b3a5b22e6ec84c9979d541acb792f8ae9be072cf89e6c2652427195dcac50f5c89862d3d SHA512 16e4543c6de8fab3e0077475e9324fbbbd6a7b67b3baa5e8e7d91b0cb401a5fa39e770620a14a4707acba9a82c30bfa8ef0b0ec286b1d55f4c5ac7028fefeae0
-DIST gentoo-kernel-5.4.95-1.x86.xpak 52897802 BLAKE2B b8cf51aa47d6a3701d78042f3dcab485b9a1664d124dc4113346817d3fb6c6bd9159bd209872ec400156e4c0427c44fa82f8d6b5fb3ea6679a24160197ad0ab6 SHA512 ac0b1689a96baaea5509af5a7af30420871c27846d9672b103e2fcdebd0bd19b432657d3d0edda7785cc3bf50c56f3115bb7162318ff171f5f1de1455ab0568a
-DIST gentoo-kernel-5.4.96-1.amd64.xpak 61082860 BLAKE2B 5521a3a4d5dccd127c91f35ffe8453d7b296f278c60d855133253f3752f47a74dc49bf19a110e5176762488e39697c35ad29658dfc70d0d58bd5fc8ce2f86fcf SHA512 9559c82e6980a8b2b32bb633d7957577544b2756f065fb66d688636919ba6532b82bb72ea6313c4d386317b45234a2c2226b7d78d52eb45667a10bee5d6b85d4
-DIST gentoo-kernel-5.4.96-1.x86.xpak 52902599 BLAKE2B e79d7ade352b071f57f4ffa4ec2407d835eb55e4926cec9212237a89d1a88780c5b91066bed8d42a839196278edc52658a08476926970ce9f9a8b5e864591f8d SHA512 5ba67830ef51d5918f2f4c08c2bbb78fc49cd0c37868e7a715c060a22a6220d2d1c1ac7db809021f3876b135c1ca5f8734817775234c02a524559b6602d806f6
DIST gentoo-kernel-5.4.97-1.amd64.xpak 61094072 BLAKE2B d0d79009d53fda887c79f2ec8fd9f3a22fd8fbdc93442635e626a7dd956cdfef89df930b907487b26fd7fc5e6230e19413939d2395515d441b9e7386b540ca1e SHA512 512b1616356a7b6f44695d4d34f25405134cdb84c2c98df34c477572643c9acb3e7740e763ce10b57c0fb0cf56bf5be14774ebde76cd90aa1f180ba756461abc
+DIST gentoo-kernel-5.4.97-1.arm64.xpak 56299241 BLAKE2B 260c5a028f64fd7c73ec8bbe6207d20dfedd92eb510fb49ff50656114fb8f76758b10a0e11497520aca7b2002713345e0d3623c8177be97be7dc0fd90668ee0e SHA512 327b55f7ce9aa6b63798a35d623e92f461a31460b759f12624358e5fbdbdc3e521bd09d7efadd9b1e03c8d5f50eb961590586163ad81d6dc02bd0f88609f3b4d
DIST gentoo-kernel-5.4.97-1.x86.xpak 52892614 BLAKE2B 7faee99492c9b319b3bbbf45180547bd4af6c732a084c522612c8774015e5ca3768fe5d25c23954821331effc0266d1462437f6d6d8870026ea96cc006b0ab90 SHA512 318d6481a75ebf60c0844269d1c1e67f26f45cde032d4c0597b49f97d733d5c44738e2e2839fa7d4ce06426bad2b35e77a601acefbfe645e8d654761b82ba683
+DIST gentoo-kernel-5.4.99-1.amd64.xpak 61077919 BLAKE2B 1d0bab84d8dba7b3c8495ef5fb2fde5cd5290579cad51e2e5c9714d02263b2b621f5c982d6c00285b469476595c540e7a93e2de8f6caf4a89b6a8e7cc123ad51 SHA512 74c92c49875e8d80e0afc2ea5198d613982d24afc300c9b9a4fdcb97689d1dd00fc5f9bdb795bc609dd12b8f1b671ddf4937860e4d94401da580e17090cd534a
+DIST gentoo-kernel-5.4.99-1.arm64.xpak 56363608 BLAKE2B a082403950475a9b398c0f8fbadd371f81d2aa01160bc3656a104dfdd342f9a98979e3701ce5b7d6042c0a4ba7cf33b34de8c6bf7a98356694b33e78dd461bfe SHA512 562706e5f84240d631886ba677292aed84935deb13abbf8fd0ce023772008fffd0cdc9a965b61fc7c38fbd4235b8221c4d2af717ef7c690fbfec621d3c564134
+DIST gentoo-kernel-5.4.99-1.x86.xpak 52893402 BLAKE2B 9964fb97580c87e15248c81e48352a4efecb6b278a3a087e0752484103ca87ccdb16c360d0c1db34a6874c3234fc0dd6502e012d601d381cb4ec402f92bffd55 SHA512 94d985d0b20fd0903539888308cb543d21374b523c5b4d95eecf0589a5a3998ac139b667056975431043efa9691d61755b11c902e4b2f8e9e4cc063b82192129
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.14.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.14.ebuild
deleted file mode 100644
index 31b6fee9f812..000000000000
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.14.ebuild
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-install
-
-MY_P=${P/-bin/}-1
-DESCRIPTION="Pre-built Linux kernel with genpatches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+="
- amd64? (
- https://dev.gentoo.org/~mgorny/binpkg/amd64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.amd64.xpak
- )
- x86? (
- https://dev.gentoo.org/~mgorny/binpkg/x86/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.x86.xpak
- )"
-S=${WORKDIR}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~x86"
-
-RDEPEND="
- !sys-kernel/gentoo-kernel:${SLOT}
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-QA_PREBUILT='*'
-
-src_unpack() {
- ebegin "Unpacking ${MY_P}.${ARCH}.xpak"
- tar -x < <(xz -c -d --single-stream "${DISTDIR}/${MY_P}.${ARCH}.xpak")
- eend ${?} || die "Unpacking ${MY_P} failed"
-}
-
-src_test() {
- kernel-install_test "${PV}" \
- "${WORKDIR}/usr/src/linux-${PV}/$(dist-kernel_get_image_path)" \
- "lib/modules/${PV}"
-}
-
-src_install() {
- mv * "${ED}" || die
-}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.15.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.15.ebuild
deleted file mode 100644
index 31b6fee9f812..000000000000
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.15.ebuild
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-install
-
-MY_P=${P/-bin/}-1
-DESCRIPTION="Pre-built Linux kernel with genpatches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+="
- amd64? (
- https://dev.gentoo.org/~mgorny/binpkg/amd64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.amd64.xpak
- )
- x86? (
- https://dev.gentoo.org/~mgorny/binpkg/x86/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.x86.xpak
- )"
-S=${WORKDIR}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~x86"
-
-RDEPEND="
- !sys-kernel/gentoo-kernel:${SLOT}
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-QA_PREBUILT='*'
-
-src_unpack() {
- ebegin "Unpacking ${MY_P}.${ARCH}.xpak"
- tar -x < <(xz -c -d --single-stream "${DISTDIR}/${MY_P}.${ARCH}.xpak")
- eend ${?} || die "Unpacking ${MY_P} failed"
-}
-
-src_test() {
- kernel-install_test "${PV}" \
- "${WORKDIR}/usr/src/linux-${PV}/$(dist-kernel_get_image_path)" \
- "lib/modules/${PV}"
-}
-
-src_install() {
- mv * "${ED}" || die
-}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.10-r1.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.17-r1.ebuild
index fa7357082db9..fa7357082db9 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.10-r1.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.17-r1.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.10.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.17.ebuild
index 31b6fee9f812..31b6fee9f812 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.10.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.17.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.11-r1.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.18-r1.ebuild
index fa7357082db9..fa7357082db9 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.11-r1.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.18-r1.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.11.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.18.ebuild
index 31b6fee9f812..31b6fee9f812 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.11.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.18.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.12-r1.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.19-r1.ebuild
index fa7357082db9..fa7357082db9 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.12-r1.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.19-r1.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.12.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.19.ebuild
index 31b6fee9f812..31b6fee9f812 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.12.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.19.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.9.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.9.ebuild
deleted file mode 100644
index 31b6fee9f812..000000000000
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.9.ebuild
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-install
-
-MY_P=${P/-bin/}-1
-DESCRIPTION="Pre-built Linux kernel with genpatches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+="
- amd64? (
- https://dev.gentoo.org/~mgorny/binpkg/amd64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.amd64.xpak
- )
- x86? (
- https://dev.gentoo.org/~mgorny/binpkg/x86/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.x86.xpak
- )"
-S=${WORKDIR}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~x86"
-
-RDEPEND="
- !sys-kernel/gentoo-kernel:${SLOT}
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-QA_PREBUILT='*'
-
-src_unpack() {
- ebegin "Unpacking ${MY_P}.${ARCH}.xpak"
- tar -x < <(xz -c -d --single-stream "${DISTDIR}/${MY_P}.${ARCH}.xpak")
- eend ${?} || die "Unpacking ${MY_P} failed"
-}
-
-src_test() {
- kernel-install_test "${PV}" \
- "${WORKDIR}/usr/src/linux-${PV}/$(dist-kernel_get_image_path)" \
- "lib/modules/${PV}"
-}
-
-src_install() {
- mv * "${ED}" || die
-}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.9-r1.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.11.2-r1.ebuild
index fa7357082db9..4f6fd6df565a 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.9-r1.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.11.2-r1.ebuild
@@ -11,7 +11,7 @@ HOMEPAGE="https://www.kernel.org/"
SRC_URI+="
arm64? (
https://dev.gentoo.org/~sam/binpkg/arm64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.arm64.xpak
+ -> ${MY_P}.arm64.xpak
)"
S=${WORKDIR}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.13.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.11.2.ebuild
index 31b6fee9f812..31b6fee9f812 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.10.13.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.11.2.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.91-r1.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.100-r1.ebuild
index 8ec8fdea9936..8ec8fdea9936 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.91-r1.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.100-r1.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.91.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.100.ebuild
index b8eb2c63573a..b8eb2c63573a 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.91.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.100.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.92-r1.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.101-r1.ebuild
index 8ec8fdea9936..8ec8fdea9936 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.92-r1.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.101-r1.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.92.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.101.ebuild
index b8eb2c63573a..b8eb2c63573a 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.92.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.101.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.80-r2.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.80-r2.ebuild
deleted file mode 100644
index ed835559ae22..000000000000
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.80-r2.ebuild
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-install
-
-MY_P=${P/-bin/}-r1-1
-DESCRIPTION="Pre-built Linux kernel with genpatches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+="
- amd64? (
- https://dev.gentoo.org/~mgorny/binpkg/amd64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.amd64.xpak
- )
- x86? (
- https://dev.gentoo.org/~mgorny/binpkg/x86/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.x86.xpak
- )"
-S=${WORKDIR}
-
-LICENSE="GPL-2"
-KEYWORDS="amd64 x86"
-
-RDEPEND="
- !sys-kernel/gentoo-kernel:${SLOT}
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-
-QA_PREBUILT='*'
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- ebegin "Unpacking ${MY_P}.${ARCH}.xpak"
- tar -x < <(xz -c -d --single-stream "${DISTDIR}/${MY_P}.${ARCH}.xpak")
- eend ${?} || die "Unpacking ${MY_P} failed"
-}
-
-src_test() {
- kernel-install_test "${PV}" \
- "${WORKDIR}/usr/src/linux-${PV}/$(dist-kernel_get_image_path)" \
- "lib/modules/${PV}"
-}
-
-src_install() {
- mv * "${ED}" || die
-}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.83-r1.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.83-r1.ebuild
deleted file mode 100644
index f507f70d33cb..000000000000
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.83-r1.ebuild
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-install
-
-MY_P=${P/-bin/}-1
-DESCRIPTION="Pre-built Linux kernel with genpatches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+="
- amd64? (
- https://dev.gentoo.org/~mgorny/binpkg/amd64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.amd64.xpak
- )
- arm64? (
- https://dev.gentoo.org/~sam/binpkg/arm64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.arm64.xpak
- )
- x86? (
- https://dev.gentoo.org/~mgorny/binpkg/x86/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.x86.xpak
- )"
-S=${WORKDIR}
-
-LICENSE="GPL-2"
-KEYWORDS="arm64"
-
-RDEPEND="
- !sys-kernel/gentoo-kernel:${SLOT}
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-
-QA_PREBUILT='*'
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- ebegin "Unpacking ${MY_P}.${ARCH}.xpak"
- tar -x < <(xz -c -d --single-stream "${DISTDIR}/${MY_P}.${ARCH}.xpak")
- eend ${?} || die "Unpacking ${MY_P} failed"
-}
-
-src_test() {
- kernel-install_test "${PV}" \
- "${WORKDIR}/usr/src/linux-${PV}/$(dist-kernel_get_image_path)" \
- "lib/modules/${PV}"
-}
-
-src_install() {
- mv * "${ED}" || die
-}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.83.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.83.ebuild
deleted file mode 100644
index 4a18c43a2642..000000000000
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.83.ebuild
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-install
-
-MY_P=${P/-bin/}-1
-DESCRIPTION="Pre-built Linux kernel with genpatches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+="
- amd64? (
- https://dev.gentoo.org/~mgorny/binpkg/amd64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.amd64.xpak
- )
- x86? (
- https://dev.gentoo.org/~mgorny/binpkg/x86/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.x86.xpak
- )"
-S=${WORKDIR}
-
-LICENSE="GPL-2"
-KEYWORDS="amd64 ~x86"
-
-RDEPEND="
- !sys-kernel/gentoo-kernel:${SLOT}
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-
-QA_PREBUILT='*'
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- ebegin "Unpacking ${MY_P}.${ARCH}.xpak"
- tar -x < <(xz -c -d --single-stream "${DISTDIR}/${MY_P}.${ARCH}.xpak")
- eend ${?} || die "Unpacking ${MY_P} failed"
-}
-
-src_test() {
- kernel-install_test "${PV}" \
- "${WORKDIR}/usr/src/linux-${PV}/$(dist-kernel_get_image_path)" \
- "lib/modules/${PV}"
-}
-
-src_install() {
- mv * "${ED}" || die
-}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.88.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.88.ebuild
deleted file mode 100644
index b4fab44a5169..000000000000
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.88.ebuild
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-install
-
-MY_P=${P/-bin/}-1
-DESCRIPTION="Pre-built Linux kernel with genpatches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+="
- amd64? (
- https://dev.gentoo.org/~mgorny/binpkg/amd64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.amd64.xpak
- )
- x86? (
- https://dev.gentoo.org/~mgorny/binpkg/x86/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.x86.xpak
- )"
-S=${WORKDIR}
-
-LICENSE="GPL-2"
-KEYWORDS="amd64 ~x86"
-
-RDEPEND="
- !sys-kernel/gentoo-kernel:${SLOT}
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-QA_PREBUILT='*'
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- ebegin "Unpacking ${MY_P}.${ARCH}.xpak"
- tar -x < <(xz -c -d --single-stream "${DISTDIR}/${MY_P}.${ARCH}.xpak")
- eend ${?} || die "Unpacking ${MY_P} failed"
-}
-
-src_test() {
- kernel-install_test "${PV}" \
- "${WORKDIR}/usr/src/linux-${PV}/$(dist-kernel_get_image_path)" \
- "lib/modules/${PV}"
-}
-
-src_install() {
- mv * "${ED}" || die
-}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.94-r1.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.94-r1.ebuild
index 8ec8fdea9936..1a05b19758a8 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.94-r1.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.94-r1.ebuild
@@ -24,7 +24,7 @@ SRC_URI+="
S=${WORKDIR}
LICENSE="GPL-2"
-KEYWORDS="~arm64"
+KEYWORDS="arm64"
RDEPEND="
!sys-kernel/gentoo-kernel:${SLOT}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.94.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.94.ebuild
index b8eb2c63573a..2e3ec53900e4 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.94.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.94.ebuild
@@ -20,7 +20,7 @@ SRC_URI+="
S=${WORKDIR}
LICENSE="GPL-2"
-KEYWORDS="~amd64 ~x86"
+KEYWORDS="amd64 x86"
RDEPEND="
!sys-kernel/gentoo-kernel:${SLOT}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.95.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.95.ebuild
deleted file mode 100644
index b8eb2c63573a..000000000000
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.95.ebuild
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-install
-
-MY_P=${P/-bin/}-1
-DESCRIPTION="Pre-built Linux kernel with genpatches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+="
- amd64? (
- https://dev.gentoo.org/~mgorny/binpkg/amd64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.amd64.xpak
- )
- x86? (
- https://dev.gentoo.org/~mgorny/binpkg/x86/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.x86.xpak
- )"
-S=${WORKDIR}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~x86"
-
-RDEPEND="
- !sys-kernel/gentoo-kernel:${SLOT}
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-QA_PREBUILT='*'
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- ebegin "Unpacking ${MY_P}.${ARCH}.xpak"
- tar -x < <(xz -c -d --single-stream "${DISTDIR}/${MY_P}.${ARCH}.xpak")
- eend ${?} || die "Unpacking ${MY_P} failed"
-}
-
-src_test() {
- kernel-install_test "${PV}" \
- "${WORKDIR}/usr/src/linux-${PV}/$(dist-kernel_get_image_path)" \
- "lib/modules/${PV}"
-}
-
-src_install() {
- mv * "${ED}" || die
-}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.96.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.96.ebuild
deleted file mode 100644
index b8eb2c63573a..000000000000
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.96.ebuild
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-install
-
-MY_P=${P/-bin/}-1
-DESCRIPTION="Pre-built Linux kernel with genpatches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+="
- amd64? (
- https://dev.gentoo.org/~mgorny/binpkg/amd64/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.amd64.xpak
- )
- x86? (
- https://dev.gentoo.org/~mgorny/binpkg/x86/kernel/sys-kernel/gentoo-kernel/${MY_P}.xpak
- -> ${MY_P}.x86.xpak
- )"
-S=${WORKDIR}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~x86"
-
-RDEPEND="
- !sys-kernel/gentoo-kernel:${SLOT}
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-QA_PREBUILT='*'
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- ebegin "Unpacking ${MY_P}.${ARCH}.xpak"
- tar -x < <(xz -c -d --single-stream "${DISTDIR}/${MY_P}.${ARCH}.xpak")
- eend ${?} || die "Unpacking ${MY_P} failed"
-}
-
-src_test() {
- kernel-install_test "${PV}" \
- "${WORKDIR}/usr/src/linux-${PV}/$(dist-kernel_get_image_path)" \
- "lib/modules/${PV}"
-}
-
-src_install() {
- mv * "${ED}" || die
-}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.93-r1.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.97-r1.ebuild
index 8ec8fdea9936..8ec8fdea9936 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.93-r1.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.97-r1.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.97.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.97.ebuild
index b8eb2c63573a..b4fab44a5169 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.97.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.97.ebuild
@@ -20,7 +20,7 @@ SRC_URI+="
S=${WORKDIR}
LICENSE="GPL-2"
-KEYWORDS="~amd64 ~x86"
+KEYWORDS="amd64 ~x86"
RDEPEND="
!sys-kernel/gentoo-kernel:${SLOT}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.88-r1.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.99-r1.ebuild
index 1a05b19758a8..8ec8fdea9936 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.88-r1.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.99-r1.ebuild
@@ -24,7 +24,7 @@ SRC_URI+="
S=${WORKDIR}
LICENSE="GPL-2"
-KEYWORDS="arm64"
+KEYWORDS="~arm64"
RDEPEND="
!sys-kernel/gentoo-kernel:${SLOT}
diff --git a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.93.ebuild b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.99.ebuild
index b8eb2c63573a..b8eb2c63573a 100644
--- a/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.93.ebuild
+++ b/sys-kernel/gentoo-kernel-bin/gentoo-kernel-bin-5.4.99.ebuild
diff --git a/sys-kernel/gentoo-kernel-bin/metadata.xml b/sys-kernel/gentoo-kernel-bin/metadata.xml
index b0b959adbe61..3eca39567e28 100644
--- a/sys-kernel/gentoo-kernel-bin/metadata.xml
+++ b/sys-kernel/gentoo-kernel-bin/metadata.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="project">
- <email>dist-kernel@gentoo.org</email>
- <name>Distribution Kernel Project</name>
- </maintainer>
- <use>
- <flag name='initramfs'>Build initramfs along with the kernel.</flag>
- </use>
-</pkgmetadata>
+ <maintainer type="project">
+ <email>dist-kernel@gentoo.org</email>
+ <name>Distribution Kernel Project</name>
+ </maintainer>
+
+ <use>
+ <flag name="initramfs">Build initramfs along with the kernel.</flag>
+ </use>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/gentoo-kernel/Manifest b/sys-kernel/gentoo-kernel/Manifest
index f5bdbf536b1f..3d34b5cf10d7 100644
--- a/sys-kernel/gentoo-kernel/Manifest
+++ b/sys-kernel/gentoo-kernel/Manifest
@@ -1,53 +1,36 @@
-DIST genpatches-5.10-11.base.tar.xz 343372 BLAKE2B d844a4ce292477da26bc02743916143cd6851b2ba85229ed37361213580b47b5386f260bde7cb77eb5842f3fd1022b6af64d47dcc3fcf2161be8157380e082bd SHA512 069efa3d348d8a7601c6bf37ec92e3efa692abe4a7ca5dc4bfe30fb76f1b7fe8daf1a0f237d60dcf66a0815e909ac77cb1cc189d46f6fb4884a260f30a4af48b
-DIST genpatches-5.10-11.extras.tar.xz 1772 BLAKE2B 8d4c4b94e9bd7c585f56038900256b3ec1ae721b4ed7adb326f393094e5c8960575efdbe2cc14cd219ae0a69cdde5c626d6983741e3f13a39bed3e85f3eb7060 SHA512 90ce771ad84ffbeaeaff6a2827577fc9c9113930dc4fd394300e1a971cc205a1f4805404e1b356dc36b373bfcd9daa95de7a364144f0fbeb0f923209946635fe
-DIST genpatches-5.10-12.base.tar.xz 354672 BLAKE2B 4c92a3c4d144e7abb130371a5d12e839d280789b2c44e97fced3a35d25fcc9b084c3e3e8832fc7670a4811da7026963a1c498a0cb2c44cd325ab13aa62a3d142 SHA512 7ee954e44305b4276717aa4a1198ea036fdd1f18e17c95fb0c5e8070acf390c1644dd0499d42ed1464fa7d9cef8d90abbeb6d0e0448c2fefd5a655834a5afa5b
-DIST genpatches-5.10-12.extras.tar.xz 1772 BLAKE2B c219ce68835104664a93e78e57c5bce67a3d654666504ae38fc5058d6f8df67c9e37941f549d047b446061f54928230a384d813b4bde2508323facef6502bc16 SHA512 3b2b6ba233226f9c0d54d1dbcbd36133429dba1e0bc7a355fb0794389fd729e8ebcfd1789c4b79529ca4bf48dc50d7b07c1e167ff19d837d67296f36705e7db3
-DIST genpatches-5.10-13.base.tar.xz 407940 BLAKE2B 21566164ea821e5ee95e4b4583395625384347d0e8440b29fa71f4b63365c5481dbb683c84818a5379242a25a59fa85c3caf420be3e6cb8553a43834dcdbfb94 SHA512 0f4e5aa39cc8dd6f2cd62fe5293de1d9fa5a0f6e0dd6da9af52ad68ee8318f995d9095df65b93d6e15994227feb87b5bbcf0403ebe774141045b05bf239dab86
-DIST genpatches-5.10-13.extras.tar.xz 1772 BLAKE2B 29357a93bb6b4e34937e6655bb8cecc4f57edea8a7e7a903dd8196c6f075b27e2b1176a56a998777c850994c5131a2a57266a7fc579a25fc43db9c9aac4dd80b SHA512 e9ed41cc3b81ae7e76fce6bd6df271eb354110252da85e7e90c4d08816babd1262c5c8fbb62fe56dff1fde712abc35ee40c67f9f04e3541920eee78b32074928
-DIST genpatches-5.10-14.base.tar.xz 416468 BLAKE2B cfde628c2594a568c8f699ffb63bb1bfa5054fb810a0baf8cc08c87886d49a5e33725be6a6eb03ed0f8fa40521b9591ae0ac1253708a3ae72556e0cff7efe17c SHA512 84b815aad491aab1592c253da7c37d307b102fda9d08c741cbe5df9c5bd636a83eb8af0e96faf6b54c13bad77068d3ca1f632ab4c68211bbdfb8a9c1d233f06a
-DIST genpatches-5.10-14.extras.tar.xz 1772 BLAKE2B 9694bc87e97e7899f2d47199c42082a666e775f35a49a3efb20f8b15cf35345b0905b5d36bd3845e4b62e0ae49260a7fb381f26c6cdcfeb20c3eda5672e81e29 SHA512 be9fbe10adae2acb813abf94f7008620ee9c5f1ca28053e4c387ecb814e3fa6b0e08b6c0404f1585049ceba4ed419dbcd524f9ce69f25dc12006b20d5db3dfc5
-DIST genpatches-5.10-15.base.tar.xz 455860 BLAKE2B cc02492f8f33e3b644df293231e9e6718007b4556f7e056256eb6040e0adaee076f1b25dd8086097d2ae1c50f1169488c2188e45756d0aa47e0b0d34f132715e SHA512 983f45356831d74a6b5001bfc68f4252d687f307cfc8ad2925c3a844f5e9c13e6407f6c591b49028d9cee599106b771078fdfe57137801ba0096552b99126666
-DIST genpatches-5.10-15.extras.tar.xz 1772 BLAKE2B b7cefe073d4c1c6b6f5b57e79faa95baadea2a79be973524876941275be05b60be2008ddcadb02ffab605d47dec4fa325609e70b58d7c59aba83d2075d7c3766 SHA512 ab18ecf108271a4a132ca5983a47985dd462e5b312bf0cbc356340713738c40888b59fe4fb2597c218b41098d6496594f2ad98638b6b14c435ba271b8f4b2882
-DIST genpatches-5.10-16.base.tar.xz 468704 BLAKE2B b7476d5db21c56f2b0e3082e47d643b12b163277e84aecd4b7df75e97f6b703ce8fbdea29aee0a7150f0f193a35ecd896766e9e6bef8dc47a4dac941f83b7f02 SHA512 9623b5fb47de8a93d036e301220031d5b6508e07ce87002193a5d52a34902a486811f133419c84c35cfd7f7bb6076fb5be87992d6934ed57b830d4c7542313df
-DIST genpatches-5.10-16.extras.tar.xz 1772 BLAKE2B 5652ee641cc180d14e7a28d3dabecc46430bbe8daa5d5e0cba3090d8a2e28ee56b92073efa996bd9ec598897045c29f1a8c3fdb28f69d7ef94422d31275d7fc0 SHA512 90d245b44e33ca5f8356dac3d3ddf0d736530384ffc232fb230b88e799b362c8cf9b4a147f7b9fc5c32aaccf18cec4ebfa7b8c80bc530ac300b5444fb9263021
-DIST genpatches-5.10-17.base.tar.xz 502160 BLAKE2B e243f962bdb26797424cbf27eb64e37cc42a5d7297d8eac4dfdff556f641aa0d34461b9845df3c203dfc0df462e130089a83c1cb8fae4774df5e99cee27ed67f SHA512 d573c4f168fc65cacd01931d0cb52636ee4c739ec7a285f069cf8c0e487f606e2cab5a9524dbc020b830ede4a5660e2204a49d27596fc661ca96f3db26856c31
-DIST genpatches-5.10-17.extras.tar.xz 1772 BLAKE2B 14f5f5b8a2a70190f80376f20a83c2f7a70ca31b2a956c2cfd84fb2999436bc3cfad925ce9744d333c896f520df6dec5337ad820340d9b4dd007d91abc95b0c4 SHA512 2bf9b8444f8d53937a24e1d0304236f04ca220eb1a2bf4d4c47d7655149d752948a0050684d1d1f18065226e7b50501b3182b264b2ff009b6f9e45e6886037ae
-DIST genpatches-5.4-81.base.tar.xz 2591356 BLAKE2B 63c0ef166e2691c6747a2b2a8317aeac286ddac1454ae1eba7a34035abeba67ea2627257d17f266fde57da0684f83cb102b465252a3b95075c1442123c2473e4 SHA512 88d4deb9002cfe6aa8a8045770cf5c7ffde8cf9bad324a72296b1a5202c94386807fad53460147420363b3c73613be424bb54000e5cade7baa4df254ef2c61ab
-DIST genpatches-5.4-81.extras.tar.xz 1772 BLAKE2B 93bedfbb023ab9d3913751cd242a4221b204685751f57d0ac31494fa8f8caf8e5faeb3ae10eed5332016f9a40b20670a6af6c4198eeae1136b14a3b28174beb7 SHA512 8776735a73aad4672d4b857d750f985ff6681f8e565a906106e2cfcd4d7839fa518d8fa19b39a0ac948736a3384656be44aad239ce2516786c797303f492ce01
-DIST genpatches-5.4-82.base.tar.xz 2792480 BLAKE2B 39960646116f5f85ee657a29557d8fd9e809ae9bc60aac349c91e7680f2a0565800ba37a478573098dbad41b686336a058985d2925e5046fa68eeaea8df25477 SHA512 6a76eebd7178e2ccc522477f53c36f74e6fd691f87c547dffa2602a516ad9a6a01f05c953e12bbe6ba9aa2ce34b176a6a081a22da40c7d86855e5dfc34098059
-DIST genpatches-5.4-82.extras.tar.xz 1772 BLAKE2B 8eff7ca01490badd5dad15497f77bf43c268ccb494db9eb4c18f4f59219f1a5d79ef2a6f35caee87e3c423b0fff1ef94a6d6477e5074397f78e4bd23b9c40d95 SHA512 bdcc7eb08c1cdb599e69b254f55685f7beec83f256518d42c31d0df9a4e1c6376c184145ce47d28e0b688d2166e139445ef5f9f284e817ba9f37eaf812852a88
-DIST genpatches-5.4-85.base.tar.xz 2833404 BLAKE2B 56a8a49c1c61693ea344d26fedbb85c2682a16d55dfda57b5bbc5df65d2311c5d92b2d464c6b951b9ef58b04879038ee134e179c1dc4d692308b2eeb3eeb517d SHA512 fa277427a7e5c3c44a681e08ff1570587173a1471de8425013afde212a9aef6e6d68f8e707f52b21d76672a4cd0e6cfdb33c32b78d02908eaa55264517d3d4c1
-DIST genpatches-5.4-85.extras.tar.xz 1768 BLAKE2B 5a5e25a02014fd06b8742a2e505f9998d766c6c95d1a515f0c5a6f3b433163c97c1b8ec758be9bff0c017c947fe4c9c1210fd5fb9d1d838f8571ccd9178d251b SHA512 9ca5271fda3619765363f8fdc5e837b0c6bd218de7d956795e9ef01e9000c85d85f0b49479b8d20a33227008ecbb268d9353c622b37f81619329f358b2fcdff7
-DIST genpatches-5.4-90.base.tar.xz 2956112 BLAKE2B e0ba7a4fed329f452cb754ee4fcd2578a544dbcd7fed57a66cd6a825c4dafcd70d23c4d9571a7ac8de14794ba505816226e5a2b06b8df5d220d4243926edd800 SHA512 bd7fff0edf1635b2de08893a3e1ca5147a86574d87c33c3869c506e232b8c53add688357f7ef2a790185c2df73366610ee5ddd46fe1d88db16c3fb9f43c0a6ca
-DIST genpatches-5.4-90.extras.tar.xz 1772 BLAKE2B 557c305f86b0b6d5a93c1ca2da7751362f55d385cb4f57df12f15258d5cdcb1a0ad2c99c9ce53ba89b6c27abe761d5033ce54fa97ca6eaacbd845244d6b20d8b SHA512 eb2fc3f76099bd504f8e0cdf3c0aca60aa083b5c055e06fa2560e895278aa7d32f518ab2e671f9d0182e713ec6807552843448a38d633a4051b926ae4fd2adc4
-DIST genpatches-5.4-93.base.tar.xz 3001024 BLAKE2B d5f3020aae1a920a076457cf28ae640e8ab7387652a61db3d631a3494c5cb0e8706d92debb6356768fea992679aefd4bda6d212a9918a714740439811dd3ef6d SHA512 420512b65e20f00fcabf4d122cf5fd166a6cc196a77451f8a06b333ca2cdc189c38654333e565cc555b1f3e9745e9c4b188b98648cd57ccb395ca1259675e4d2
-DIST genpatches-5.4-93.extras.tar.xz 1772 BLAKE2B 0ad1eff5f82120235a1f326176beeaefcf7aa547eecc94ad103a5be1701dd922ae0309431a10233c0df5bf63c5ba970bdec32e6ca782965e369be2fa5a4577dc SHA512 b5415fe59ba41d60a46e0c123abcee0bb72b5a7d7358789947627ae086c7391c09f116a16c32b2475c278ea14d7275932046d686aa4a849942cbf64440506c92
-DIST genpatches-5.4-94.base.tar.xz 3006280 BLAKE2B a8130e4be0b40fd0c82d9da6c3f42d3e45dc0119b7a981a62b0577e16cb73ae7edb76b407ecdaaf0bd53a118164208529d9bde3958c9592cedb3ef04815e64e9 SHA512 bf4b59da586a4f5f4a03b40273cbb6d5e9e49273c9c15fa2d3dd7eb002c0c24db895fa3987c93268c1dbfb1402197192f2f2c42b22f443a50089ce26d0f721a2
-DIST genpatches-5.4-94.extras.tar.xz 1772 BLAKE2B d7f9cbdd2739ff180d7fa1de7ae24f9d0beeed259b00b0a67e6a3e9dfeb7a2e7136c0682af7e50491fa9010ea3e3e03a37cb8eac96047a4d4e58177d64caf72d SHA512 eee973e296444e301a6d9f59e82e39b2d2b1aa6605fe62c54a3710f300bad9e3b3a13c14f16f357a6c8775c50b47d390f537f15030c4fb08a6d81e5ba4008f1d
-DIST genpatches-5.4-95.base.tar.xz 3022876 BLAKE2B e935ec5e2cacf478fd8ac2f343d0e582cceddf811ea4d87d5518b946b8b0501e7aff29d406407d3f0d276ea32a616f022789ee1318b282c6fd77b3aaf0d64631 SHA512 4e87014b78683372d525d6409c5c038429423371a1369f2c3b1455e53f5360290dd323ccc24aaeeb4a9e66452e9c87dba439c75192b77e4fc7bc888bc1c4cdac
-DIST genpatches-5.4-95.extras.tar.xz 1772 BLAKE2B 29c822d815b565e99441f122bb978db211288f69ec3e3795e2555aa58cc3d2911debaeddcf202ce7be335771310589548a9de82d0500982894b621d0f773d7a3 SHA512 860978d98d7715b1359e0f3e47a0369ee6ef9e1cc4fd4201ad879dcab0aac644f6a951875643ccb70d31b6dad8b23d0b4ca7b32e50739bd87499760829949749
+DIST genpatches-5.10-19.base.tar.xz 543060 BLAKE2B 9219d5463c51bc574984ab37795a2150deaecf861c0b2ec3c7c91eebacbd6d5e045da40acb09ac01a56e33e5329401e80d8804d1227869d5a856e8c11e2da70d SHA512 795e38b25e6c11a936e8366a3081a5f9d170bdb807296e3c0c58545b43b937ecd47e4a66fff521a0a554ff4142aaf4b4b5543427437f1458f672e57016de1f58
+DIST genpatches-5.10-19.extras.tar.xz 1768 BLAKE2B 8579ab3ab97f6bc906a8e16d90e8bfde74bc6782323a0defc86e0099593431d54bc4457c2cf3bc64bcc623bfde74ba6387ca33af58e367062cc23b78057d0ec8 SHA512 7b658d488dfe372a5cd799042c9e6227fa35bf8cbd56ef505bf25344b052c2fa2db137bfb315d9a65b844c475a052e8845ba9d3b30e57fc6417aaab7c3886176
+DIST genpatches-5.10-20.base.tar.xz 551256 BLAKE2B fc2db45cc49ae771f3c87cd97ba3643c6ae35ebee7104a3e6cea50b5fa444871f069480c73e63ad5ca41903f4c180be34e905cd7701dbf3f49590cd98d255873 SHA512 c176101a167fec0df6dd60a366daa0d5b2ca96b2610ea3de8ba0bd5887037ddb989eed5febdd40ec2fbfc1473837160713b331e37c370c992c95b3db9bfddfd9
+DIST genpatches-5.10-20.extras.tar.xz 1768 BLAKE2B e69295002cda9c81df01d0e20a6ae691f3d584dc91ae7bfe3cae777fae430829b6b4450c5f38f91a2aa42fcd9b6adfb89bc85642f30e8caf7cb34cd301f5261e SHA512 1bfce3155025596db1c1e90c4119812a83d1574519d16805574c84e0b8f5936b5e3a2e5400e92b59c2844b903b9517eb2b9d220054ebd3912af23a4b6914db7f
+DIST genpatches-5.10-22.base.tar.xz 554876 BLAKE2B 18d2a41fea4a8a95983a71185248f9fd27d2f4e8863419eaae66cf826ecd74218e0563804262368f3d23bee1f835b18869644af734f0baa8d1266a37ff495061 SHA512 7fca3a5fcd35425b0d6aa37cd0eb1146c6fec8ae5f4a462f058180057e956a4316a26a0c0600780014ffe2f632cf64f135f8d0b337ca6642a949c3654783a4c0
+DIST genpatches-5.10-22.extras.tar.xz 1772 BLAKE2B 3a72d1838aca6ca79985e06d9efc44a10bc3e766431c2ebca64b773c96be52cf27f121331585030e334d2eb7d1415deb34f42c265619b16186fb406baa12bd23 SHA512 81559580dda2d4ecbe693eb25d9d537f0d3dc3a01c1a863f17eff3b0e890a2850bdbb7ed5e856bf6b9c7dde944dd771710a8b64812391b5a3c214cc0e2c8538f
+DIST genpatches-5.11-3.base.tar.xz 11280 BLAKE2B 83a975b07b3e04e19b008e5a5c4f08fa551b3558b68afb800cb3c886f782a21950d5ea1029b631a6caa2658f02e7ae819e8d8c137a076470120d94deab99e524 SHA512 0a8b19f888af853e6a12aff9d6675f7a9977fef92efa19e69c79a6325fc1626efe7aa9fec8c42ee65ba29f0757b166567679a54d0351f19ea502183e92a63ac5
+DIST genpatches-5.11-3.extras.tar.xz 1772 BLAKE2B 165d5928e6afc65544392186737efd1df9e1179591ef7edd85a1868971ea76016161a38a615e9e692c4515fe7fc19424a0cfd01420b5ec57a60c8d1d2d223cb7 SHA512 c74015c4e1b824c61db9e9deca6b30a839ae9a8fb5747cb6c46e2af99a9221f11bb971099554107bbfc58ea5389d96e810f9cf8e55d0bcc16a093eef941c6ec8
+DIST genpatches-5.4-101.base.tar.xz 3089116 BLAKE2B c6e716ab8d0e98d3b3b4c492d6a516ada65f5e77d375cb9164a080aabd94311c50a222135499eef9dcad3f80b29b831a3fe015c3006178651c2136620f9079c5 SHA512 1bdd6f8f23a6151298e2e2fec493c9a2e95a1a65f4a4b6ff95598f45d4fad783da2a596c05b5582ec3d82ed8d8aaf654706da768a1b248bdae37fb08481b3dc3
+DIST genpatches-5.4-101.extras.tar.xz 1768 BLAKE2B 44b92b9c288f4f10f499e5b6d2179b44ee3418890905341703901a71b703ff99e992d6e7424521e67d3b1f80e41286c2357187c66e9b1ae7c1feef430f0ed74a SHA512 e397f970bc3b68b91f059e4b4f2d6163f8416340096b16b040eed8a5242a001db37b0fe8c1fd2a54c73bf6121aa55efa1c362b7837e930b758bc3bd33f8dce09
+DIST genpatches-5.4-102.base.tar.xz 3090460 BLAKE2B fa17228e7cfebb2c128b73682cc97f9e96a1a3c4936f98b021ae3f21a1f6a1167c357db2570902ca554b6facf27d507a0d258c4a9e9898cacde502762306c2ca SHA512 e3b7b0826115a7f7c92f5509eafe25803ea943733a8be8404a333d54ac93c607704f742ab20576517a7ac6e5467a7dfc9c2a54205a10f3fcf4af9b2557a5da0d
+DIST genpatches-5.4-102.extras.tar.xz 1768 BLAKE2B e9bdc3e77e4cd6feb17c3b84b0b573f60b399262cfb5cf5893444afcda38b3017f41c5e00313fc5af30108d60fef2603dd3ce32cfd36b0e3644f85b782da0206 SHA512 bf88c37717a240a62f64cb7a04af13244ea3c5e531b160c649d39243184266de8e61e7c84f092b4b931760fa786dbe40523a0ed55eabc65824f63f0b330604d1
+DIST genpatches-5.4-104.base.tar.xz 3093716 BLAKE2B da8a9f572f4a22eb101a477ed2b2a81b0adaed65f1913c163b58dc958de661707733fb1e0d06e49ec342666ca0c212313d3a5fbca60c79779009b91361e23f42 SHA512 2ef214d2e4ea982c6702991519aaa183d6731f882fa59db5cc2d7832c7fcaf8de57dc2173f4a59922e5d90da2d046753b3eed609513c84c784c13d5be747303b
+DIST genpatches-5.4-104.extras.tar.xz 1768 BLAKE2B 7f335d61bd5f44cfa74ce2082259a48791ed90c21da4d05ff13c191adf1f658e68634c4cf9779274e6f775409695634ca40187754b0f9d50b406c26df26adbc4 SHA512 a8080605c59079063065d9bebc9d846ab8aab73f2f192f6c5becea2b51304a1e4d91e20d9aacd61f2cfa5b967bb8e30d620ddd60592017f308ad2f65ab7287a5
DIST genpatches-5.4-96.base.tar.xz 3031600 BLAKE2B 9ba35f7958842a1fd4c9a7e7d3666ea1339ee5fadde6b771b78f67a8bb27c07e8dad8498e9b85fa0bcfd641f5aef9641793a02061b03becd372ea86245820895 SHA512 3edea8a4fc2a29e0f989089633256b270589ad77a225f3cef6e414c5877de1be8a4d5d9da28bfa4fba848f33ee322c4f01befcdf384c9271c97c90e2e2d3ad39
DIST genpatches-5.4-96.extras.tar.xz 1772 BLAKE2B f33c734139f65245694d3cb98712733a901e89c79d05fab03de42d82d6e45ed3ec41ab4e17f2cd20be2ec31d469cf02a5efc7bad93832c67d3ad0bbf147b07e6 SHA512 8b7d6d058906b9c9afb7addba0c3072d70758bd75ea2989787beab5a3a83725541b4084c34cbb1e90b6cc8bb323a002dfca7065cc88fc834891f04397caa645c
-DIST genpatches-5.4-97.base.tar.xz 3041620 BLAKE2B 4b738b0b9dc990d47577b44c4d1931c28727b461891a673eaa82e3add22f56f57494548c76ce6f63872f62d2b58c2c4e1fbdb84d5b4233f1a9df326fe29de60a SHA512 34adda6c55d8fd491c8c667c9ed71deb6afd4f92fcb26999baec619088dd3483be0b665a76bcf72f1f52abfb6b0bb8a0909c2cb549220ec130afdaa0ea482c84
-DIST genpatches-5.4-97.extras.tar.xz 1772 BLAKE2B 5c0ed8ac19c10d0e95ff270bb7c2fd559405218f836290df7bdcd5c07ac3cb7e06221d05e40906d97242807ece263c1aa226cba583e5a822d55328608c765d1c SHA512 08cbda97510319fc497b806238c76eb60ad12b35ec7e075ee10ae3cbc6db61b1b3ea061c9c7b3a11f21125fb0d9e111a6a717eed6c3f885a7244d9e63e02c697
-DIST genpatches-5.4-98.base.tar.xz 3049548 BLAKE2B 38d6f3b3c7121721667ae183683e7e2fb9e3edb66d5caccb7a802429c4f6ee68b2cbda5503464064268efbc8f7f3d7fb5c66164f08c815f228c439fc3d55adb4 SHA512 174247357b558834635b90b79346c7c5005a84fd17c0d20cbe09d2405a7d32b0d7e3f14a8683e26f1c12058d510f2827ed0cab5fbb12cb829679a10c317e25bd
-DIST genpatches-5.4-98.extras.tar.xz 1772 BLAKE2B 620bd1c1f60762806ecf90c391f97864567d8ebbf41279bf3a10e1a98de636cefa9616907bdb4922e7ae8c202ef5f3d68a5f551d83af54e70f5252431172730b SHA512 a1c5f239564745bbf1347831995699d52011d856d0965d020cb6f082bb5ca9031f8f9e6fa7d692f04042bbfdcd9aea7e20721198a961021ffa62bd5fcce666a1
DIST genpatches-5.4-99.base.tar.xz 3064716 BLAKE2B f71d76c88a9932d3b0e1b45d065fa0946f36a3100e3b59c5ce4c373519119066973067e4bb74d094cd5b79e689affa4615faf40da75a730b62df2259d3361c43 SHA512 833a83d7aecb1a216783fdf57e0fda342fd481c74166d976326a8333dfb2a13bd61f1b20b749f17b3498756b6134f8538a971507427f4e955bc9128742a3be5f
DIST genpatches-5.4-99.extras.tar.xz 1772 BLAKE2B 6ffe84c928fc61b306d3e9a096470c090b79bfe99c90981b64e324d40157e818b50c0aebbaf342f51eeba29867b8cf8a6e91394dd594c1ecdb4f2a64f8d76e00 SHA512 7f2db3353809e7922951e1e884d7fe4a426556750bf4e38619278185fb09d519b30a972f4b5aeda3f7aca335fc95372edcc5dadd0881febbf43403c4d5c1c497
+DIST gentoo-kernel-config-5.10.18.tar.gz 1219 BLAKE2B 55ec8c66a9b090e590e23574b54edde0fefb575f25e6848b1c84834847304e30e52fc0810b8fd219cfb23c097bb8f7444e0b010bde44209f0c4811f99db7e0aa SHA512 ee137c85e94fe5989646cb19a72aca62ddd4795813f7bbf15d66262b0e72d90d84d5d17a31bae7980c061e0576e3f3254dca53ba6e547cf12cb7ab08771e3900
DIST gentoo-kernel-config-5.10.7.tar.gz 1146 BLAKE2B f755581e9f3be3122e5f6e6fc133d3e5c3116d4580b53f95ff5b2cee5150233fe82be5cd45637a9792ae4612be5d2cb4dd954506f97fe82c9e96cb8b772cb342 SHA512 8c64768e83d2552e69a29c6c3f958ef6a1e5a767acd04b3bfcd0cd49453ab5d0aa54fcfee76a8c9d07f72abdbf70380b070e3d1584e7b7d05a6daa3399892f51
-DIST gentoo-kernel-config-5.4.77-r1.tar.gz 1289 BLAKE2B 6612741cfbf458f4bd8915b476aac3aa6934e8bbab344da877fa4ad52b6133e01f5d44bf0e5d048e79e56c1a351774135ee55f1aa839b230e2418db7c5d9b123 SHA512 2a09dd85af37447b278847aeaad114ef47470726cec015ed5ee1b54b3080f4b2c48de8b2f7b817eeb4e27c753579cf0820053e22caa762cb1552116d8d69eba0
DIST gentoo-kernel-config-5.4.89.tar.gz 1240 BLAKE2B 50bd2e64eb1a62d2f0d67e02b78da56cb507fd7a5993d663b880c94ecd535898285ed01e00d5d07fc1ba0d044657e776456736d8fdcacecf7ca464979a8a1d06 SHA512 ad31f9895b9dd45edd7f8715516edfc303c23600f243f3ca122c7c554c9fdbe3c3aa62970a24ef7291d7937e04c63c0258f6348e796686902a011c055c1bed01
DIST kernel-aarch64-fedora.config.5.10.12 223184 BLAKE2B a0246dac2f7a4ad6a55b611538d24382ac87a8960077811a859c9595ac67f961b4bccb7e139a89abc7c0e26e80832da5c94211fc658082f2e7dde984f14dd29d SHA512 7d803b347b136331db1ad6e22e0445fe0224c3e26cd7c034cbe9794915d457b492e05f77664865079874ec001351553652646e2e08d0fee31e30b841b0008f52
-DIST kernel-aarch64-fedora.config.5.10.7 223162 BLAKE2B 23d78fadc509edd2219ba263266e4a865f98d6aef87ee2e299b81ba86ac36eff580e5c7bdccb0d4a8593afad07136e06171c79e0dd0e072c892a523e6e352933 SHA512 9791c26368173da444ca5ed281effdd5e20f3968f0a65eb607c2741f114443db2bf260d033a28a7f826963b59a8893a1311befcb3eb3609f9b85472e95234bcd
+DIST kernel-aarch64-fedora.config.5.11.1 225847 BLAKE2B 50e3db29a9afc3db3c35e3af173e89e2e8d3b573dd8af7c35584e3d0152211cbd5e6ddb749acb3d6d2caa54392a3f51e52b5394a5d032d43ed35861230b277d0 SHA512 6d0594658e205767599453d4d8695c37eabc065d6c17362c3775dd745f6ca62131d7c15126ec41a17e757d3ae2a0569cea6621a7ada4666a8f90e4414391b3dc
DIST kernel-aarch64.config.5.4.21 199104 BLAKE2B 578ad451a76204df2a9bbbe34b5cb27051d2ac5e2c33967f562b01338c43f35da6dc33a4c2cc67ea6c3b32b155729360d3748ec28dcaa750f18449245b2e8a09 SHA512 66e9a437beb350fdc59512c17b8f72c5b5bfacf2b35070d810d77e66f49cf7929026cc28ad44b04a016d61e65d9fb4a10af6996ba09b604bf97e9c467d08f8ff
DIST kernel-i686-fedora.config.5.10.12 205412 BLAKE2B 92c715b7e2cd7dd74da7970c05981f520597d3e403ce82c8cf4eee31c9f1f50b638792a6bdb256ef5bfdc99f1bcd594e819e8f44dc6febb2ad9a854bad817f2b SHA512 69d8db11723ae1b40fdedfaace74d15bb63198cdb0485e0a1e5eba95b31217110c93a93e39cc7370cf45f1d3a8bc7f75ec096d6db5ea9ecb28ac6b56702ebb10
-DIST kernel-i686-fedora.config.5.10.7 205390 BLAKE2B 103131caa856ae9b062b39cb88ad8616a8ebd7aa53b7562399d72ba998a4049a22ab251927bf43a4936127246455c2cdeeee3b7e349e12bb94af8f6dc242d8ea SHA512 58279d0076f7551569e48db45909263c5c494c4349afaff4087682d7dd0ecadc22dde56482b521ce2eec39b1e6110f5c370206e0c8f7045d4419bb164da7e2ec
+DIST kernel-i686-fedora.config.5.11.1 208027 BLAKE2B b4183e8d1121aa8b3f65d0a4542b8ba0f507430ab4cf0004dd0e8b1e24b3be1783316b8bf6becb2002f7fbacc8236b640f533fc2e9dc5696e84d1627c3b0e9c4 SHA512 5b107e376ddef783ee6852ef67143a94340b37ab764ef3ee3c6642401883d314809c959c2025d976336923c115d21d6b39332aa1699c0f884d1faad1d9c3fa32
DIST kernel-i686.config.5.4.21 183910 BLAKE2B 185126ffb85718bb73761d01683def80b6f002d7a7a6eddd8e858a30d8eadc863fb378d83a1cd2ed82b3540337fa66ae44475e31fb41ebc46d77005b6f54e5c0 SHA512 6307afc2295902e44fe65b1cccaa7a0260b295a5f21f1d67ec66197bd972bd3f5675b624f08d9da8b224cb3ec987d5c21cbd743599aeab9ac6214bc651f43476
DIST kernel-ppc64le-fedora.config.5.10.12 192105 BLAKE2B 889141debb0656a358a3381bae14b5216b982acdfce0bc758f9445c16647807a68a788fb290199c2a1a23627bda1ef4c9405b3f5ac2a4176d1d2b55c71fb7db9 SHA512 3ab0f1401d9f50a61477c71369dede438f575d9d2c3a2f5c2cf36d624c2b59a938efca9c981b075511b3860c983eaaf5e5a9f877d659277f09ceba45edd43770
-DIST kernel-ppc64le-fedora.config.5.10.7 192083 BLAKE2B 71c97c04629a05ac8cb4f4cf1740c60e8a25c71a5c9184cf53f13088073b04b269887ee6e57ff83c8caff61ccbfd6845809e6e3057f1fdfc13d9b913b032c653 SHA512 732f4e93b3074180e86bed865e0b6d487857d5eefcb2436e7c24706be0e41c813b27b2292e6995df2d63e9a9f7721c2d566a50ba06675bfa862ca1fc91dc2af5
+DIST kernel-ppc64le-fedora.config.5.11.1 194870 BLAKE2B df6e5a0a789dc6d0c2fbec45820f5e19ec455388f02f04d88d7b3dd5081d2f11e89cfd0159b7a3885aaa029470e916743d59ec3f86756ff4182aa56552aa8476 SHA512 e170912e76e8980435df2a1387792d616490ededda4df681a90312f7fc8ce4065f1c9fd7559d746d8edc0fccfbd35b20fd5db294774f9db7f4635d898cd0dab1
DIST kernel-ppc64le.config.5.4.21 172003 BLAKE2B b53887cb44f7c378cb3866780f8e556e19fdb02130d3b0df01d97698d2a91f7d90a200012559f288e962935742c3fdb67dfb6711876fad37862fe55cdca5b5f6 SHA512 82df8d0be47e9eb20bd7db570539bb061d0b6e2101dc78a54596cf4d0b4e0c536041449304ff9240b051ee09b342ea336c5645e9a3b66a5dfb96d7778ff86008
DIST kernel-x86_64-fedora.config.5.10.12 206357 BLAKE2B 0eda9d4f3f973336cabd67c1ac78f100aabde926354743e8dcb7ff84496f0de49210d45f99bc850a2096078b0b4687aa7fd965d999248559506004f2b29dac0c SHA512 b12f43d3c1a52a4915cd73db98874ce9ae6c425672c0f1c19ed1b1101341c868ebf1c9620bef5449752ec0d7342c1ce38fb77779d0f89b9267096a605ebf7a26
-DIST kernel-x86_64-fedora.config.5.10.7 206335 BLAKE2B 1133bf0f58f8073578d048c5905cc4a539f63a01b57fceb225046c4678172861de20419d8cbf42b0f4655c27a6366ddee41343458d577a2685f3d96b2fd444c6 SHA512 8c5d0de931526d3315793e0a1af4c9c2493c09573c4f2233aaa85f0413a912190c14fa8427593fc3956fff61d89c795f7c9b0509bb30936cc8b9976deafeda66
+DIST kernel-x86_64-fedora.config.5.11.1 208870 BLAKE2B 86e075a95cbc5d6c3cdecb0caf67e18f671ed663aee94b7d0688e25f111dfdf12d890e1f409df04446d18057b6fad8e0fc67adcde34ed581266d458d9c9cabbd SHA512 ab39c8b107471bdd492e6f9c2e181e85e44134b4a2934fedd2f454b9766a32aa2cef2cbf7ed83111e82ffd7794d4bf20f81d98b238751d505c13077abff2b543
DIST kernel-x86_64.config.5.4.21 184907 BLAKE2B 0eb2b07c14cea7545350fcdf3a94f2a531f0137c502ebda9299cacf44da5385686e2049b480b28bc153c9d413d453cfe682b9655eefe70428cb720f57c7bd200 SHA512 f3b3ee6841555ac3a9cc11536a7d44e1a5a8df2bab14ba341fda7df1ceb0de45cf1c799a1d54a64f2858fd1272d348bb52cf269ffa396878c5402baf2730237f
DIST linux-5.10.tar.xz 116606704 BLAKE2B b923d7b66309224f42f35f8a5fa219421b0a9362d2adacdadd8d96251f61f7230878ea297a269a7f3b3c56830f0b177e068691e1d7f88501a05653b0a13274d1 SHA512 95bc137d0cf9148da6a9d1f1a878698dc27b40f68e22c597544010a6c591ce1b256f083489d3ff45ff77753289b535135590194d88ef9f007d0ddab3d74de70e
+DIST linux-5.11.tar.xz 117619104 BLAKE2B 81300c27bd5476387a83123aaeb4163c73eb61e9245806c23660cb5e6a4fa88ffc9def027031335fa0270fc4080506cd415990014364e3a98b9d2e8c58a29524 SHA512 a567ec133018bb5ec00c60281479b466c26e02137a93a9c690e83997947df02b6fd94e76e8df748f6d70ceb58a19bacc3b1467de10b7a1fad2763db32b3f1330
DIST linux-5.4.tar.xz 109441440 BLAKE2B 193bc4a3147e147d5529956164ec4912fad5d5c6fb07f909ff1056e57235834173194afc686993ccd785c1ff15804de0961b625f3008cca0e27493efc8f27b13 SHA512 9f60f77e8ab972b9438ac648bed17551c8491d6585a5e85f694b2eaa4c623fbc61eb18419b2656b6795eac5deec0edaa04547fc6723fbda52256bd7f3486898f
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.11.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.11.ebuild
deleted file mode 100644
index 57b838f8aba7..000000000000
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.11.ebuild
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build
-
-MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.10.7
-CONFIG_HASH=b238267df7cd80dc3aa6b5b654cbe145367383df
-GENTOO_CONFIG_VER=5.10.7
-
-DESCRIPTION="Linux kernel built with Gentoo patches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.base.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64-fedora.config
- -> kernel-x86_64-fedora.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64-fedora.config
- -> kernel-aarch64-fedora.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le-fedora.config
- -> kernel-ppc64le-fedora.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686-fedora.config
- -> kernel-i686-fedora.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~x86"
-IUSE="debug"
-REQUIRED_USE="arm? ( savedconfig )"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-src_prepare() {
- local PATCHES=(
- # meh, genpatches have no directory
- "${WORKDIR}"/*.patch
- )
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- arm)
- return
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le-fedora.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686-fedora.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.14.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.14.ebuild
deleted file mode 100644
index 1eef3068fb9b..000000000000
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.14.ebuild
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build
-
-MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.10.12
-CONFIG_HASH=836165dd2dff34e4f2c47ca8f9c803002c1e6530
-GENTOO_CONFIG_VER=5.10.7
-
-DESCRIPTION="Linux kernel built with Gentoo patches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://dev.gentoo.org/~alicef/dist/genpatches/${GENPATCHES_P}.base.tar.xz
- https://dev.gentoo.org/~alicef/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64-fedora.config
- -> kernel-x86_64-fedora.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64-fedora.config
- -> kernel-aarch64-fedora.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le-fedora.config
- -> kernel-ppc64le-fedora.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686-fedora.config
- -> kernel-i686-fedora.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~x86"
-IUSE="debug"
-REQUIRED_USE="arm? ( savedconfig )"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-src_prepare() {
- local PATCHES=(
- # meh, genpatches have no directory
- "${WORKDIR}"/*.patch
- )
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- arm)
- return
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le-fedora.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686-fedora.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.15.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.15.ebuild
deleted file mode 100644
index 1eef3068fb9b..000000000000
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.15.ebuild
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build
-
-MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.10.12
-CONFIG_HASH=836165dd2dff34e4f2c47ca8f9c803002c1e6530
-GENTOO_CONFIG_VER=5.10.7
-
-DESCRIPTION="Linux kernel built with Gentoo patches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://dev.gentoo.org/~alicef/dist/genpatches/${GENPATCHES_P}.base.tar.xz
- https://dev.gentoo.org/~alicef/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64-fedora.config
- -> kernel-x86_64-fedora.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64-fedora.config
- -> kernel-aarch64-fedora.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le-fedora.config
- -> kernel-ppc64le-fedora.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686-fedora.config
- -> kernel-i686-fedora.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~x86"
-IUSE="debug"
-REQUIRED_USE="arm? ( savedconfig )"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-src_prepare() {
- local PATCHES=(
- # meh, genpatches have no directory
- "${WORKDIR}"/*.patch
- )
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- arm)
- return
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le-fedora.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686-fedora.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.13.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.17.ebuild
index 1eef3068fb9b..1eef3068fb9b 100644
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.13.ebuild
+++ b/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.17.ebuild
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.9.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.18.ebuild
index 57b838f8aba7..76a99b1b3ead 100644
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.9.ebuild
+++ b/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.18.ebuild
@@ -8,9 +8,9 @@ inherit kernel-build
MY_P=linux-${PV%.*}
GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.10.7
-CONFIG_HASH=b238267df7cd80dc3aa6b5b654cbe145367383df
-GENTOO_CONFIG_VER=5.10.7
+CONFIG_VER=5.10.12
+CONFIG_HASH=836165dd2dff34e4f2c47ca8f9c803002c1e6530
+GENTOO_CONFIG_VER=5.10.18
DESCRIPTION="Linux kernel built with Gentoo patches"
HOMEPAGE="https://www.kernel.org/"
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.10.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.19.ebuild
index 57b838f8aba7..76bcba59d2bd 100644
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.10.ebuild
+++ b/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.19.ebuild
@@ -6,11 +6,11 @@ EAPI=7
inherit kernel-build
MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
+GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 3 ))
# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.10.7
-CONFIG_HASH=b238267df7cd80dc3aa6b5b654cbe145367383df
-GENTOO_CONFIG_VER=5.10.7
+CONFIG_VER=5.10.12
+CONFIG_HASH=836165dd2dff34e4f2c47ca8f9c803002c1e6530
+GENTOO_CONFIG_VER=5.10.18
DESCRIPTION="Linux kernel built with Gentoo patches"
HOMEPAGE="https://www.kernel.org/"
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.12.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.11.2.ebuild
index b34a35880d65..498040ab71be 100644
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.10.12.ebuild
+++ b/sys-kernel/gentoo-kernel/gentoo-kernel-5.11.2.ebuild
@@ -6,11 +6,11 @@ EAPI=7
inherit kernel-build
MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
+GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 1 ))
# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.10.7
-CONFIG_HASH=b238267df7cd80dc3aa6b5b654cbe145367383df
-GENTOO_CONFIG_VER=5.10.7
+CONFIG_VER=5.11.1
+CONFIG_HASH=07992209452cd7ba529ffdbdd83d01d44cd8ae14
+GENTOO_CONFIG_VER=5.10.18
DESCRIPTION="Linux kernel built with Gentoo patches"
HOMEPAGE="https://www.kernel.org/"
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.91.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.100.ebuild
index e8748c9098fd..e8748c9098fd 100644
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.91.ebuild
+++ b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.100.ebuild
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.92.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.101.ebuild
index e8748c9098fd..7c3266150716 100644
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.92.ebuild
+++ b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.101.ebuild
@@ -6,7 +6,7 @@ EAPI=7
inherit kernel-build
MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
+GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 3 ))
# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
CONFIG_VER=5.4.21
CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
@@ -15,8 +15,8 @@ GENTOO_CONFIG_VER=5.4.89
DESCRIPTION="Linux kernel built with Gentoo patches"
HOMEPAGE="https://www.kernel.org/"
SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.base.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
+ https://dev.gentoo.org/~alicef/dist/genpatches/${GENPATCHES_P}.base.tar.xz
+ https://dev.gentoo.org/~alicef/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
-> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
amd64? (
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.80-r1.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.80-r1.ebuild
deleted file mode 100644
index a9746567969a..000000000000
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.80-r1.ebuild
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright 2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build
-
-MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.77-r1
-
-DESCRIPTION="Linux kernel built with Gentoo patches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.base.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="amd64 ~arm64 ~ppc64 x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )"
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_prepare() {
- local PATCHES=(
- # meh, genpatches have no directory
- "${WORKDIR}"/*.patch
- )
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.80.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.80.ebuild
deleted file mode 100644
index 348823c20ed5..000000000000
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.80.ebuild
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright 2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build
-
-MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 1 ))
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.77-r1
-
-DESCRIPTION="Linux kernel built with Gentoo patches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.base.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 arm64 ppc64 ~x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )"
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_prepare() {
- local PATCHES=(
- # meh, genpatches have no directory
- "${WORKDIR}"/*.patch
- )
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.83.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.83.ebuild
deleted file mode 100644
index 37b2c84e06d5..000000000000
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.83.ebuild
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright 2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build
-
-MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.77-r1
-
-DESCRIPTION="Linux kernel built with Gentoo patches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.base.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="amd64 arm64 ~ppc64 ~x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )"
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_prepare() {
- local PATCHES=(
- # meh, genpatches have no directory
- "${WORKDIR}"/*.patch
- )
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.88.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.88.ebuild
deleted file mode 100644
index e86c0b79240f..000000000000
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.88.ebuild
+++ /dev/null
@@ -1,96 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build
-
-MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.77-r1
-
-DESCRIPTION="Linux kernel built with Gentoo patches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.base.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="amd64 arm64 ~ppc64 ~x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_prepare() {
- local PATCHES=(
- # meh, genpatches have no directory
- "${WORKDIR}"/*.patch
- )
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.93.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.93.ebuild
deleted file mode 100644
index e8748c9098fd..000000000000
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.93.ebuild
+++ /dev/null
@@ -1,96 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build
-
-MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.89
-
-DESCRIPTION="Linux kernel built with Gentoo patches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.base.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm64 ~ppc64 ~x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_prepare() {
- local PATCHES=(
- # meh, genpatches have no directory
- "${WORKDIR}"/*.patch
- )
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.94.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.94.ebuild
index f26abd9fdf78..789220f8e3e7 100644
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.94.ebuild
+++ b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.94.ebuild
@@ -38,7 +38,7 @@ SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.x
S=${WORKDIR}/${MY_P}
LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm64 ~ppc64 ~x86"
+KEYWORDS="amd64 arm64 ppc64 x86"
IUSE="debug"
RDEPEND="
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.95.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.95.ebuild
deleted file mode 100644
index e8748c9098fd..000000000000
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.95.ebuild
+++ /dev/null
@@ -1,96 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build
-
-MY_P=linux-${PV%.*}
-GENPATCHES_P=genpatches-${PV%.*}-$(( ${PV##*.} + 2 ))
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.89
-
-DESCRIPTION="Linux kernel built with Gentoo patches"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.base.tar.xz
- https://dev.gentoo.org/~mpagano/dist/genpatches/${GENPATCHES_P}.extras.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm64 ~ppc64 ~x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel:${SLOT}
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_prepare() {
- local PATCHES=(
- # meh, genpatches have no directory
- "${WORKDIR}"/*.patch
- )
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.97.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.97.ebuild
index f26abd9fdf78..ebd06b8aecfd 100644
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.97.ebuild
+++ b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.97.ebuild
@@ -38,7 +38,7 @@ SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.x
S=${WORKDIR}/${MY_P}
LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm64 ~ppc64 ~x86"
+KEYWORDS="amd64 ~arm64 ppc64 ~x86"
IUSE="debug"
RDEPEND="
diff --git a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.96.ebuild b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.99.ebuild
index f26abd9fdf78..f26abd9fdf78 100644
--- a/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.96.ebuild
+++ b/sys-kernel/gentoo-kernel/gentoo-kernel-5.4.99.ebuild
diff --git a/sys-kernel/gentoo-kernel/metadata.xml b/sys-kernel/gentoo-kernel/metadata.xml
index b0b959adbe61..3eca39567e28 100644
--- a/sys-kernel/gentoo-kernel/metadata.xml
+++ b/sys-kernel/gentoo-kernel/metadata.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="project">
- <email>dist-kernel@gentoo.org</email>
- <name>Distribution Kernel Project</name>
- </maintainer>
- <use>
- <flag name='initramfs'>Build initramfs along with the kernel.</flag>
- </use>
-</pkgmetadata>
+ <maintainer type="project">
+ <email>dist-kernel@gentoo.org</email>
+ <name>Distribution Kernel Project</name>
+ </maintainer>
+
+ <use>
+ <flag name="initramfs">Build initramfs along with the kernel.</flag>
+ </use>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/gentoo-sources/Manifest b/sys-kernel/gentoo-sources/Manifest
index d1ccc8e09d35..25e010b238f6 100644
--- a/sys-kernel/gentoo-sources/Manifest
+++ b/sys-kernel/gentoo-sources/Manifest
@@ -1,18 +1,6 @@
DIST genpatches-4.14-219.base.tar.xz 4733352 BLAKE2B 3a2c41bcdee77395ae2b19ee4a9e53771795d2b21a9a31c821d20853521f911ceb6f49219fd9c2e65fe0088251aa6cdee2a139e5d3f23f5cd665001e48154822 SHA512 a0837de333740e20a870324638b81708133420e7c9152bb194ef5623f29a38df6b8211686fb13f9b6f3785be8071c1dc3cbc989cae8cecda79db97aaf85d1868
DIST genpatches-4.14-219.experimental.tar.xz 6092 BLAKE2B 7df1ac766e4bda252718f06751aae3181af7bbf68e609562db059577c8d123e816fde728a049a9d1ea3baa4148d9433c5c698c79e61097ec2de2389ea781216f SHA512 1dbee51c8021a3103c64e79684ed810de436d88f3f1883c4d53b1898a55274600da07f452910eece720b0cee1f6a6d32af68760a468a42759bd9b0b15e28eea4
DIST genpatches-4.14-219.extras.tar.xz 3340 BLAKE2B 2a7077ff685b93d393f8c1ef3e7d02fcc3aa69ec209d88cc19339e4a5bf64e29e456f88cd1d49826e4a81537622365cd390884d6a621e358525179c0f97f343e SHA512 e2e32ebb01afdeb67c4556982c9a9abaa26f0fb46d251c07513e191b03429d9c238193345fb4c6b08de315e67d89b28f675da4ef942c30ec4d9ba31d8466a913
-DIST genpatches-4.14-225.base.tar.xz 4819872 BLAKE2B f5bf3d4870b155bd88ca80e0b2fa58d85d5b29abbf35ed7d9c9f5032c3c023f0fb50a398896a7159d0c7b2c6a1a2f4305d08f684a64bef9d6c4d5ffaf9805ee7 SHA512 3a96311f51ed2958174b369f549d7e2f705ba5d01fccc28211e4ee915fdbf44c9aac2136ce5ac44cf01be342dadcdc32438d9be3eef53b31c77eba2c64a01938
-DIST genpatches-4.14-225.experimental.tar.xz 6084 BLAKE2B 7367e447e62008580611d138e88175965b19bdb698a68c7320d49357e95e15cd2ee031a37085455c7cd544d7b60ea25c712bdf4bf3428b8b3231631a7c897de2 SHA512 4212233753d8dae8124536f0710acd3250975be78bcbd697bf42aea2623f00359201767da334ddfbabb554ad26eafdbafca65cb3f326e5ef8162084104208290
-DIST genpatches-4.14-225.extras.tar.xz 3336 BLAKE2B 3f151cbd04ed1b4767e648433997750dc9e1a511736418abad915c48922af37f80907aa968ab2566ad7a307f332e6dee5619d29173a70e6acf2ffaf59c40b73c SHA512 cd05474af1809daeb4e2198fa2415e29f336fb61c8e2b65c93c520dcd47f225b26daf577529c4673efe6aba17070e626a80ce5d0e298e896888ef16a56aa59be
-DIST genpatches-4.14-226.base.tar.xz 4824692 BLAKE2B 06e014464e4e9b394cf2122f25cfffae949d97698f211e25c029826efe36f696d134f3c0cba0f80d2599fb1dab675f5f004b737785f98a654802b7e28856a5fd SHA512 e10fde32e50f151543ab4739a3e19aa168193fccbd1d91c02946ecf56abfe45e99a442ee060cd16ea7f11e65c1181441c5f61a9c38a633589c754e32d10f4994
-DIST genpatches-4.14-226.experimental.tar.xz 6088 BLAKE2B 85ee64c4fba94e2e3a5633af8abc931ee0969de8ab414194b58f80c509847ec6e8b836a193512e73deabdbcef4da0e034b32760b907ea41d7c5fc06154969815 SHA512 fb1e7b6bc51729c987bf346f968354d6a7155a2322a989a3f9ab411f53e5408918e6dd02c4b0a3b6ee18089f4e19f548a3b23faebe65fb063175edd824133399
-DIST genpatches-4.14-226.extras.tar.xz 3340 BLAKE2B c427ad8d18fb57bb6c0d47a920bd903f26f5ac0b6c8358640e07d00ef33f54a45523087eed8cd6ef474f2907be9d5ed74e6c0f46994678daeccc2495696432a5 SHA512 311ee330b643ffc3832e45f20f0e762b157645747f85105034a15d4c775e8ba7f67b985d49da55d04f7046f70e0f923957703efcc0aaabe9c658c6debb5f2c4f
-DIST genpatches-4.14-227.base.tar.xz 4831676 BLAKE2B 052c6f13209c589fa53a9c57fe39e1b8b6a12070ad075a4d2fee99b22becab8e8642466c1d01f17e5d5492e1a25b804910c77de78e57ec99deba43af13151c3a SHA512 38a5dfb3e870a52821a99e7bc11f10cf549c86fce2d80767e21e5e7f470d3f4fde8ec8dba107224cef351ad0095520c50d640e6741cc81b96b77d3fc4e418fa8
-DIST genpatches-4.14-227.experimental.tar.xz 6084 BLAKE2B abb57683a3f22bdde5e8c4b6cbd9ae239a10ef59d099c5e2ad6006b9bc7139e7b9f8ebfa892b8675cf7a62cc4dc879cf4b9f21a51bebbd32b30ac7989826d24a SHA512 87503496543f94d5b79f71da4c73deba7e771b47af813e4b9023e120b6f356b15655e84e3ab30be06a694245f12dae33e80a8b67da35f784fd6909dbce8f219b
-DIST genpatches-4.14-227.extras.tar.xz 3340 BLAKE2B 7921c02980b16c19b19807f776f5f0513619f24621580240065fc119008c92fe16ec4eb7e2b08991e5390559a0ac9a0c2c7a22f77ebaeed362ad6f2b06fbe2c8 SHA512 a02fe59fac681b177fed6a28b9bf1e5d4ba5c7401ec4d783ffc5169037f23fb8d2a5fdc439e3d4eb2c0d8807080c69b470027bbbe1eecb671608d512c83f5364
-DIST genpatches-4.14-228.base.tar.xz 4842300 BLAKE2B 9fbcaeecc9913e8f3e959201aee3575321f065e971d7db606ba86bfef225ce78e7c72e7be700bb0ee5501d8cf9e8b00576f6b43a3106b3d7ad0f02a9c2968d33 SHA512 08abf23ac36704d0cefea99449c9fa425051f0cea60c6c090c0d92f9159f587f90813a471337d553e361efa3346f5205eb6d8c7bed572d0e066986849343c39b
-DIST genpatches-4.14-228.experimental.tar.xz 6088 BLAKE2B 5d4770913b9269743abbf9051ae66c1569a4c7aa04286609a39a22258c3fe876964a5596737d7a755d1fd543eca249e8986949c66e47f4ab51d91781f42168eb SHA512 0ed1fefe93a5c0c3324946901ee8b4ea59717d1ef30efd39df83b834df8b30a40856128fbe811c6b66d14d7f826b024e195cdf697453a708c846a314053bdedb
-DIST genpatches-4.14-228.extras.tar.xz 3344 BLAKE2B 1e89184144c4640f821dda2b58e898f6992a5ae2844b39da40ed06cf0e8b3e9a0ce74c9e7d8ecca5bfb35be8a2ab799cff8581d9927b4f108389c1a65922364e SHA512 ef2f7dbcfd199d1f5410c9014ab3b15c1501c1b3c14e19a6d905848a64844bbcf1e9c369c520d9965aa086a84f96a33eef7fba8e163a7613fa6720f657cce2cf
DIST genpatches-4.14-229.base.tar.xz 4847632 BLAKE2B 2455fa20f83a0867c80cedd06df645ff99452cabbe03121489dfa99c3bb26db792b40d88989fbdfb8eb1a9607bdaaaba6bbabdc6852594715f26903d54c58415 SHA512 8b6043c69277ad0b48249b2c888a660df31cc9edb3c52d68bfc4a9d62b81ff4c60618932a115d7fb4e01b09b68890e7bd5f9970ce674b1e45699d3f46c85af4a
DIST genpatches-4.14-229.experimental.tar.xz 6088 BLAKE2B 4508ad523cda5e0f9760ad5fd26ee24d90aab18cbfecc714303b3804545e3457375f33cee87f9f709bec0bdc4a3aba7a53b25cf37535c532dc9376f1d2289a01 SHA512 dd07b6362de2d587ef809f9601c503d6e984d78ba2b635fab475feed16933d000d0fe943dc6d8798943debaefeeb387490c26aa0c520744153c6aa23d1355d21
DIST genpatches-4.14-229.extras.tar.xz 3340 BLAKE2B 6fc4b2789946d350f28b00b800bf78e85a2f882a746ff9da3ebae89e788db195a166b9b4907251db04594e0f3592089d0a189ddc75a0cf45db3dcb97df57cf00 SHA512 772fea4386df287a8d6ddad9508dc95427e911c7bac7ceb9b70bc32db44701548951f3ea783e12f82219e45c6abce12f81a59664009ab92ce8c52eb63dac202a
@@ -22,24 +10,12 @@ DIST genpatches-4.14-230.extras.tar.xz 3340 BLAKE2B 0d4d5873573cfbb9c38dff979278
DIST genpatches-4.14-231.base.tar.xz 4857832 BLAKE2B ce145e696b67a55b69ac7cb20cf1aea9066ad9b58b1863fe5251243253d4e4a01bbddf0e1cce99c6e776a46326137f7269edf306cc10c9d9555d3844306a9cb8 SHA512 a738e62171e8c797ce1640456e0dc019486fa58ad347bbc6dae2b29de65a9442217052906671961369507c7e15d9d6ab545a776b309d86e41b654eaddae2f503
DIST genpatches-4.14-231.experimental.tar.xz 6088 BLAKE2B 1c75abeeb62811ede6d3b51c6a24ed898d92874a9251b7b022e6ef9cca24074b29a22b72a5557b68012e5f68025589268973d9bcae2729c68aebef78bea9078f SHA512 867c66268e0a182af0425e54d517df5305264d4c761ce1114b61dfe71f9d802bfc53d941e2f4b766f73c8278fbeb29cbe8e4c5ca2b0165bce5cb0869c6488422
DIST genpatches-4.14-231.extras.tar.xz 3340 BLAKE2B 51570d6a9b361247a5bc9518a9ee29c54b855c7fc3ff17cf3f823b6626795e7b421b2161280c730c54c1524fd1dbdb6c6bf1b328dc6ca4844674b9842f3e596b SHA512 4282d7d2d45f1eb436d29f57f8dcd42afcccc68fba56847859571b384cdb343972aa6f610f90a609edf543bf21241fec3d4e8a7847c635f1db1d39e9a67e23e1
+DIST genpatches-4.14-232.base.tar.xz 4871276 BLAKE2B 0d9110a6eb0e8b66fbced93b0a2247c61efc987d13a72d136be4a28124a8c573ff2425718d1af8dfe8eb4ffb5ee107438739e6ff4febb21187de823fed0b6fb4 SHA512 13c2fe3f012d8f06f3945f7a250b3c067889c32d43386f745f3c642d9ee88c3e7b15bd5d92d823ea7546f5d3f6e20ffe202be1f99c66378169894533163b8409
+DIST genpatches-4.14-232.experimental.tar.xz 6084 BLAKE2B b8739a3ef24628a61094771edc108a0a1858c9dc8a3e0757f11eee62a5be14b3974e7ba32d9672e4cbddaac8ef1442448aabcbf5df4ccab27059b5e2e40cf00e SHA512 bf771a2b9069fb928597c517ee92952ea8912369bf9bf4284eaf338a6c8d2e17418398faeef73574f75046b048e4f9ed8e59371fe56eb48ae6925bc7f1a98d56
+DIST genpatches-4.14-232.extras.tar.xz 3340 BLAKE2B cead12b5fc48d232dae9bfab7bcbaf1317760d618638783448531b9dcfe3d26f66e650104f2a4104dd2cc2547efbdd8dbfb46a2e9f4b652dc68f038e8bcacd03 SHA512 cbeabf270ae02ddc6eeab74796e7eecc846e78f3008a17980189f04714e6fca255aff2470015d7daf177d97bb0de3ad92248433a9198427f121ad7425f9f0081
DIST genpatches-4.19-159.base.tar.xz 4174792 BLAKE2B 1381a2531b6297e1f76af70107c08a3b7b304177b14a1407ffc41a5851a4249ec4adf5ed00539542c97a0c8dc0cffdb20c3681b9da17409cd9d4ac711b353dd8 SHA512 e75991fde39f093c77b4e7f16aca7b24be47e1e438df7a60a97e0db7aa14ae6c0ed868685da0979c10ce9064839adca84c76a6ec87c1fbe41eed7a20788ca776
DIST genpatches-4.19-159.experimental.tar.xz 6980 BLAKE2B 62605b1fe8ad86233bdfb183df2019dc4d6c74243678f5aad08167ae67b8e0dc45be7a33cae59a9c30678c986c9066722dd32ff18ee572d9ee5f7f2f51caae20 SHA512 240ecdaecca79bf417b080f6ea3dd2cad113694d2f49ae7a9910e26250f381721dcac0804b3e983272a5ea66cc1455cf94c668442e98ce5938868fea1913050e
DIST genpatches-4.19-159.extras.tar.xz 3312 BLAKE2B 480dfb15464c46ff0cad7447476ec66535c6b32ea9ca822ef7f8911b4db7d389c6bb1d1b80811107afb77e290fd4c887ac1786a95729c58673180324246d655e SHA512 8d55a3f9e1516e32e95719a5c9d5c1018bbcdd8f2412b138a46da1419252d9e088d2f1071a5c44dea969bbf4d93461c58edd17ca1b9ef835addb9bd065eda259
-DIST genpatches-4.19-167.base.tar.xz 4302532 BLAKE2B f43c9e993395762203cff0846b91bf475e5d9c72dbede62a6cc6c545f5ecef8369788f0813e3eb052fe66d9adeaa62c9e7f9666e4140bc9aa54c4a364c5a18d5 SHA512 6d9dd2b1d10c2c81f495f8c3ceb3dd365b1649cc63200fa9bf407ac1afbdf8895dad0855d050384fd427132c1827c3be10697c401824460189a6ae2bb0a937cb
-DIST genpatches-4.19-167.experimental.tar.xz 6972 BLAKE2B 4e70a4784b6c485517cfe2b75418ccf7df3f3d40e501ce11edd978b6c1593426b39a7a2241f50c4a7ae63158e7d939f62da57b4c18197675ae05ead5a379d87b SHA512 258bd39888c4156dab864539e7438c7abf7b4ae8113815d1b115a76d13821c3d761c5632f23f8a317bf67cd13e0ee8bb888ee94f98a7799a16484424c2c034db
-DIST genpatches-4.19-167.extras.tar.xz 3316 BLAKE2B bed1495c2beb33aed0814d93a739663b35c3d7012c185ed81c0af44e2e4a8024923b4ad47228a59103e1bff397314695ed975e740f85afbd8304549234cc7de7 SHA512 53e245d970b92c01cf74f72918e386cabd1214b9531734a7656709e50ee7c900b5b428ced4085306fdae72d56eebe162b945da3e4094cd41ef2eb7daca3ed157
-DIST genpatches-4.19-168.base.tar.xz 4309240 BLAKE2B 5940bc82e8139091bf61c8062d110700a394cf3bcd212de7235e17767db47e7f6665498477c956e59c91d67160ba15d1cf5ff1a2e23c5aecb4374e1872522eb2 SHA512 4e60c57d7fb9f5e2a0396d7818521c914e8d5d24cf796f0f10e3e0bc9ab33712780d05a1c86f1e538cc08d67164ac9c5041d000108442bd22ea737dcdf8898ce
-DIST genpatches-4.19-168.experimental.tar.xz 6980 BLAKE2B 47e764768bdbcfd53f6eeb0c33b50a2f2d5d83ecbb32e2ab9fc0e941bcc9dceb4dfe682d5027f83d79ba0cede9c9dcfddc3f2e763241fd8aac1ad129cd6d12fa SHA512 aa0d945be8881d2808a64077bccb4386a6945418f41375bed11bfe0bf37d7de7a67c45eaaabf957b2025bd0a10cf0680c58c745fa511e73e6e3b954ee9aa570c
-DIST genpatches-4.19-168.extras.tar.xz 3316 BLAKE2B 015a2122b25ee086b371dfe7d5e5c7846c52cb2778491c79ec9b556dea0dbe317dcddc2b614c3cab92fd341e77c994fbe9ce61adaa1f4c416d44e8f09c2c1e5d SHA512 693dddac91c2300f0f27da0a686997b30350b3ddee590c2be2e9cb92e6fe14cdbf3428bdd421df84838c26f714c9a05888b097ba5380a8b8fd3f334a28d12199
-DIST genpatches-4.19-169.base.tar.xz 4312680 BLAKE2B 3f93e38654ac3afe57e8ca74e66e7f8b9730bdaf4b668c4f38a117a3dfed84fe537755f108c4e23762683a5e64b5fe8fc96a647100c9b7b6ce9909dc11b73580 SHA512 e8dc17c522d36109da6fe647965616f7c75dc964afd4f0d0be38630bd95f43dcb388ac22cf499c48a16feb755d4e9bee9bfeb9424b85b65eba10fb2fbf64cb37
-DIST genpatches-4.19-169.experimental.tar.xz 6980 BLAKE2B fd8b3a34a804ce8c1619422a347d1c8fc9118701b7e03066cbe58062da6b4dfee37067fe1f9094e77724eec2efc7cf99d08f0f327d4306fe9f387274918aeb9f SHA512 400563053492ef87e6301b771636162611285a8b44174dc84a5c988c797cf6bc4615ce5348f75487139f4c03b189bf3a8f2c0327ea81dac904bfe406b119bf61
-DIST genpatches-4.19-169.extras.tar.xz 3316 BLAKE2B 79436bc140d54d68128d2f356fcd26e136127d8e985ef4922c39834cebe1faf270342df8cb466f2af21582afa989e2ee1ca17894e6c81c233722557009ca9a9a SHA512 3444295b661f66745a9d994b17df20d14c01b7c00b9e00afbf5f7e97569ebfa5103998265426bfb3b0af815eb107beb6fa36e5726d36a65447082e20a1d5e919
-DIST genpatches-4.19-170.base.tar.xz 4322008 BLAKE2B f4502ea57b9beab77b856a94d0221d8fa8100d1b5abced54a192d78b50acee203631ee6906b07d42b615bd278055851ced8056ff8ce6b4e5afedabfcd0361c16 SHA512 3c9147279be62e673337e8767f58bba40a452f7b00e9985f061f29bc5207a712504625b54758882c30f23325f7d8100bcf18a931bd046e4fcb23dd2ded87a502
-DIST genpatches-4.19-170.experimental.tar.xz 6972 BLAKE2B 7ee5acfd2c193e5d7fd251790862fb0f9e331a90f37117f55d11c10e0eb82023581be067196ca6a3246977261edbd064210e5f486acc8cde423c011e9b4dd8d3 SHA512 8e4da47d10a58e86dd592310d420015471ab345727e2ade9bc37bf5f16a648ff0b6a58dd3aacadb2d55fc559b912eba1f94dd72f8604b888588e77ec3f502d73
-DIST genpatches-4.19-170.extras.tar.xz 3316 BLAKE2B 9710f67fbca0ad2561a40a6f3ba9b3f650c5e05e2763cc50c3ef60b5893e76901b9386e01209e25b76099accdc510c6d23cd908f59e5c9f4550cdfebbe0589d8 SHA512 907eca914fe2b381d800f1f45b342084c7277d9f5051134117971ff6d7a4ac40a054079f163bf83a1e330b4cca33fec73665beccf70303c20fc6a3c6065d5eca
-DIST genpatches-4.19-171.base.tar.xz 4332136 BLAKE2B be08f1eb6edcb2f6c86c088b4585324a0b1049374d8d4783a813b25f1f845996602c016fb20e1dbe5ac222a3d4308a49fa9c9eea8524d797e0b9e29f90cb8cdc SHA512 b3f5a081b597d910970c853458ef930050704fe84b3f1bf147e30f0ab3a30240b4806f4dcff84079ef0dd25d813cbb30ed4d5c43037031421a7e8357334fc46b
-DIST genpatches-4.19-171.experimental.tar.xz 6980 BLAKE2B b4f9c82e260a389065aee0c5365321dbba39b914e5e7f47aeb24cc35be91338ea3535c358a090fcdd76affd044dbfe0046ff6308876387d19592bf5a548da8db SHA512 0d1b93f7fadd9c646b2956c957db80246223b0d0d7783e8b27e29413ebcb449af23bbe96bb6387bb1ad29d8d97170a0270edf607a1b660efd3524e63b1b515c2
-DIST genpatches-4.19-171.extras.tar.xz 3316 BLAKE2B a60f4523d9ae382d99ef55e2a2f4eea7d583f187d9a4a0a8ff6cd6c6c9dce8cdb321f0f12b62195e430f353bc243dc6e2e407818493fe0400100b2ccc8786fa2 SHA512 1717a6d74da1b6a1de1a509d5710a84dd73a1fa86ddd61871f4027b2416a1b1e5226cb1d3b0b157f464c2b14865dfc97c677a3054f02f52592dc9927dfc1d305
DIST genpatches-4.19-172.base.tar.xz 4338112 BLAKE2B 9598c528008e9e827b0a03f4ff7bf406e04c17622a5704fbed8bd2b0ee774374eaff93aa6b18b507b45482f08cc49668fbb001c0a69180b6e851cc40eafd77d3 SHA512 f654e57a87cfc00dc068b1f43b47d11fd51f15c7041ffea9402a15b222f82048444ccdeb4bf19628b974b21ed8a853fec54f83cb62e51bb8e4d69172b5c599a2
DIST genpatches-4.19-172.experimental.tar.xz 6976 BLAKE2B e968e3c35ad00a07cdf6f563f159d47d70571f16acac7033a9f45d70e60abf24b5544b6f2cd35f9f7af4f0c886c1e7e7fade7d3e49068ca3db4eb5b71cf5d3b8 SHA512 714359313a32b99d13db158093571a725eaf05b985f821d049c96aac0a24af8c2600914632a2c556740adb9f0d5b667f836de8a8ba019fee6e696fc320842056
DIST genpatches-4.19-172.extras.tar.xz 3316 BLAKE2B 6bd3f8d3653722f3550a604451cd11babb18af1858deacee74a9bb6b6e99eb7c1c1ed33007fba5a599381b45a32507eb188647baa7e11374a8c02a90646367ab SHA512 7d077c8acf9e963d6605a74cabe75658b72a8ed98bc011102ac0729af4a4628790124a9d53bab5eb10b38f30fac85c8df5930a6ac4fa69766509836bd1edb96d
@@ -49,21 +25,15 @@ DIST genpatches-4.19-173.extras.tar.xz 3316 BLAKE2B f3c95da98341cde3929bf471d755
DIST genpatches-4.19-174.base.tar.xz 4351748 BLAKE2B bd4838c6f6a0fa7b681d961c6d0e159f7ae2df805618b514175ec35bf634620962e74dbe3a02541c3a7b90c5d72d2b5ac21d098f6eeaffbeb41c618683bf6372 SHA512 a316e1d60668f86b40547d72aca498c9280da98490369687a1f182d957aa8997e416fcf8464bf7d569cf9c4e3c245b4257958f8623f4b6eca769271fd16eef2f
DIST genpatches-4.19-174.experimental.tar.xz 6980 BLAKE2B 372def848bc5394179e6b0dcdf047ad4adeea472a094b573f8b430ce4fa0c45a015a2e423194c8c12909c83b71a80e2c4cee40eb2edb2c87f06f9662e8381301 SHA512 b06b976ecede2ff415303cba109a8cce240ba7110c2f7947f083d06d9b31ee9f28b0e7653acfa87e05579586ad073596a08b1024df65b4ec93f568da0c2485d3
DIST genpatches-4.19-174.extras.tar.xz 3312 BLAKE2B 3bffb0f36d9a383b5ef2b556fa4026c4d9046b58174f683e4c6f1e8c7f64460e8d5f0f97f8892218a6922674a31d41a2b7f04d3bb886ec4f4fa6d05d552e02f2 SHA512 178b929b5a193b9b8272c50ba9b6213cec4b73dcc7110a83231a89f778b90af098d19eba215d8b42557668f5e43c696fbb090f856c35278eaec8f804c94faa1e
+DIST genpatches-4.19-175.base.tar.xz 4359896 BLAKE2B ffc8654f8834a5c561903b4703e77fde83595cb039b840f7092c13c4676ffe5dac7e53b6d0dd6a24c2c94731b0bfbb3c062baf7feab2b2fd0a86e8e26b7e9d8f SHA512 a38d029c6767731e3d32e085e5bb1f5fabf1308818d9bca798b7c4416bf9034a608d6e8f0516e916e7381bf3164e4a13d2429c4d885f62456cd013d75741e9e6
+DIST genpatches-4.19-175.experimental.tar.xz 6976 BLAKE2B 5ed6602506e84f236245a66500900f8302469f18e46b04398c422cebf9ee99baee91c49cb8d1d2467ebdec670da6820ccaacdde7651e62d9f391b87d84110950 SHA512 c0c429a33227b19f91ff986a07db7dffd06eef888391e2be98c53d60c247f43fde27a3edac8fb1635e37aa62b959ece9291823a0dc3bfccd69ce3c17bce2ffd5
+DIST genpatches-4.19-175.extras.tar.xz 3320 BLAKE2B e44b1dbf9ef89900a1a557190861513ba2ac023df3a44a6ba2e7dada82469d6ef1e95cf61ae5ee46174883257c9124d7c8abf28c01be55a54af06a2b8ceb8fe5 SHA512 56b8cafcaf18e77f198a6fa6a8701a3ba3e02bdc4f78e94402a8282ee38269a9f193cb341344666aaa474a9ca7241fd6e1c35d557bf408003c841f937229e778
+DIST genpatches-4.19-176.base.tar.xz 4369596 BLAKE2B a6f8ff5a906cdd8d969307044c0a40f1f8ccf7db15359574322bb5860e6b4aac7be783d121d779c6e5f0301b5c8ca9d5fbe420f92c90fa429ff864a8976827e7 SHA512 b610a2ca7f2f29631f04858c3ad98dc6176afbfcc271e7c62875a0c71cdccd5e3f669321a19dff7df271d9d4f510f4e4e8c916887940a9ca7cc5044aa74f5a4a
+DIST genpatches-4.19-176.experimental.tar.xz 6980 BLAKE2B 86f92cde5c96fb053bb5fe826207226336ad27595477fb6d000e1a7686c868cdd6a1623763d125aac8e545bd945f7a24c7aa1002852b4c42b9a24d4267fd6ae3 SHA512 e75f382c21799a79933a5974724db8020cdc6ec915963488d0a18dbcc4cdad109f270a52d2fd3f3ab760821d11ba37fbeb18a18398db74f9acca983fcb7a2a05
+DIST genpatches-4.19-176.extras.tar.xz 3316 BLAKE2B e7cc9aca5dd8a686db5ffa43e6f903adcc94208bf2c168ef5d3fb7d31d9349e0178da73fc083e28941872892ebbe9085c670804e9c29925e656044acfbc4d758 SHA512 a34c02a3f1ab5f04e427c04d7c8e0c96217f62644e873172e9e71923caff2d43d3d6eba543a831232b1308a5e71212346dfd22457e0ead006674cbcc0083faa4
DIST genpatches-4.4-248.base.tar.xz 3950896 BLAKE2B 86c1c74e41d3b450079492d26ffb773e9c78bd69e128869ad90938adb35e00efdc55f6ae2eaf5d163fbfbc592f6556d4cabcfdb83b7c874203fa02698986632f SHA512 266467cd2a82e51ba8d388540b260e86c058de48761c083e6a6c3dd37f7e2c6b2d4a3901b030e69d0eb7a5b13b323e141764ea79a9d5637d7a3568c6672218b6
DIST genpatches-4.4-248.experimental.tar.xz 83320 BLAKE2B 1f30185954ad3247e5cded8074f4a28350116d3ce1006b717de63842d9cd5cbef8241ce29e3ec52aaeb0fcd08082502a722ad2b618a26778d2553d9999530c72 SHA512 e5b5401e6a47c34a5eb495f317f4db9aac2c43676e07798d385b947db179e41e6e462fa0ef577100ed21a8a7491e7387df77a8c1e7250ce45e887e65a9d1bcf0
DIST genpatches-4.4-248.extras.tar.xz 1788 BLAKE2B 3526b5cc83cb4c9fef68c4613d23c44acdfe84e89b46a3d50df90b91536077ce76973993eb6469947150faa2302ac1739ee9824264903a80edf8c24f763b7553 SHA512 e7e63456442b7fc51b3f3c1aec0512e0598d6e85cf5e0a2ca2c2046e86f754932900dd59b4f5510cec2a782f4c806c5b979cea8b13ae2fe455604efb478ac985
-DIST genpatches-4.4-253.base.tar.xz 3995836 BLAKE2B 018bb03a58335d66b28d1405d25c17e83a624e7a192560016ca799c616e031031464f5a58d1beb874ef54e4993814ca316b1f3cce747baad92c605906cc1cc47 SHA512 0b3f164ae34618dd3b7f800dd3ec1258de20ce2705294f86f34d2af49d3329f1d095fb027918e2530ccd06f14c0d08011afc56104db9837e65122a23d4397c21
-DIST genpatches-4.4-253.experimental.tar.xz 83260 BLAKE2B b5a198ce4b5a4803a64beba8e76227da1b11fe9b3eb289e132171c5b70eb78a845f3c915ec09f4feac66fcf7059dbf2d94f5fe6d3c91ab3d1292b5897ee15167 SHA512 367205bd834081fc5869dc38a607fc63b804c9a8d80093099753a6987ffcf0cdde16826560cc06841d4f23e03279cd1559d76a619f38b4dfbcdf4e7fc077f62f
-DIST genpatches-4.4-253.extras.tar.xz 1792 BLAKE2B 38044d9cee57fa820ee618e96f99ffe6e66addc43b795e582e05a168c51fde20057930889fb317c7571b79d3a2f50de63e1169969723572707e056568848888c SHA512 7ddfa7cf2f498c9128d22c1dbd71e65e36d41738a395c83bc310e2efe547e537934b25e70609e4a119904adea09828b5b721faecaef69210e4bba09f89dc38b8
-DIST genpatches-4.4-254.base.tar.xz 4000472 BLAKE2B 544bb06a81bfea361f55aafe8d94c02724e09ba248197249a0dee8415cc60bd12ee43ea88a9d17b00dca66523af56aef8ec473631fb8c4e38f6d3d3c615c7f90 SHA512 911c851bf913dd2e35b29bd2454b8653fdc7ce20b859fb76d78d7e1b25946c5945091a52c208653982e19650c8fe58c24a62bcde64d1a6b1a4491eb1f3ad34bd
-DIST genpatches-4.4-254.experimental.tar.xz 83284 BLAKE2B 7df0f3fff7bcde301f456ef547a9bb2c306c1a17ca90f700a1f4f9da490ca708a981eae8c0ed8825905eaacfda8366c423d72ee33989fe51ec288f8b6d407bd0 SHA512 81aa1792931e3fbff146f8e089721ad01e4a2696ecbcd6b8e0788607f1ff273767b25494635ac79b4d5dc8a2f4edd1103315c79526fd545e4c4f8a0585488b04
-DIST genpatches-4.4-254.extras.tar.xz 1792 BLAKE2B 981fb3ea47b9f5642552688a61efe7533453ad61d88e239e64d117850c91d4f5d6a30fd9d29db163010bac34abdfd80e457765db6c1034f85d8f5c2a202a1ff1 SHA512 9d20cb140ab7fde7410b4e908289053f88988f626c8a5a70b59d1a66b95849d07b80da9d6a5e08e5a8819a394ea61a7369a57ec3b2b382044481858f7a4e7d54
-DIST genpatches-4.4-255.base.tar.xz 4005524 BLAKE2B 9c938bf3c93fc4261723717f866a46d2ae6db068642ad510c5a3dfa3d4800b307b50586e8301bef53fe2b41b248a6ab3b6f7c72490c5ce8de05a8d7b43001135 SHA512 3b2474c3fa5a017fc68ddc32e8540b1b8d39cee68919d4d9e603ee804e8f0a4e35d22822c156fab7470fe5b0ca7367840cc4869fcdf1c400db46789187803c3a
-DIST genpatches-4.4-255.experimental.tar.xz 83296 BLAKE2B 41a4d270b0a97849c792e48b6fb00e53504d42ed783fdf82e031c3dc012a3f6717a308dece8e1d8e0707ea6aa75141065c5fe2dc14cc823e8d345c69299984f8 SHA512 0ea4ac981a70e1f56eb8b59e5496e13f218a4d471a407572da50e4f015ddb7358a015c8106a9685b511da6245f70ead4be29a2aa1d339c6ff62bce9b2cbce31d
-DIST genpatches-4.4-255.extras.tar.xz 1788 BLAKE2B 4bef240656562de76e2b22a5975dd3ed27dc57168eba30f78e34191ef06351cd6406a5c849b0a4f534577183d7b3945eec4dbdce3ad5a496ef7d783d1a3eb369 SHA512 56fb66fae36ac32efca12a7c28b9dbb24afc37f2ae389f4c64f107e962c005c8c8a5f7413fa87743d7a2bbaf98c0d6ab055b8038f8a4823441fa116cb40c1bd5
-DIST genpatches-4.4-256.base.tar.xz 4008644 BLAKE2B 05529f58067f723e767cc3b9d11bd64c01213febd2061d238280cdddf60776a21067595f5d4f65c0b1e742d95a847e7801e3ce5a6d19e8b14f7d77b42abaa3c4 SHA512 4e1ccfba6b7dd355fbf54eec89d59e30cd3ccbfcc9a3a507756f6d3d3fc4e90308ff9d99962097f98358a72e68dff744948438c1d9e91b7847ea961ead758890
-DIST genpatches-4.4-256.experimental.tar.xz 83268 BLAKE2B b2e6b2d97093ff14b67858e0bf175981bcefbbda59c4ecee91b45096de487be29c47b1c0d1d3283bf82740c42ae6f6c01c416c58a282bbe83527a24fd0cd3fac SHA512 0f60033d305c9c112d250fd99ba32bc148a067400fe7cbc089a90b67012f8b9d3ab62c1a49e334965790ce3144d5a0c068700bc6c839e9ca6264e4e4f8113aa7
-DIST genpatches-4.4-256.extras.tar.xz 1788 BLAKE2B 6655c4250b5d63fdb41ecc5b443df968977a6453bce5e9d98ba26ce5fae9957cd8050b3ba12cea31f20cba3b790bc2394026a42d4f72d557b463e5d87ef6a56b SHA512 b2c66d6315e8184f90dbe2461943dd70ba67cb571587f479770cfa89bbf0789c74db4c8b05fd8b794afa5c93be4ddbb1f5f4beab5034849698af48a011a862e1
DIST genpatches-4.4-257.base.tar.xz 4017812 BLAKE2B fa2338100efdf5180823e6491ff5e0fccb284c2b15e60a1991c93cd315e1fa6c8a16546f3d2fb7090b631ecc8b448ce58f43a36b6267f16d36550a33f6e063a1 SHA512 73d694b286d8bc3e3305de0f8901bd23805796a33f0df77835f6f8d0fd8d5b0b44c457cec9a5444c1df5bb37d9ecf13f167ff9263d0148fd1e3eda257abc3eb0
DIST genpatches-4.4-257.experimental.tar.xz 83332 BLAKE2B 6e11b135b7a5de7bff5681f026dc0bc981cc59a6211a91ca8b66ae6e114757522ed98a0e97ee4fc38606c42679c2728d4b027c629ca4dc2f9691c05542f31b48 SHA512 df47db5a3fc308b605f0ef47143e676f7a999e8e70623840b6a0df9ab502e931a222fad135e6c04865440a5e1ea11349b915f089b09113f2acdd06f3029a8654
DIST genpatches-4.4-257.extras.tar.xz 1788 BLAKE2B a6cd780c720bc523469c3be72ec1845fe49bd97e8f79cca3ed6e816a54f1e4d792a30a1f18f9fcf7dec70945934334cfa2880d6cee02cbcca0fc0511041d55ff SHA512 70a5f8a0ebed2a36c7b003227613f289f4c4f9d125dd3573b4815b4f48685f3236d57cc1a195aa7fbcb990583a15405820e9bcf8b2b2d46824664d3ec21c3286
@@ -73,21 +43,12 @@ DIST genpatches-4.4-258.extras.tar.xz 1788 BLAKE2B e1815cc3bafee3590b062704e3fcd
DIST genpatches-4.4-259.base.tar.xz 4028152 BLAKE2B c01f5acc3523aea23b3d0d20e714db1a91b70b51b1ffe9bd57738882b28823ef8ef2fb2aa3766a050dd5efb597c1605d34be2584d83f170d4efa741ef49043c3 SHA512 8dc0bed820643799007068a1a00287c7cd55cc0df1c2b83a945c1ae7cb75fdbbf41a7f6df1cd3853079746dbd2b7e6c9ab21a531457ae1f71a4b03aafc8c23a5
DIST genpatches-4.4-259.experimental.tar.xz 83312 BLAKE2B 998cc7fbe38a981251691026abba9fdcb17bdd388ed92d7aa61745a772c3072ad630be7e8cebda4ca1c64642e94ca6ba5e46452641f306c65a04908f58c47659 SHA512 9944a0bc502db83edd04c683ebcd15552f02edbe34e19b5687b04830786f2dcc7baaaa2b613bbcb568cca6abcee73da830e1bc4bcb9248aae80bfe15eda0222c
DIST genpatches-4.4-259.extras.tar.xz 1788 BLAKE2B 4512f1496b02147d6237c970b9330af46511bab342645467687cd7f7d0417ba2373a1ae07361e4b0020caa878665f3c76a3763cd92edc07d3d677661a50226e7 SHA512 464129ea698d8515a6d3d2cd8603adf0b3c9bc8a3c5436c10ce1e43ffc7ca4b8ac1def12d20356705707cf3d25d10c79ff714ecea842ce1fe4f439cdbe3427fc
+DIST genpatches-4.4-260.base.tar.xz 4037716 BLAKE2B d2ce0f0711f27b2ac8f88585f1b2013b290c511d7a52e384f47ef3f0d60432c3e877cb84ec91ea31ddafdc9cf1eacc99c1ee836878c2e9e45d87dbc2056d9db3 SHA512 5f8136861ab7eed3c46472af1f090528331b0628bf3061c7e9b022a87102c34577fe34e0f8ad0f1df49438fac3db03b6e7f7c2b2d9f96e5c558b5b4a350fccfc
+DIST genpatches-4.4-260.experimental.tar.xz 83304 BLAKE2B ab611f5b88f4526409f4bf5b50a2c9ebac10d986ac36a75decc15386bdf0f2dc20d5a1efc85563eec4e820a6441fe8f8404f02a727f19f064dee8c42e3d8f0f0 SHA512 c07e67534af3549b2e81b378cb4e6ef22c87d527808b846038d7c45df73a5d8ebcaa3eb9539a9432e6578d94273798ed6f51d6d711d16c8a3f3a6cb73ac50385
+DIST genpatches-4.4-260.extras.tar.xz 1788 BLAKE2B 0ffa226d157811b6870f68d610f25feb71e82472f692cec3420c896bb59b9c33879a31d0e1e898d9e51f5bda2d5389706b931e01ebc847c932095e4325dfadc5 SHA512 1ba0e11603bd0d1c24caec3a2e0f2c51c79ce5f6052bdba9ce79ef86d40150fd87d0e0587c59738e3c3965d22e031a5de4791e1ac3199849bac4189391e7ebae
DIST genpatches-4.9-250.base.tar.xz 4423652 BLAKE2B 028223b668bc00d1bfbd4bcdd5dd201f9fab0c9a4ce68f5e107c1de83320c88865826eca0f38b5aaf25c96e2d66a76f0d305b73bd659197898818515275d48f5 SHA512 f10dc4626b1863177d1dbc5e1283c8848b84e6ab10b3208291a0679a3023c5f7d34cfbcc6091f7fcdb71e34f02afba3e7685e24b1f38730c88197c621e41fe08
DIST genpatches-4.9-250.experimental.tar.xz 106372 BLAKE2B 409a0fdfc2246e57f461abfea86f76694ee835215e0ed816e1c445c2e5bb3439ccd47414315f81e9cc791f7206b12ce45c9f46892e9152341194e15d0a44a090 SHA512 63f8d3e6dd777fbb8ed0dad1b67e0405926fdb0c1e40d3c9bae63494de87a3cdba37e41f20cbd7ed109eba6a933125bc6354814f5539c20c377be449cfac3b48
DIST genpatches-4.9-250.extras.tar.xz 3340 BLAKE2B 14cb6c6993c772cc8fd2a4a63f7fce94d850a926c74ac954aebf66e3bbb5db1c20001c264056a8f49561d21e754048963464226d56a0c10eb03cb59384420487 SHA512 a1eac658ade3bc0ecd6c98d1e0fc82f006e75ad4147ba0f2facc58e647bef731098527ff77d1d817f7605c0acdf3dd3f536464953fa2af27c32eba2863065db5
-DIST genpatches-4.9-255.base.tar.xz 4486212 BLAKE2B 78f14a525a2bafa11408ae34fd30af4c93459875e41905070133d413377247a2405f5c83c04fdbe18f5044a6f2b450a8cfbecc0dfd9496bd26f2b8b350cb4d38 SHA512 a235dedd73c6102dbe6fcd2c6dd1737647de991eed2c92a385c3b79bc6719e0078219ed04403b09d36d3152058210e2a1209f9c1f856599aa616f0e846ea99fa
-DIST genpatches-4.9-255.experimental.tar.xz 106392 BLAKE2B 96ea1a34e5edf9866c47cb9dd190442062ce94cd2cd0723e37a746b10aff6143d88e6a8afb4b8f458f92a03f20f94ce98f4fdd2557dce76c5a1af5b0da9c3e99 SHA512 86f1b6960489e3d7977f79d8c826441a81587d21f3534383d0e6cabe6e1ec8fd6ed0449dc9b58f60e74b427179bc139983699be4b3df7deb7dc44c1adcb18de6
-DIST genpatches-4.9-255.extras.tar.xz 3336 BLAKE2B 896f9f51ba73a601c6d2b7c16398c9c475147b03712429223d4998f36dddcc24f06cd6903f1a469ed9092b99cc1dc00a5b5ca611931816b838aa33f913a7cbe6 SHA512 dd99c9e2e5d9f6c4b17d395223d395da1688e62afa021f7c5ce0959011dbbc7bb71a8ca5f3c8766568da73fd5a82371554ab92277d79baa0454b1d069ad50c7d
-DIST genpatches-4.9-256.base.tar.xz 4492036 BLAKE2B 651238a0ab334f295e5bbc80b306529b4d0e90294e673376a52ad3ee6d0ea391440c4d22d71935c6d19a861e7d7b1792a6e4a96a0f906ae4eda566d8765fc9d2 SHA512 acbc6bdf424514821a695118492bd9a5fa2accae7ef387acf50363d56763f1e14cd4ab3427450bed804ad86a15b3412f6615a7f215410cdcd67bcd00beb91719
-DIST genpatches-4.9-256.experimental.tar.xz 106372 BLAKE2B e0de68aa4f0e98f2ac59b4cb379e737eaa8c6055673dfcc1f197b2ca30fbda257b035adfe27cddac5d8c57b0f42c46a9166b4c4eb8c0305b86212d253ee0d223 SHA512 c76f7c490a8f97c312d09a480adebe049c8553fa43b26ae1508bb1c491d507cd2741b7a590c90a6f11f1536523719c8a6c0a7c2d4fc60d647779a64d3db54542
-DIST genpatches-4.9-256.extras.tar.xz 3336 BLAKE2B d760dd5d8b5985fb0d26b4ebc3b7f98f16e876ec1bee39fe207d5dc4ca6d8750a9d6e5626c3f0ed9305955b16c5b78c610ea2120d5b742a73b9849196b64090c SHA512 c96add4e4b9285844fe3b7a8cd4cd9b59f07326699e84a5d3c9df19e023f0bc3cd156d8448d233743f57f851a7a1bde4855e8cc275df41131e402baf22903f4b
-DIST genpatches-4.9-257.base.tar.xz 4497684 BLAKE2B c18c0545a739235dbc4e31714b820b6131ebc1bf2db05956d41210af724799f1d0ee8daa4e3acfe5a3378f9ebea017403e33ae86521243f54abee054bf01b75e SHA512 76b34da6c80be68bc3626800126797b09d6ae2272abe2687f8f30c87d9fc83e7739e8b664cd2304f89f8bc4d18fb72fb4db5a79b38ec75613fdd367f6ebab2e8
-DIST genpatches-4.9-257.experimental.tar.xz 106376 BLAKE2B a2ea68bb783a4e8b63faa6cc4e5c67179748202a680e28c47287e80a9476db4b3094dea772a3252ab5939a3168687ac782a84a8d57840758fc58b75ed206c256 SHA512 542a0a8d62e26c8852a56b32c6e949c38b25a93ddb7f968f4ee79c5e4abd28d6ecbcab0341da89d988657dce8f9f526710063daac0306abff8eebdee9a8806ee
-DIST genpatches-4.9-257.extras.tar.xz 3340 BLAKE2B 81e5d485d49dec56444164cecdc5fd2b2449e140366871a488bc944c216eae5aac720a311609a63c91bd7f861515acb468bafd74e217269221bf403e01260e3c SHA512 3941a439ddb67ed6e824fa60da0cf4568b8d01511ec3fa3d12e80fb9be5c33e1087d0b3ba0a8e39cf92e512dbee6b1f5d51e402a86f826b0956d8acf0c0b6b48
-DIST genpatches-4.9-258.base.tar.xz 4502052 BLAKE2B d91fc14684832f56dbdba84a6ba9052f6529bc8598b87b7eecd71387d85197f8e779074a66b7da475cbce58d43456d83f98ec9527aafb4f38255839e1db8fde6 SHA512 3556f603f941d64365ea0da1e4c76675c0d44bf13bbebf0f2345be36abd761b8477588bce9bb3060d44a4949ba94811bbcabe9a2686ac94956ed4553bb4d1fb1
-DIST genpatches-4.9-258.experimental.tar.xz 106408 BLAKE2B 70b721d56490d11d4b869141ca2635a2c304bc4967c1f7bf7a436c8b1d45a373768d6763661975fef24788683cd5d6c33b48dab31162441997ab11132d7709fb SHA512 c2596e0f051c0f6ceab3564342ae862703bf6c5498aed6e8bf467ea6ac297deba394b38fbad5b504fd7cd0673d2d80578026415a63c40f698a2444f87b6c3b6d
-DIST genpatches-4.9-258.extras.tar.xz 3340 BLAKE2B 8b242afbed3d5b2e0b2bc1d2790c81393048c94b3457dff981f64562978f3e1d19a9e3eff243c8ed480be5f3b47acc2f437b326cff401f92824ea8a8d8a636b2 SHA512 37bd31f746d9863ef382383238dd1b164eb718e132227df54d0a7bf013a92be261d467c7cdc505faca5af9e9fe7faaee98ff6b0e3375cafb936eb9b0d35e4aa0
DIST genpatches-4.9-259.base.tar.xz 4511348 BLAKE2B a2ec1e9d0020098f75f3756cac378608654c13ae8ce97bdb1f9b8909d527a8a8e1deaeb512a6333a8597b049373332463180c8ae8d6a9a4f0946965e43f560cf SHA512 3b2636e0c8a8535759af0678e04dafdc8bb764b948145ed00ca7c4848a53ab5b7dd1aa4efb668a2539ea4d8dfedcd24c5dd02a9590ae99907b5a8a918644f22e
DIST genpatches-4.9-259.experimental.tar.xz 106368 BLAKE2B f3ea97ede99e5661c31a623d65f9546c9f63e27857a2883f81c21e9abc916c1111ddb4cfaee101266797edbf4c11ef60118df54102413facbf469d50801fd8f5 SHA512 f32940476b3f4996a67b8c646c95a882d325ca54fe0e67208ca47a89b93a803f3a7c5b3f030c01f510125fac5632aeb6a37ab1b28f6451aefca3749ff2f9d382
DIST genpatches-4.9-259.extras.tar.xz 3340 BLAKE2B 757e880e6c4cbde23208c1d720d13ba46ebc050634a15d9146f80f066f320238e65aa37ff836dcba21ff3562d63432c8cbde3661c63730b22fcdf189aa4cab73 SHA512 fcd1aace4eb35aee67a49a0128c165bfd36a7a8599ec99d0506e199f8828647938cf066bd535dbe72aca07d4870fbd70ff5d5d676c402f7a5486e36a9083ba61
@@ -97,54 +58,51 @@ DIST genpatches-4.9-260.extras.tar.xz 3340 BLAKE2B a382bbb0cffe55cc8b07a8e39e8e3
DIST genpatches-4.9-261.base.tar.xz 4523340 BLAKE2B db59ac0593896867e8499c2f261cf86c51dad7072e4ede8d36f112f3f7571aa9e0e7f4da6de03b2222af4c2e6aa6464426c16dc1ee46629808fb5835865c4218 SHA512 a98c3891178a831ab7cfb2d2185d6dc5439a958ec7331f2a42cda0d59a9b1b19a04537271016c1183a5c69db1601462641bf2d90dcffbcbc5632c79cdbd23a07
DIST genpatches-4.9-261.experimental.tar.xz 106412 BLAKE2B ef9d97961ee9d92a73d026d6663827d8c1fcd4f6e5c5b88011d5a2648e0e9c2041089d443d5b5ffbef47ef5fcb21c79373293d5fe074d2ca5622cc7a4293960e SHA512 a9eabf021afddc52f08123a7fee8566bd102f5ce4dd484301c4626c8a97c514fb015ccd814441039e96e7415669d88333c82aa4415b397dcf9adf4978824e232
DIST genpatches-4.9-261.extras.tar.xz 3340 BLAKE2B 832c4297efd20a6699892a938867cd47c34fbcb77e1a993092ca4dca4d9113372b2362059295f0419db923da953713f7987e90bcff5c2771593166f77eaf1688 SHA512 950dad68d92c802fd844853cf0136db90b46dfff2ef26eac633b80f9a36610c03b9ea0dbbf20f1af80c43d1def26ee7492d040072c8c799ac22c9487cefade16
-DIST genpatches-5.10-10.base.tar.xz 303380 BLAKE2B 61d1378cbde5f4df5ee41d2a3391705279e647410125350a2329c6448357617cc93e1acb7f8af4cb43869ff11b6759caa3652242b52feeb8ce2aa2c36c26260a SHA512 9d9bd200682a6cd92e067024e42bdb80347e7083a698d2aa135de34998a80454130ac82ab49018e538197d35f48fdfb0e60827a219e2d6844e221450b86b9ada
-DIST genpatches-5.10-10.experimental.tar.xz 17524 BLAKE2B e0d44619d202267e4d999b0066e1475661534ca0e0a4b50bab7f3cfc7959210b6830b13e03b534553be1f80adb4e5f53c0bc7bfe181839982821670be8827176 SHA512 61114072025d7a3af31a07f7000b125c410c3431f88cf43f92244dd9af4d33d090bcce7a675df220a3215b6e68e219ed8a186f49b4e9caf49717cdf67c100cc8
-DIST genpatches-5.10-10.extras.tar.xz 1768 BLAKE2B cabeb1ebfbd545382a8bd7fe89ca78d58665848b86a5b25519c2d018720d04253847824d4059308b80edfe137383d26c89491c15be8efe86b95dcc184d3f35e0 SHA512 1e7c37441d3324c961d8d55eda3e43afed64cdbb45f2080673ab888b65b3b93c5f74495d8a3a53197b17f9d07f01cfc84a0b1719e5f3cd93652a512b9be536e4
-DIST genpatches-5.10-11.base.tar.xz 343372 BLAKE2B d844a4ce292477da26bc02743916143cd6851b2ba85229ed37361213580b47b5386f260bde7cb77eb5842f3fd1022b6af64d47dcc3fcf2161be8157380e082bd SHA512 069efa3d348d8a7601c6bf37ec92e3efa692abe4a7ca5dc4bfe30fb76f1b7fe8daf1a0f237d60dcf66a0815e909ac77cb1cc189d46f6fb4884a260f30a4af48b
-DIST genpatches-5.10-11.experimental.tar.xz 17520 BLAKE2B 657af869b0c897695834caf87dd99ff4b95358a081b08dba7b3c4c7dcd61f6d1f7fb9038e4ff093bfa26373dfbc81cfb69a674752d067acc043dea05d3d8b820 SHA512 57ac770e33f1f56f66daa1a6c1d2b8fb6104642d3ab21abacfca8bdb92c945d2aea64a3d383d72a19813621ea086e6c0f1b3aae4b918a9d9f1d21581a4fcc7e2
-DIST genpatches-5.10-11.extras.tar.xz 1772 BLAKE2B 8d4c4b94e9bd7c585f56038900256b3ec1ae721b4ed7adb326f393094e5c8960575efdbe2cc14cd219ae0a69cdde5c626d6983741e3f13a39bed3e85f3eb7060 SHA512 90ce771ad84ffbeaeaff6a2827577fc9c9113930dc4fd394300e1a971cc205a1f4805404e1b356dc36b373bfcd9daa95de7a364144f0fbeb0f923209946635fe
-DIST genpatches-5.10-12.base.tar.xz 354672 BLAKE2B 4c92a3c4d144e7abb130371a5d12e839d280789b2c44e97fced3a35d25fcc9b084c3e3e8832fc7670a4811da7026963a1c498a0cb2c44cd325ab13aa62a3d142 SHA512 7ee954e44305b4276717aa4a1198ea036fdd1f18e17c95fb0c5e8070acf390c1644dd0499d42ed1464fa7d9cef8d90abbeb6d0e0448c2fefd5a655834a5afa5b
-DIST genpatches-5.10-12.experimental.tar.xz 17520 BLAKE2B a67d4e2049278f677004813fc1cc144e4e84ae58e6a52bc41534a7794a2a52bbffcaefd91665a6c91cdf47c445971e756063833792c0fcaaf6516c61c3f1b93b SHA512 8b79c3056dc5015bb7219d7eefc13ebdea1a70f8d970f16a5eaa3b32d63ac25575fdadc9da627be92f457f23824e0a2be8560a8dd1bb69cca692c4f69be10d84
-DIST genpatches-5.10-12.extras.tar.xz 1772 BLAKE2B c219ce68835104664a93e78e57c5bce67a3d654666504ae38fc5058d6f8df67c9e37941f549d047b446061f54928230a384d813b4bde2508323facef6502bc16 SHA512 3b2b6ba233226f9c0d54d1dbcbd36133429dba1e0bc7a355fb0794389fd729e8ebcfd1789c4b79529ca4bf48dc50d7b07c1e167ff19d837d67296f36705e7db3
-DIST genpatches-5.10-13.base.tar.xz 407940 BLAKE2B 21566164ea821e5ee95e4b4583395625384347d0e8440b29fa71f4b63365c5481dbb683c84818a5379242a25a59fa85c3caf420be3e6cb8553a43834dcdbfb94 SHA512 0f4e5aa39cc8dd6f2cd62fe5293de1d9fa5a0f6e0dd6da9af52ad68ee8318f995d9095df65b93d6e15994227feb87b5bbcf0403ebe774141045b05bf239dab86
-DIST genpatches-5.10-13.experimental.tar.xz 17520 BLAKE2B 0f3241b311dd4c58e707f313395b56030a1c4f5b5912daef903de47172757167c53dad2236cbc69598d9549fc369d6575508e7a0553d1ed3d9581b5ddd020007 SHA512 383cbe2fad5a4453ff603e41f10fd7ba4b68b7529e92eebb7977888d9d822133815f1bcba7ae5902f7ff70cdc2997e3a1a023f07847fe6604ee386ef0b09602f
-DIST genpatches-5.10-13.extras.tar.xz 1772 BLAKE2B 29357a93bb6b4e34937e6655bb8cecc4f57edea8a7e7a903dd8196c6f075b27e2b1176a56a998777c850994c5131a2a57266a7fc579a25fc43db9c9aac4dd80b SHA512 e9ed41cc3b81ae7e76fce6bd6df271eb354110252da85e7e90c4d08816babd1262c5c8fbb62fe56dff1fde712abc35ee40c67f9f04e3541920eee78b32074928
-DIST genpatches-5.10-14.base.tar.xz 416468 BLAKE2B cfde628c2594a568c8f699ffb63bb1bfa5054fb810a0baf8cc08c87886d49a5e33725be6a6eb03ed0f8fa40521b9591ae0ac1253708a3ae72556e0cff7efe17c SHA512 84b815aad491aab1592c253da7c37d307b102fda9d08c741cbe5df9c5bd636a83eb8af0e96faf6b54c13bad77068d3ca1f632ab4c68211bbdfb8a9c1d233f06a
-DIST genpatches-5.10-14.experimental.tar.xz 17524 BLAKE2B f81ff677340b959011dd1895f28d12a084ce9817e8e0e3fb1a7bf93d8cb900a8cc5557ee3cd18da6c4d81b5394c57ef94508d3529d10a37cca9f72c04ed8fdbe SHA512 bb7310d697c9c1f1d862b56c0b13b7d835ba8311fc628a2f5829d07a4a651696bfa6be6de0e268973ea59e19fcf99de4bbb175d519681d0113fd4f8ba0d41aa5
-DIST genpatches-5.10-14.extras.tar.xz 1772 BLAKE2B 9694bc87e97e7899f2d47199c42082a666e775f35a49a3efb20f8b15cf35345b0905b5d36bd3845e4b62e0ae49260a7fb381f26c6cdcfeb20c3eda5672e81e29 SHA512 be9fbe10adae2acb813abf94f7008620ee9c5f1ca28053e4c387ecb814e3fa6b0e08b6c0404f1585049ceba4ed419dbcd524f9ce69f25dc12006b20d5db3dfc5
-DIST genpatches-5.10-15.base.tar.xz 455860 BLAKE2B cc02492f8f33e3b644df293231e9e6718007b4556f7e056256eb6040e0adaee076f1b25dd8086097d2ae1c50f1169488c2188e45756d0aa47e0b0d34f132715e SHA512 983f45356831d74a6b5001bfc68f4252d687f307cfc8ad2925c3a844f5e9c13e6407f6c591b49028d9cee599106b771078fdfe57137801ba0096552b99126666
-DIST genpatches-5.10-15.experimental.tar.xz 17516 BLAKE2B c4b3fa7014724fda6be3e7f530f0f78a9caa3cb531469b11ca5cd4962b545c6a9d7bb5e6b8db35d98c2f84321808ecad5ba307effde8f6beb3c0761647a94d9e SHA512 3a0ebd497561682e4bb23ca70737f67b73b59d5053284b1df17ca602b2be9fc71718b59b86774479e1c455df86ae240ac5abb2c847db20e05e4e4e503ef9d5af
-DIST genpatches-5.10-15.extras.tar.xz 1772 BLAKE2B b7cefe073d4c1c6b6f5b57e79faa95baadea2a79be973524876941275be05b60be2008ddcadb02ffab605d47dec4fa325609e70b58d7c59aba83d2075d7c3766 SHA512 ab18ecf108271a4a132ca5983a47985dd462e5b312bf0cbc356340713738c40888b59fe4fb2597c218b41098d6496594f2ad98638b6b14c435ba271b8f4b2882
+DIST genpatches-4.9-262.base.tar.xz 4538164 BLAKE2B fcafb64156ae72f214414128b5a915d4dddb037907d48b954df0235b235ba39d4fe45ef9b30211fa267b722f4b7970f7c617747ddf5eef3d9ddccb0825d5c73a SHA512 725ad4ff484578dff30748ab264f37368a05a9999243116200a828b5592eed3fc8a8bac670ac70d94cb6caadd830f6c90e8c349a05f81bb3e4369c5cb892447a
+DIST genpatches-4.9-262.experimental.tar.xz 106396 BLAKE2B dc7f47f983fb5365dbb6974fac91508af8150f237d7686f7f6d705d39e07f3036e3929f0a8032acf95c47add09239c32c627d4da1ed1f5cc27bb5e80bdd8b35f SHA512 17848ce6c9a6333f41ed878a39d33c55f98ce0ff628b2d4074866753b2ba44afd27af1d79a52b3c11c50964c565cc5f8376d6019ca9996b29b128e2cdd8386c7
+DIST genpatches-4.9-262.extras.tar.xz 3340 BLAKE2B a53ca6066598904e4ea023ad132905d594b30af5a1a8478e4ef2d942b6139770eb6724808a0655a87e5bb1465345a5a47e7c691730488d8f19ef174817986255 SHA512 10c6c315c27919f0eb0aff5504ec73064b57feaef7621c2545849ae16ee8f3de139f53757ed4f3997fad033889ba3e27a1bdebaa6e422db5f6530908deb26022
DIST genpatches-5.10-16.base.tar.xz 468704 BLAKE2B b7476d5db21c56f2b0e3082e47d643b12b163277e84aecd4b7df75e97f6b703ce8fbdea29aee0a7150f0f193a35ecd896766e9e6bef8dc47a4dac941f83b7f02 SHA512 9623b5fb47de8a93d036e301220031d5b6508e07ce87002193a5d52a34902a486811f133419c84c35cfd7f7bb6076fb5be87992d6934ed57b830d4c7542313df
DIST genpatches-5.10-16.experimental.tar.xz 17528 BLAKE2B d70fc8326e57ce729c7a097f64cf8e049821034498644cc9f6246b93c1184b9fb3700c7802e28dcb353c7db8c399f916e7f4f99f5d2bca153005223bf9aacc78 SHA512 cec35f59ede000682ef5cac7a5382c6de7444bc6c78c84b54eb5e5b10c3b06afbe00b4b86cf986f635e0842b6e767c3728651525b1deeb294228044747d57001
DIST genpatches-5.10-16.extras.tar.xz 1772 BLAKE2B 5652ee641cc180d14e7a28d3dabecc46430bbe8daa5d5e0cba3090d8a2e28ee56b92073efa996bd9ec598897045c29f1a8c3fdb28f69d7ef94422d31275d7fc0 SHA512 90d245b44e33ca5f8356dac3d3ddf0d736530384ffc232fb230b88e799b362c8cf9b4a147f7b9fc5c32aaccf18cec4ebfa7b8c80bc530ac300b5444fb9263021
DIST genpatches-5.10-17.base.tar.xz 502160 BLAKE2B e243f962bdb26797424cbf27eb64e37cc42a5d7297d8eac4dfdff556f641aa0d34461b9845df3c203dfc0df462e130089a83c1cb8fae4774df5e99cee27ed67f SHA512 d573c4f168fc65cacd01931d0cb52636ee4c739ec7a285f069cf8c0e487f606e2cab5a9524dbc020b830ede4a5660e2204a49d27596fc661ca96f3db26856c31
DIST genpatches-5.10-17.experimental.tar.xz 17532 BLAKE2B f808e5529fb6535c78ea10222faf02a3d09661546565f61a2456530291d635073ece4db20c800f97132c29403d17e6e6699cfc424e4f85d9b08c86c6f3e562de SHA512 3c830f9364954713e4598fb19336bd6636a3bb2f28de2b9e2ed37bb8d24df129a77be1dedfb7272d422f5f2470885eed7fa629f059dff35aa19f9d512eb830f4
DIST genpatches-5.10-17.extras.tar.xz 1772 BLAKE2B 14f5f5b8a2a70190f80376f20a83c2f7a70ca31b2a956c2cfd84fb2999436bc3cfad925ce9744d333c896f520df6dec5337ad820340d9b4dd007d91abc95b0c4 SHA512 2bf9b8444f8d53937a24e1d0304236f04ca220eb1a2bf4d4c47d7655149d752948a0050684d1d1f18065226e7b50501b3182b264b2ff009b6f9e45e6886037ae
+DIST genpatches-5.10-18.base.tar.xz 515540 BLAKE2B 245520300cb9ea1a0803dd4497b3f98bad3ddd29851f8f1273e3b51a3479c03a4915f601f1df216593a36b6f7593ba852dbbb7f106a40260c14b4590201b8fb9 SHA512 baa107fdd1c893ba977391cc429542b90de96d0cf4e6a671e392ef8e0f795d5ce1e4d2e74c214a907c9bf35fbdcfcec220785a4e66322b6191f097eabadeb567
+DIST genpatches-5.10-18.experimental.tar.xz 17520 BLAKE2B 73543b9a749d3c675e0d625a32167cada138e6481fd1c66529a35a193e61fecd1cd1183c33cdecc4023abfc96052e70a90735ecb7bc6b2129445ff9d4b42b7c7 SHA512 e68fc65e40f87be37a5637c25f34710ae5f9ead0151e7435d943882e8e262bf7d835602d55153372cba8535945889f7ff44dd52450e8f5db4ac5161f9ae6db94
+DIST genpatches-5.10-18.extras.tar.xz 1772 BLAKE2B e4c9b0ccfcdade38239cbf0e8db14e46b394b3da9a08c2538f81c602e9c8f52ffaeac0b441831ac771e6a19314a8a7d61b5411e1762c7705c555bea5a478dd68 SHA512 59290f7ea30bebb5137829a1d69b22b2170ff06a794e06b334f03312174e31ed9be9c8372396b482a936283a79e557f813755b5fed77a5485b2144d1d4b0e52a
+DIST genpatches-5.10-19.base.tar.xz 543060 BLAKE2B 9219d5463c51bc574984ab37795a2150deaecf861c0b2ec3c7c91eebacbd6d5e045da40acb09ac01a56e33e5329401e80d8804d1227869d5a856e8c11e2da70d SHA512 795e38b25e6c11a936e8366a3081a5f9d170bdb807296e3c0c58545b43b937ecd47e4a66fff521a0a554ff4142aaf4b4b5543427437f1458f672e57016de1f58
+DIST genpatches-5.10-19.experimental.tar.xz 17520 BLAKE2B 447e90a11bb69a5dd41ee28fa28aaa5bf9e80e9b880b05aeb5f217913e8279ab670eb3a79bb9ad01578bd7f8541c4d89353f368ad8cb6f72286d9879c4091bb9 SHA512 8299745ceb5f888da5560b22ed013d73f339f52bf479f646602235d248b9a869b0b6643e758012602cf43dbe0f8bfdc854a9b3a0888047d72f63437933bf3964
+DIST genpatches-5.10-19.extras.tar.xz 1768 BLAKE2B 8579ab3ab97f6bc906a8e16d90e8bfde74bc6782323a0defc86e0099593431d54bc4457c2cf3bc64bcc623bfde74ba6387ca33af58e367062cc23b78057d0ec8 SHA512 7b658d488dfe372a5cd799042c9e6227fa35bf8cbd56ef505bf25344b052c2fa2db137bfb315d9a65b844c475a052e8845ba9d3b30e57fc6417aaab7c3886176
+DIST genpatches-5.10-21.base.tar.xz 551256 BLAKE2B fc2db45cc49ae771f3c87cd97ba3643c6ae35ebee7104a3e6cea50b5fa444871f069480c73e63ad5ca41903f4c180be34e905cd7701dbf3f49590cd98d255873 SHA512 c176101a167fec0df6dd60a366daa0d5b2ca96b2610ea3de8ba0bd5887037ddb989eed5febdd40ec2fbfc1473837160713b331e37c370c992c95b3db9bfddfd9
+DIST genpatches-5.10-21.experimental.tar.xz 17820 BLAKE2B a33240a66d452b4409611cf6ab508099dc82f0e9bee456312b25d75aa584ab78bdf53c189d4bd522e57e9211fa77b2c65a8d96de8644d45ca8371a7f9991c207 SHA512 b8add41cf51c7e2802d9073db4e3240fb91a67edffd5d5eff75963d3861f40584df5a970bde8c3fa807696984f209fb9d7bf7c62f62886ca44e2d648b0637758
+DIST genpatches-5.10-21.extras.tar.xz 1768 BLAKE2B e69295002cda9c81df01d0e20a6ae691f3d584dc91ae7bfe3cae777fae430829b6b4450c5f38f91a2aa42fcd9b6adfb89bc85642f30e8caf7cb34cd301f5261e SHA512 1bfce3155025596db1c1e90c4119812a83d1574519d16805574c84e0b8f5936b5e3a2e5400e92b59c2844b903b9517eb2b9d220054ebd3912af23a4b6914db7f
+DIST genpatches-5.10-22.base.tar.xz 554876 BLAKE2B 18d2a41fea4a8a95983a71185248f9fd27d2f4e8863419eaae66cf826ecd74218e0563804262368f3d23bee1f835b18869644af734f0baa8d1266a37ff495061 SHA512 7fca3a5fcd35425b0d6aa37cd0eb1146c6fec8ae5f4a462f058180057e956a4316a26a0c0600780014ffe2f632cf64f135f8d0b337ca6642a949c3654783a4c0
+DIST genpatches-5.10-22.experimental.tar.xz 17824 BLAKE2B a05cdc918c9f37fd78f2a61e02ccaf22efc31a72131db6c4b4d3ae1edc1d49c1cb58917b77a3a7a5c6b866616980a8247bef3c80a35103b2a044ff1e86daa741 SHA512 6d0b9f07095e219ddf4bb2e590ac50bd28494c3ec42f58318f889856e6110e6cf9a20ecdde19699a3303867287edef60d448f426d8389a58117fa97435e2005a
+DIST genpatches-5.10-22.extras.tar.xz 1772 BLAKE2B 3a72d1838aca6ca79985e06d9efc44a10bc3e766431c2ebca64b773c96be52cf27f121331585030e334d2eb7d1415deb34f42c265619b16186fb406baa12bd23 SHA512 81559580dda2d4ecbe693eb25d9d537f0d3dc3a01c1a863f17eff3b0e890a2850bdbb7ed5e856bf6b9c7dde944dd771710a8b64812391b5a3c214cc0e2c8538f
+DIST genpatches-5.11-1.base.tar.xz 3440 BLAKE2B eb1e9a9f2060023cb410bf3db8c4f4fe283eff47f545a434dfc1edb98aa513940f30a2a88566422192b79f7ab36c607b9bc63253c067070d9a479d6318fd34b3 SHA512 a862fe33272bb6b0e4095c862c74361f015fc57316b9dbbdf2782f2e57c131fbe7fe9b9ba81c3d5a7d71788f2d56abdbd28f1c7571973c3f378cd05199c0421f
+DIST genpatches-5.11-1.experimental.tar.xz 6096 BLAKE2B be00b2b75d44ebdd7c69e03b7b6488e5689f1417d2a101be806446fd290575813f246c209cf3be3b981cbb22913ce67a5b0703806b7905f8eb7fac835e0093f7 SHA512 3ddd49fe67cacf45335010e8f1fdaa0c01eeeb025ef3f73153055319b5e53b6222467f8281bfb2ceb89eeff8421a57109aada0f1b9bc37b8039c37aa1b227382
+DIST genpatches-5.11-1.extras.tar.xz 1772 BLAKE2B e6f8eae67db54099424f33e17bbfa66d36ae44c98d5f58969634a709a4b949a675a7ec1053eab4db4f745513d9730b68439ecf888e92f0fc9ef369822b39a388 SHA512 cf9d0ee27618b1b49322cefda8d85f66fd94820b9902948c8dd9a33d4e14acf511e7aabf611df5e070a4011e06d80164a512d124f5686b5b16fd81409098d8eb
+DIST genpatches-5.11-2.base.tar.xz 7488 BLAKE2B 380a7f62e8a65fdaccc89df23b67a0d5dc95baee09a8e83d4ec249a920f60b3e5834afaaa870b3ffb89f10c55f8958a5458b9d0fe8968e2990bc8c710316e3a1 SHA512 b025e4a40fe3e7b568f8007a8047c7e85bd66cad3617b5bc7e3420f92a71083b1b1ca3c71170a24865c40b721b0a3ad5cd0db1441a4641f0057b59ce9dcd58c5
+DIST genpatches-5.11-2.experimental.tar.xz 6096 BLAKE2B 383a1c5d8464dc9165374a01889071132f3c110d92c371b04a2c70a025136e3002c3a4f739baffbe41a8e894c4056f317c1f9915a0cf120040af000f9b89cf2b SHA512 65040c1d78b89b47a0440f1e14d35a9889ea429bf2a22bad110126f317c2d444a5c4e8cfac9ec2b0a5b6b43bad0513cb370b32ad67a05485e18ad1f38b96d3f4
+DIST genpatches-5.11-2.extras.tar.xz 1772 BLAKE2B cf53815e6d8ff17ab8d8877a6e4ac0fb75c36905e84a6343367bdc81169cf30183b103de00390e5c73f911730d86305acbc1ea51f88c23cffdbf83347d9fbd79 SHA512 010ccddf99b02e03bef2204a4ce9c094c56e31d79fc6e5fb2f63711fb66bcda063b0fa4ff198a0dce7885cb07e6ff85dc6f89739b2fe4f2b8fb3e5ee0f615007
+DIST genpatches-5.11-3.base.tar.xz 11280 BLAKE2B 83a975b07b3e04e19b008e5a5c4f08fa551b3558b68afb800cb3c886f782a21950d5ea1029b631a6caa2658f02e7ae819e8d8c137a076470120d94deab99e524 SHA512 0a8b19f888af853e6a12aff9d6675f7a9977fef92efa19e69c79a6325fc1626efe7aa9fec8c42ee65ba29f0757b166567679a54d0351f19ea502183e92a63ac5
+DIST genpatches-5.11-3.experimental.tar.xz 6092 BLAKE2B ac1c5aa031e99dd332c51c44c05e00460bf2d1244ab6e00179d81c941b58c97c9aef3b8dd14ebc87e3b00f2fb4a393172d17e38121898850452ec3377ce02b7c SHA512 248d5a585d8963a31e3951a0ecce5c6b0522c32df14505bb6d7ad4fa69a9e00eb4dd5c31e561f13f14dd3aeac50db9aa2c43ff8dcb10cb363eba5af386fe8788
+DIST genpatches-5.11-3.extras.tar.xz 1772 BLAKE2B 165d5928e6afc65544392186737efd1df9e1179591ef7edd85a1868971ea76016161a38a615e9e692c4515fe7fc19424a0cfd01420b5ec57a60c8d1d2d223cb7 SHA512 c74015c4e1b824c61db9e9deca6b30a839ae9a8fb5747cb6c46e2af99a9221f11bb971099554107bbfc58ea5389d96e810f9cf8e55d0bcc16a093eef941c6ec8
+DIST genpatches-5.4-100.base.tar.xz 3072228 BLAKE2B e9dcc72a03ee2ceb3e02d8dc76b57178c6b7066e07b925bffbd6edf72befb262b68c953522052a357040ee1d087da414a5a100d29762fb65c0e0e1dd122879b7 SHA512 7ab34d9742d5d941632abbc392ca38c6dede00993263e9487a0f7f329b6d36803b9c26017e8f1daf00956f79d34a0a9365fcf5ddfb2322a03ed58476441c7bdf
+DIST genpatches-5.4-100.experimental.tar.xz 18084 BLAKE2B 61c2dadebeb773b2bb463580c84e12e43f67e5f22ffb6b7d6636e506ccff7f24d5bd6eaec35a4607c6c116589375a7ebe1cf89132c8df5254868c8202f2c8b18 SHA512 76eda39adc319d465f4670aa36d62a7b2f484008d92906969e346670574f6af44a858f254daae5466598c0ce7c9fb5d0500fb2322ef43bc45ad526a79e070e10
+DIST genpatches-5.4-100.extras.tar.xz 1772 BLAKE2B 60ef6c84479783e92f613314e753e723201e8f58938e1ba7d58831b045cb02669dadbb4fe66eb10f4c7543359d9d16371aec09d6dbbf341471dedcf6bca29121 SHA512 0e8b851b181fa711645996b989c92ea0a4665094197700c4b5315bd92c2f4e6dde59ddeb6931f2533c8095a3f9e8a4e5e23bd5d0d473814a46aadacd10c30a62
+DIST genpatches-5.4-101.base.tar.xz 3089116 BLAKE2B c6e716ab8d0e98d3b3b4c492d6a516ada65f5e77d375cb9164a080aabd94311c50a222135499eef9dcad3f80b29b831a3fe015c3006178651c2136620f9079c5 SHA512 1bdd6f8f23a6151298e2e2fec493c9a2e95a1a65f4a4b6ff95598f45d4fad783da2a596c05b5582ec3d82ed8d8aaf654706da768a1b248bdae37fb08481b3dc3
+DIST genpatches-5.4-101.experimental.tar.xz 18088 BLAKE2B 23c77868245b6b19dd6c06de11f06c511baf17f461f7b3e487a86df852a4a7030513c3e87d3ef1496d5f9bb0c6943b198caaf5a4351c448fdf4bb3743aa3e88e SHA512 bca35c22b8c59370d29cffe854e355fb65889c3e3d0783768b7d0de3060f564dced4a2db443a3144b9ec48a95dbb9f39b2637f376399f97d4d2b25f0eec60027
+DIST genpatches-5.4-101.extras.tar.xz 1768 BLAKE2B 44b92b9c288f4f10f499e5b6d2179b44ee3418890905341703901a71b703ff99e992d6e7424521e67d3b1f80e41286c2357187c66e9b1ae7c1feef430f0ed74a SHA512 e397f970bc3b68b91f059e4b4f2d6163f8416340096b16b040eed8a5242a001db37b0fe8c1fd2a54c73bf6121aa55efa1c362b7837e930b758bc3bd33f8dce09
+DIST genpatches-5.4-103.base.tar.xz 3091428 BLAKE2B 73b7a87dea4ca50bc1ab188b0948c0236f740f18b9dce7d8e4238dcbe9e045dc96dffb7a4c363e195dd2f04b537c53a537920bb6bbcfabc363bc109355771bfb SHA512 afea1a44e1eee6692aa8b398c21bbea62ab0ced41db7eb821d879015cff6c88a80a605dc263085119affd6a4005ae08e483f2293438c5986f6772031956e62b0
+DIST genpatches-5.4-103.experimental.tar.xz 6704 BLAKE2B be746144877ce742a7ba65adaea01f479a93be410d13e3661d181586404f12c32f05835273143d47984f251dc49deea5e83b46c0ffb7a80225c76a428e5a84b0 SHA512 71c43112ab0b2c564c8190bc4312c2485f370cdcf060c1799f60cbe9ed11f8f625ca28a2330f911560fb682e866ab3ed162ce99a64191b2513553983b921d130
+DIST genpatches-5.4-103.extras.tar.xz 1768 BLAKE2B 0b28c7f0c9bf45f3ac7370e751045760069d078e0609f5987b7faac6e367bdc0d0a16f9f94a7684f9c76c43a25b6e59acdfa44614e86e3fdb13eff532621926c SHA512 7e7c4653684a09bfe9b264b0e4c6b8de7d842c91e4ed1c005bd87ac996f1e2cdbc461c8d4cb084707ee5214a0e16e9e26ab21d6860331e245924feeafc1900be
+DIST genpatches-5.4-104.base.tar.xz 3093716 BLAKE2B da8a9f572f4a22eb101a477ed2b2a81b0adaed65f1913c163b58dc958de661707733fb1e0d06e49ec342666ca0c212313d3a5fbca60c79779009b91361e23f42 SHA512 2ef214d2e4ea982c6702991519aaa183d6731f882fa59db5cc2d7832c7fcaf8de57dc2173f4a59922e5d90da2d046753b3eed609513c84c784c13d5be747303b
+DIST genpatches-5.4-104.experimental.tar.xz 6700 BLAKE2B 3254eb73899fbe426890f7effdbe484dc2b1398469fb35ca1006503a91aa558a9e5d775b5587c73500686bc334eda1ceea49f10a5479d920ce3a1662fda5fec8 SHA512 a8f6193cd6fd4a6214a28a7039c7407d3d714e398d16da63ac63703da81a1bbc7cc903808106c11125e7c973a2709728e0100d379b22a214bfe51edeed1dfab6
+DIST genpatches-5.4-104.extras.tar.xz 1768 BLAKE2B 7f335d61bd5f44cfa74ce2082259a48791ed90c21da4d05ff13c191adf1f658e68634c4cf9779274e6f775409695634ca40187754b0f9d50b406c26df26adbc4 SHA512 a8080605c59079063065d9bebc9d846ab8aab73f2f192f6c5becea2b51304a1e4d91e20d9aacd61f2cfa5b967bb8e30d620ddd60592017f308ad2f65ab7287a5
DIST genpatches-5.4-82.base.tar.xz 2792480 BLAKE2B 39960646116f5f85ee657a29557d8fd9e809ae9bc60aac349c91e7680f2a0565800ba37a478573098dbad41b686336a058985d2925e5046fa68eeaea8df25477 SHA512 6a76eebd7178e2ccc522477f53c36f74e6fd691f87c547dffa2602a516ad9a6a01f05c953e12bbe6ba9aa2ce34b176a6a081a22da40c7d86855e5dfc34098059
DIST genpatches-5.4-82.experimental.tar.xz 6704 BLAKE2B 4dcaa6977e25a2d9327d043a15115eba34a802bfa80d532ff2ae3c1495a861d4a4a85ad102e69558d247ae9a0effbf4628e8963f435b949eeffd35f735ea49bc SHA512 4fba72e9efc3dd11fe934be4820703f2f8268c5479dcdae1183104a6b1c2c22715b4529d6e8a4f65d8e46d52b12ab47e3d2eee8dda038af5cac7b799263e84d2
DIST genpatches-5.4-82.extras.tar.xz 1772 BLAKE2B 8eff7ca01490badd5dad15497f77bf43c268ccb494db9eb4c18f4f59219f1a5d79ef2a6f35caee87e3c423b0fff1ef94a6d6477e5074397f78e4bd23b9c40d95 SHA512 bdcc7eb08c1cdb599e69b254f55685f7beec83f256518d42c31d0df9a4e1c6376c184145ce47d28e0b688d2166e139445ef5f9f284e817ba9f37eaf812852a88
-DIST genpatches-5.4-92.base.tar.xz 2987648 BLAKE2B ffdccfc93b1b759494cd3adf2496e2074e847c46ec1c9dfdab32d3a7dfaf5a334df0391ba7ccb35250c562a529df8ae2784656628e110887b593536ac6b0d3ea SHA512 d2c08ecebcabaeb658407626c71c98201f86cf6510c4906b37f45d0f9fd6677b709fbdd9a1ce16622632c9a2e72a11d93463bdae62c5d8d0655c999223909e51
-DIST genpatches-5.4-92.experimental.tar.xz 18084 BLAKE2B 8341edc51d259311407055d080b7759b5895c7899724ac19f49ef18115a6eaf0192606fc8b63edb37770e8daed75e3d69d9b0395238a1ae3b1da391af2f6c39d SHA512 4d77cf39d5bc8dba49c1a430b4f0e5570db24e7f91fe3bdaf9661be98432c5b8bc492f3ecc24e4495c880601fa563af2dc538684ce3c31daabd31fb55a253ec2
-DIST genpatches-5.4-92.extras.tar.xz 1768 BLAKE2B 41cca01e9893db97ab1c7bc920d3240b3aec6207ff6516b346a87f24b47811077d7bbbdca49ed267238af4f5eeb2e8e0de03c946fb6f3784a08bdde348a5a64b SHA512 bb88a3c13a4335b93eb1ded903696e63ffa87b0a1dc587f464335fe077623abc36831fe514f33737960328ec765c5c0bf5489e84dff3fc6ae37ab2e1cd61d94e
-DIST genpatches-5.4-93.base.tar.xz 3001024 BLAKE2B d5f3020aae1a920a076457cf28ae640e8ab7387652a61db3d631a3494c5cb0e8706d92debb6356768fea992679aefd4bda6d212a9918a714740439811dd3ef6d SHA512 420512b65e20f00fcabf4d122cf5fd166a6cc196a77451f8a06b333ca2cdc189c38654333e565cc555b1f3e9745e9c4b188b98648cd57ccb395ca1259675e4d2
-DIST genpatches-5.4-93.experimental.tar.xz 18084 BLAKE2B be9a54735db9f489daf3d739edf8ea52d28212400f70635c480debe46a47b029c2e364a83be897c28a013539ed4340cf1730daa1b2aea862a11bc3435b3e7cfc SHA512 cd61fd88df270a49fdce6cb4362ec4aa73b101fb26a83a5a0361133775702a59c9c19abc5ed201dd697054bca66d233f0289d0174abf663de8f18a92baaff301
-DIST genpatches-5.4-93.extras.tar.xz 1772 BLAKE2B 0ad1eff5f82120235a1f326176beeaefcf7aa547eecc94ad103a5be1701dd922ae0309431a10233c0df5bf63c5ba970bdec32e6ca782965e369be2fa5a4577dc SHA512 b5415fe59ba41d60a46e0c123abcee0bb72b5a7d7358789947627ae086c7391c09f116a16c32b2475c278ea14d7275932046d686aa4a849942cbf64440506c92
-DIST genpatches-5.4-94.base.tar.xz 3006280 BLAKE2B a8130e4be0b40fd0c82d9da6c3f42d3e45dc0119b7a981a62b0577e16cb73ae7edb76b407ecdaaf0bd53a118164208529d9bde3958c9592cedb3ef04815e64e9 SHA512 bf4b59da586a4f5f4a03b40273cbb6d5e9e49273c9c15fa2d3dd7eb002c0c24db895fa3987c93268c1dbfb1402197192f2f2c42b22f443a50089ce26d0f721a2
-DIST genpatches-5.4-94.experimental.tar.xz 18092 BLAKE2B 9f404c2ec62147ad30cd50c3d47727f254fdf3fb6c291a4c97ffc4ca260f979cde0d907ddc27fccd013dea871016fbec70a8cd21da86ba1422d9bcfcfe28b9fe SHA512 2496144bd1b7210290837c88c63b5ee648fb935deae76354101097f30ed2e50a02ae666ba9451aa8c658999ac72fd52c0bf3091348301093aa7ebf74a271ab7b
-DIST genpatches-5.4-94.extras.tar.xz 1772 BLAKE2B d7f9cbdd2739ff180d7fa1de7ae24f9d0beeed259b00b0a67e6a3e9dfeb7a2e7136c0682af7e50491fa9010ea3e3e03a37cb8eac96047a4d4e58177d64caf72d SHA512 eee973e296444e301a6d9f59e82e39b2d2b1aa6605fe62c54a3710f300bad9e3b3a13c14f16f357a6c8775c50b47d390f537f15030c4fb08a6d81e5ba4008f1d
-DIST genpatches-5.4-95.base.tar.xz 3022876 BLAKE2B e935ec5e2cacf478fd8ac2f343d0e582cceddf811ea4d87d5518b946b8b0501e7aff29d406407d3f0d276ea32a616f022789ee1318b282c6fd77b3aaf0d64631 SHA512 4e87014b78683372d525d6409c5c038429423371a1369f2c3b1455e53f5360290dd323ccc24aaeeb4a9e66452e9c87dba439c75192b77e4fc7bc888bc1c4cdac
-DIST genpatches-5.4-95.experimental.tar.xz 18096 BLAKE2B 5e37e20fc56f19d06ca044028507115a61d322e0cc4b31919824052243a23a1516077c0744d1f8377fc4d44b091fc0901714ec34f469a5a93f3364d1994943ed SHA512 3bae5d5b4844c2cf9085cd060c217ed249ce1476a1220c531bf1ffec3f88612bdc34027946fe9739ae8a6ea06677c75cdd5d491dc0475b41f0c18f5c085c024a
-DIST genpatches-5.4-95.extras.tar.xz 1772 BLAKE2B 29c822d815b565e99441f122bb978db211288f69ec3e3795e2555aa58cc3d2911debaeddcf202ce7be335771310589548a9de82d0500982894b621d0f773d7a3 SHA512 860978d98d7715b1359e0f3e47a0369ee6ef9e1cc4fd4201ad879dcab0aac644f6a951875643ccb70d31b6dad8b23d0b4ca7b32e50739bd87499760829949749
-DIST genpatches-5.4-96.base.tar.xz 3031600 BLAKE2B 9ba35f7958842a1fd4c9a7e7d3666ea1339ee5fadde6b771b78f67a8bb27c07e8dad8498e9b85fa0bcfd641f5aef9641793a02061b03becd372ea86245820895 SHA512 3edea8a4fc2a29e0f989089633256b270589ad77a225f3cef6e414c5877de1be8a4d5d9da28bfa4fba848f33ee322c4f01befcdf384c9271c97c90e2e2d3ad39
-DIST genpatches-5.4-96.experimental.tar.xz 18092 BLAKE2B 00610aa541214806bd5fa8a0c239b5f3fa4a731471284b50038a8e2278fdcf711da5dde2ec35b992856f9f496dda13b015c11b24e571824f17f741a228898979 SHA512 6c2dd5cce9f85f7b27cf26e2495bb7c0cf62f8a554b09465b843baee70dcffbc265ae780c735c82605427033d25070ee6e540cf5297923388a80db173d0b8f2e
-DIST genpatches-5.4-96.extras.tar.xz 1772 BLAKE2B f33c734139f65245694d3cb98712733a901e89c79d05fab03de42d82d6e45ed3ec41ab4e17f2cd20be2ec31d469cf02a5efc7bad93832c67d3ad0bbf147b07e6 SHA512 8b7d6d058906b9c9afb7addba0c3072d70758bd75ea2989787beab5a3a83725541b4084c34cbb1e90b6cc8bb323a002dfca7065cc88fc834891f04397caa645c
-DIST genpatches-5.4-97.base.tar.xz 3041620 BLAKE2B 4b738b0b9dc990d47577b44c4d1931c28727b461891a673eaa82e3add22f56f57494548c76ce6f63872f62d2b58c2c4e1fbdb84d5b4233f1a9df326fe29de60a SHA512 34adda6c55d8fd491c8c667c9ed71deb6afd4f92fcb26999baec619088dd3483be0b665a76bcf72f1f52abfb6b0bb8a0909c2cb549220ec130afdaa0ea482c84
-DIST genpatches-5.4-97.experimental.tar.xz 18088 BLAKE2B ef222d8b76cfc71cf29bbb3eff90729f8521466e967d03612fc04d02dcfbc766471931fe4ed263aa85e9f53c09453a81266cdeff781eb94a57e7f755bc08d427 SHA512 a8ace0a51ca8c51c6dc07339b3ef5dc05ef4ed6642736fa69123a49f9ec18bd36ea3f875a6f35c1dc8a1d9e0f6d87bde0a6f388ad3851e97b4dcd51243058f5f
-DIST genpatches-5.4-97.extras.tar.xz 1772 BLAKE2B 5c0ed8ac19c10d0e95ff270bb7c2fd559405218f836290df7bdcd5c07ac3cb7e06221d05e40906d97242807ece263c1aa226cba583e5a822d55328608c765d1c SHA512 08cbda97510319fc497b806238c76eb60ad12b35ec7e075ee10ae3cbc6db61b1b3ea061c9c7b3a11f21125fb0d9e111a6a717eed6c3f885a7244d9e63e02c697
-DIST genpatches-5.4-98.base.tar.xz 3049548 BLAKE2B 38d6f3b3c7121721667ae183683e7e2fb9e3edb66d5caccb7a802429c4f6ee68b2cbda5503464064268efbc8f7f3d7fb5c66164f08c815f228c439fc3d55adb4 SHA512 174247357b558834635b90b79346c7c5005a84fd17c0d20cbe09d2405a7d32b0d7e3f14a8683e26f1c12058d510f2827ed0cab5fbb12cb829679a10c317e25bd
-DIST genpatches-5.4-98.experimental.tar.xz 18084 BLAKE2B 2a4a66a51bed50ace689e2777f31811010dead8fdc44af2c10c865e459ce54c2eb00479b3daea6ff3ef78373800844c45aff4c375eb4e6ca3e269196ebf1e038 SHA512 94bd6b11f40be6fedc8a56546fbed4b5f266e4a778e6f06ad03842e86e61d9537e6b9675f11e8554814ddf8f4715fa2eb77c64da03ffa1dde568786bae57b769
-DIST genpatches-5.4-98.extras.tar.xz 1772 BLAKE2B 620bd1c1f60762806ecf90c391f97864567d8ebbf41279bf3a10e1a98de636cefa9616907bdb4922e7ae8c202ef5f3d68a5f551d83af54e70f5252431172730b SHA512 a1c5f239564745bbf1347831995699d52011d856d0965d020cb6f082bb5ca9031f8f9e6fa7d692f04042bbfdcd9aea7e20721198a961021ffa62bd5fcce666a1
DIST genpatches-5.4-99.base.tar.xz 3064716 BLAKE2B f71d76c88a9932d3b0e1b45d065fa0946f36a3100e3b59c5ce4c373519119066973067e4bb74d094cd5b79e689affa4615faf40da75a730b62df2259d3361c43 SHA512 833a83d7aecb1a216783fdf57e0fda342fd481c74166d976326a8333dfb2a13bd61f1b20b749f17b3498756b6134f8538a971507427f4e955bc9128742a3be5f
DIST genpatches-5.4-99.experimental.tar.xz 18092 BLAKE2B a6263f1dd87eb2f701e248ce34c48251cb3ab796fc38ac4a9477c14528436eac0a767a3f380f634f8a68b987dad500b3c11ddba873982e958b0c8d14aaba2691 SHA512 995c465b79f4f67678c325c84abf3d66970b2e3de786b1b83863b224f2a83335401384f236a71b9294daa6a2d815ae79c6b612b0e157463a317c507e447eda76
DIST genpatches-5.4-99.extras.tar.xz 1772 BLAKE2B 6ffe84c928fc61b306d3e9a096470c090b79bfe99c90981b64e324d40157e818b50c0aebbaf342f51eeba29867b8cf8a6e91394dd594c1ecdb4f2a64f8d76e00 SHA512 7f2db3353809e7922951e1e884d7fe4a426556750bf4e38619278185fb09d519b30a972f4b5aeda3f7aca335fc95372edcc5dadd0881febbf43403c4d5c1c497
@@ -153,4 +111,5 @@ DIST linux-4.19.tar.xz 103117552 BLAKE2B 1dbf16cf410867412d17568fe42bc1e90c03418
DIST linux-4.4.tar.xz 87295988 BLAKE2B f260f1858994f5d481fd078c86e51bddbc958f7c5d1586f60dced772e1b1107ecf3aae0558c3e6f39c36f7d3aa1e6cd1e5c64ec9d6f2218f47b98413da6466fb SHA512 13c8459933a8b80608e226a1398e3d1848352ace84bcfb7e6a4a33cb230bbe1ab719d4b58e067283df91ce5311be6d2d595fc8c19e2ae6ecc652499415614b3e
DIST linux-4.9.tar.xz 93192404 BLAKE2B 83ae310b17d47f1f18d6d28537c31e10f3e60458c5954c4611158ca99e71cc0da2e051272eabf27d5887df4a7cb4a5dd66ff993077c11d2221e92d300a0b48d7 SHA512 bf67ff812cc3cb7e5059e82cc5db0d9a7c5637f7ed9a42e4730c715bf7047c81ed3a571225f92a33ef0b6d65f35595bc32d773356646df2627da55e9bc7f1f1a
DIST linux-5.10.tar.xz 116606704 BLAKE2B b923d7b66309224f42f35f8a5fa219421b0a9362d2adacdadd8d96251f61f7230878ea297a269a7f3b3c56830f0b177e068691e1d7f88501a05653b0a13274d1 SHA512 95bc137d0cf9148da6a9d1f1a878698dc27b40f68e22c597544010a6c591ce1b256f083489d3ff45ff77753289b535135590194d88ef9f007d0ddab3d74de70e
+DIST linux-5.11.tar.xz 117619104 BLAKE2B 81300c27bd5476387a83123aaeb4163c73eb61e9245806c23660cb5e6a4fa88ffc9def027031335fa0270fc4080506cd415990014364e3a98b9d2e8c58a29524 SHA512 a567ec133018bb5ec00c60281479b466c26e02137a93a9c690e83997947df02b6fd94e76e8df748f6d70ceb58a19bacc3b1467de10b7a1fad2763db32b3f1330
DIST linux-5.4.tar.xz 109441440 BLAKE2B 193bc4a3147e147d5529956164ec4912fad5d5c6fb07f909ff1056e57235834173194afc686993ccd785c1ff15804de0961b625f3008cca0e27493efc8f27b13 SHA512 9f60f77e8ab972b9438ac648bed17551c8491d6585a5e85f694b2eaa4c623fbc61eb18419b2656b6795eac5deec0edaa04547fc6723fbda52256bd7f3486898f
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.14.217.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.14.217.ebuild
deleted file mode 100644
index 5783404f2ecc..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.14.217.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="227"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.14.218.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.14.222.ebuild
index 6db90d2787e6..41f1b71a7ef0 100644
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.14.218.ebuild
+++ b/sys-kernel/gentoo-sources/gentoo-sources-4.14.222.ebuild
@@ -4,7 +4,7 @@
EAPI="6"
ETYPE="sources"
K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="228"
+K_GENPATCHES_VER="232"
inherit kernel-2
detect_version
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.19.169.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.19.169.ebuild
deleted file mode 100644
index f10f4e927f86..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.19.169.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="168"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.19.170.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.19.170.ebuild
deleted file mode 100644
index 434c93393eab..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.19.170.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="169"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.19.171.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.19.171.ebuild
deleted file mode 100644
index 8bc4bab20978..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.19.171.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="170"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.19.172.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.19.172.ebuild
deleted file mode 100644
index 9972407c88b9..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.19.172.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="171"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.14.215.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.19.176.ebuild
index 2c465b51b092..b4674d571fd4 100644
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.14.215.ebuild
+++ b/sys-kernel/gentoo-sources/gentoo-sources-4.19.176.ebuild
@@ -4,7 +4,7 @@
EAPI="6"
ETYPE="sources"
K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="225"
+K_GENPATCHES_VER="175"
inherit kernel-2
detect_version
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.14.216.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.19.177.ebuild
index 0c6403a95493..f7c2b2668565 100644
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.14.216.ebuild
+++ b/sys-kernel/gentoo-sources/gentoo-sources-4.19.177.ebuild
@@ -4,7 +4,7 @@
EAPI="6"
ETYPE="sources"
K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="226"
+K_GENPATCHES_VER="176"
inherit kernel-2
detect_version
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.4.251.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.4.251.ebuild
deleted file mode 100644
index bc91bdc17905..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.4.251.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="253"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.4.252.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.4.252.ebuild
deleted file mode 100644
index 909eda897d23..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.4.252.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="254"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.4.253.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.4.253.ebuild
deleted file mode 100644
index dc51d0bfe419..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.4.253.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="255"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.4.254.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.4.254.ebuild
deleted file mode 100644
index 44e29420f662..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.4.254.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="256"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.19.168.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.4.258.ebuild
index 36464fadd431..2d050c08857c 100644
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.19.168.ebuild
+++ b/sys-kernel/gentoo-sources/gentoo-sources-4.4.258.ebuild
@@ -4,7 +4,7 @@
EAPI="6"
ETYPE="sources"
K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="167"
+K_GENPATCHES_VER="260"
inherit kernel-2
detect_version
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.9.251.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.9.251.ebuild
deleted file mode 100644
index 4856aa05c1d6..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.9.251.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="255"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.9.252.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.9.252.ebuild
deleted file mode 100644
index 44e29420f662..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.9.252.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="256"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.9.253.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.9.253.ebuild
deleted file mode 100644
index 77aa974ecb87..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.9.253.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="257"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.9.254.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.9.254.ebuild
deleted file mode 100644
index 09534dde64fc..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-4.9.254.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="258"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-4.9.258.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-4.9.258.ebuild
new file mode 100644
index 000000000000..201bb9292ead
--- /dev/null
+++ b/sys-kernel/gentoo-sources/gentoo-sources-4.9.258.ebuild
@@ -0,0 +1,28 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="6"
+ETYPE="sources"
+K_WANT_GENPATCHES="base extras experimental"
+K_GENPATCHES_VER="262"
+
+inherit kernel-2
+detect_version
+detect_arch
+
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
+HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
+IUSE="experimental"
+
+DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
+SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
+
+pkg_postinst() {
+ kernel-2_pkg_postinst
+ einfo "For more info on this patchset, and how to report problems, see:"
+ einfo "${HOMEPAGE}"
+}
+
+pkg_postrm() {
+ kernel-2_pkg_postrm
+}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.10.10.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.10.10.ebuild
deleted file mode 100644
index 56efe9fc96f9..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.10.10.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="12"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.10.11.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.10.16.ebuild
index c8d0c37d4a34..888fd442db11 100644
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.10.11.ebuild
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.10.16.ebuild
@@ -4,7 +4,7 @@
EAPI="6"
ETYPE="sources"
K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="13"
+K_GENPATCHES_VER="18"
inherit kernel-2
detect_version
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.10.12.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.10.17.ebuild
index 0be2f31b2432..2cd5c9892bc9 100644
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.10.12.ebuild
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.10.17.ebuild
@@ -4,7 +4,7 @@
EAPI="6"
ETYPE="sources"
K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="14"
+K_GENPATCHES_VER="19"
inherit kernel-2
detect_version
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.10.13.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.10.18.ebuild
index 6bd952a77a73..93ddcea2be73 100644
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.10.13.ebuild
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.10.18.ebuild
@@ -4,7 +4,7 @@
EAPI="6"
ETYPE="sources"
K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="15"
+K_GENPATCHES_VER="21"
inherit kernel-2
detect_version
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.10.19.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.10.19.ebuild
new file mode 100644
index 000000000000..782dc7f46c14
--- /dev/null
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.10.19.ebuild
@@ -0,0 +1,28 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="6"
+ETYPE="sources"
+K_WANT_GENPATCHES="base extras experimental"
+K_GENPATCHES_VER="22"
+
+inherit kernel-2
+detect_version
+detect_arch
+
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86"
+HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
+IUSE="experimental"
+
+DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
+SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
+
+pkg_postinst() {
+ kernel-2_pkg_postinst
+ einfo "For more info on this patchset, and how to report problems, see:"
+ einfo "${HOMEPAGE}"
+}
+
+pkg_postrm() {
+ kernel-2_pkg_postrm
+}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.10.8.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.10.8.ebuild
deleted file mode 100644
index 260c6174d12e..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.10.8.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="10"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.10.9.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.10.9.ebuild
deleted file mode 100644
index b3115878befc..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.10.9.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="11"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.11.0.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.11.0.ebuild
new file mode 100644
index 000000000000..5133f7764460
--- /dev/null
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.11.0.ebuild
@@ -0,0 +1,28 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="6"
+ETYPE="sources"
+K_WANT_GENPATCHES="base extras experimental"
+K_GENPATCHES_VER="1"
+
+inherit kernel-2
+detect_version
+detect_arch
+
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86"
+HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
+IUSE="experimental"
+
+DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
+SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
+
+pkg_postinst() {
+ kernel-2_pkg_postinst
+ einfo "For more info on this patchset, and how to report problems, see:"
+ einfo "${HOMEPAGE}"
+}
+
+pkg_postrm() {
+ kernel-2_pkg_postrm
+}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.11.1.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.11.1.ebuild
new file mode 100644
index 000000000000..bcf9f3cb6f73
--- /dev/null
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.11.1.ebuild
@@ -0,0 +1,28 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="6"
+ETYPE="sources"
+K_WANT_GENPATCHES="base extras experimental"
+K_GENPATCHES_VER="2"
+
+inherit kernel-2
+detect_version
+detect_arch
+
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86"
+HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
+IUSE="experimental"
+
+DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
+SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
+
+pkg_postinst() {
+ kernel-2_pkg_postinst
+ einfo "For more info on this patchset, and how to report problems, see:"
+ einfo "${HOMEPAGE}"
+}
+
+pkg_postrm() {
+ kernel-2_pkg_postrm
+}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.11.2.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.11.2.ebuild
new file mode 100644
index 000000000000..847b80ffe4b1
--- /dev/null
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.11.2.ebuild
@@ -0,0 +1,28 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="6"
+ETYPE="sources"
+K_WANT_GENPATCHES="base extras experimental"
+K_GENPATCHES_VER="3"
+
+inherit kernel-2
+detect_version
+detect_arch
+
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86"
+HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
+IUSE="experimental"
+
+DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
+SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
+
+pkg_postinst() {
+ kernel-2_pkg_postinst
+ einfo "For more info on this patchset, and how to report problems, see:"
+ einfo "${HOMEPAGE}"
+}
+
+pkg_postrm() {
+ kernel-2_pkg_postrm
+}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.100.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.100.ebuild
new file mode 100644
index 000000000000..cdd2043692ab
--- /dev/null
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.4.100.ebuild
@@ -0,0 +1,28 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="6"
+ETYPE="sources"
+K_WANT_GENPATCHES="base extras experimental"
+K_GENPATCHES_VER="103"
+
+inherit kernel-2
+detect_version
+detect_arch
+
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
+HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
+IUSE="experimental"
+
+DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
+SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
+
+pkg_postinst() {
+ kernel-2_pkg_postinst
+ einfo "For more info on this patchset, and how to report problems, see:"
+ einfo "${HOMEPAGE}"
+}
+
+pkg_postrm() {
+ kernel-2_pkg_postrm
+}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.101.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.101.ebuild
new file mode 100644
index 000000000000..e46bcfd231b2
--- /dev/null
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.4.101.ebuild
@@ -0,0 +1,28 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="6"
+ETYPE="sources"
+K_WANT_GENPATCHES="base extras experimental"
+K_GENPATCHES_VER="104"
+
+inherit kernel-2
+detect_version
+detect_arch
+
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
+HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
+IUSE="experimental"
+
+DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
+SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
+
+pkg_postinst() {
+ kernel-2_pkg_postinst
+ einfo "For more info on this patchset, and how to report problems, see:"
+ einfo "${HOMEPAGE}"
+}
+
+pkg_postrm() {
+ kernel-2_pkg_postrm
+}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.90.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.90.ebuild
deleted file mode 100644
index 9b3b0d35df46..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.4.90.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="92"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.91.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.91.ebuild
deleted file mode 100644
index 46d0bbb4d5d7..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.4.91.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="93"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.92.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.92.ebuild
deleted file mode 100644
index c85015165b19..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.4.92.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="94"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.93.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.93.ebuild
deleted file mode 100644
index f77c5f2a22d7..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.4.93.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="95"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.94.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.94.ebuild
deleted file mode 100644
index c7fbc7184f24..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.4.94.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="96"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.95.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.95.ebuild
deleted file mode 100644
index 4c5ce9be6c28..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.4.95.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="97"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.96.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.96.ebuild
deleted file mode 100644
index 334c698499dc..000000000000
--- a/sys-kernel/gentoo-sources/gentoo-sources-5.4.96.ebuild
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="6"
-ETYPE="sources"
-K_WANT_GENPATCHES="base extras experimental"
-K_GENPATCHES_VER="98"
-
-inherit kernel-2
-detect_version
-detect_arch
-
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
-HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
-IUSE="experimental"
-
-DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
-SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
-
-pkg_postinst() {
- kernel-2_pkg_postinst
- einfo "For more info on this patchset, and how to report problems, see:"
- einfo "${HOMEPAGE}"
-}
-
-pkg_postrm() {
- kernel-2_pkg_postrm
-}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.98.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.98.ebuild
new file mode 100644
index 000000000000..fcc62220bfe6
--- /dev/null
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.4.98.ebuild
@@ -0,0 +1,28 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="6"
+ETYPE="sources"
+K_WANT_GENPATCHES="base extras experimental"
+K_GENPATCHES_VER="100"
+
+inherit kernel-2
+detect_version
+detect_arch
+
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
+HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
+IUSE="experimental"
+
+DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
+SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
+
+pkg_postinst() {
+ kernel-2_pkg_postinst
+ einfo "For more info on this patchset, and how to report problems, see:"
+ einfo "${HOMEPAGE}"
+}
+
+pkg_postrm() {
+ kernel-2_pkg_postrm
+}
diff --git a/sys-kernel/gentoo-sources/gentoo-sources-5.4.99.ebuild b/sys-kernel/gentoo-sources/gentoo-sources-5.4.99.ebuild
new file mode 100644
index 000000000000..0d9c210c0aae
--- /dev/null
+++ b/sys-kernel/gentoo-sources/gentoo-sources-5.4.99.ebuild
@@ -0,0 +1,28 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="6"
+ETYPE="sources"
+K_WANT_GENPATCHES="base extras experimental"
+K_GENPATCHES_VER="101"
+
+inherit kernel-2
+detect_version
+detect_arch
+
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
+HOMEPAGE="https://dev.gentoo.org/~mpagano/genpatches"
+IUSE="experimental"
+
+DESCRIPTION="Full sources including the Gentoo patchset for the ${KV_MAJOR}.${KV_MINOR} kernel tree"
+SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
+
+pkg_postinst() {
+ kernel-2_pkg_postinst
+ einfo "For more info on this patchset, and how to report problems, see:"
+ einfo "${HOMEPAGE}"
+}
+
+pkg_postrm() {
+ kernel-2_pkg_postrm
+}
diff --git a/sys-kernel/gentoo-sources/metadata.xml b/sys-kernel/gentoo-sources/metadata.xml
index 93b88c1e713c..6bda06198dbc 100644
--- a/sys-kernel/gentoo-sources/metadata.xml
+++ b/sys-kernel/gentoo-sources/metadata.xml
@@ -1,14 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
-<maintainer type="project">
+ <maintainer type="project">
<email>kernel@gentoo.org</email>
<name>Gentoo Kernel Project</name>
-</maintainer>
-<use>
- <flag name="experimental">Apply experimental patches; for more information, see "https://wiki.gentoo.org/wiki/Project:Kernel/Experimental".</flag>
-</use>
-<upstream>
+ </maintainer>
+ <upstream>
<remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
-</upstream>
-</pkgmetadata>
+ </upstream>
+ <use>
+ <flag name="experimental">Apply experimental patches; for more information, see "https://wiki.gentoo.org/wiki/Project:Kernel/Experimental".</flag>
+ </use>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/git-sources/metadata.xml b/sys-kernel/git-sources/metadata.xml
index b51fee66c7d2..f8bdb386bfdd 100644
--- a/sys-kernel/git-sources/metadata.xml
+++ b/sys-kernel/git-sources/metadata.xml
@@ -1,15 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>mpagano@gentoo.org</email>
- <name>Mike Pagano</name>
- </maintainer>
- <maintainer type="project">
- <email>kernel@gentoo.org</email>
- <name>Gentoo Kernel Project</name>
- </maintainer>
- <upstream>
- <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
- </upstream>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>mpagano@gentoo.org</email>
+ <name>Mike Pagano</name>
+ </maintainer>
+ <maintainer type="project">
+ <email>kernel@gentoo.org</email>
+ <name>Gentoo Kernel Project</name>
+ </maintainer>
+ <upstream>
+ <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
+ </upstream>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/installkernel-gentoo/metadata.xml b/sys-kernel/installkernel-gentoo/metadata.xml
index 20e07cdc2be9..4864e10535a8 100644
--- a/sys-kernel/installkernel-gentoo/metadata.xml
+++ b/sys-kernel/installkernel-gentoo/metadata.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="project">
- <email>dist-kernel@gentoo.org</email>
- <name>Distribution Kernel Project</name>
- </maintainer>
-</pkgmetadata>
+ <maintainer type="project">
+ <email>dist-kernel@gentoo.org</email>
+ <name>Distribution Kernel Project</name>
+ </maintainer>
+
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/installkernel-systemd-boot/metadata.xml b/sys-kernel/installkernel-systemd-boot/metadata.xml
index 20e07cdc2be9..4864e10535a8 100644
--- a/sys-kernel/installkernel-systemd-boot/metadata.xml
+++ b/sys-kernel/installkernel-systemd-boot/metadata.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="project">
- <email>dist-kernel@gentoo.org</email>
- <name>Distribution Kernel Project</name>
- </maintainer>
-</pkgmetadata>
+ <maintainer type="project">
+ <email>dist-kernel@gentoo.org</email>
+ <name>Distribution Kernel Project</name>
+ </maintainer>
+
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/kergen/metadata.xml b/sys-kernel/kergen/metadata.xml
index 83085da60e11..a3a9194be9d7 100644
--- a/sys-kernel/kergen/metadata.xml
+++ b/sys-kernel/kergen/metadata.xml
@@ -1,15 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>jakov.smolic@sartura.hr</email>
- <name>Jakov Smolic</name>
- </maintainer>
- <maintainer type="project">
- <email>proxy-maint@gentoo.org</email>
- <name>Proxy Maintainers</name>
- </maintainer>
- <upstream>
- <remote-id type="github">nichoski/kergen</remote-id>
- </upstream>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>jakov.smolic@sartura.hr</email>
+ <name>Jakov Smolic</name>
+ </maintainer>
+ <maintainer type="project">
+ <email>proxy-maint@gentoo.org</email>
+ <name>Proxy Maintainers</name>
+ </maintainer>
+ <upstream>
+ <remote-id type="github">nichoski/kergen</remote-id>
+ </upstream>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/kpatch/metadata.xml b/sys-kernel/kpatch/metadata.xml
index 22ced41d43d1..711dd8f00a40 100644
--- a/sys-kernel/kpatch/metadata.xml
+++ b/sys-kernel/kpatch/metadata.xml
@@ -1,13 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>alicef@gentoo.org</email>
- </maintainer>
-<use>
- <flag name="kpatch-build">Enable tools which convert a source diff patch to a patch module.</flag>
- <flag name="kpatch">Enable a command-line tool which allows a user to manage a collection of patch modules.</flag>
- <flag name="kmod">Enable a kernel module (.ko file) which provides an interface for the patch modules to register new functions for replacement.</flag>
- <flag name="contrib">Enable contrib kpatch services files.</flag>
-</use>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>alicef@gentoo.org</email>
+ </maintainer>
+
+ <use>
+ <flag name="kpatch-build">Enable tools which convert a source diff patch to a patch module.</flag>
+ <flag name="kpatch">Enable a command-line tool which allows a user to manage a collection of patch modules.</flag>
+ <flag name="kmod">Enable a kernel module (.ko file) which provides an interface for the patch modules to register new functions for replacement.</flag>
+ <flag name="contrib">Enable contrib kpatch services files.</flag>
+ </use>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/linux-docs/Manifest b/sys-kernel/linux-docs/Manifest
index 6f671c986215..7ab10c20e5a2 100644
--- a/sys-kernel/linux-docs/Manifest
+++ b/sys-kernel/linux-docs/Manifest
@@ -1,3 +1 @@
-DIST linux-4.19.114.tar.xz 103432512 BLAKE2B b35122b6ff2871053d136c5a259ca0c18b12f5b5854df791508fb8d00dd6cef7b3afe436d604c8bc4628b525a166c9d81697c4938707074d9a15d737841828d7 SHA512 a99b3eb2e458199d4143464f3e35023ed5e7fe26e09f1dcddbbd7e6709cf6fea065012a3d0d538c0d22123b97647bc0265de7f79ea7c756ed5192dc0b78a8b06
DIST linux-5.10.tar.xz 116606704 BLAKE2B b923d7b66309224f42f35f8a5fa219421b0a9362d2adacdadd8d96251f61f7230878ea297a269a7f3b3c56830f0b177e068691e1d7f88501a05653b0a13274d1 SHA512 95bc137d0cf9148da6a9d1f1a878698dc27b40f68e22c597544010a6c591ce1b256f083489d3ff45ff77753289b535135590194d88ef9f007d0ddab3d74de70e
-DIST linux-5.4.39.tar.xz 109528644 BLAKE2B 359300cf9628267e5f450623d6ca5e0a918201f3f376c680412e8dad8a196ee86b5b50ccefb95c4ea9e40b0acfdffad07947e64092be4b6b0aa565068615ed12 SHA512 d95a1bace75430a8502ffd5d2225f449580b8cff3d68bd084e4792eceb18a38ae8092f223ef7834bf2b2bcc7cb21487bedc01ae8f1640db14c83bf8dfbcc7360
diff --git a/sys-kernel/linux-docs/linux-docs-4.19.114.ebuild b/sys-kernel/linux-docs/linux-docs-4.19.114.ebuild
deleted file mode 100644
index 55cb8e3da43d..000000000000
--- a/sys-kernel/linux-docs/linux-docs-4.19.114.ebuild
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 1999-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-inherit toolchain-funcs
-
-MY_P=linux-${PV}
-S=${WORKDIR}/${MY_P}
-
-DESCRIPTION="Developer documentation generated from the Linux kernel"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI="https://www.kernel.org/pub/linux/kernel/v4.x/${MY_P}.tar.xz"
-
-LICENSE="GPL-2"
-SLOT="0"
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~m68k ~ppc ~ppc64 ~s390 ~sparc ~x86"
-
-IUSE=""
-DEPEND="<=dev-python/sphinx-2.4.4"
-RDEPEND=""
-
-src_compile() {
- local ARCH=$(tc-arch-kernel)
- unset KBUILD_OUTPUT
- emake htmldocs
-}
-
-src_install() {
- HTML_DOCS=( Documentation/output/. )
- einstalldocs
-}
diff --git a/sys-kernel/linux-docs/linux-docs-5.10.0.ebuild b/sys-kernel/linux-docs/linux-docs-5.10.17.ebuild
index 2b1d4fcb3da2..08dd35006927 100644
--- a/sys-kernel/linux-docs/linux-docs-5.10.0.ebuild
+++ b/sys-kernel/linux-docs/linux-docs-5.10.17.ebuild
@@ -1,8 +1,9 @@
-# Copyright 1999-2020 Gentoo Authors
+# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=7
-inherit toolchain-funcs
+PYTHON_COMPAT=( python3_{6,7,8,9,10} )
+inherit python-any-r1 toolchain-funcs
MY_PV="$(ver_cut 1-2)"
MY_P=linux-${MY_PV}
@@ -18,17 +19,27 @@ SLOT="0"
KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~m68k ~ppc ~ppc64 ~s390 ~sparc ~x86"
IUSE=""
-BDEPEND="media-libs/fontconfig"
-DEPEND="dev-python/sphinx"
+
+DEPEND=""
RDEPEND=""
+BDEPEND="${PYTHON_DEPS}
+ dev-python/sphinx
+ dev-python/sphinx_rtd_theme
+ media-libs/fontconfig"
+
+src_prepare() {
+ default
+ # Fix the Python shebangs.
+ python_fix_shebang "${S}/Documentation/sphinx/"
+}
src_compile() {
local ARCH=$(tc-arch-kernel)
unset KBUILD_OUTPUT
+ HTML_DOCS=( Documentation/output/. )
emake htmldocs
}
src_install() {
- HTML_DOCS=( Documentation/output/. )
einstalldocs
}
diff --git a/sys-kernel/linux-docs/linux-docs-5.4.39.ebuild b/sys-kernel/linux-docs/linux-docs-5.4.39.ebuild
deleted file mode 100644
index 6047c3f394d0..000000000000
--- a/sys-kernel/linux-docs/linux-docs-5.4.39.ebuild
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 1999-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-inherit toolchain-funcs
-
-MY_P=linux-${PV}
-S=${WORKDIR}/${MY_P}
-
-DESCRIPTION="Developer documentation generated from the Linux kernel"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI="https://www.kernel.org/pub/linux/kernel/v5.x/${MY_P}.tar.xz"
-
-LICENSE="GPL-2"
-SLOT="0"
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~m68k ~ppc ~ppc64 ~s390 ~sparc ~x86"
-
-IUSE=""
-BDEPEND="media-libs/fontconfig"
-DEPEND="<=dev-python/sphinx-2.4.4"
-RDEPEND=""
-
-src_compile() {
- local ARCH=$(tc-arch-kernel)
- unset KBUILD_OUTPUT
- emake htmldocs
-}
-
-src_install() {
- HTML_DOCS=( Documentation/output/. )
- einstalldocs
-}
diff --git a/sys-kernel/linux-docs/metadata.xml b/sys-kernel/linux-docs/metadata.xml
index 8c8d3c0814eb..2b08a4786b0e 100644
--- a/sys-kernel/linux-docs/metadata.xml
+++ b/sys-kernel/linux-docs/metadata.xml
@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>mpagano@gentoo.org</email>
- </maintainer>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>mpagano@gentoo.org</email>
+ </maintainer>
+
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/linux-firmware/metadata.xml b/sys-kernel/linux-firmware/metadata.xml
index b1cdaa4debb2..996fdacc5be3 100644
--- a/sys-kernel/linux-firmware/metadata.xml
+++ b/sys-kernel/linux-firmware/metadata.xml
@@ -1,22 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
-<maintainer type="person">
- <email>chithanh@gentoo.org</email>
- <name>Chí-Thanh Christopher Nguyễn</name>
-</maintainer>
-<maintainer type="person">
- <email>zerochaos@gentoo.org</email>
- <name>Rick Farina</name>
-</maintainer>
-<maintainer type="project">
- <email>kernel@gentoo.org</email>
- <name>Gentoo Kernel Project</name>
-</maintainer>
-<use>
- <flag name="initramfs">Create and install initramfs for early microcode loading in /boot (only AMD for now)</flag>
- <flag name="redistributable">Install also non-free (but redistributable) firmware files</flag>
- <flag name="savedconfig">Allows individual selection of firmware files</flag>
- <flag name="unknown-license">Install firmware files whose license is unknown</flag>
-</use>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>chithanh@gentoo.org</email>
+ <name>Chí-Thanh Christopher Nguyễn</name>
+ </maintainer>
+ <maintainer type="person">
+ <email>zerochaos@gentoo.org</email>
+ <name>Rick Farina</name>
+ </maintainer>
+ <maintainer type="project">
+ <email>kernel@gentoo.org</email>
+ <name>Gentoo Kernel Project</name>
+ </maintainer>
+
+ <use>
+ <flag name="initramfs">Create and install initramfs for early microcode loading in /boot (only AMD for now)</flag>
+ <flag name="redistributable">Install also non-free (but redistributable) firmware files</flag>
+ <flag name="savedconfig">Allows individual selection of firmware files</flag>
+ <flag name="unknown-license">Install firmware files whose license is unknown</flag>
+ </use>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/linux-headers/Manifest b/sys-kernel/linux-headers/Manifest
index 658edf3d5078..058352380924 100644
--- a/sys-kernel/linux-headers/Manifest
+++ b/sys-kernel/linux-headers/Manifest
@@ -4,7 +4,7 @@ DIST gentoo-headers-4.19-1.tar.xz 4040 BLAKE2B 4ccaf4fb6bde84f0b1f29534cf2f6effc
DIST gentoo-headers-4.4-1.tar.xz 6624 BLAKE2B 9cdf0c22520e413f175942c4994dd90b0fed8f72c67332a05e7ed72b901ee04594f4e4a3c0252e0a6e057d9c08c4d653387dc36cda82ce9ef8a16e7317ba9ea0 SHA512 dd8a5c627a9cd373022d7afa1beb126f15694f80452821f31fc5c1a3439635814d205bcbc873a5869946472d86cdec872a44f4870751b96d42e89893fca1b983
DIST gentoo-headers-4.9-1.tar.xz 5416 BLAKE2B 2538870b340d4e4b260ada37b0571ba770a4bf93b0f0cf78819b4bf68b8ddc43c314d7fc5d12a78bc71c9bb12306d986ae0ae74159ec7edc7deea371f6b5f015 SHA512 1069f50c58f25ceb8a13c8e53dce6a21e352e2a624da3b9a6d139939e7613e9a97226eb0173fa060ee69443c6a50b53b6d5c6d752dcaebffbe2a78f06cfbe2b6
DIST gentoo-headers-5.10-1.tar.xz 4304 BLAKE2B b5006ff13c8ef8394806919d547f1b15ac32cc4d290e8c5f5a5073f54112db194a9e743177ae54941d8a504e15b662751258259183c47c574936744d7c51b405 SHA512 3154558df20e3a8821af23b2a585eaccb6c40877850b1cf752c435c170f7f322a48e77cee63bcc061b69aff8602987f4506d803c73f394929716295aface4f3d
-DIST gentoo-headers-5.4-1.tar.xz 4720 BLAKE2B 74c1f47d8ad77a2df36db005adb25f81ba6128037357dfc1b6d65deb2a5d3e53d2f3b5af60098c3f3f514f85e53bef4c906fb182101d35ae32d73a5af417a583 SHA512 9d83a68c6e9a463bc27efd469a79d58690bdd0fd93d77c1de29938d7192bb546b63d9acad9633e6e043d0089638e67ee39382e987d7403c43d3f3edc83c5ccba
+DIST gentoo-headers-5.11-1.tar.xz 3624 BLAKE2B 378eed88876a911e47ea08563f4fea840bfc11def916bce47c3268029ba926ced06e621edb53c9248fed4de547cfb447cc25da2222a864983a746fec06fb60d9 SHA512 896cacd48e9965ea724c13ca5a69b8c9aa4f47e631b539c71e4936462d50da3d34863e7419217ba434bcd97ebf8b05d2fc65bc9e60a584a108e864f4cf7f02fc
DIST gentoo-headers-5.4-2.tar.xz 11352 BLAKE2B 0ff989dbfff9070c291efe1a8b925462770e71d0c3faeb2e53581dcce02abe45969ec293a7293b6d843f483927b15f4accc1f24ee4966483164e8f72727cfad8 SHA512 b460e4d00bdd9ec2ecf229f3b2dde7c6468f775399ba6a49fa0533c0688628c7b27d83835c21eab07407fd98c220043cd1b20e37cc4decbd08a3f2fd9cf6c2be
DIST gentoo-headers-5.9-1.tar.xz 4304 BLAKE2B 5dda91dac529cf3afca220d0ec323f679eae00e850e127ca6fb7dd42313afe7d4e2b23860a5b58673c070456e1ebd6b0d48efd681a764eef1bab996de579fd11 SHA512 3522d25e4d13f703e69a7e8da1813b38c8977821363b56af1988d78c446087dea4c3499283a2fdef2dc000fde29b945abb821a01f53ac0ac6c2b551699b3b18c
DIST gentoo-headers-base-3.18.tar.xz 3776668 BLAKE2B 837a675ecf05ec270549d0ba6b9dcb98fb0e40f22007ebfa3e430152b7149dcfa29c8bbe38c737add07f75642234f1633c1d5ae0170788e8d4f765faf00bbdbe SHA512 6615c604e5e618d26fff5a61691f7827bb05be9790db6c9f8e16e3842bce8f056f9928f85ae5714710b75743b0d0804faba4ba9c76e934e1de22dc03ef6d5535
@@ -13,5 +13,6 @@ DIST gentoo-headers-base-4.19.tar.xz 7956220 BLAKE2B 5b6868188b6cb505556b8f30797
DIST gentoo-headers-base-4.4.tar.xz 3911752 BLAKE2B 5031ecd48b99cb0c9c35ca935fa6a62cc36c076bab193ec397fc0d543170f29c6d5a0827a2ea5517eb68fc838819cbe3e5abd125bb920992492369d5e5c1e7cb SHA512 1cd3de58ff790c3730bea38138c7a45ef95d04288c69ffeabebb884fab3add13bd9c99785ddd87a3ee467a0e1b1cdc457bbd28da349e7c178b4d2374c5fb78a3
DIST gentoo-headers-base-4.9.tar.xz 4052748 BLAKE2B e279954c56170fbfa4ebae8dade731825b3d5f0cd5d73a5b33cd93a9c8f5fa140e14edf0d5ac26a452fe8a61b16fdcc851f5329f56e4c8dcf4472a995de44c4c SHA512 a03418cfba7fa4531279d9122411af3e285e962506e8df9279fbbb27ae08a4e30725bd1cf03f48ad523f61f2889195e6c844fa4c7b4ef2f828baf47ef402abfa
DIST linux-5.10.tar.xz 116606704 BLAKE2B b923d7b66309224f42f35f8a5fa219421b0a9362d2adacdadd8d96251f61f7230878ea297a269a7f3b3c56830f0b177e068691e1d7f88501a05653b0a13274d1 SHA512 95bc137d0cf9148da6a9d1f1a878698dc27b40f68e22c597544010a6c591ce1b256f083489d3ff45ff77753289b535135590194d88ef9f007d0ddab3d74de70e
+DIST linux-5.11.tar.xz 117619104 BLAKE2B 81300c27bd5476387a83123aaeb4163c73eb61e9245806c23660cb5e6a4fa88ffc9def027031335fa0270fc4080506cd415990014364e3a98b9d2e8c58a29524 SHA512 a567ec133018bb5ec00c60281479b466c26e02137a93a9c690e83997947df02b6fd94e76e8df748f6d70ceb58a19bacc3b1467de10b7a1fad2763db32b3f1330
DIST linux-5.4.tar.xz 109441440 BLAKE2B 193bc4a3147e147d5529956164ec4912fad5d5c6fb07f909ff1056e57235834173194afc686993ccd785c1ff15804de0961b625f3008cca0e27493efc8f27b13 SHA512 9f60f77e8ab972b9438ac648bed17551c8491d6585a5e85f694b2eaa4c623fbc61eb18419b2656b6795eac5deec0edaa04547fc6723fbda52256bd7f3486898f
DIST linux-5.9.tar.xz 115507140 BLAKE2B e8d11472d63a9f8409ca12a2e8c97c6963a3d4516b5a398b627d6ece565584526f9b5a1377a2fa4bd184c09c7db94c987428bc5d52df0c788464a67e9e8d6dcb SHA512 d3d92ce4246bad74c9a784212f160d98449b1e8793970c2c308276568d852b8effe0528686bdb87d55d691f09a826abf7938d69bdd4759ce65ddd5c05ffe4eca
diff --git a/sys-kernel/linux-headers/linux-headers-5.10.ebuild b/sys-kernel/linux-headers/linux-headers-5.10.ebuild
index adf8f695fe67..2d58b2ba544f 100644
--- a/sys-kernel/linux-headers/linux-headers-5.10.ebuild
+++ b/sys-kernel/linux-headers/linux-headers-5.10.ebuild
@@ -15,7 +15,7 @@ SRC_URI="${KERNEL_URI}
${PATCH_VER:+https://dev.gentoo.org/~slyfox/distfiles/gentoo-headers-${PATCH_PV}-${PATCH_VER}.tar.xz}
"
-KEYWORDS="~alpha ~amd64 ~arm ~arm64 hppa ~ia64 ~m68k ~mips ~ppc ppc64 ~riscv ~s390 sparc ~x86 ~amd64-linux ~x86-linux"
+KEYWORDS="~alpha amd64 ~arm ~arm64 hppa ~ia64 ~m68k ~mips ppc ppc64 ~riscv ~s390 sparc x86 ~amd64-linux ~x86-linux"
DEPEND="app-arch/xz-utils
net-misc/rsync
diff --git a/sys-kernel/linux-headers/linux-headers-5.4.ebuild b/sys-kernel/linux-headers/linux-headers-5.11.ebuild
index d89a67aa0507..e30b503134aa 100644
--- a/sys-kernel/linux-headers/linux-headers-5.4.ebuild
+++ b/sys-kernel/linux-headers/linux-headers-5.11.ebuild
@@ -1,4 +1,4 @@
-# Copyright 1999-2020 Gentoo Authors
+# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI="6"
@@ -15,7 +15,7 @@ SRC_URI="${KERNEL_URI}
${PATCH_VER:+https://dev.gentoo.org/~slyfox/distfiles/gentoo-headers-${PATCH_PV}-${PATCH_VER}.tar.xz}
"
-KEYWORDS="~alpha amd64 arm arm64 hppa ~ia64 ~m68k ~mips ppc ppc64 ~riscv s390 sparc x86 ~amd64-linux ~x86-linux"
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux"
DEPEND="app-arch/xz-utils
net-misc/rsync
@@ -43,5 +43,5 @@ src_install() {
}
src_test() {
- emake ARCH=$(tc-arch-kernel) headers_check
+ emake headers_check ${xmakeopts}
}
diff --git a/sys-kernel/linux-headers/metadata.xml b/sys-kernel/linux-headers/metadata.xml
index fcf3f047e8b4..87a9e39d0491 100644
--- a/sys-kernel/linux-headers/metadata.xml
+++ b/sys-kernel/linux-headers/metadata.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
-<maintainer type="project">
+ <maintainer type="project">
<email>toolchain@gentoo.org</email>
<name>Gentoo Toolchain Project</name>
-</maintainer>
-<upstream>
+ </maintainer>
+ <upstream>
<remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
-</upstream>
-</pkgmetadata>
+ </upstream>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/liquorix-sources/Manifest b/sys-kernel/liquorix-sources/Manifest
new file mode 100644
index 000000000000..cefc957b9aa8
--- /dev/null
+++ b/sys-kernel/liquorix-sources/Manifest
@@ -0,0 +1,8 @@
+AUX 4567_distro-Gentoo-Kconfig.patch 4621 BLAKE2B 07a79d4a95b93e57402358dcc5d712d607fe273cee9b9523c37a79ee1d1b8d56542757b79e200b59292a0da69d8865d6e86116e86e3cc8552988ec83fa71d70d SHA512 b1306f9d6b5ad26e2ade5810a7b724ab83b5788c5afc4460c95f9259542d9ac5f0c7b5f2546db97a0baa3d7ba45ab536247eab599fb2cd17316ba60c997658f7
+DIST linux-5.10.tar.xz 116606704 BLAKE2B b923d7b66309224f42f35f8a5fa219421b0a9362d2adacdadd8d96251f61f7230878ea297a269a7f3b3c56830f0b177e068691e1d7f88501a05653b0a13274d1 SHA512 95bc137d0cf9148da6a9d1f1a878698dc27b40f68e22c597544010a6c591ce1b256f083489d3ff45ff77753289b535135590194d88ef9f007d0ddab3d74de70e
+DIST linux-5.11.tar.xz 117619104 BLAKE2B 81300c27bd5476387a83123aaeb4163c73eb61e9245806c23660cb5e6a4fa88ffc9def027031335fa0270fc4080506cd415990014364e3a98b9d2e8c58a29524 SHA512 a567ec133018bb5ec00c60281479b466c26e02137a93a9c690e83997947df02b6fd94e76e8df748f6d70ceb58a19bacc3b1467de10b7a1fad2763db32b3f1330
+DIST liquorix-sources-5.10.17_p1.tar.gz 1096189 BLAKE2B de63cef509a2b45ac4ca2410ec3133a8826c3f1682877ebc15a04ee827709e342b216df2181b07198e36de8d7a8a096503bee0ab024576eaf12cec61ad9e8244 SHA512 93de2a0bc01537f9d9e5f117257c5d6c7ec8c16e5ad7ae8c350dd776c774190fc90add3361a15889b95bd24b3ca9d2a192bd4c3fb9a7431de61ea06bc3801792
+DIST liquorix-sources-5.11.2_p2.tar.gz 470518 BLAKE2B 0c70bd844f6d7f2e65311ef1c86a5838a1d706b8ab8bd7eca13b9d5c9e64d66e81e5de8632571e31aa15baf42a41f66da9ccefd8a4a209d3342b1fc12ecc8ad4 SHA512 45674b1170dfa65ee9382ed59b1bfffa4f4cdfe295af41052c1e933e20dfbb61c45a30c0d1d647c16cb544d29a7e243a3923289ff447f646b00f30f7395ba70b
+EBUILD liquorix-sources-5.10.17_p1.ebuild 1817 BLAKE2B 63fe896688a91f8ead46582f5f715a866f6ed24a0e5a4ddaaef208fab71cd0c3e728b1ad0745f2a040f72780ed57f2b9953f566f427ac405f64ea208adea26f5 SHA512 e58c7a3b98141e0950888bc837905e7ca27ea323ba43a4a0307a9ac4cad82e729cd7546ef9a9d479671f8e66dd60ddded658aeb96bd23f57e73ff2d0920bbd05
+EBUILD liquorix-sources-5.11.2_p2.ebuild 1816 BLAKE2B 4acf1a21a027e7f1603605c97117eb1f2e5b6e854c01f00eefaecf610c930431f133d2d61e2e792ad8a1ee2b58adccd154611e17fe12016d7cce0d2d38a5e19c SHA512 fecffefcdd07628ec4be584f4c47d184137aeba9c2d5f7732d026b1321846a19a9cf2dae64506972376d6df3caaacfbc0d4e0fb5a19943b2e3d34cb911d7c5bc
+MISC metadata.xml 227 BLAKE2B dd2ac5f8e910fdcd398041e812b41ae620497e9506eb716f37a685632b152087ca6e3e8b8ad0c40fc235dddbb383c7dd091e6d12ac767607cec031c1e98f3692 SHA512 ba8bbc456d19901db460bec6512ffb1e3ab905978e7f4bda11f9dd0ec8761faacde2c9487771b30ff5863febe20ccea294bc1731763eab2f8a2bb2af5d6e1ae2
diff --git a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/4567_distro-Gentoo-Kconfig.patch b/sys-kernel/liquorix-sources/files/4567_distro-Gentoo-Kconfig.patch
index e754a3e6e459..ecff093a3843 100644
--- a/sys-kernel/cairn-sources/files/5.10.14/gentoo-patches/4567_distro-Gentoo-Kconfig.patch
+++ b/sys-kernel/liquorix-sources/files/4567_distro-Gentoo-Kconfig.patch
@@ -1,14 +1,14 @@
---- a/Kconfig 2020-04-15 11:05:30.202413863 -0400
-+++ b/Kconfig 2020-04-15 10:37:45.683952949 -0400
+--- a/Kconfig 2019-08-07 08:33:43.669367779 -0400
++++ b/Kconfig 2019-08-07 08:34:29.669657000 -0400
@@ -32,3 +32,5 @@ source "lib/Kconfig"
source "lib/Kconfig.debug"
source "Documentation/Kconfig"
+
+source "distro/Kconfig"
---- /dev/null 2020-09-24 03:06:47.590000000 -0400
-+++ b/distro/Kconfig 2020-09-24 11:31:29.403150624 -0400
-@@ -0,0 +1,158 @@
+--- /dev/null 2019-09-18 03:31:42.730171526 -0400
++++ b/distro/Kconfig 2019-09-18 13:28:03.170769896 -0400
+@@ -0,0 +1,149 @@
+menu "Gentoo Linux"
+
+config GENTOO_LINUX
@@ -65,7 +65,6 @@
+ select NET_NS
+ select PID_NS
+ select SYSVIPC
-+ select UTS_NS
+
+ help
+ This enables options required by various Portage FEATURES.
@@ -92,12 +91,7 @@
+ depends on GENTOO_LINUX
+
+ select BINFMT_SCRIPT
-+ select CGROUPS
-+ select EPOLL
+ select FILE_LOCKING
-+ select INOTIFY_USER
-+ select SIGNALFD
-+ select TIMERFD
+
+ help
+ The init system is the first thing that loads after the kernel booted.
@@ -120,8 +114,6 @@
+
+ select AUTOFS4_FS
+ select BLK_DEV_BSG
-+ select BPF_SYSCALL
-+ select CGROUP_BPF
+ select CGROUPS
+ select CHECKPOINT_RESTORE
+ select CRYPTO_HMAC
@@ -145,7 +137,6 @@
+ select TIMERFD
+ select TMPFS_POSIX_ACL
+ select TMPFS_XATTR
-+ select USER_NS
+
+ select ANON_INODES
+ select BLOCK
diff --git a/sys-kernel/liquorix-sources/liquorix-sources-5.10.17_p1.ebuild b/sys-kernel/liquorix-sources/liquorix-sources-5.10.17_p1.ebuild
new file mode 100644
index 000000000000..d5b19e52e5a1
--- /dev/null
+++ b/sys-kernel/liquorix-sources/liquorix-sources-5.10.17_p1.ebuild
@@ -0,0 +1,67 @@
+# Copyright 2020-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=6
+ETYPE="sources"
+
+inherit eapi7-ver
+
+K_USEPV="yes"
+UNIPATCH_STRICTORDER="yes"
+K_SECURITY_UNSUPPORTED="1"
+GIT_COMMIT="5.10-25"
+
+CKV="$(ver_cut 1-2)"
+ETYPE="sources"
+
+inherit kernel-2
+#detect_version
+K_NOSETEXTRAVERSION="don't_set_it"
+
+DESCRIPTION="The Liquorix Kernel Sources v5.x"
+HOMEPAGE="https://liquorix.net/"
+LIQUORIX_VERSION="${GIT_COMMIT/_p[0-9]*}"
+LIQUORIX_FILE="${P}.tar.gz"
+LIQUORIX_URI="https://github.com/damentz/liquorix-package/archive/${LIQUORIX_VERSION}.tar.gz -> ${LIQUORIX_FILE}"
+SRC_URI="${KERNEL_URI} ${LIQUORIX_URI}";
+
+KEYWORDS="-* ~amd64 ~ppc ~ppc64 ~x86"
+IUSE=""
+
+KV_FULL="${PVR/_p/-pf}"
+S="${WORKDIR}"/linux-"${KV_FULL}"
+
+pkg_setup(){
+ ewarn
+ ewarn "${PN} is *not* supported by the Gentoo Kernel Project in any way."
+ ewarn "If you need support, please contact the Liquorix developers directly."
+ ewarn "Do *not* open bugs in Gentoo's bugzilla unless you have issues with"
+ ewarn "the ebuilds. Thank you."
+ ewarn
+ kernel-2_pkg_setup
+}
+
+src_unpack() {
+ unpack "${LIQUORIX_FILE}"
+ kernel-2_src_unpack
+}
+
+src_prepare(){
+ # Taken from
+ # https://github.com/damentz/liquorix-package/blob/5.6/linux-liquorix/debian/patches/series
+ local lqx_patches="${WORKDIR}/liquorix-package-${GIT_COMMIT}/linux-liquorix/debian/patches"
+ eapply "${lqx_patches}/zen/v${PV/_p/-lqx}.patch"
+
+ # Probably don't need these.
+ eapply "${lqx_patches}/debian/version.patch"
+ eapply "${lqx_patches}/debian/uname-version-timestamp.patch"
+ eapply "${lqx_patches}/debian/kernelvariables.patch"
+
+ # Adds config options for OpenRC/Systemd
+ eapply "${FILESDIR}"/4567_distro-Gentoo-Kconfig.patch
+
+ eapply_user
+}
+
+K_EXTRAEINFO="For more info on liquorix-sources and details on how to report problems, see: \
+${HOMEPAGE}."
diff --git a/sys-kernel/liquorix-sources/liquorix-sources-5.11.2_p2.ebuild b/sys-kernel/liquorix-sources/liquorix-sources-5.11.2_p2.ebuild
new file mode 100644
index 000000000000..16699a32887a
--- /dev/null
+++ b/sys-kernel/liquorix-sources/liquorix-sources-5.11.2_p2.ebuild
@@ -0,0 +1,67 @@
+# Copyright 2020-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=6
+ETYPE="sources"
+
+inherit eapi7-ver
+
+K_USEPV="yes"
+UNIPATCH_STRICTORDER="yes"
+K_SECURITY_UNSUPPORTED="1"
+GIT_COMMIT="5.11-4"
+
+CKV="$(ver_cut 1-2)"
+ETYPE="sources"
+
+inherit kernel-2
+#detect_version
+K_NOSETEXTRAVERSION="don't_set_it"
+
+DESCRIPTION="The Liquorix Kernel Sources v5.x"
+HOMEPAGE="https://liquorix.net/"
+LIQUORIX_VERSION="${GIT_COMMIT/_p[0-9]*}"
+LIQUORIX_FILE="${P}.tar.gz"
+LIQUORIX_URI="https://github.com/damentz/liquorix-package/archive/${LIQUORIX_VERSION}.tar.gz -> ${LIQUORIX_FILE}"
+SRC_URI="${KERNEL_URI} ${LIQUORIX_URI}";
+
+KEYWORDS="-* ~amd64 ~ppc ~ppc64 ~x86"
+IUSE=""
+
+KV_FULL="${PVR/_p/-pf}"
+S="${WORKDIR}"/linux-"${KV_FULL}"
+
+pkg_setup(){
+ ewarn
+ ewarn "${PN} is *not* supported by the Gentoo Kernel Project in any way."
+ ewarn "If you need support, please contact the Liquorix developers directly."
+ ewarn "Do *not* open bugs in Gentoo's bugzilla unless you have issues with"
+ ewarn "the ebuilds. Thank you."
+ ewarn
+ kernel-2_pkg_setup
+}
+
+src_unpack() {
+ unpack "${LIQUORIX_FILE}"
+ kernel-2_src_unpack
+}
+
+src_prepare(){
+ # Taken from
+ # https://github.com/damentz/liquorix-package/blob/5.6/linux-liquorix/debian/patches/series
+ local lqx_patches="${WORKDIR}/liquorix-package-${GIT_COMMIT}/linux-liquorix/debian/patches"
+ eapply "${lqx_patches}/zen/v${PV/_p/-lqx}.patch"
+
+ # Probably don't need these.
+ eapply "${lqx_patches}/debian/version.patch"
+ eapply "${lqx_patches}/debian/uname-version-timestamp.patch"
+ eapply "${lqx_patches}/debian/kernelvariables.patch"
+
+ # Adds config options for OpenRC/Systemd
+ eapply "${FILESDIR}"/4567_distro-Gentoo-Kconfig.patch
+
+ eapply_user
+}
+
+K_EXTRAEINFO="For more info on liquorix-sources and details on how to report problems, see: \
+${HOMEPAGE}."
diff --git a/sys-kernel/liquorix-sources/metadata.xml b/sys-kernel/liquorix-sources/metadata.xml
new file mode 100644
index 000000000000..dd23ea1018d0
--- /dev/null
+++ b/sys-kernel/liquorix-sources/metadata.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <maintainer type="person">
+ <email>jmcclain2020@protonmail.com</email>
+ </maintainer>
+</pkgmetadata>
diff --git a/sys-kernel/mips-sources/Manifest b/sys-kernel/mips-sources/Manifest
index ae956ca3af1f..31fb2c77cbf1 100644
--- a/sys-kernel/mips-sources/Manifest
+++ b/sys-kernel/mips-sources/Manifest
@@ -5,6 +5,6 @@ DIST mips-sources-4.14.0-patches-v2.tar.xz 287560 BLAKE2B 9fb6b07dcb0336be95c863
DIST mips-sources-4.19.0-patches-v2.tar.xz 289940 BLAKE2B ffca5540cbd663ed3eab3f748dec7727ca6f1abe11ce107fe1780b8191175b77d8c59f70d5e9254f01c43d507f805f081f15bd150f66da1d11e2a91715dcb038 SHA512 c67ac8c6f041a96348a5a6023919fc5586b70b6c3aa52777945d5f1a831e6bd24d867c0318034cf304a3c8f4c6ff0d2af3611b3ad2bc476f3bf3762d39a215f8
DIST mips-sources-5.4-patches-v3.tar.xz 195616 BLAKE2B 389d5d86265d14961d739f13623ed5a1efa0b4e6a649816eccb41f947186316560473a1ec0222d1db84ce8cc1e0c8dadb4dd499b941e37de201571cc37359e74 SHA512 4181b776ec17526c246516d0d2fb2737f12a214a18c2526085a71174a12e30735d7b497d9cba658a2579c05055a74191ebbdd658003c7b28265d49915bc94b58
DIST mipsgit-4.14.0-20180128.diff.xz 1008 BLAKE2B 2a317ff97aab096883680c6b653e993aee31994e6caec52c52dfbbb61f1dc1f25d03ebd3182fa122923a67aeee0aa598b36e603692333e4c9ccdc741fd456d96 SHA512 378deb1bc1d10a6b4912e5e4a0d6fcab28952e2e59c35fc879601841cf8160081b318a2598ef74db225e95f0f26483f6b9a56a348811b1ee7b8934391dd271ae
-DIST patch-4.14.213.xz 4083152 BLAKE2B d99d56454b23101cfe0fdbaa9284d1d000d29f73d782783a71b27ec57fd2a19ddeaa24702bb072566d222e3b554c8719b1025cefc243dd1c826793671865cb4b SHA512 dd5cabd8f2422d642bd953e398b2b3fbc11456f8f3ab7846713e27d0339c85e93cd97ce436986b3d6518c4a3e9f8449d9a53e1c6215273cb2b56688adcf2e075
-DIST patch-4.19.163.xz 3661280 BLAKE2B 182cdeec98f3c4a5ec057e3f286f8019ff5cc22d23863a08b820aeb8404fd34afae913c0bdb06c4d4f571c9146cd13778eedba840e2920f9af2348c5c38fad12 SHA512 6302649e09aae6e35d7963de5dbe4edf9e9fe5439e67188bd604929752853e5e57e31c140e76db87f2cf79345ca254e4b9a893489942c87159aea62746e10663
-DIST patch-5.4.85.xz 2424448 BLAKE2B 21d66e5642782d20a620544397f89f2c5fb85c8261582c4cf915623b564973a2e36d7d933c0b088f88c5198a3f889e24f1bf58ba17a0cb615f2223c47855bb7c SHA512 32c2a9e4555d978b05bce821ced22f99b86be97bec50314716f374c3cc4a74da4807bf7735c038e03af2998d85092db770115acf584ed3f6f9c1d8924f159c97
+DIST patch-4.14.221.xz 4125144 BLAKE2B 474f8791e2b59f1524681e70300d5a9543a4b56fb7affbd02a22d67d4df2632c7aa37a73d032697b3b10291671efd96f5eaf13c4632c05801a4a7cac99a4c219 SHA512 fd332b076ac0231ea4b3806bd6cb58f0b66bd9317ae352fb6f90856e92df5cc96d2c89bc8c44001f2f34ea98b43fbbe8b8eae0abe2249fe561b8dd4a2c76bcb5
+DIST patch-4.19.176.xz 3779956 BLAKE2B 136d927a3254a8214b7c0766971b4585e7a08d13ac4b5e7160f24a1a0d687dfe234632b873aac3cff9fd596b9191acee202e88b7f5d7e139a3284aa544983f0a SHA512 9bb51df1822242aee8340b8d54b5d1eb9bab8c0fff37a5b671f2ab7d10e5b3f1bd9f6a7e13af600434cc406a42b6638a5659cc056917c44a158bf243b5383146
+DIST patch-5.4.99.xz 2620252 BLAKE2B e6b965a159fd019e95207eab66f0cee6ed35334d634594c4d8a433cfdb4be6b8274bc3794754c27ab9dc52223b6760c303ba5a9a2624b7799fb4d831ba49c8df SHA512 00b9128b450c86742ecdfd9656d2527625cd257e95dd18bf032d0c9325e5eb67dc65e30b30b95e1dd00f590eb6ea85710d9c43b2d92fe03e93d761b34b7cc498
diff --git a/sys-kernel/mips-sources/metadata.xml b/sys-kernel/mips-sources/metadata.xml
index 83fb9fad8bd8..4d2a44d14581 100644
--- a/sys-kernel/mips-sources/metadata.xml
+++ b/sys-kernel/mips-sources/metadata.xml
@@ -1,17 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="project">
- <email>mips@gentoo.org</email>
- <name>Mips Team</name>
- </maintainer>
- <use>
- <flag name="ip27">Enables additional support for SGI Origin (IP27)</flag>
- <flag name="ip28">Enables additional support for SGI Indigo2 Impact R10000 (IP28)</flag>
- <flag name="ip30">Enables support for SGI Octane (IP30, 'Speedracer')</flag>
- <flag name="experimental">Apply experimental (80xx) patches.</flag>
- </use>
- <upstream>
- <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
- </upstream>
-</pkgmetadata>
+ <maintainer type="project">
+ <email>mips@gentoo.org</email>
+ <name>Mips Team</name>
+ </maintainer>
+ <upstream>
+ <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
+ </upstream>
+ <use>
+ <flag name="ip27">Enables additional support for SGI Origin (IP27)</flag>
+ <flag name="ip28">Enables additional support for SGI Indigo2 Impact R10000 (IP28)</flag>
+ <flag name="ip30">Enables support for SGI Octane (IP30, 'Speedracer')</flag>
+ <flag name="experimental">Apply experimental (80xx) patches.</flag>
+ </use>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/mips-sources/mips-sources-4.14.213.ebuild b/sys-kernel/mips-sources/mips-sources-4.14.221.ebuild
index 9f9dc8ee3367..64bd5b08b301 100644
--- a/sys-kernel/mips-sources/mips-sources-4.14.213.ebuild
+++ b/sys-kernel/mips-sources/mips-sources-4.14.221.ebuild
@@ -1,4 +1,4 @@
-# Copyright 1999-2020 Gentoo Authors
+# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# EAPI Version
diff --git a/sys-kernel/mips-sources/mips-sources-4.19.163.ebuild b/sys-kernel/mips-sources/mips-sources-4.19.176.ebuild
index 076bf3615ae8..4f2c0e512d0b 100644
--- a/sys-kernel/mips-sources/mips-sources-4.19.163.ebuild
+++ b/sys-kernel/mips-sources/mips-sources-4.19.176.ebuild
@@ -1,4 +1,4 @@
-# Copyright 1999-2020 Gentoo Authors
+# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# EAPI Version
diff --git a/sys-kernel/mips-sources/mips-sources-5.4.85.ebuild b/sys-kernel/mips-sources/mips-sources-5.4.99.ebuild
index bc279adfe801..1a6b743ec994 100644
--- a/sys-kernel/mips-sources/mips-sources-5.4.85.ebuild
+++ b/sys-kernel/mips-sources/mips-sources-5.4.99.ebuild
@@ -1,4 +1,4 @@
-# Copyright 1999-2020 Gentoo Authors
+# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# EAPI Version
diff --git a/sys-kernel/opensuse-sources/metadata.xml b/sys-kernel/opensuse-sources/metadata.xml
index 36b446b63544..35b97c0ead43 100644
--- a/sys-kernel/opensuse-sources/metadata.xml
+++ b/sys-kernel/opensuse-sources/metadata.xml
@@ -1,11 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <herd>funtoo</herd>
- <maintainer>
- <email>dev@liguros.net</email>
- </maintainer>
- <use>
- <flag name='binary'>Builds and installs kernel automatically</flag>
- <flag name='rt'>Applies the CONFIG_PREEMPT_RT patch series</flag>
- </use>
- <origin>ports</origin>
-</pkgmetadata>
+ <maintainer type="project">
+ <email>dev@liguros.net</email>
+ <name>Development</name>
+ </maintainer>
+
+ <use>
+ <flag name="binary">Builds and installs kernel automatically</flag>
+ <flag name="rt">Applies the CONFIG_PREEMPT_RT patch series</flag>
+ </use>
+ <origin>ports</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/opensuse-sources/opensuse-sources-5.6.2.ebuild b/sys-kernel/opensuse-sources/opensuse-sources-5.6.2.ebuild
index 1123fee01858..988b2bc07fe6 100644
--- a/sys-kernel/opensuse-sources/opensuse-sources-5.6.2.ebuild
+++ b/sys-kernel/opensuse-sources/opensuse-sources-5.6.2.ebuild
@@ -1,3 +1,4 @@
+# Copyright 2020-2021 LiGurOs Authors
# Distributed under the terms of the GNU General Public License v2
# Documentation for adding new kernels -- do not remove!
diff --git a/sys-kernel/pf-sources/Manifest b/sys-kernel/pf-sources/Manifest
index 3372b1b6c961..409c3d3592b1 100644
--- a/sys-kernel/pf-sources/Manifest
+++ b/sys-kernel/pf-sources/Manifest
@@ -1,20 +1,13 @@
DIST genpatches-5.10-1.base.tar.xz 3840 BLAKE2B 08ac1f83dc9a1cfc1d4cf0a3a5ab4c9d4686a80348247ec7cd1da6e49db92d6932a1864113f2631d5528a4ba732945b2afe73d03061bd3c532b3d1e4d9571999 SHA512 04356093c4df6a7ee0876b89be5b90f8bc90c920628e5fe69b5787ce82e003be05eaac142310f10f32d0549a6676af846734ae4ac188c2b96c2eca2cb0a6f4b0
DIST genpatches-5.10-1.extras.tar.xz 1768 BLAKE2B e99d5d2137d5752845ba8284a0dd57620851c3620603e871973af5841b54e9bfdde92ea2408ddedb55355f2c954c80641b06098060043916d2483e10cfb8293a SHA512 0034e5ab57cccb2e969a3b9e1f674614ca853779c552c37be9c5afb0a37112bf8f2c30e1b21832d56320c70c1d622081b60369c6a86fa737a23c3ed953267453
-DIST genpatches-5.10-3.base.tar.xz 5524 BLAKE2B 3811736bbb95e9f4b9745cc0f02bd1c183bde82e4c10924a72cb1b4a0fdd3703cdc591c2e8fe266c3ffd29ef65258bf57ac314318c01d73dd08a17e449108c60 SHA512 50d8e1c26600657f76a4aefc4cbb7aa7db1b9265db77344769ac33bc988d692d84f4d7d7b9055ed2278c6e8c195902b6561ccfede741c7a77c42cfec9dd3ed56
-DIST genpatches-5.10-3.extras.tar.xz 1772 BLAKE2B a5453e4e9187373c7dc1b2e77a7877a53eaf3c0cfb578b199d93715dae78cb47c72e644e4de50e0837712b8a61ef151b4f6cd61a7d85de306bbe8d5dfdda4af6 SHA512 394220858394f89a1beadaaa1bbc86049f1bfd8e850c72fd7e27d0db23b4600d148a602fb4c68a3399e6a8fef3a7e0d45ae0c946976dce7418f0547841a4d21d
+DIST genpatches-5.11-1.base.tar.xz 3440 BLAKE2B eb1e9a9f2060023cb410bf3db8c4f4fe283eff47f545a434dfc1edb98aa513940f30a2a88566422192b79f7ab36c607b9bc63253c067070d9a479d6318fd34b3 SHA512 a862fe33272bb6b0e4095c862c74361f015fc57316b9dbbdf2782f2e57c131fbe7fe9b9ba81c3d5a7d71788f2d56abdbd28f1c7571973c3f378cd05199c0421f
+DIST genpatches-5.11-1.extras.tar.xz 1772 BLAKE2B e6f8eae67db54099424f33e17bbfa66d36ae44c98d5f58969634a709a4b949a675a7ec1053eab4db4f745513d9730b68439ecf888e92f0fc9ef369822b39a388 SHA512 cf9d0ee27618b1b49322cefda8d85f66fd94820b9902948c8dd9a33d4e14acf511e7aabf611df5e070a4011e06d80164a512d124f5686b5b16fd81409098d8eb
DIST genpatches-5.9-1.base.tar.xz 4004 BLAKE2B 8a4577d42262fa901186acc60d28221d00e5c9140886705f018d9989f818d96ee4d9a6586b292e7b1d945bea9e2408e3161a73e0999defe1b7f99d0a339eb7be SHA512 d6ba1051f9561aa30d7b196336c34930285d613e8119b152f1d6cc447cb22db5ac07c25f89d4ceddf58c9370c42699d0250a31449be2da3c591896b0c87d8718
DIST genpatches-5.9-1.extras.tar.xz 1764 BLAKE2B 32d29f0448aef113ba9c9591c5d3b671d00d07abde9f35f365b48168887913bb2da95a8a52b852453307cabb111115a26178be4cbcc016e53a26a31f783a9df7 SHA512 df007dc98c1acdd31773f7dcf8aeb22812aa55e5593e8509b6a8762f2dcf06c95d69ad7cdce992e7a5fe730754bef26242acdc4e4da51ee29206fabb86c9cb0e
DIST linux-5.10.tar.xz 116606704 BLAKE2B b923d7b66309224f42f35f8a5fa219421b0a9362d2adacdadd8d96251f61f7230878ea297a269a7f3b3c56830f0b177e068691e1d7f88501a05653b0a13274d1 SHA512 95bc137d0cf9148da6a9d1f1a878698dc27b40f68e22c597544010a6c591ce1b256f083489d3ff45ff77753289b535135590194d88ef9f007d0ddab3d74de70e
+DIST linux-5.11.tar.xz 117619104 BLAKE2B 81300c27bd5476387a83123aaeb4163c73eb61e9245806c23660cb5e6a4fa88ffc9def027031335fa0270fc4080506cd415990014364e3a98b9d2e8c58a29524 SHA512 a567ec133018bb5ec00c60281479b466c26e02137a93a9c690e83997947df02b6fd94e76e8df748f6d70ceb58a19bacc3b1467de10b7a1fad2763db32b3f1330
DIST linux-5.9.tar.xz 115507140 BLAKE2B e8d11472d63a9f8409ca12a2e8c97c6963a3d4516b5a398b627d6ece565584526f9b5a1377a2fa4bd184c09c7db94c987428bc5d52df0c788464a67e9e8d6dcb SHA512 d3d92ce4246bad74c9a784212f160d98449b1e8793970c2c308276568d852b8effe0528686bdb87d55d691f09a826abf7938d69bdd4759ce65ddd5c05ffe4eca
-DIST pf-sources-5.10_p10.patch 4844801 BLAKE2B d38596ac73cc10cc81d3ce742a587bf9de918c7fdda7aa721d3ff721d562339bc6dc3a97f361888804754c7182e99459fc312a9efaaa37b94b58b7f502539586 SHA512 377ab784d9dc138ec4482382c912335cae05e86be7dd47f13fe3df402f12a40d613f3e30a0067f01b682bb5ca4dfbcf9592cc166f0b42424af70a702f8651dcd
-DIST pf-sources-5.10_p11.patch 5051168 BLAKE2B e27dbf5ba44ed5ad7892b06cc3760fd44b4036c0281284a05f6d783078c2b719384efa9b9e0ff39a59cdfd5143f8c43d336a7e413fea5ddd1ff7c0fc8e43b2c8 SHA512 953b034583683574e6d95d6dbce03bad43973bd27037352dc5bfa12c966660792b92fd87ad0de47b6543e599f22ee89dd9e10bc2e76e9bfff377c353fe9e2205
DIST pf-sources-5.10_p12.patch 5244822 BLAKE2B ca004890e20a07864e858bf1834265f125d1a1a7130ecd2f4a1718b4be61dd8dbfd6c4ca7f5740219afc83f1a4645d159d57b546937bcabec59511abe3d78e58 SHA512 5aa8f303798f93e5ad2042878fa15f5ab717ad265fc6db5d35e2b429cf240ce57f042ff8c2c0ac442e552a4925093e1550f1405caffcce648b46140fb809266b
-DIST pf-sources-5.10_p2.patch 2555927 BLAKE2B 69684df6616e243f5bda273ce4fd30300cde82355e3e71ef3f265bbc2fe2f680d035875ce76e836c0ee432692b69736ada54026bedbfa4423826260b5c3e05a1 SHA512 cdcaa01a9b89b935ee7b3035516c38b69ed38b897e4566adc132416fdb1953f965c33471192a3e0c85187af8edc2f0645d65e324d7b591fb4e3cabda4b05126c
-DIST pf-sources-5.10_p3.patch 2588302 BLAKE2B 47a3aaa429b773edfa4f1a2eeb046648f57204a8b1985710eaf11d95baceb92950352b03e819250d59614b52e8315758a78e72a646f4bedddc5674c2571a06ab SHA512 3701656ddb88b59bb816b96c8b986f9abf4087231dac7ef2c07f1a406e8edbffb7da6e0099ff0ce3a9f73557c96984e8e7b6a9cc69d4cd129d7f7e05535fee1f
-DIST pf-sources-5.10_p4.patch 3769450 BLAKE2B 5f470380efe3224150267125022012553daa36aea6bcc62d7df28a78a0f091aef925f6a2964d11e68877750b25ef5449a7d87577db30068d417106e6a76dd396 SHA512 8c0f0f48ff19e2c93ab1a0ec0387ba59365c4b5dedd4d4b7f323ac0f24502862e6e2a50c8c3c5be911836392aefba3d1c99b2fe1bc2ec8849ffff9c72a4dff2d
-DIST pf-sources-5.10_p5.patch 3767157 BLAKE2B 7ea53839532d97225bbb95cd0e56c5e81d51cbe7e01bbfb09a5aea08fabbad7dee415da0ff79b6b248e2f88bb73434d53ba17808a8d62d403387cccc269e9f9d SHA512 2c07b1e66fad2e2ae1c279cfe9a41585c98ad0fe7d592a20d04e203e7a74ef9dddf6d8a970adb797727185dcbb28fa7a6a1faefcc2adb6a1eb0d309c43356f7e
-DIST pf-sources-5.10_p6.patch 3863592 BLAKE2B 5ce92850e459f9ea9bdd19d4375f13a7554adbdcd3ed2b2c77c1e138c6cb508554ab8701398f77485f9551ad6422fd14e4f7ba708d607d9a107ccd818c42f560 SHA512 44398b4bcef521267ed4b9dc56281cff2587680498f68130361bab8de8bf164601bc95642493dcbb08eaf43ffca3b333ab2a12db825e7f52eb0171bb191bbaea
-DIST pf-sources-5.10_p7.patch 4104263 BLAKE2B a53f381c255aa242955d7401496b5b21fba743c2a4d3d0c31a06d67c15806e1672c8910f165140ddc1aff6958e93d2871c50e64b81afeff50f1982bd854c9c19 SHA512 583f48a8fba4cc62b60a17a0274ada2f17bd8a75b16b0e9e27fa9536e743bfbba57c561a544a7c8b7a87e65059aa01e92259c9c55dc46544445d5026b06fcd82
-DIST pf-sources-5.10_p8.patch 4232466 BLAKE2B efe977028da96031c2834af65fc7da943ad0d7d0155a54e614a61ae825672b147dca31491487c8bb500aac9db869e303d3ced6a30bdd9f6fdf4bf0a0d93dc9c3 SHA512 bf64e4a12627f5c0b39dba44f815d7a42758a9e0a79fb341c535ed2b64e99068c8fdc1b8e3ae6656e815280337715b2b19d084fb589a5c60a1e5ab8e2153e27a
-DIST pf-sources-5.10_p9.patch 4509136 BLAKE2B a0bd46d0e6f833849736da492e89fbc3885bf3b96db0f1cbd03525e5d60a2a8f224851f92c73f51224565ba27517ab3310af8b853fa03fedc55d8f035bda0389 SHA512 45ad1097dc270a347be598c053bc19d0a830f86e124e317c5bdf3682ed41c523ed80d277ae94ca6ecee247792254b8f16b9c9ad5c90288dec9ab6d4cb5f0d272
+DIST pf-sources-5.11_p1.patch 2710131 BLAKE2B 67a3528d1c59f24af9f09bc669e736d41394041874e07ebaa68bba8393d98b6094f3c733f1f395cb0a816f418702934d7ac828fceabebcec187526ca378929f4 SHA512 0bc79a5eb093c0b072826098b78894d59bab2bb8107221c9727c4aebb839b2e4d066c2f4918614bfbf4e3af210a6d1852189303f9ebf338f2e5038f166d4dfb0
+DIST pf-sources-5.11_p2.patch 2720760 BLAKE2B db2ccb4449d6ed2d545c15ef82b99d581e462908ab2290b62119c09da93a7cf202e3a1792a1bf3afb6ae98f4c9f8ea34ef7ad7056206f3eac7daa8a7a9559f4a SHA512 1ab4748cac5a8a210a48543606c2c3e30e4528c819b4e7d7e29d992d4f9b14ae6e7219d7d96d090fc887d72887735e52dad9a8d396d775c8c32b80b01532a9ea
DIST pf-sources-5.9_p7.patch 3027972 BLAKE2B 9247ea63b30f9d42d79303b73a900d468a71e703333932f7f15ae697cdba52c46358297023e037226c219fad5df912fb5d21e6f4b7190556ca799fa84924480e SHA512 c69e14f59bf98944b3329c65b7e2c271d74a756bc8c890130bf3cc68b4b96d31f1c33c4edb128580fcaefeb6e42dd04b1eb3d7f071b2d58bc764d26322bda8cd
diff --git a/sys-kernel/pf-sources/metadata.xml b/sys-kernel/pf-sources/metadata.xml
index c10c60b8af4d..c721efa075f4 100644
--- a/sys-kernel/pf-sources/metadata.xml
+++ b/sys-kernel/pf-sources/metadata.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>juippis@gentoo.org</email>
- <name>Joonas Niilola</name>
- </maintainer>
- <upstream>
- <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
- </upstream>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>juippis@gentoo.org</email>
+ <name>Joonas Niilola</name>
+ </maintainer>
+ <upstream>
+ <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
+ </upstream>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/pf-sources/pf-sources-5.10_p2.ebuild b/sys-kernel/pf-sources/pf-sources-5.10_p2.ebuild
deleted file mode 100644
index f73be470724f..000000000000
--- a/sys-kernel/pf-sources/pf-sources-5.10_p2.ebuild
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright 1999-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-
-# Define what default functions to run
-ETYPE="sources"
-
-# No 'experimental' USE flag provided, but we still want to use genpatches
-K_EXP_GENPATCHES_NOUSE="1"
-
-# Just get basic genpatches, -pf patch set already includes vanilla-linux updates
-K_GENPATCHES_VER="3"
-
-# -pf already sets EXTRAVERSION to kernel Makefile
-K_NOSETEXTRAVERSION="1"
-
-# Not supported by the Gentoo security team
-K_SECURITY_UNSUPPORTED="1"
-
-# We want the very basic patches from gentoo-sources, experimental patch is
-# already included in pf-sources
-K_WANT_GENPATCHES="base extras"
-
-# This is already patched via -pf patch set.
-UNIPATCH_EXCLUDE="1001_linux-5.10.1.patch"
-
-inherit kernel-2 optfeature
-detect_version
-
-DESCRIPTION="Linux kernel fork that includes the pf-kernel patchset and Gentoo's genpatches"
-HOMEPAGE="https://gitlab.com/post-factum/pf-kernel/-/wikis/README
- https://dev.gentoo.org/~mpagano/genpatches/"
-SRC_URI="${KERNEL_URI}
- https://github.com/pfactum/pf-kernel/compare/v${PV/_p*/}...v${PV/_p*/}-pf${PV/*_p/}.diff -> ${P}.patch
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.base.tar.xz
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.extras.tar.xz"
-
-KEYWORDS="~amd64 ~ppc ~ppc64 ~x86"
-
-S="${WORKDIR}/linux-${PVR}-pf"
-
-PATCHES=( "${DISTDIR}/${P}.patch" )
-
-K_EXTRAEINFO="For more info on pf-sources and details on how to report problems,
- see: ${HOMEPAGE}."
-
-pkg_setup() {
- ewarn ""
- ewarn "${PN} is *not* supported by the Gentoo Kernel Project in any way."
- ewarn "If you need support, please contact the pf developers directly."
- ewarn "Do *not* open bugs in Gentoo's bugzilla unless you have issues with"
- ewarn "the ebuilds. Thank you."
- ewarn ""
-
- kernel-2_pkg_setup
-}
-
-src_prepare() {
- # kernel-2_src_prepare doesn't apply PATCHES().
- default
-}
-
-pkg_postinst() {
- kernel-2_pkg_postinst
-
- elog "Optional features:"
- optfeature "Userspace KSM helper" sys-process/uksmd
-}
diff --git a/sys-kernel/pf-sources/pf-sources-5.10_p3.ebuild b/sys-kernel/pf-sources/pf-sources-5.10_p3.ebuild
deleted file mode 100644
index 28b132ed0a4e..000000000000
--- a/sys-kernel/pf-sources/pf-sources-5.10_p3.ebuild
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 1999-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-
-# Define what default functions to run
-ETYPE="sources"
-
-# No 'experimental' USE flag provided, but we still want to use genpatches
-K_EXP_GENPATCHES_NOUSE="1"
-
-# Just get basic genpatches, -pf patch set already includes vanilla-linux updates
-K_GENPATCHES_VER="1"
-
-# -pf already sets EXTRAVERSION to kernel Makefile
-K_NOSETEXTRAVERSION="1"
-
-# Not supported by the Gentoo security team
-K_SECURITY_UNSUPPORTED="1"
-
-# We want the very basic patches from gentoo-sources, experimental patch is
-# already included in pf-sources
-K_WANT_GENPATCHES="base extras"
-
-inherit kernel-2 optfeature
-detect_version
-
-DESCRIPTION="Linux kernel fork that includes the pf-kernel patchset and Gentoo's genpatches"
-HOMEPAGE="https://gitlab.com/post-factum/pf-kernel/-/wikis/README
- https://dev.gentoo.org/~mpagano/genpatches/"
-SRC_URI="${KERNEL_URI}
- https://github.com/pfactum/pf-kernel/compare/v${PV/_p*/}...v${PV/_p*/}-pf${PV/*_p/}.diff -> ${P}.patch
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.base.tar.xz
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.extras.tar.xz"
-
-KEYWORDS="~amd64 ~ppc ~ppc64 ~x86"
-
-S="${WORKDIR}/linux-${PVR}-pf"
-
-PATCHES=( "${DISTDIR}/${P}.patch" )
-
-K_EXTRAEINFO="For more info on pf-sources and details on how to report problems,
- see: ${HOMEPAGE}."
-
-pkg_setup() {
- ewarn ""
- ewarn "${PN} is *not* supported by the Gentoo Kernel Project in any way."
- ewarn "If you need support, please contact the pf developers directly."
- ewarn "Do *not* open bugs in Gentoo's bugzilla unless you have issues with"
- ewarn "the ebuilds. Thank you."
- ewarn ""
-
- kernel-2_pkg_setup
-}
-
-src_prepare() {
- # kernel-2_src_prepare doesn't apply PATCHES().
- default
-}
-
-pkg_postinst() {
- kernel-2_pkg_postinst
-
- elog "Optional features:"
- optfeature "Userspace KSM helper" sys-process/uksmd
-}
diff --git a/sys-kernel/pf-sources/pf-sources-5.10_p4.ebuild b/sys-kernel/pf-sources/pf-sources-5.10_p4.ebuild
deleted file mode 100644
index 223e79a03a51..000000000000
--- a/sys-kernel/pf-sources/pf-sources-5.10_p4.ebuild
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-
-# Define what default functions to run
-ETYPE="sources"
-
-# No 'experimental' USE flag provided, but we still want to use genpatches
-K_EXP_GENPATCHES_NOUSE="1"
-
-# Just get basic genpatches, -pf patch set already includes vanilla-linux updates
-K_GENPATCHES_VER="1"
-
-# -pf already sets EXTRAVERSION to kernel Makefile
-K_NOSETEXTRAVERSION="1"
-
-# Not supported by the Gentoo security team
-K_SECURITY_UNSUPPORTED="1"
-
-# We want the very basic patches from gentoo-sources, experimental patch is
-# already included in pf-sources
-K_WANT_GENPATCHES="base extras"
-
-inherit kernel-2 optfeature
-detect_version
-
-DESCRIPTION="Linux kernel fork that includes the pf-kernel patchset and Gentoo's genpatches"
-HOMEPAGE="https://gitlab.com/post-factum/pf-kernel/-/wikis/README
- https://dev.gentoo.org/~mpagano/genpatches/"
-SRC_URI="${KERNEL_URI}
- https://github.com/pfactum/pf-kernel/compare/v${PV/_p*/}...v${PV/_p*/}-pf${PV/*_p/}.diff -> ${P}.patch
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.base.tar.xz
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.extras.tar.xz"
-
-KEYWORDS="~amd64 ~ppc ~ppc64 ~x86"
-
-S="${WORKDIR}/linux-${PVR}-pf"
-
-PATCHES=( "${DISTDIR}/${P}.patch" )
-
-K_EXTRAEINFO="For more info on pf-sources and details on how to report problems,
- see: ${HOMEPAGE}."
-
-pkg_setup() {
- ewarn ""
- ewarn "${PN} is *not* supported by the Gentoo Kernel Project in any way."
- ewarn "If you need support, please contact the pf developers directly."
- ewarn "Do *not* open bugs in Gentoo's bugzilla unless you have issues with"
- ewarn "the ebuilds. Thank you."
- ewarn ""
-
- kernel-2_pkg_setup
-}
-
-src_prepare() {
- # kernel-2_src_prepare doesn't apply PATCHES().
- default
-}
-
-pkg_postinst() {
- kernel-2_pkg_postinst
-
- elog "Optional features:"
- optfeature "Userspace KSM helper" sys-process/uksmd
-}
diff --git a/sys-kernel/pf-sources/pf-sources-5.10_p5.ebuild b/sys-kernel/pf-sources/pf-sources-5.10_p5.ebuild
deleted file mode 100644
index 223e79a03a51..000000000000
--- a/sys-kernel/pf-sources/pf-sources-5.10_p5.ebuild
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-
-# Define what default functions to run
-ETYPE="sources"
-
-# No 'experimental' USE flag provided, but we still want to use genpatches
-K_EXP_GENPATCHES_NOUSE="1"
-
-# Just get basic genpatches, -pf patch set already includes vanilla-linux updates
-K_GENPATCHES_VER="1"
-
-# -pf already sets EXTRAVERSION to kernel Makefile
-K_NOSETEXTRAVERSION="1"
-
-# Not supported by the Gentoo security team
-K_SECURITY_UNSUPPORTED="1"
-
-# We want the very basic patches from gentoo-sources, experimental patch is
-# already included in pf-sources
-K_WANT_GENPATCHES="base extras"
-
-inherit kernel-2 optfeature
-detect_version
-
-DESCRIPTION="Linux kernel fork that includes the pf-kernel patchset and Gentoo's genpatches"
-HOMEPAGE="https://gitlab.com/post-factum/pf-kernel/-/wikis/README
- https://dev.gentoo.org/~mpagano/genpatches/"
-SRC_URI="${KERNEL_URI}
- https://github.com/pfactum/pf-kernel/compare/v${PV/_p*/}...v${PV/_p*/}-pf${PV/*_p/}.diff -> ${P}.patch
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.base.tar.xz
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.extras.tar.xz"
-
-KEYWORDS="~amd64 ~ppc ~ppc64 ~x86"
-
-S="${WORKDIR}/linux-${PVR}-pf"
-
-PATCHES=( "${DISTDIR}/${P}.patch" )
-
-K_EXTRAEINFO="For more info on pf-sources and details on how to report problems,
- see: ${HOMEPAGE}."
-
-pkg_setup() {
- ewarn ""
- ewarn "${PN} is *not* supported by the Gentoo Kernel Project in any way."
- ewarn "If you need support, please contact the pf developers directly."
- ewarn "Do *not* open bugs in Gentoo's bugzilla unless you have issues with"
- ewarn "the ebuilds. Thank you."
- ewarn ""
-
- kernel-2_pkg_setup
-}
-
-src_prepare() {
- # kernel-2_src_prepare doesn't apply PATCHES().
- default
-}
-
-pkg_postinst() {
- kernel-2_pkg_postinst
-
- elog "Optional features:"
- optfeature "Userspace KSM helper" sys-process/uksmd
-}
diff --git a/sys-kernel/pf-sources/pf-sources-5.10_p6.ebuild b/sys-kernel/pf-sources/pf-sources-5.10_p6.ebuild
deleted file mode 100644
index 223e79a03a51..000000000000
--- a/sys-kernel/pf-sources/pf-sources-5.10_p6.ebuild
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-
-# Define what default functions to run
-ETYPE="sources"
-
-# No 'experimental' USE flag provided, but we still want to use genpatches
-K_EXP_GENPATCHES_NOUSE="1"
-
-# Just get basic genpatches, -pf patch set already includes vanilla-linux updates
-K_GENPATCHES_VER="1"
-
-# -pf already sets EXTRAVERSION to kernel Makefile
-K_NOSETEXTRAVERSION="1"
-
-# Not supported by the Gentoo security team
-K_SECURITY_UNSUPPORTED="1"
-
-# We want the very basic patches from gentoo-sources, experimental patch is
-# already included in pf-sources
-K_WANT_GENPATCHES="base extras"
-
-inherit kernel-2 optfeature
-detect_version
-
-DESCRIPTION="Linux kernel fork that includes the pf-kernel patchset and Gentoo's genpatches"
-HOMEPAGE="https://gitlab.com/post-factum/pf-kernel/-/wikis/README
- https://dev.gentoo.org/~mpagano/genpatches/"
-SRC_URI="${KERNEL_URI}
- https://github.com/pfactum/pf-kernel/compare/v${PV/_p*/}...v${PV/_p*/}-pf${PV/*_p/}.diff -> ${P}.patch
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.base.tar.xz
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.extras.tar.xz"
-
-KEYWORDS="~amd64 ~ppc ~ppc64 ~x86"
-
-S="${WORKDIR}/linux-${PVR}-pf"
-
-PATCHES=( "${DISTDIR}/${P}.patch" )
-
-K_EXTRAEINFO="For more info on pf-sources and details on how to report problems,
- see: ${HOMEPAGE}."
-
-pkg_setup() {
- ewarn ""
- ewarn "${PN} is *not* supported by the Gentoo Kernel Project in any way."
- ewarn "If you need support, please contact the pf developers directly."
- ewarn "Do *not* open bugs in Gentoo's bugzilla unless you have issues with"
- ewarn "the ebuilds. Thank you."
- ewarn ""
-
- kernel-2_pkg_setup
-}
-
-src_prepare() {
- # kernel-2_src_prepare doesn't apply PATCHES().
- default
-}
-
-pkg_postinst() {
- kernel-2_pkg_postinst
-
- elog "Optional features:"
- optfeature "Userspace KSM helper" sys-process/uksmd
-}
diff --git a/sys-kernel/pf-sources/pf-sources-5.10_p7.ebuild b/sys-kernel/pf-sources/pf-sources-5.10_p7.ebuild
deleted file mode 100644
index 223e79a03a51..000000000000
--- a/sys-kernel/pf-sources/pf-sources-5.10_p7.ebuild
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-
-# Define what default functions to run
-ETYPE="sources"
-
-# No 'experimental' USE flag provided, but we still want to use genpatches
-K_EXP_GENPATCHES_NOUSE="1"
-
-# Just get basic genpatches, -pf patch set already includes vanilla-linux updates
-K_GENPATCHES_VER="1"
-
-# -pf already sets EXTRAVERSION to kernel Makefile
-K_NOSETEXTRAVERSION="1"
-
-# Not supported by the Gentoo security team
-K_SECURITY_UNSUPPORTED="1"
-
-# We want the very basic patches from gentoo-sources, experimental patch is
-# already included in pf-sources
-K_WANT_GENPATCHES="base extras"
-
-inherit kernel-2 optfeature
-detect_version
-
-DESCRIPTION="Linux kernel fork that includes the pf-kernel patchset and Gentoo's genpatches"
-HOMEPAGE="https://gitlab.com/post-factum/pf-kernel/-/wikis/README
- https://dev.gentoo.org/~mpagano/genpatches/"
-SRC_URI="${KERNEL_URI}
- https://github.com/pfactum/pf-kernel/compare/v${PV/_p*/}...v${PV/_p*/}-pf${PV/*_p/}.diff -> ${P}.patch
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.base.tar.xz
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.extras.tar.xz"
-
-KEYWORDS="~amd64 ~ppc ~ppc64 ~x86"
-
-S="${WORKDIR}/linux-${PVR}-pf"
-
-PATCHES=( "${DISTDIR}/${P}.patch" )
-
-K_EXTRAEINFO="For more info on pf-sources and details on how to report problems,
- see: ${HOMEPAGE}."
-
-pkg_setup() {
- ewarn ""
- ewarn "${PN} is *not* supported by the Gentoo Kernel Project in any way."
- ewarn "If you need support, please contact the pf developers directly."
- ewarn "Do *not* open bugs in Gentoo's bugzilla unless you have issues with"
- ewarn "the ebuilds. Thank you."
- ewarn ""
-
- kernel-2_pkg_setup
-}
-
-src_prepare() {
- # kernel-2_src_prepare doesn't apply PATCHES().
- default
-}
-
-pkg_postinst() {
- kernel-2_pkg_postinst
-
- elog "Optional features:"
- optfeature "Userspace KSM helper" sys-process/uksmd
-}
diff --git a/sys-kernel/pf-sources/pf-sources-5.10_p8.ebuild b/sys-kernel/pf-sources/pf-sources-5.10_p8.ebuild
deleted file mode 100644
index 223e79a03a51..000000000000
--- a/sys-kernel/pf-sources/pf-sources-5.10_p8.ebuild
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-
-# Define what default functions to run
-ETYPE="sources"
-
-# No 'experimental' USE flag provided, but we still want to use genpatches
-K_EXP_GENPATCHES_NOUSE="1"
-
-# Just get basic genpatches, -pf patch set already includes vanilla-linux updates
-K_GENPATCHES_VER="1"
-
-# -pf already sets EXTRAVERSION to kernel Makefile
-K_NOSETEXTRAVERSION="1"
-
-# Not supported by the Gentoo security team
-K_SECURITY_UNSUPPORTED="1"
-
-# We want the very basic patches from gentoo-sources, experimental patch is
-# already included in pf-sources
-K_WANT_GENPATCHES="base extras"
-
-inherit kernel-2 optfeature
-detect_version
-
-DESCRIPTION="Linux kernel fork that includes the pf-kernel patchset and Gentoo's genpatches"
-HOMEPAGE="https://gitlab.com/post-factum/pf-kernel/-/wikis/README
- https://dev.gentoo.org/~mpagano/genpatches/"
-SRC_URI="${KERNEL_URI}
- https://github.com/pfactum/pf-kernel/compare/v${PV/_p*/}...v${PV/_p*/}-pf${PV/*_p/}.diff -> ${P}.patch
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.base.tar.xz
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.extras.tar.xz"
-
-KEYWORDS="~amd64 ~ppc ~ppc64 ~x86"
-
-S="${WORKDIR}/linux-${PVR}-pf"
-
-PATCHES=( "${DISTDIR}/${P}.patch" )
-
-K_EXTRAEINFO="For more info on pf-sources and details on how to report problems,
- see: ${HOMEPAGE}."
-
-pkg_setup() {
- ewarn ""
- ewarn "${PN} is *not* supported by the Gentoo Kernel Project in any way."
- ewarn "If you need support, please contact the pf developers directly."
- ewarn "Do *not* open bugs in Gentoo's bugzilla unless you have issues with"
- ewarn "the ebuilds. Thank you."
- ewarn ""
-
- kernel-2_pkg_setup
-}
-
-src_prepare() {
- # kernel-2_src_prepare doesn't apply PATCHES().
- default
-}
-
-pkg_postinst() {
- kernel-2_pkg_postinst
-
- elog "Optional features:"
- optfeature "Userspace KSM helper" sys-process/uksmd
-}
diff --git a/sys-kernel/pf-sources/pf-sources-5.10_p9.ebuild b/sys-kernel/pf-sources/pf-sources-5.10_p9.ebuild
deleted file mode 100644
index 223e79a03a51..000000000000
--- a/sys-kernel/pf-sources/pf-sources-5.10_p9.ebuild
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-
-# Define what default functions to run
-ETYPE="sources"
-
-# No 'experimental' USE flag provided, but we still want to use genpatches
-K_EXP_GENPATCHES_NOUSE="1"
-
-# Just get basic genpatches, -pf patch set already includes vanilla-linux updates
-K_GENPATCHES_VER="1"
-
-# -pf already sets EXTRAVERSION to kernel Makefile
-K_NOSETEXTRAVERSION="1"
-
-# Not supported by the Gentoo security team
-K_SECURITY_UNSUPPORTED="1"
-
-# We want the very basic patches from gentoo-sources, experimental patch is
-# already included in pf-sources
-K_WANT_GENPATCHES="base extras"
-
-inherit kernel-2 optfeature
-detect_version
-
-DESCRIPTION="Linux kernel fork that includes the pf-kernel patchset and Gentoo's genpatches"
-HOMEPAGE="https://gitlab.com/post-factum/pf-kernel/-/wikis/README
- https://dev.gentoo.org/~mpagano/genpatches/"
-SRC_URI="${KERNEL_URI}
- https://github.com/pfactum/pf-kernel/compare/v${PV/_p*/}...v${PV/_p*/}-pf${PV/*_p/}.diff -> ${P}.patch
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.base.tar.xz
- https://dev.gentoo.org/~mpagano/genpatches/tarballs/genpatches-${PV/_p*/}-${K_GENPATCHES_VER}.extras.tar.xz"
-
-KEYWORDS="~amd64 ~ppc ~ppc64 ~x86"
-
-S="${WORKDIR}/linux-${PVR}-pf"
-
-PATCHES=( "${DISTDIR}/${P}.patch" )
-
-K_EXTRAEINFO="For more info on pf-sources and details on how to report problems,
- see: ${HOMEPAGE}."
-
-pkg_setup() {
- ewarn ""
- ewarn "${PN} is *not* supported by the Gentoo Kernel Project in any way."
- ewarn "If you need support, please contact the pf developers directly."
- ewarn "Do *not* open bugs in Gentoo's bugzilla unless you have issues with"
- ewarn "the ebuilds. Thank you."
- ewarn ""
-
- kernel-2_pkg_setup
-}
-
-src_prepare() {
- # kernel-2_src_prepare doesn't apply PATCHES().
- default
-}
-
-pkg_postinst() {
- kernel-2_pkg_postinst
-
- elog "Optional features:"
- optfeature "Userspace KSM helper" sys-process/uksmd
-}
diff --git a/sys-kernel/pf-sources/pf-sources-5.10_p10.ebuild b/sys-kernel/pf-sources/pf-sources-5.11_p1.ebuild
index 223e79a03a51..223e79a03a51 100644
--- a/sys-kernel/pf-sources/pf-sources-5.10_p10.ebuild
+++ b/sys-kernel/pf-sources/pf-sources-5.11_p1.ebuild
diff --git a/sys-kernel/pf-sources/pf-sources-5.10_p11.ebuild b/sys-kernel/pf-sources/pf-sources-5.11_p2.ebuild
index 223e79a03a51..223e79a03a51 100644
--- a/sys-kernel/pf-sources/pf-sources-5.10_p11.ebuild
+++ b/sys-kernel/pf-sources/pf-sources-5.11_p2.ebuild
diff --git a/sys-kernel/raspberrypi-image/Manifest b/sys-kernel/raspberrypi-image/Manifest
index 2d3543d359b9..91fa34ba8ff7 100644
--- a/sys-kernel/raspberrypi-image/Manifest
+++ b/sys-kernel/raspberrypi-image/Manifest
@@ -1,3 +1,4 @@
DIST raspberrypi-firmware-1.20190925.tar.gz 185571086 BLAKE2B c3a9b2760fa853fbd1dd09bc4048c9e78594f88da5af608c3a761554d4046a4c869db8981c64140a24e82e0a61b8dc776bb8d895df60c6424e44780f78b18cb0 SHA512 4b7b29cc6c2a33d7a37987c492034d9afbb2220364c50cf265e0adf8e5f393c2275dcffaa77c89b3f43b2e98d199741b67590cb60ff8beae8ef677852f63b4a0
DIST raspberrypi-firmware-1.20201201.tar.gz 189332299 BLAKE2B b3ec91f07b4713d26c29be5412d018a220129eef7ddf7c5c09d85e645c2c5754a95f13be7e690ab40648a982e3974cc760aa5b33c76612da836227d38c4ee3a5 SHA512 a7f4591552718956bd7f2d0d377234277e2e6f18cc9714ea30fe13f26d5ae1164b982f39dcf72ae4a18663369ef06d0187d8182713763262371c13107aac4c65
+DIST raspberrypi-firmware-1.20210201.tar.gz 191785657 BLAKE2B 7ef315411e3bc572515f9e60d953166056bd5dfe9afc496eda978dbbbd6f38aa12f1eaba72448bb72166d6bda1ec79e3e3e7c613f4202bc804784b566f118971 SHA512 13d899a103e8d3deb98a6fcca661f712b085935336fc31156e0b8ec5e3c71b373d3394777895ee1907cad9a2ca3efd1a66995ff6df3429c732b002d9ad603414
DIST raspberrypi-image-4.14.98_p20190215.tar.gz 123074917 BLAKE2B cefedb5c979db7dfd47938aad37a567d91d3ad78247c7a63f789362768ab7a39a1967ac116b4b0475e3b210ab11f6474706df042af85a622e8e7905c85ec7498 SHA512 082f26caf427222d838881e5f1e9fa0136765b3eaf74a84877fc33616fd07e49085db0889226c40c655039a9d41a10566510c7d752cfc48a67b4683616a51193
diff --git a/sys-kernel/raspberrypi-image/metadata.xml b/sys-kernel/raspberrypi-image/metadata.xml
index 729e6b371508..93f32c4fc772 100644
--- a/sys-kernel/raspberrypi-image/metadata.xml
+++ b/sys-kernel/raspberrypi-image/metadata.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>sam@gentoo.org</email>
- <name>Sam James</name>
- </maintainer>
- <upstream>
- <remote-id type="github">raspberrypi/firmware</remote-id>
- </upstream>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>sam@gentoo.org</email>
+ <name>Sam James</name>
+ </maintainer>
+ <upstream>
+ <remote-id type="github">raspberrypi/firmware</remote-id>
+ </upstream>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/raspberrypi-image/raspberrypi-image-5.10.11_p20210201.ebuild b/sys-kernel/raspberrypi-image/raspberrypi-image-5.10.11_p20210201.ebuild
new file mode 100644
index 000000000000..26d80041afd0
--- /dev/null
+++ b/sys-kernel/raspberrypi-image/raspberrypi-image-5.10.11_p20210201.ebuild
@@ -0,0 +1,43 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+
+inherit mount-boot
+
+DESCRIPTION="Raspberry Pi (all versions) kernel and modules"
+HOMEPAGE="https://github.com/raspberrypi/firmware"
+LICENSE="GPL-2 raspberrypi-videocore-bin"
+SLOT="0"
+RESTRICT="binchecks strip"
+
+# Temporary safety measure to prevent ending up with a pair of
+# sys-kernel/raspberrypi-image and sys-boot/raspberrypi-firmware
+# both of which installed device tree files.
+# Restore to simply "sys-boot/raspberrypi-firmware" when the mentioned version
+# and all older ones are deleted.
+RDEPEND=">sys-boot/raspberrypi-firmware-1.20190709"
+
+if [[ "${PV}" == 9999 ]]; then
+ inherit git-r3
+ EGIT_REPO_URI="https://github.com/raspberrypi/firmware"
+ EGIT_CLONE_TYPE="shallow"
+else
+ [[ "$(ver_cut 4)" == 'p' ]] || die "Unsupported version format, tweak the ebuild."
+ MY_PV="1.$(ver_cut 5)"
+ SRC_URI="https://github.com/raspberrypi/firmware/archive/${MY_PV}.tar.gz -> raspberrypi-firmware-${MY_PV}.tar.gz"
+ S="${WORKDIR}/firmware-${MY_PV}"
+ KEYWORDS=""
+ # No keywords until I can give it a boot test
+ #KEYWORDS="-* ~arm ~arm64"
+fi
+
+src_install() {
+ insinto /lib/modules
+ doins -r modules/*
+ insinto /boot
+ doins boot/*.img
+
+ doins boot/*.dtb
+ doins -r boot/overlays
+}
diff --git a/sys-kernel/raspberrypi-sources/metadata.xml b/sys-kernel/raspberrypi-sources/metadata.xml
index 3bc86a942642..8eaec336ce4a 100644
--- a/sys-kernel/raspberrypi-sources/metadata.xml
+++ b/sys-kernel/raspberrypi-sources/metadata.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>sam@gentoo.org</email>
- <name>Sam James</name>
- </maintainer>
- <upstream>
- <remote-id type="github">raspberrypi/linux</remote-id>
- </upstream>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>sam@gentoo.org</email>
+ <name>Sam James</name>
+ </maintainer>
+ <upstream>
+ <remote-id type="github">raspberrypi/linux</remote-id>
+ </upstream>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/rt-sources/metadata.xml b/sys-kernel/rt-sources/metadata.xml
index 1346447ab3f0..e7b4807cca07 100644
--- a/sys-kernel/rt-sources/metadata.xml
+++ b/sys-kernel/rt-sources/metadata.xml
@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>alicef@gentoo.org</email>
- </maintainer>
- <use>
- <flag name="deblob">Remove binary blobs from kernel sources to provide libre license compliance.</flag>
- </use>
- <upstream>
- <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
- </upstream>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>alicef@gentoo.org</email>
+ </maintainer>
+ <upstream>
+ <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
+ </upstream>
+ <use>
+ <flag name="deblob">Remove binary blobs from kernel sources to provide libre license compliance.</flag>
+ </use>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/vanilla-kernel/Manifest b/sys-kernel/vanilla-kernel/Manifest
index b515fcca0050..404e195eaba4 100644
--- a/sys-kernel/vanilla-kernel/Manifest
+++ b/sys-kernel/vanilla-kernel/Manifest
@@ -1,49 +1,33 @@
+DIST gentoo-kernel-config-5.10.18.tar.gz 1219 BLAKE2B 55ec8c66a9b090e590e23574b54edde0fefb575f25e6848b1c84834847304e30e52fc0810b8fd219cfb23c097bb8f7444e0b010bde44209f0c4811f99db7e0aa SHA512 ee137c85e94fe5989646cb19a72aca62ddd4795813f7bbf15d66262b0e72d90d84d5d17a31bae7980c061e0576e3f3254dca53ba6e547cf12cb7ab08771e3900
DIST gentoo-kernel-config-5.10.7.tar.gz 1146 BLAKE2B f755581e9f3be3122e5f6e6fc133d3e5c3116d4580b53f95ff5b2cee5150233fe82be5cd45637a9792ae4612be5d2cb4dd954506f97fe82c9e96cb8b772cb342 SHA512 8c64768e83d2552e69a29c6c3f958ef6a1e5a767acd04b3bfcd0cd49453ab5d0aa54fcfee76a8c9d07f72abdbf70380b070e3d1584e7b7d05a6daa3399892f51
-DIST gentoo-kernel-config-5.4.77-r1.tar.gz 1289 BLAKE2B 6612741cfbf458f4bd8915b476aac3aa6934e8bbab344da877fa4ad52b6133e01f5d44bf0e5d048e79e56c1a351774135ee55f1aa839b230e2418db7c5d9b123 SHA512 2a09dd85af37447b278847aeaad114ef47470726cec015ed5ee1b54b3080f4b2c48de8b2f7b817eeb4e27c753579cf0820053e22caa762cb1552116d8d69eba0
DIST gentoo-kernel-config-5.4.89.tar.gz 1240 BLAKE2B 50bd2e64eb1a62d2f0d67e02b78da56cb507fd7a5993d663b880c94ecd535898285ed01e00d5d07fc1ba0d044657e776456736d8fdcacecf7ca464979a8a1d06 SHA512 ad31f9895b9dd45edd7f8715516edfc303c23600f243f3ca122c7c554c9fdbe3c3aa62970a24ef7291d7937e04c63c0258f6348e796686902a011c055c1bed01
DIST kernel-aarch64-fedora.config.5.10.12 223184 BLAKE2B a0246dac2f7a4ad6a55b611538d24382ac87a8960077811a859c9595ac67f961b4bccb7e139a89abc7c0e26e80832da5c94211fc658082f2e7dde984f14dd29d SHA512 7d803b347b136331db1ad6e22e0445fe0224c3e26cd7c034cbe9794915d457b492e05f77664865079874ec001351553652646e2e08d0fee31e30b841b0008f52
-DIST kernel-aarch64-fedora.config.5.10.7 223162 BLAKE2B 23d78fadc509edd2219ba263266e4a865f98d6aef87ee2e299b81ba86ac36eff580e5c7bdccb0d4a8593afad07136e06171c79e0dd0e072c892a523e6e352933 SHA512 9791c26368173da444ca5ed281effdd5e20f3968f0a65eb607c2741f114443db2bf260d033a28a7f826963b59a8893a1311befcb3eb3609f9b85472e95234bcd
+DIST kernel-aarch64-fedora.config.5.11.1 225847 BLAKE2B 50e3db29a9afc3db3c35e3af173e89e2e8d3b573dd8af7c35584e3d0152211cbd5e6ddb749acb3d6d2caa54392a3f51e52b5394a5d032d43ed35861230b277d0 SHA512 6d0594658e205767599453d4d8695c37eabc065d6c17362c3775dd745f6ca62131d7c15126ec41a17e757d3ae2a0569cea6621a7ada4666a8f90e4414391b3dc
DIST kernel-aarch64.config.5.4.21 199104 BLAKE2B 578ad451a76204df2a9bbbe34b5cb27051d2ac5e2c33967f562b01338c43f35da6dc33a4c2cc67ea6c3b32b155729360d3748ec28dcaa750f18449245b2e8a09 SHA512 66e9a437beb350fdc59512c17b8f72c5b5bfacf2b35070d810d77e66f49cf7929026cc28ad44b04a016d61e65d9fb4a10af6996ba09b604bf97e9c467d08f8ff
DIST kernel-i686-fedora.config.5.10.12 205412 BLAKE2B 92c715b7e2cd7dd74da7970c05981f520597d3e403ce82c8cf4eee31c9f1f50b638792a6bdb256ef5bfdc99f1bcd594e819e8f44dc6febb2ad9a854bad817f2b SHA512 69d8db11723ae1b40fdedfaace74d15bb63198cdb0485e0a1e5eba95b31217110c93a93e39cc7370cf45f1d3a8bc7f75ec096d6db5ea9ecb28ac6b56702ebb10
-DIST kernel-i686-fedora.config.5.10.7 205390 BLAKE2B 103131caa856ae9b062b39cb88ad8616a8ebd7aa53b7562399d72ba998a4049a22ab251927bf43a4936127246455c2cdeeee3b7e349e12bb94af8f6dc242d8ea SHA512 58279d0076f7551569e48db45909263c5c494c4349afaff4087682d7dd0ecadc22dde56482b521ce2eec39b1e6110f5c370206e0c8f7045d4419bb164da7e2ec
+DIST kernel-i686-fedora.config.5.11.1 208027 BLAKE2B b4183e8d1121aa8b3f65d0a4542b8ba0f507430ab4cf0004dd0e8b1e24b3be1783316b8bf6becb2002f7fbacc8236b640f533fc2e9dc5696e84d1627c3b0e9c4 SHA512 5b107e376ddef783ee6852ef67143a94340b37ab764ef3ee3c6642401883d314809c959c2025d976336923c115d21d6b39332aa1699c0f884d1faad1d9c3fa32
DIST kernel-i686.config.5.4.21 183910 BLAKE2B 185126ffb85718bb73761d01683def80b6f002d7a7a6eddd8e858a30d8eadc863fb378d83a1cd2ed82b3540337fa66ae44475e31fb41ebc46d77005b6f54e5c0 SHA512 6307afc2295902e44fe65b1cccaa7a0260b295a5f21f1d67ec66197bd972bd3f5675b624f08d9da8b224cb3ec987d5c21cbd743599aeab9ac6214bc651f43476
DIST kernel-ppc64le-fedora.config.5.10.12 192105 BLAKE2B 889141debb0656a358a3381bae14b5216b982acdfce0bc758f9445c16647807a68a788fb290199c2a1a23627bda1ef4c9405b3f5ac2a4176d1d2b55c71fb7db9 SHA512 3ab0f1401d9f50a61477c71369dede438f575d9d2c3a2f5c2cf36d624c2b59a938efca9c981b075511b3860c983eaaf5e5a9f877d659277f09ceba45edd43770
-DIST kernel-ppc64le-fedora.config.5.10.7 192083 BLAKE2B 71c97c04629a05ac8cb4f4cf1740c60e8a25c71a5c9184cf53f13088073b04b269887ee6e57ff83c8caff61ccbfd6845809e6e3057f1fdfc13d9b913b032c653 SHA512 732f4e93b3074180e86bed865e0b6d487857d5eefcb2436e7c24706be0e41c813b27b2292e6995df2d63e9a9f7721c2d566a50ba06675bfa862ca1fc91dc2af5
+DIST kernel-ppc64le-fedora.config.5.11.1 194870 BLAKE2B df6e5a0a789dc6d0c2fbec45820f5e19ec455388f02f04d88d7b3dd5081d2f11e89cfd0159b7a3885aaa029470e916743d59ec3f86756ff4182aa56552aa8476 SHA512 e170912e76e8980435df2a1387792d616490ededda4df681a90312f7fc8ce4065f1c9fd7559d746d8edc0fccfbd35b20fd5db294774f9db7f4635d898cd0dab1
DIST kernel-ppc64le.config.5.4.21 172003 BLAKE2B b53887cb44f7c378cb3866780f8e556e19fdb02130d3b0df01d97698d2a91f7d90a200012559f288e962935742c3fdb67dfb6711876fad37862fe55cdca5b5f6 SHA512 82df8d0be47e9eb20bd7db570539bb061d0b6e2101dc78a54596cf4d0b4e0c536041449304ff9240b051ee09b342ea336c5645e9a3b66a5dfb96d7778ff86008
DIST kernel-x86_64-fedora.config.5.10.12 206357 BLAKE2B 0eda9d4f3f973336cabd67c1ac78f100aabde926354743e8dcb7ff84496f0de49210d45f99bc850a2096078b0b4687aa7fd965d999248559506004f2b29dac0c SHA512 b12f43d3c1a52a4915cd73db98874ce9ae6c425672c0f1c19ed1b1101341c868ebf1c9620bef5449752ec0d7342c1ce38fb77779d0f89b9267096a605ebf7a26
-DIST kernel-x86_64-fedora.config.5.10.7 206335 BLAKE2B 1133bf0f58f8073578d048c5905cc4a539f63a01b57fceb225046c4678172861de20419d8cbf42b0f4655c27a6366ddee41343458d577a2685f3d96b2fd444c6 SHA512 8c5d0de931526d3315793e0a1af4c9c2493c09573c4f2233aaa85f0413a912190c14fa8427593fc3956fff61d89c795f7c9b0509bb30936cc8b9976deafeda66
+DIST kernel-x86_64-fedora.config.5.11.1 208870 BLAKE2B 86e075a95cbc5d6c3cdecb0caf67e18f671ed663aee94b7d0688e25f111dfdf12d890e1f409df04446d18057b6fad8e0fc67adcde34ed581266d458d9c9cabbd SHA512 ab39c8b107471bdd492e6f9c2e181e85e44134b4a2934fedd2f454b9766a32aa2cef2cbf7ed83111e82ffd7794d4bf20f81d98b238751d505c13077abff2b543
DIST kernel-x86_64.config.5.4.21 184907 BLAKE2B 0eb2b07c14cea7545350fcdf3a94f2a531f0137c502ebda9299cacf44da5385686e2049b480b28bc153c9d413d453cfe682b9655eefe70428cb720f57c7bd200 SHA512 f3b3ee6841555ac3a9cc11536a7d44e1a5a8df2bab14ba341fda7df1ceb0de45cf1c799a1d54a64f2858fd1272d348bb52cf269ffa396878c5402baf2730237f
-DIST linux-5.10.10.tar.sign 991 BLAKE2B 7b9aa801aeb243c0434172d29fc7e79bc8965c19cef0c7e51d9f00c51f7d8aa2bbcbddcba54d924c0d7538d1dbb638ac3b45043ed212df0e3e92471ea0067f08 SHA512 3045e4c78aeb224c3b320b1104f1429bb742d79b8fab4d4b7b1e3711bcc1dbbe1219b81371857207121300cb99606a1695b6c9f707bf755bb7a4b4630c6486d9
-DIST linux-5.10.10.tar.xz 116625516 BLAKE2B 180f0dd063eab9542fd799c54dd335c4f310bea739048800ab3222526cb1ea7cc4ef43d2a2c27ed0e37a776f5c77540c33795aa63297704d9e215735a1a98606 SHA512 05a3f91470e1402510f10d9ad8b04350be7aa1232fec5083e5bb59e16cae8168b1f117b15508fc0dd345d7f8d20a43029a48ebcf54278596b778c37d2f966ca7
-DIST linux-5.10.11.tar.sign 991 BLAKE2B 8ac1b11f90ddde889d6b76e37048804efcf0357dd8cca975b2f2c1df811c69d8108d6c51a92023dda503ce50f4d9b9e5f633e3f22ca62c9b475901fb35a3cd18 SHA512 252f7fb5397d8766a07bd98f05a6a53ca5b606ff2172b3604ecb9f9c6d240ba2b7aec8956d85967bf6de67117a595100be81153376b62fab0fdb0edccd9833be
-DIST linux-5.10.11.tar.xz 116619904 BLAKE2B f2ffb77efeab44e5ac74f275f1c728618a0893c752018946a3908a34dca2797982efb6646df1350f31c9cab2b780aca871dff82b63e2ec59e3bfcdafa0457581 SHA512 251cdb885190769551c7c51476113e53ca11ea32f0234491ece3cfffe9f1c15e517dbba1c8f3c0d1a41351e2c14ccfff94aa00301a0c8a4a86b2569b1dd70ca5
-DIST linux-5.10.12.tar.sign 991 BLAKE2B 9071fa84cf4bb38f815935766787b406e54a976bb95d0829e45b8a1fa50b6c1abd31573bd80e6d3fbb955545a719bd640c3e39d58cd93cbecf1456d76ac69a42 SHA512 1f89429aa3b6d7fe27e8fe358c404e486367344ddea43a06ee2e25492956515f72039a97f50617e9a3eeb3b756f42a1cfbd50d732aede13baca284ede027ee83
-DIST linux-5.10.12.tar.xz 116262828 BLAKE2B f5e16e92c9543708997d9dfee28feb2cd6e6909a33dc7f97c40b507a8d03bd72717b1af84bed3fa25b2a167652d8cd93b66d145d484e5ad292af24b3bf64a649 SHA512 01062437c9af1654346b5baf550dbefe3cedab18b3d793ee528d1fc27556d5ecc438b6a39a4163acb65434f50516f8c98a3b1be723afbb620680695b909a376e
-DIST linux-5.10.13.tar.sign 991 BLAKE2B 9a6b3d7602a56917bae3c7de7cf24afbce4a0a8e90471da02b87dd7a868898c0553c52e805bf5d0de33c390575582058b60b90154d1ba7e3e8b7810ce75f6c62 SHA512 0dcbc678ae6fb3bd9f71907e7c32c2a60bd1a9d0f6d2106ed50ebd48a59c6a0fccaeea21bb6bc74b390c5674fe4ace7e9d1b44034096f793e9a2f695f5862abd
-DIST linux-5.10.13.tar.xz 116258488 BLAKE2B f2d6f5512c10ced0990d0d0cbc1aa29e5b54b90bff01f16d16093e9c192de9eb0f31e60c9dd51c686ce88c2a1d89a49bedb503af61c91a6a186794fbe71eedde SHA512 e894b9a98d34b0734ad87336530361b712ce60b57e47ea51e0efd66a4446e740b7e2bebc489e41e59523c0cc5f4066f36036eac2c4cfd7d99a63682c24d887be
-DIST linux-5.10.14.tar.sign 991 BLAKE2B 089cabc583b586a4dcd5d9b9eb0f33903a2110e7bbda492edd220e7116533af06d41b40d987d952656f9ab62f62287c7d79c30bd1283f82060781760a8d6cc01 SHA512 7942ce1d976af3dedf453a3b2ba142a9f2ce1d7a97764b69b92c65262625ecc81c5c432b8bbf29eeb406f233a38f419a56dc01765cc8d15b5ddb655aa77d0cb6
-DIST linux-5.10.14.tar.xz 116254224 BLAKE2B 34ba86c15532eff73ed3cd5d34bb125a534776425a98c43ceff187a9f950c4a12afbe35c5e63306150cdeff5d4e43c5094182d6533381661fe6e5ce82aeaed16 SHA512 8e5016bfc7f5c090af6247ddac41cb3f811576bd078b2e145d798be6f214f72ee77bbff09d48d54a0154a9b137166650c88a1d178d50d5901dcaa03bb2c5e6f1
-DIST linux-5.10.15.tar.sign 991 BLAKE2B c95f2580e972f4cd1dca76a1b16fb15e118cc271b9ee8564e242669c975a27ced4c632d5c8d8e202fd1d0681e6a34660ba777550c7940277666dba7c15968701 SHA512 202bff0d8fcf1356e8c6df1805fcc76993c7320771979bb1f692672af5f3047ac2ca6e03e63518120f959e2d04a45f5dadcc23722b301e8372ca9561d04d7b0b
-DIST linux-5.10.15.tar.xz 116262528 BLAKE2B 7cf58513bf2266697843f6d91fbb214268ad511e110a4e2b66bc0db84ecb4df724a7d65f641eee5837f4d88c1371ec8b313ee8aaa1d1f0260709eae2e3af32b3 SHA512 7b2c38920ebfc9c9aea8cb319949f089a374b6604de4fb01dc6957234970d96830761d784c6f94a5f165f5792dfa9d3a6d8691d18147dc05cc0f03c78efbb61a
-DIST linux-5.10.9.tar.sign 989 BLAKE2B 4573f4a502d7b86924051da635af393a0d61628fb88f01d14ec5a8b454974b707f547c60bcf965f73af92e850f496c659847142058e61951065db4e2e40cf8e6 SHA512 0a1700731809dd615a8d692a9be195564d6f0edbf722e72d8fd36cecbe4c3dbbcc26e3a194ab08945445a883d5ef3f491f5358d715537240a430bd750179f5f9
-DIST linux-5.10.9.tar.xz 116619508 BLAKE2B faedb4032fd709d3f0089d706232ec0dcfdf3817223aa910112e6cd58bffea20a3127fee407a465fa3b4db1a54050fabd839809c404492820216fadae70885b9 SHA512 63271212f300a58a5c2826052928aa980994fff6af553f801b0d2a1ae05e3b55788cc46fa26c97f330bab74068a93df58ce768f21fc5edd1481c841b975e56cf
-DIST linux-5.4.80.tar.sign 989 BLAKE2B 7d0fa889c353c83eeb38d4868de3736baf6dd668db2b6660472b85dd6f9fffa83350954da80bd8e6441b54aa15324d68734ca863b0b1980b92a7b3a58073037e SHA512 54b7a124065020a69702fbc4ec82359c728ba32e8cafb7ba083d12974914c8309cc6b33b85769d87f91cbb2583b7c0a20d019d1b3808f32f07dda0ec795e8906
-DIST linux-5.4.80.tar.xz 109626784 BLAKE2B b395b0326162ca6d9b9a59966e641eb1df63dbd402c8287b276c915478819132e201ae68fcbab2fbae353591ff4f38951a643b6a2e1283a551ab8464c21a2abc SHA512 ba400e61ce4e55a8bf391b45df15bb71f43f42de1f2cf2c19468f503b102ec1269589908fa186bfff946baf031ae1531f30ab420605a078439508898e5fdfb37
-DIST linux-5.4.83.tar.sign 989 BLAKE2B 0c1c9737b51eb02747146498475436682fec4d0e97c6e90e840682878eff34aeffa6970eac0ce117ce18bb8ca2e15fc1a9b0bfb83e021b710fa10dd713437c32 SHA512 be2564571dc109611e802d5dfe1d69339d375bb01259d46888c18ef03979401d9943721131c10609a8a07f14cfe0b990e558e15c7d89a2eccc71e86d620cf4c0
-DIST linux-5.4.83.tar.xz 109638356 BLAKE2B 0287ca87cc09702a3ce9c83494a3f49712aab4f805cab560fdee29cecb18f9ef132c9f8352793705b371f0faf60fd24f357448a8323ba1c1a2d0ab832b5bac8d SHA512 0b40ffb66fc5b3f35a0c187ffeea0df3dd90644490298fe78ad1fef210f1c72e4b0c33aafc6b1d0959c915a6a0d3ec57ae8a36f8b28486965a8ef158674b1ec3
-DIST linux-5.4.88.tar.sign 989 BLAKE2B a3757a095bb72f810847a45e0dcb7401ba264317cbe6ca4a6cad5503ae5836d77795ac26f00c3ceb9166e188904dd074fcaab0080c42413115f9849222c0b8ee SHA512 f91fe3552b889a0aabf0678876221bb5cc0632485e279d75fa25008a9f409711db63ffdd782653302e522ff04f4ed2e0b34d0e5d2dd7d8c2265f370740269165
-DIST linux-5.4.88.tar.xz 109644692 BLAKE2B 002e09b5a4571a6967979cc7907cbd7f064ef8bb38045cabd73de09735157798db058ac0150cd53b83fdcf69740ec0a2034868626d028aab24d01b86bb8577c6 SHA512 85cfc22c93c40dce1032a909c7af4f7f26e0b9506469a401f8d9b569de6e3f6fe177dbfe7044fd8a786358fae4b4a1df10a08b3cef3a3e0d541ce4f750511346
-DIST linux-5.4.91.tar.sign 989 BLAKE2B 9eb7b9e7201ce69e6779a501e6f6e4a862cec1606150a55961a238d6031ed4b4f5d75b7b16dc2ddf9c4be0984fee53ad264d4b6f2bee2ef8e4a4740f23ca5846 SHA512 d2fbbff77bfd2f927d62f14a47587894b0de479de25c01aafcb74d3a52928992303600a8435ccc7025f33731e9dfd437842b707603e30a2192f6eff5f043478a
-DIST linux-5.4.91.tar.xz 109653720 BLAKE2B 5b017547953aded31e54a69c2609dfae6e516b50b10d58fe1aeedbbd93652de33aac737a688b284889bf6d0ee2d5d6551eae73a693ddbf45d9d9fdd0663268d1 SHA512 81d02edc9b4ea416e630064904187e981bd607ac9ae795e19935f53bd91a48d0371ba2786693f6c0f26245752113eb8009bcdf7d04664982eb6343584732c22b
-DIST linux-5.4.92.tar.sign 989 BLAKE2B 6140d9b3511b2736d1984390997ac4de59d5b4d760283e52b7024e5d6f243499699b08ee2b6a0297bed052ddb5ad77780dc5c4aa1cca03b8fc6c97f610a5bae3 SHA512 e90ca0faf9e7bd6b76187a2bb0f9edee2aa14fb26c0508cd9e55d90ddd973ae1535a39a143f7d5cd4a8081428de874b09b0fda4c2dfac9e639ede0854fb6d3df
-DIST linux-5.4.92.tar.xz 109644104 BLAKE2B 9808a44f886bb4d3d48a2e622ca6cdd53e8756d2d85135a46abafde9e37fca2448411080b8b1dcb3c0df85fcf40cf409dddf2dcf9140b186cd8b43d1a21a18b4 SHA512 ad61b167001b3119056c316261d76ae1d7ce16562f3c47599da460a0d2860f1f38a581dbdb72fd0f941bc8a0245522b6856893a3be7d7d5b03775521e168b0b9
-DIST linux-5.4.93.tar.sign 989 BLAKE2B 0c689529e483c971526bb20bab3d5a63e63c18a48d773c30c8d7131606d97b5ee5be0df8e83d34b41230e9239ab108d175912585bf482252352074b7cf9e8354 SHA512 5b273851ccf9bab4ae3a840348fa91e817cb46ed2fa6159bf6289c8eb03a3075c3b06cb31da4a8d2ef6a6d3a9048d4738c4bd73c9c35b3c44b4ecbf09868b6d6
-DIST linux-5.4.93.tar.xz 109661584 BLAKE2B 78f0369835ba737fadb4145fab290408c163c74293fbb29d6e7e28eb7a4f505f90786394509ad955d76d68b8ace919cb2d297fa765efece13aaf9c3e4c056db7 SHA512 b60839ae4efe4563396897723e5cf644e9f15f058efc72b7eb3b91ac42a6190863fa9f7023bbff4f1339a6d542555af34fffe7fb278ca7efb0922585ad27922e
+DIST linux-5.10.17.tar.sign 991 BLAKE2B b3b2947df46c96771643ebb2248c83fb81b1ff6bca9191e3ede8e18cf06e5e26ec2c4e179fb1c14026cfddcb110447faeb28fcd7ad93779413353ac8335ef37c SHA512 8abaa8abe2475c0017f755836208c38007c419b832605e81c775d23aa4e23bb20cd5ca88d5a482b331560bb4d940eaf7db3c2a795f77d7b5bb0a39f86130c3a9
+DIST linux-5.10.17.tar.xz 116272648 BLAKE2B 7317e13e6262adf6d69f1192370be8eb2a31054a3626cf20e3e42d4f794f1f1767495c85cc891853a647c246828de31915090706fcdc514c7c563dbd5bbae4bf SHA512 2d8700ceee0c027597415de2b9fa478a651c6f5074b68d60609a4c46398ac5a854f9323fc07b187caca5294759bf99832d7496c4f4cca222240b07435b27bd60
+DIST linux-5.10.18.tar.sign 991 BLAKE2B 2fce16ebaabfa28241ea267bf96c365d044315f7aef281b98153703e86fda15e19d21d89130898a54bb89b61bde7cecaf8ee951ae980ef0bd7d2cd86201d554e SHA512 1e603f79a8783933a078da7d155294ee6cb1490914626c247cd29929a74936297504e1b9967616cbc57bd48da5dae73c26c0a9bab98a5ababb1e689cff0168a4
+DIST linux-5.10.18.tar.xz 116263744 BLAKE2B c633632c8a2c80f238105878c1b4a062ae81e1c7e404b73572c0cb0dd458645cf46c0881cea96668c8cf40a9b12da2d4693e18495f8fee0627ceab87eea34236 SHA512 e9ab577036391692d7237e2d945d8a682afa4bc889f03934db4e1873db26df6404f7ae0cb989986ec64fdb529a3308c6c9c496247596ad43592c1d8fc52e9c46
+DIST linux-5.10.19.tar.sign 991 BLAKE2B 70ee178a74d6c1a779ea399875bb884b52f918e9a8a797fccae7fb26e7eff9eec1a0cc9421e43597d9d477d53d4a26a7fab4afb8f6280a67d48b171829a56bfe SHA512 af99693e0a30d625f346fc682b19bac68247af58574e9a78b2a5478cc0df4a5fca0a2a3ebc3c86f7d5451a6b1f87c0ff524336c4f09b49cfbfb4d21b9776309d
+DIST linux-5.10.19.tar.xz 116276000 BLAKE2B bda18c64b1d7be5cba5d3942386764a778a60b360eb47faeb3f2c84806835d2b325b75a00f5cc3a8a3680e0004ff339caa3a7a301cb6a453e838c92b9f89c3db SHA512 95a9e41d3b23a8b88e2a2ad12e6503efe577b80cff398b51ba7f6ccb0b73768a1cefb2cacb727dd54bd5b5638ad1d5cdabdb23c06aed37d726a59b190de1f2d6
+DIST linux-5.11.2.tar.sign 989 BLAKE2B 404589119de8a0bff3e0feb77a54eb98add568470d4260767830ecb488fec415a0eb79a87eb6b19963b26a78ab8944d4041a38a80dc515f42f14350dcf825fcc SHA512 497f0c06d43cede60cb60816bac0cc22a3c7976bb71bb2f2aedced69c44561b842bae94cf51d5cd0ed506c1eb5b58c038bbf17049176f074cd0e7442eded4fdc
+DIST linux-5.11.2.tar.xz 117609344 BLAKE2B 62f47c769998fa713cda9024a4ecbe7ba2140acde629082630c2c0b076b4e941b0a1e82f7d2b7cd4ed6e84759ea93de78e212ecbe1341d9055091d26d83286dc SHA512 16090ec6dea7a8c417ca7483b296902c9b55b423482ad8a881dffcaae76411806bc9502373efd6a51b0acefec3a44c19c5a7d42c5b76c1321183a4798a5959d3
+DIST linux-5.4.100.tar.sign 991 BLAKE2B f1442b1523de568ed757ab3ba89d571b0c5d85a192718a85ec72736858c0025b09b0d22eee906d4300e41a8f24ab8d56eb0039ba0b46b63b049a16c8cd65153b SHA512 7e7e298917a6167aa9d3a61cd1423c5fad89fad06f66c1ac01277aba7000dcbb1558f978644558cc79b57d70b677016077f0f4cdc3eaa69e39cda75b0d5b18d7
+DIST linux-5.4.100.tar.xz 109081252 BLAKE2B 2647a326c55050c3f0340c2e7ce98761e8bc3d5900c74785eac779295ba6e84d99d65a2ba9ab575fb412bd5caf6db6d25b32ce9b10373cb3879de2cbafd861a0 SHA512 8483e34ac7ac59903d51ef2b5607fa2608a824d0f95548f3c8eeefe9a6b4be3bef44865df68960feacd02ed7bc8dbbb1625f0bb8e6626bbf096c2a0db474998a
+DIST linux-5.4.101.tar.sign 991 BLAKE2B f10908550c9ebe18dcc06839046ea215d5fa91cef48180836c2582a3200852dd005e39ff5ed6b203bc5ffb4098018fe2437d363ae84404370a9f40e8e92d446d SHA512 bcae0baa578b248d21b270106b5ba0b4ea23f383a24086ba04d7433c2df534ddac9f2373383407637cc3a8e81d14e3f5407dababc3b01333bbeafd36101e2f54
+DIST linux-5.4.101.tar.xz 109078848 BLAKE2B 9dd7727655005ba2bf906fbaac86107dbe541cd42878eb3fb96f9731e8196b4e059dbcd772e7c11c620ef784d09ed353f7d92e2388adecc0906d1c71fc8edea3 SHA512 225d5aeb1e0aad9f048cafe94477c8ea5123f26145681b2a2fe24f81dc61694f964b585b6cdc63eaf3898e5feb38159097cb611b9e2e2455de331e6a4875970e
DIST linux-5.4.94.tar.sign 989 BLAKE2B 779a725d0164c98bf2ebc0590af693eebb6fe71837e0f8642b376fb0fa4bc893e8c2b52a16bd0c1cab7aaff4295f6bf31b8fdb7c2d95bd8601eac74925e2211f SHA512 85ec9c16642aac5640d0486ba704b787e2e4156fccdf80f4d538b4d6524c914b64e6ba1d52bdda15b3601faec643d6656fa2cf57976a9afaff5265f9dea840e0
DIST linux-5.4.94.tar.xz 109082512 BLAKE2B fac6683453e41065760cbdd170ea4a5f72778e39807389d2f4c4dd9165dc1727a875ee26e6e440089ec2d8e8b4dca9fa1e1dc02a9b217cada700f9a118ae7613 SHA512 2d9f0feeb9ba6871d31c8a5e281c8e3eed99ce7da3af3be4f222db37f082374f852021a5117a994c8cc37681e5f335329c9e430e7edb835de801c901765a505b
-DIST linux-5.4.95.tar.sign 989 BLAKE2B 527763c6afbf7e02269dbe1c4779c5a5464e428a0fae9f44351aeff301ba629b148497a7beb11f9d53479d33414704a5db9ce2535b027e7beda45aef35dc62c3 SHA512 31104d4db2b30a95df0574bcc7eecc07e579b8bbac378d31b015a00294d3a17569f165d5aaed5ae9231c4e707eaf0b2d0d3c594c046c53daad6be31822d4dcb9
-DIST linux-5.4.95.tar.xz 109065052 BLAKE2B 732c57458e4179cf87c46c7ef80e4afbf445e462d877b29d4111b5a8256a0d88879136f6184361b6d8eb2c623978297d994d4db6e572f56f393a917bdf8f540f SHA512 c6f5b306a8dc844dfff006ecc27879a8e120100bee8b429a143cebafd689403d93d8650dc3d962d4e13e906476c4b43bb32e4f2dbcc3002eee9dd070d63b26f7
-DIST linux-5.4.96.tar.sign 989 BLAKE2B b4641189da90cf6e854d9ff9d5cfa7d6f559f4f5fbd9f795a820a0e3f1a57d56122c2a59a94ebaba5c9e444a5839e9bcb684a4139ff09bb6299ad732c462ce86 SHA512 481673d29883c0f150bc1df483e763152aeba251d742471216710d7af61e4ab0f95f6220dfcda0d267d63a5e7d997e700434d8efe8dd0f39f9dee23335383bda
-DIST linux-5.4.96.tar.xz 109075552 BLAKE2B b6e604030f3d1f14880a38ec65d2169e668a7eeb43f21045fef28be98560a7fcc91189149a3ccbf2500f3d55860ef71351ea1c79cceb940c67beb6b01149c912 SHA512 4f2017c374af9485aaec6fc021cfa22a1f5e635a2fca7ffe5cd535306a93d3ebcb985d30491f7f4e05ce1d91647ff62a41e766a677acfa7f5b0269b808e069c4
DIST linux-5.4.97.tar.sign 989 BLAKE2B 767058a0c491aa1435d5dcd25d5f26ed1dd283cbb903063d00020e2a5e7a2a965b7774df3fe4e5484bb1c76e906e9622057f60420d9dfe31a5305d85b15e2d1e SHA512 09fc4efaf777d12cfeb61e7d24651ca68461c108666be90bf216ee5586cabf47976d60451f8cbdb636ff3f3a4b66b84edfc0255b26d3589f918c22aa394dd76a
DIST linux-5.4.97.tar.xz 109075272 BLAKE2B d8362d202d437953fa7c78a1e7dc3eda31d1fb605b176a92ced0b9d6608c92134fcf1ae8426308f07d5af5cb5fabbee6122cc30bff8abf6a99dc4b5848d3a16c SHA512 fb882d5949ac0cab2910947cc2af3c6f219ff4d8b6941100972caad8133486678a2dfe8af68c9d527a2f55b663a96dabf8c41ea85d941c04934016a0c067eb70
+DIST linux-5.4.99.tar.sign 989 BLAKE2B 92c51f2da875787cc3867319e8e174925443bf43cf07f9dd54d31ba34852e946ae73158db1dc6532c90c3589a3e6bfc27cae42ac22359a2b15999cdf5b3d008f SHA512 5c332cc60d29d615354b1e555dde31e3aaf8846ccc8c4bfe7bc5ebdce20d4a491af367388f1f07feed81f6eaaabb1baf4afc9d995f00541843f2d18eef9c2580
+DIST linux-5.4.99.tar.xz 109078664 BLAKE2B f0a869edf3aa04a2211f039561fa16a419ebde44437c1aca9ac8a7f11ccda240b58eef45c2135a4d7ccd4b7093cf5ce758fba1ed850a653c2debc33f90d4ba91 SHA512 e064ff3c68291c7fb6823499230b3838b5a9471d9e0789ab6eea89ac1cc9c579dc3670dfa3f64cc0c2b68b8027cdb2a239158da73ce7febd600d424eafd6d203
diff --git a/sys-kernel/vanilla-kernel/metadata.xml b/sys-kernel/vanilla-kernel/metadata.xml
index b0b959adbe61..3eca39567e28 100644
--- a/sys-kernel/vanilla-kernel/metadata.xml
+++ b/sys-kernel/vanilla-kernel/metadata.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="project">
- <email>dist-kernel@gentoo.org</email>
- <name>Distribution Kernel Project</name>
- </maintainer>
- <use>
- <flag name='initramfs'>Build initramfs along with the kernel.</flag>
- </use>
-</pkgmetadata>
+ <maintainer type="project">
+ <email>dist-kernel@gentoo.org</email>
+ <name>Distribution Kernel Project</name>
+ </maintainer>
+
+ <use>
+ <flag name="initramfs">Build initramfs along with the kernel.</flag>
+ </use>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.11.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.11.ebuild
deleted file mode 100644
index 51afd5f766b8..000000000000
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.11.ebuild
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build verify-sig
-
-MY_P=linux-${PV}
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.10.7
-CONFIG_HASH=b238267df7cd80dc3aa6b5b654cbe145367383df
-GENTOO_CONFIG_VER=5.10.7
-
-DESCRIPTION="Linux kernel built from vanilla upstream sources"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- verify-sig? (
- https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.sign
- )
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64-fedora.config
- -> kernel-x86_64-fedora.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64-fedora.config
- -> kernel-aarch64-fedora.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le-fedora.config
- -> kernel-ppc64le-fedora.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686-fedora.config
- -> kernel-i686-fedora.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~x86"
-IUSE="debug"
-REQUIRED_USE="
- arm? ( savedconfig )"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )
- verify-sig? ( app-crypt/openpgp-keys-kernel )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/kernel.org.asc
-
-src_unpack() {
- if use verify-sig; then
- einfo "Unpacking linux-${PV}.tar.xz ..."
- verify-sig_verify_detached - "${DISTDIR}"/linux-${PV}.tar.sign \
- < <(xz -cd "${DISTDIR}"/linux-${PV}.tar.xz | tee >(tar -x))
- assert "Unpack failed"
- unpack "gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz"
- else
- default
- fi
-}
-
-src_prepare() {
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- arm)
- return
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le-fedora.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686-fedora.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.12.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.12.ebuild
deleted file mode 100644
index 51afd5f766b8..000000000000
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.12.ebuild
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build verify-sig
-
-MY_P=linux-${PV}
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.10.7
-CONFIG_HASH=b238267df7cd80dc3aa6b5b654cbe145367383df
-GENTOO_CONFIG_VER=5.10.7
-
-DESCRIPTION="Linux kernel built from vanilla upstream sources"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- verify-sig? (
- https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.sign
- )
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64-fedora.config
- -> kernel-x86_64-fedora.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64-fedora.config
- -> kernel-aarch64-fedora.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le-fedora.config
- -> kernel-ppc64le-fedora.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686-fedora.config
- -> kernel-i686-fedora.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~x86"
-IUSE="debug"
-REQUIRED_USE="
- arm? ( savedconfig )"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )
- verify-sig? ( app-crypt/openpgp-keys-kernel )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/kernel.org.asc
-
-src_unpack() {
- if use verify-sig; then
- einfo "Unpacking linux-${PV}.tar.xz ..."
- verify-sig_verify_detached - "${DISTDIR}"/linux-${PV}.tar.sign \
- < <(xz -cd "${DISTDIR}"/linux-${PV}.tar.xz | tee >(tar -x))
- assert "Unpack failed"
- unpack "gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz"
- else
- default
- fi
-}
-
-src_prepare() {
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- arm)
- return
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le-fedora.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686-fedora.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.13.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.17.ebuild
index 04ef5ea94afc..04ef5ea94afc 100644
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.13.ebuild
+++ b/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.17.ebuild
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.15.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.18.ebuild
index 04ef5ea94afc..9fe09baa8621 100644
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.15.ebuild
+++ b/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.18.ebuild
@@ -9,7 +9,7 @@ MY_P=linux-${PV}
# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
CONFIG_VER=5.10.12
CONFIG_HASH=836165dd2dff34e4f2c47ca8f9c803002c1e6530
-GENTOO_CONFIG_VER=5.10.7
+GENTOO_CONFIG_VER=5.10.18
DESCRIPTION="Linux kernel built from vanilla upstream sources"
HOMEPAGE="https://www.kernel.org/"
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.14.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.19.ebuild
index 04ef5ea94afc..9fe09baa8621 100644
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.14.ebuild
+++ b/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.19.ebuild
@@ -9,7 +9,7 @@ MY_P=linux-${PV}
# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
CONFIG_VER=5.10.12
CONFIG_HASH=836165dd2dff34e4f2c47ca8f9c803002c1e6530
-GENTOO_CONFIG_VER=5.10.7
+GENTOO_CONFIG_VER=5.10.18
DESCRIPTION="Linux kernel built from vanilla upstream sources"
HOMEPAGE="https://www.kernel.org/"
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.9.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.9.ebuild
deleted file mode 100644
index 51afd5f766b8..000000000000
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.9.ebuild
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build verify-sig
-
-MY_P=linux-${PV}
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.10.7
-CONFIG_HASH=b238267df7cd80dc3aa6b5b654cbe145367383df
-GENTOO_CONFIG_VER=5.10.7
-
-DESCRIPTION="Linux kernel built from vanilla upstream sources"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- verify-sig? (
- https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.sign
- )
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64-fedora.config
- -> kernel-x86_64-fedora.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64-fedora.config
- -> kernel-aarch64-fedora.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le-fedora.config
- -> kernel-ppc64le-fedora.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686-fedora.config
- -> kernel-i686-fedora.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~x86"
-IUSE="debug"
-REQUIRED_USE="
- arm? ( savedconfig )"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )
- verify-sig? ( app-crypt/openpgp-keys-kernel )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/kernel.org.asc
-
-src_unpack() {
- if use verify-sig; then
- einfo "Unpacking linux-${PV}.tar.xz ..."
- verify-sig_verify_detached - "${DISTDIR}"/linux-${PV}.tar.sign \
- < <(xz -cd "${DISTDIR}"/linux-${PV}.tar.xz | tee >(tar -x))
- assert "Unpack failed"
- unpack "gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz"
- else
- default
- fi
-}
-
-src_prepare() {
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- arm)
- return
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64-fedora.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le-fedora.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686-fedora.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.10.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.11.2.ebuild
index 51afd5f766b8..6faf44c48778 100644
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.10.10.ebuild
+++ b/sys-kernel/vanilla-kernel/vanilla-kernel-5.11.2.ebuild
@@ -7,9 +7,9 @@ inherit kernel-build verify-sig
MY_P=linux-${PV}
# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.10.7
-CONFIG_HASH=b238267df7cd80dc3aa6b5b654cbe145367383df
-GENTOO_CONFIG_VER=5.10.7
+CONFIG_VER=5.11.1
+CONFIG_HASH=07992209452cd7ba529ffdbdd83d01d44cd8ae14
+GENTOO_CONFIG_VER=5.10.18
DESCRIPTION="Linux kernel built from vanilla upstream sources"
HOMEPAGE="https://www.kernel.org/"
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.91.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.100.ebuild
index f8ec23f5913a..f8ec23f5913a 100644
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.91.ebuild
+++ b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.100.ebuild
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.92.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.101.ebuild
index f8ec23f5913a..f8ec23f5913a 100644
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.92.ebuild
+++ b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.101.ebuild
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.80.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.80.ebuild
deleted file mode 100644
index 7f4ea0861252..000000000000
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.80.ebuild
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright 2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build verify-sig
-
-MY_P=linux-${PV}
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.77-r1
-
-DESCRIPTION="Linux kernel built from vanilla upstream sources"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- verify-sig? (
- https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.sign
- )
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm64 ~x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )
- verify-sig? ( app-crypt/openpgp-keys-kernel )"
-
-VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/kernel.org.asc
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- if use verify-sig; then
- einfo "Unpacking linux-${PV}.tar.xz ..."
- verify-sig_verify_detached - "${DISTDIR}"/linux-${PV}.tar.sign \
- < <(xz -cd "${DISTDIR}"/linux-${PV}.tar.xz | tee >(tar -x))
- assert "Unpack failed"
- unpack "gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz"
- else
- default
- fi
-}
-
-src_prepare() {
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.83.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.83.ebuild
deleted file mode 100644
index 7f4ea0861252..000000000000
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.83.ebuild
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright 2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build verify-sig
-
-MY_P=linux-${PV}
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.77-r1
-
-DESCRIPTION="Linux kernel built from vanilla upstream sources"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- verify-sig? (
- https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.sign
- )
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm64 ~x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )
- verify-sig? ( app-crypt/openpgp-keys-kernel )"
-
-VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/kernel.org.asc
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- if use verify-sig; then
- einfo "Unpacking linux-${PV}.tar.xz ..."
- verify-sig_verify_detached - "${DISTDIR}"/linux-${PV}.tar.sign \
- < <(xz -cd "${DISTDIR}"/linux-${PV}.tar.xz | tee >(tar -x))
- assert "Unpack failed"
- unpack "gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz"
- else
- default
- fi
-}
-
-src_prepare() {
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.88.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.88.ebuild
deleted file mode 100644
index af6cbd04ffc6..000000000000
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.88.ebuild
+++ /dev/null
@@ -1,107 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build verify-sig
-
-MY_P=linux-${PV}
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.77-r1
-
-DESCRIPTION="Linux kernel built from vanilla upstream sources"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- verify-sig? (
- https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.sign
- )
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm64 ~x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )
- verify-sig? ( app-crypt/openpgp-keys-kernel )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/kernel.org.asc
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- [[ ${PV} == 5.4.88 ]] || die "Bump GENTOO_CONFIG_VER!"
- if use verify-sig; then
- einfo "Unpacking linux-${PV}.tar.xz ..."
- verify-sig_verify_detached - "${DISTDIR}"/linux-${PV}.tar.sign \
- < <(xz -cd "${DISTDIR}"/linux-${PV}.tar.xz | tee >(tar -x))
- assert "Unpack failed"
- unpack "gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz"
- else
- default
- fi
-}
-
-src_prepare() {
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.95.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.95.ebuild
deleted file mode 100644
index f8ec23f5913a..000000000000
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.95.ebuild
+++ /dev/null
@@ -1,106 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build verify-sig
-
-MY_P=linux-${PV}
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.89
-
-DESCRIPTION="Linux kernel built from vanilla upstream sources"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- verify-sig? (
- https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.sign
- )
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm64 ~x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )
- verify-sig? ( app-crypt/openpgp-keys-kernel )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/kernel.org.asc
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- if use verify-sig; then
- einfo "Unpacking linux-${PV}.tar.xz ..."
- verify-sig_verify_detached - "${DISTDIR}"/linux-${PV}.tar.sign \
- < <(xz -cd "${DISTDIR}"/linux-${PV}.tar.xz | tee >(tar -x))
- assert "Unpack failed"
- unpack "gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz"
- else
- default
- fi
-}
-
-src_prepare() {
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.96.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.96.ebuild
deleted file mode 100644
index f8ec23f5913a..000000000000
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.96.ebuild
+++ /dev/null
@@ -1,106 +0,0 @@
-# Copyright 2020-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-inherit kernel-build verify-sig
-
-MY_P=linux-${PV}
-# https://koji.fedoraproject.org/koji/packageinfo?packageID=8
-CONFIG_VER=5.4.21
-CONFIG_HASH=2809b7faa6a8cb232cd825096c146b7bdc1e08ea
-GENTOO_CONFIG_VER=5.4.89
-
-DESCRIPTION="Linux kernel built from vanilla upstream sources"
-HOMEPAGE="https://www.kernel.org/"
-SRC_URI+=" https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.xz
- https://github.com/mgorny/gentoo-kernel-config/archive/v${GENTOO_CONFIG_VER}.tar.gz
- -> gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz
- verify-sig? (
- https://cdn.kernel.org/pub/linux/kernel/v$(ver_cut 1).x/${MY_P}.tar.sign
- )
- amd64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-x86_64.config
- -> kernel-x86_64.config.${CONFIG_VER}
- )
- arm64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-aarch64.config
- -> kernel-aarch64.config.${CONFIG_VER}
- )
- ppc64? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-ppc64le.config
- -> kernel-ppc64le.config.${CONFIG_VER}
- )
- x86? (
- https://src.fedoraproject.org/rpms/kernel/raw/${CONFIG_HASH}/f/kernel-i686.config
- -> kernel-i686.config.${CONFIG_VER}
- )"
-S=${WORKDIR}/${MY_P}
-
-LICENSE="GPL-2"
-KEYWORDS="~amd64 ~arm64 ~x86"
-IUSE="debug"
-
-RDEPEND="
- !sys-kernel/vanilla-kernel-bin:${SLOT}"
-BDEPEND="
- debug? ( dev-util/dwarves )
- verify-sig? ( app-crypt/openpgp-keys-kernel )"
-PDEPEND="
- >=virtual/dist-kernel-${PV}"
-
-VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/kernel.org.asc
-
-pkg_pretend() {
- ewarn "Starting with 5.4.52, Distribution Kernels are switching from Arch"
- ewarn "Linux configs to Fedora. Please keep a backup kernel just in case."
-
- kernel-install_pkg_pretend
-}
-
-src_unpack() {
- if use verify-sig; then
- einfo "Unpacking linux-${PV}.tar.xz ..."
- verify-sig_verify_detached - "${DISTDIR}"/linux-${PV}.tar.sign \
- < <(xz -cd "${DISTDIR}"/linux-${PV}.tar.xz | tee >(tar -x))
- assert "Unpack failed"
- unpack "gentoo-kernel-config-${GENTOO_CONFIG_VER}.tar.gz"
- else
- default
- fi
-}
-
-src_prepare() {
- default
-
- # prepare the default config
- case ${ARCH} in
- amd64)
- cp "${DISTDIR}/kernel-x86_64.config.${CONFIG_VER}" .config || die
- ;;
- arm64)
- cp "${DISTDIR}/kernel-aarch64.config.${CONFIG_VER}" .config || die
- ;;
- ppc64)
- cp "${DISTDIR}/kernel-ppc64le.config.${CONFIG_VER}" .config || die
- ;;
- x86)
- cp "${DISTDIR}/kernel-i686.config.${CONFIG_VER}" .config || die
- ;;
- *)
- die "Unsupported arch ${ARCH}"
- ;;
- esac
-
- local merge_configs=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/base.config
- )
- use debug || merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/no-debug.config
- )
- [[ ${ARCH} == x86 ]] && merge_configs+=(
- "${WORKDIR}/gentoo-kernel-config-${GENTOO_CONFIG_VER}"/32-bit.config
- )
-
- kernel-build_merge_configs "${merge_configs[@]}"
-}
diff --git a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.93.ebuild b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.99.ebuild
index f8ec23f5913a..f8ec23f5913a 100644
--- a/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.93.ebuild
+++ b/sys-kernel/vanilla-kernel/vanilla-kernel-5.4.99.ebuild
diff --git a/sys-kernel/vanilla-sources/Manifest b/sys-kernel/vanilla-sources/Manifest
index 6e240ad6656d..b769221d80a2 100644
--- a/sys-kernel/vanilla-sources/Manifest
+++ b/sys-kernel/vanilla-sources/Manifest
@@ -3,10 +3,12 @@ DIST linux-4.19.tar.xz 103117552 BLAKE2B 1dbf16cf410867412d17568fe42bc1e90c03418
DIST linux-4.4.tar.xz 87295988 BLAKE2B f260f1858994f5d481fd078c86e51bddbc958f7c5d1586f60dced772e1b1107ecf3aae0558c3e6f39c36f7d3aa1e6cd1e5c64ec9d6f2218f47b98413da6466fb SHA512 13c8459933a8b80608e226a1398e3d1848352ace84bcfb7e6a4a33cb230bbe1ab719d4b58e067283df91ce5311be6d2d595fc8c19e2ae6ecc652499415614b3e
DIST linux-4.9.tar.xz 93192404 BLAKE2B 83ae310b17d47f1f18d6d28537c31e10f3e60458c5954c4611158ca99e71cc0da2e051272eabf27d5887df4a7cb4a5dd66ff993077c11d2221e92d300a0b48d7 SHA512 bf67ff812cc3cb7e5059e82cc5db0d9a7c5637f7ed9a42e4730c715bf7047c81ed3a571225f92a33ef0b6d65f35595bc32d773356646df2627da55e9bc7f1f1a
DIST linux-5.10.tar.xz 116606704 BLAKE2B b923d7b66309224f42f35f8a5fa219421b0a9362d2adacdadd8d96251f61f7230878ea297a269a7f3b3c56830f0b177e068691e1d7f88501a05653b0a13274d1 SHA512 95bc137d0cf9148da6a9d1f1a878698dc27b40f68e22c597544010a6c591ce1b256f083489d3ff45ff77753289b535135590194d88ef9f007d0ddab3d74de70e
+DIST linux-5.11.tar.xz 117619104 BLAKE2B 81300c27bd5476387a83123aaeb4163c73eb61e9245806c23660cb5e6a4fa88ffc9def027031335fa0270fc4080506cd415990014364e3a98b9d2e8c58a29524 SHA512 a567ec133018bb5ec00c60281479b466c26e02137a93a9c690e83997947df02b6fd94e76e8df748f6d70ceb58a19bacc3b1467de10b7a1fad2763db32b3f1330
DIST linux-5.4.tar.xz 109441440 BLAKE2B 193bc4a3147e147d5529956164ec4912fad5d5c6fb07f909ff1056e57235834173194afc686993ccd785c1ff15804de0961b625f3008cca0e27493efc8f27b13 SHA512 9f60f77e8ab972b9438ac648bed17551c8491d6585a5e85f694b2eaa4c623fbc61eb18419b2656b6795eac5deec0edaa04547fc6723fbda52256bd7f3486898f
-DIST patch-4.14.221.xz 4125144 BLAKE2B 474f8791e2b59f1524681e70300d5a9543a4b56fb7affbd02a22d67d4df2632c7aa37a73d032697b3b10291671efd96f5eaf13c4632c05801a4a7cac99a4c219 SHA512 fd332b076ac0231ea4b3806bd6cb58f0b66bd9317ae352fb6f90856e92df5cc96d2c89bc8c44001f2f34ea98b43fbbe8b8eae0abe2249fe561b8dd4a2c76bcb5
-DIST patch-4.19.175.xz 3773632 BLAKE2B c292411aba5dc44ec66b3d27c27740437d22e78c361a31b043bc943ea40853106057084e9723e82f5f7d1f07f4d1714ba4ff4d7508f5ea556ab93f2572c4a27f SHA512 cf0fd3d6d6bef17f4d03a9f0929e7038814ba2754a59f0bdb4ee9d91c559ee6a04bf5ddc46ed4c1c03a0d7d17b802a66426c01098db8a25d716ba39e6baaad20
-DIST patch-4.4.257.xz 3458668 BLAKE2B 3de9cb1b83b0a846b5c6ef1471d0e1dee1d355db2fc1383a0e9272c4b47675685f2c0dd46c08f8f4dc5d5e8e3c499f8c1e25aeb71d20af29f822a009e1cc0c2e SHA512 a27d8c8fc81026b18d8954efb1f54f6dd05244f384248711e845877bf3ba0b48c7d09946b8572f95fb6065b7d89f833b040544e41fae13ebfc7fb99622d54bb8
-DIST patch-4.9.257.xz 3854704 BLAKE2B acd4beafa60bb61de1f73d3a31f4143102d56e9918ef5ebfc1040d096e70a92353014e4978d58f2cd7b4c11d15d430700417e63f17bd7d3d5110ef1ac26d9c53 SHA512 ff50eb605da6367724999fc059627954bd79da7272ad46870a25e60876d1e6b805c79821059b4cbfb9d2251e16f65a58fc39ea2262a0caad913536049f42136a
-DIST patch-5.10.15.xz 486748 BLAKE2B da5b708b6f3a1d4b20156e82d47c96d027d535464118ea20556d7bd09f3995ab02bb5d67eb1c858bae2343bb42c0fe0c45d6690b50b2b7d199f63e7b4515c9f7 SHA512 624123b4333783633d6fa417ab5fa8cbf85e56dda122487c8314b7ec37da74eb3dadded9a3d3dbda80d3c4cc734e516316f43222c85a820df1c549df8d70baad
-DIST patch-5.4.97.xz 2601604 BLAKE2B a8308677364597f9e6b12ed14639fa0774cf2e28c985b6d634caec4572d9efb835fa5234f27c13aa4a74dda03934c9003f5cd8fb4c6cd86686c515548446b513 SHA512 d32b99572006ade1eeb377c99c7b1879af08a9c177870e7548bc45f10d5c1486a50f3b50fa53decad4e58d0321c30288259e8597f0baaf95ad1537f693b677f6
+DIST patch-4.14.222.xz 4135176 BLAKE2B cf01385fa64d7541262dab01d9e75d48bb233720e7fdb4d1c00d368d16e1d07641ae9f401845c69d2965bd1eb552e1c65aea013f383dbe448f1f1ca066776a5b SHA512 ed87d0c31ceda7dff71566c7692b8ae1ba8434708024432e89a6e7ade1c90d9580034ba8fa0033849a48d20c77452c827a93b82079425a442d132af58527c1f1
+DIST patch-4.19.177.xz 3786940 BLAKE2B 2bea68978459d98cca861e33de58103d3060be5f7641c4d2d5f35868c9d395d2fbe6b76a855b01dffd2e5a812a9db11762287a55478a5c55e7bb4e5564bfd43f SHA512 e3de5d3e9547b223212a6eb38d57f69ff815fd50002544783208fb8cec9b32d716e60c2cf010f2e90672aa9f9dfd2391bcd5364de7b7c5371b8520dc5c1b2b23
+DIST patch-4.4.258.xz 3466684 BLAKE2B 0416e17a0d9233808ea244132b3ebcfcaba2eafe60070791ee5baf770595c34fea3a1e586dcba878a99522782991e3c5c6dfc3d037722f38e26470fe9fd6ec95 SHA512 61f49862b5a906c4ca67d5aeaa3cc7e86cac8d10a4f984d5ebbb0b3514a230e74ce2fcb8a384acdff7909e1757ca2422c6546a259d366c15c6ca843d23721bc7
+DIST patch-4.9.258.xz 3866012 BLAKE2B 5a17dbfc120698feb2300d6cb06f487c1594a63c76d396e662119ca5f33fd0e6a02b2c9134d223831c19ea0dc5ee20f09c4e113e43c4918bbc31833e1f81f01d SHA512 46bb41de8cee0e037890a68e995500029b6c53f78294265bdaf56290551977af1cf85d673b19c068d1c9b04a3859e241a74ead808965bef2b7998da8d3e0a89b
+DIST patch-5.10.19.xz 535612 BLAKE2B f64a1988f9daec87ad09aeb5df2ddd5ddfa0ab80b0be14e3f1085e54ac1183dc311fcfe202bce1aea9669121e2b4d92400c6ca5d684ce0e5da22b4170a2342ad SHA512 9637f8dac379ffa6d376afcce8da87250eb48a6a2ffac0e5732884cca2cc2f0a85811fc326f006d2d297680ff7dcf726665360d9c7d5d34307bc3e7169ce6a7a
+DIST patch-5.11.2.xz 8160 BLAKE2B 15c4ccf0a72bc3cf274d88d0e3e1dce45181de55a8464a2d9611e81f85638316c3b4b47202f5344897ea7e1ebd0ac5688c372ca04b625b8500724082eef65307 SHA512 32a89fc1b755249c30a263193d638983c83808a7481380567ff08a0b84df01465501f4c664b8dd5b6f1cb2525a089a0a6f5cf2fb994ee5e250210aa9cda57ced
+DIST patch-5.4.101.xz 2624564 BLAKE2B 840449f0d0e00b09b91c558f8fa384ad7fd6c3c1f0e7f57289586b98c6daa32fc9154469c7a2773e815fd2da6b3be93d8f4fffcecf08ebb0a728f0fd638dbfec SHA512 20b573c539c970c39eb63f3b97331e696436ceb19bf23649e84d6e936cb29bc459613aab0a4e7a78e29809764b34bbfd14869a19add0bfc5b0a1d6e47dec7f97
diff --git a/sys-kernel/vanilla-sources/metadata.xml b/sys-kernel/vanilla-sources/metadata.xml
index 01c0b537dc0d..f14a76b87698 100644
--- a/sys-kernel/vanilla-sources/metadata.xml
+++ b/sys-kernel/vanilla-sources/metadata.xml
@@ -1,16 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="project">
- <email>kernel@gentoo.org</email>
- <name>Gentoo kernel team</name>
- </maintainer>
- <maintainer type="person">
- <email>ago@gentoo.org</email>
- <name>Agostino Sarubbo</name>
- <description>CC/Assign to me the version bump request</description>
- </maintainer>
- <upstream>
- <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
- </upstream>
-</pkgmetadata>
+ <maintainer type="project">
+ <email>kernel@gentoo.org</email>
+ <name>Gentoo kernel team</name>
+ </maintainer>
+ <maintainer type="person">
+ <email>ago@gentoo.org</email>
+ <name>Agostino Sarubbo</name>
+ <description>CC/Assign to me the version bump request</description>
+ </maintainer>
+ <upstream>
+ <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
+ </upstream>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/vanilla-sources/vanilla-sources-4.14.221.ebuild b/sys-kernel/vanilla-sources/vanilla-sources-4.14.222.ebuild
index 7083facc514b..7083facc514b 100644
--- a/sys-kernel/vanilla-sources/vanilla-sources-4.14.221.ebuild
+++ b/sys-kernel/vanilla-sources/vanilla-sources-4.14.222.ebuild
diff --git a/sys-kernel/vanilla-sources/vanilla-sources-4.19.175.ebuild b/sys-kernel/vanilla-sources/vanilla-sources-4.19.177.ebuild
index 7083facc514b..7083facc514b 100644
--- a/sys-kernel/vanilla-sources/vanilla-sources-4.19.175.ebuild
+++ b/sys-kernel/vanilla-sources/vanilla-sources-4.19.177.ebuild
diff --git a/sys-kernel/vanilla-sources/vanilla-sources-4.4.257.ebuild b/sys-kernel/vanilla-sources/vanilla-sources-4.4.258.ebuild
index 7083facc514b..7083facc514b 100644
--- a/sys-kernel/vanilla-sources/vanilla-sources-4.4.257.ebuild
+++ b/sys-kernel/vanilla-sources/vanilla-sources-4.4.258.ebuild
diff --git a/sys-kernel/vanilla-sources/vanilla-sources-4.9.257.ebuild b/sys-kernel/vanilla-sources/vanilla-sources-4.9.258.ebuild
index 7083facc514b..7083facc514b 100644
--- a/sys-kernel/vanilla-sources/vanilla-sources-4.9.257.ebuild
+++ b/sys-kernel/vanilla-sources/vanilla-sources-4.9.258.ebuild
diff --git a/sys-kernel/vanilla-sources/vanilla-sources-5.10.15.ebuild b/sys-kernel/vanilla-sources/vanilla-sources-5.10.19.ebuild
index 7083facc514b..7083facc514b 100644
--- a/sys-kernel/vanilla-sources/vanilla-sources-5.10.15.ebuild
+++ b/sys-kernel/vanilla-sources/vanilla-sources-5.10.19.ebuild
diff --git a/sys-kernel/vanilla-sources/vanilla-sources-5.4.97.ebuild b/sys-kernel/vanilla-sources/vanilla-sources-5.11.2.ebuild
index 7083facc514b..7083facc514b 100644
--- a/sys-kernel/vanilla-sources/vanilla-sources-5.4.97.ebuild
+++ b/sys-kernel/vanilla-sources/vanilla-sources-5.11.2.ebuild
diff --git a/sys-kernel/vanilla-sources/vanilla-sources-5.4.101.ebuild b/sys-kernel/vanilla-sources/vanilla-sources-5.4.101.ebuild
new file mode 100644
index 000000000000..7083facc514b
--- /dev/null
+++ b/sys-kernel/vanilla-sources/vanilla-sources-5.4.101.ebuild
@@ -0,0 +1,16 @@
+# Copyright 1999-2021 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="6"
+K_NOUSENAME="yes"
+K_NOSETEXTRAVERSION="yes"
+K_SECURITY_UNSUPPORTED="1"
+ETYPE="sources"
+inherit kernel-2
+detect_version
+
+DESCRIPTION="Full sources for the Linux kernel"
+HOMEPAGE="https://www.kernel.org"
+SRC_URI="${KERNEL_URI}"
+
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
diff --git a/sys-kernel/zen-sources/Manifest b/sys-kernel/zen-sources/Manifest
index a99496add2bf..89f8fd35cd62 100644
--- a/sys-kernel/zen-sources/Manifest
+++ b/sys-kernel/zen-sources/Manifest
@@ -1,5 +1,8 @@
DIST genpatches-5.10-1.base.tar.xz 3840 BLAKE2B 08ac1f83dc9a1cfc1d4cf0a3a5ab4c9d4686a80348247ec7cd1da6e49db92d6932a1864113f2631d5528a4ba732945b2afe73d03061bd3c532b3d1e4d9571999 SHA512 04356093c4df6a7ee0876b89be5b90f8bc90c920628e5fe69b5787ce82e003be05eaac142310f10f32d0549a6676af846734ae4ac188c2b96c2eca2cb0a6f4b0
DIST genpatches-5.10-1.extras.tar.xz 1768 BLAKE2B e99d5d2137d5752845ba8284a0dd57620851c3620603e871973af5841b54e9bfdde92ea2408ddedb55355f2c954c80641b06098060043916d2483e10cfb8293a SHA512 0034e5ab57cccb2e969a3b9e1f674614ca853779c552c37be9c5afb0a37112bf8f2c30e1b21832d56320c70c1d622081b60369c6a86fa737a23c3ed953267453
+DIST genpatches-5.11-1.base.tar.xz 3440 BLAKE2B eb1e9a9f2060023cb410bf3db8c4f4fe283eff47f545a434dfc1edb98aa513940f30a2a88566422192b79f7ab36c607b9bc63253c067070d9a479d6318fd34b3 SHA512 a862fe33272bb6b0e4095c862c74361f015fc57316b9dbbdf2782f2e57c131fbe7fe9b9ba81c3d5a7d71788f2d56abdbd28f1c7571973c3f378cd05199c0421f
+DIST genpatches-5.11-1.extras.tar.xz 1772 BLAKE2B e6f8eae67db54099424f33e17bbfa66d36ae44c98d5f58969634a709a4b949a675a7ec1053eab4db4f745513d9730b68439ecf888e92f0fc9ef369822b39a388 SHA512 cf9d0ee27618b1b49322cefda8d85f66fd94820b9902948c8dd9a33d4e14acf511e7aabf611df5e070a4011e06d80164a512d124f5686b5b16fd81409098d8eb
DIST linux-5.10.tar.xz 116606704 BLAKE2B b923d7b66309224f42f35f8a5fa219421b0a9362d2adacdadd8d96251f61f7230878ea297a269a7f3b3c56830f0b177e068691e1d7f88501a05653b0a13274d1 SHA512 95bc137d0cf9148da6a9d1f1a878698dc27b40f68e22c597544010a6c591ce1b256f083489d3ff45ff77753289b535135590194d88ef9f007d0ddab3d74de70e
-DIST v5.10.10-zen1.patch.xz 538040 BLAKE2B 2c0ceaebd78107adf1f062a866a6ecb7cc7defcf7eb00ac9287974a6417da2431100c5bc3b23ee4ad47a2478c31c5843de32b73b64ab7928c8df019aec2fb77f SHA512 ee719511e43fa0c799a8b342254125f10cf88fd32999d63d8eb904e76b45d53af22722dd14fd3c36556713a39569266d69551278939b752580360c52ea6a3750
-DIST v5.10.6-zen1.patch.xz 387460 BLAKE2B 0e42109335d0c8d7344b8afc3addbe20c92952eea536df4db0152607dcc97d7de142124f9cb0c22c52af01bd6c117cdc69c51f36725c0f2ab2d51165a2390a28 SHA512 3ba03f703521083e629911ebf980545daa34d73aba30aed8e7355eb315d89728f322df0a3791663fa5fbe398bbd1d10951518d81126e077cf50c9fa1d34563dd
+DIST linux-5.11.tar.xz 117619104 BLAKE2B 81300c27bd5476387a83123aaeb4163c73eb61e9245806c23660cb5e6a4fa88ffc9def027031335fa0270fc4080506cd415990014364e3a98b9d2e8c58a29524 SHA512 a567ec133018bb5ec00c60281479b466c26e02137a93a9c690e83997947df02b6fd94e76e8df748f6d70ceb58a19bacc3b1467de10b7a1fad2763db32b3f1330
+DIST v5.10.16-zen1.patch.xz 702476 BLAKE2B 3aff93587e1607cfe241f81ba9f2cd00f8bdbf1f42850040afe8ed3c7b95fd5d578256f9e41f1921d105399dc88b575472b66d6434b55bb44e7f987c09742417 SHA512 6dde0849fdb9181d62fe547eb1bfd48d2577c0c795ab22c7a298a441f7da8d8e948ca081ec9a080a19222e4ae6a0a461a19109632ea96a9c224481b776652e20
+DIST v5.11-zen2.patch.xz 88440 BLAKE2B efe9997086c9af9e752113873b91caa1a1fedc826b2e7c09ffc00e153a708ad6d3db0c2e4a3f407d43162f90d1773cc4a2d98373bd8506d2450603c8777e1bb5 SHA512 4671fec5857696caec8f7dd1f65b01db1a69b27cbf87e807ef57e6c5473497ca8327f35c3a53312d2443c43448755656664b6fe6af1324974135206899ec81ce
diff --git a/sys-kernel/zen-sources/metadata.xml b/sys-kernel/zen-sources/metadata.xml
index 3c75f3aa2ec0..e7df5e32c912 100644
--- a/sys-kernel/zen-sources/metadata.xml
+++ b/sys-kernel/zen-sources/metadata.xml
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<!DOCTYPE pkgmetadata SYSTEM "https://liguros.gitlab.io/dtd/metadata.dtd">
<pkgmetadata>
- <maintainer type="person">
- <email>anarchy@gentoo.org</email>
- <name>Jory A. Pratt</name>
- </maintainer>
-<upstream>
- <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
- <remote-id type="github">zen-kernel/zen-kernel</remote-id>
-</upstream>
-</pkgmetadata>
+ <maintainer type="person">
+ <email>anarchy@gentoo.org</email>
+ <name>Jory A. Pratt</name>
+ </maintainer>
+ <upstream>
+ <remote-id type="cpe">cpe:/o:linux:linux_kernel</remote-id>
+ <remote-id type="github">zen-kernel/zen-kernel</remote-id>
+ </upstream>
+ <origin>gentoo-staging</origin>
+</pkgmetadata> \ No newline at end of file
diff --git a/sys-kernel/zen-sources/zen-sources-5.10.10.ebuild b/sys-kernel/zen-sources/zen-sources-5.10.16.ebuild
index ef149d6a6a93..ef149d6a6a93 100644
--- a/sys-kernel/zen-sources/zen-sources-5.10.10.ebuild
+++ b/sys-kernel/zen-sources/zen-sources-5.10.16.ebuild
diff --git a/sys-kernel/zen-sources/zen-sources-5.10.6.ebuild b/sys-kernel/zen-sources/zen-sources-5.11.ebuild
index ef149d6a6a93..d8686b02d3fa 100644
--- a/sys-kernel/zen-sources/zen-sources-5.10.6.ebuild
+++ b/sys-kernel/zen-sources/zen-sources-5.11.ebuild
@@ -18,10 +18,10 @@ IUSE=""
DESCRIPTION="The Zen Kernel Live Sources"
-ZEN_URI="https://github.com/zen-kernel/zen-kernel/releases/download/v${PV}-zen1/v${PV}-zen1.patch.xz"
+ZEN_URI="https://github.com/zen-kernel/zen-kernel/releases/download/v${PV}-zen2/v${PV}-zen2.patch.xz"
SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI} ${ZEN_URI}"
-UNIPATCH_LIST="${DISTDIR}/v${PV}-zen1.patch.xz"
+UNIPATCH_LIST="${DISTDIR}/v${PV}-zen2.patch.xz"
UNIPATCH_STRICTORDER="yes"
K_EXTRAEINFO="For more info on zen-sources, and for how to report problems, see: \