diff --git a/0005-haoc-kernel.patch b/0005-haoc-kernel.patch index 2d9484f6784efa313c25d75496164788062bdbca..0fd12b41a3785fa74ba931ed772f5a97b340f5f0 100644 --- a/0005-haoc-kernel.patch +++ b/0005-haoc-kernel.patch @@ -1,238 +1,24 @@ -From 099672494b5fbd626031f313bbdbc42d1eb3f02d Mon Sep 17 00:00:00 2001 -From: liuzh -Date: Wed, 22 May 2024 16:36:55 +0800 -Subject: [PATCH] Squashed commit of the following: - -commit 909ad06b3bf629d9af4e143347c1d1ef8a3a5808 -Author: liuzh -Date: Wed May 22 16:23:13 2024 +0800 - - fix mte_sync_tags() parameters after rebase to 6.6.0-27.0.0. - -commit 1cbf51371b0539a45f816419b2da82cf36162b4a -Author: ljl -Date: Mon Mar 25 08:01:32 2024 +0000 - - IEE SI: Removed redundant codes. - -commit 0178bfc79ad1769a36f4165348a671d2182cff55 -Author: zhangsy -Date: Mon Mar 25 11:01:11 2024 +0800 - - Fix bugs on qemu when opening CONFIG_CREDP. - -commit 8e714f6e8f2ace5a6fc900b4bce6b03c83c41870 -Author: ljl -Date: Thu Mar 21 04:44:26 2024 +0000 - - IEE SI: Remove PAN operations as BTLB BUG is already fixed. - -commit 7b5fc74cb99e377d3bc59da81612cd6f3dd8a4d8 -Author: ljl -Date: Wed Mar 20 18:31:47 2024 +0800 - - IEE SI: Migration of iee rwx gate. - -commit aad2c7e89c9c4ad8ff0fb3ee53cd1b974144a283 -Author: liuzh -Date: Mon Mar 18 15:32:43 2024 +0800 - - modify slub.c set_track_prepare() - -commit 7452bac06ec09bf8321dfdbfb8b6a429d2cd8637 -Author: zhangsy -Date: Thu Mar 21 11:26:19 2024 +0800 - - Set pgd of lm Privileged. - -commit 33934cfc3eed798a3a687bf86c6bd92697e68ba9 -Author: zhangsy -Date: Tue Mar 19 17:14:32 2024 +0800 - - Delete some redundant code and put trans_pgd into IEE. - -commit 2bfe9008a72f8b8ac237bc7a5f99f9d40e84c247 -Author: zhangshiyang17@mails.ucas.ac.cn -Date: Mon Mar 18 11:47:50 2024 +0000 - - Fix bugs on physical when opening CONFIG_IEE and CONFIG_PTP. - -commit dafa2df600757511ce3e8f178e05e28adabdf39b -Author: zhangsy -Date: Mon Mar 18 10:40:42 2024 +0800 - - Fix bugs on qemu when opening CONFIG_IEE and CONFIG_PTP. - -commit 9231a9f6b34c62090b5f202c9c64a52bfdac7a73 -Author: zhangsy -Date: Thu Mar 14 16:34:53 2024 +0800 - - Fix compiling bugs of CONFIG_PTP. - -commit 6469df3bcce32896c2cb297d3cd7ead82c33f35d -Author: zhangsy -Date: Thu Mar 14 11:10:00 2024 +0800 - - Fix bugs on qemu when opening CONFIG_IEE and CONFIG_INTERRUPTABLE. - -commit 5f1773dada622a3514c9ed6aa72dd50e918f2664 -Author: zhangsy -Date: Wed Mar 13 17:31:39 2024 +0800 - - Fix bugs on qemu when opening CONFIG_IEE. - -commit 73f433a093fa84cffa5e11e86bed6f17c9b30a39 -Author: liuzh -Date: Tue Mar 12 15:32:29 2024 +0800 - - fix the map of IEE_SI_TEXT. - -commit 9b92deb4b2338093d9b04f4b81f162855b31c983 -Author: liuzh -Date: Sun Mar 10 16:11:13 2024 +0800 - - modified to be able to compile. - can start the kernel with qemu and successfully reach `start_kernel()`. - -commit e892ec4790d72e9433b48b0221e7e6dc4c361dd9 -Author: liuzh -Date: Thu Mar 7 14:27:45 2024 +0800 - - fix some conflicts - -commit fdec7e39345e81e867e01258487f88801b790b02 -Author: liuzh -Date: Wed Mar 6 12:31:11 2024 +0800 - - migrate openeuler-commit code. (need some fix before compiling) ---- - Makefile | 3 +- - arch/arm64/Kconfig | 18 + - arch/arm64/include/asm/assembler.h | 67 + - arch/arm64/include/asm/daifflags.h | 16 + - arch/arm64/include/asm/efi.h | 4 + - arch/arm64/include/asm/fixmap.h | 3 + - arch/arm64/include/asm/hw_breakpoint.h | 12 + - arch/arm64/include/asm/iee-access.h | 36 + - arch/arm64/include/asm/iee-cred.h | 150 ++ - arch/arm64/include/asm/iee-def.h | 74 + - arch/arm64/include/asm/iee-si.h | 64 + - arch/arm64/include/asm/iee-slab.h | 23 + - arch/arm64/include/asm/iee-token.h | 40 + - arch/arm64/include/asm/iee.h | 10 + - arch/arm64/include/asm/kernel-pgtable.h | 21 + - arch/arm64/include/asm/koi.h | 335 +++++ - arch/arm64/include/asm/memory.h | 24 + - arch/arm64/include/asm/mmu_context.h | 20 + - arch/arm64/include/asm/pgalloc.h | 4 + - arch/arm64/include/asm/pgtable-hwdef.h | 11 + - arch/arm64/include/asm/pgtable.h | 304 +++- - arch/arm64/include/asm/pointer_auth.h | 5 + - arch/arm64/include/asm/sysreg.h | 58 + - arch/arm64/include/asm/tlb.h | 9 + - arch/arm64/include/asm/tlbflush.h | 58 +- - arch/arm64/kernel/Makefile | 2 + - arch/arm64/kernel/armv8_deprecated.c | 16 + - arch/arm64/kernel/asm-offsets.c | 11 + - arch/arm64/kernel/cpu_errata.c | 12 + - arch/arm64/kernel/cpufeature.c | 79 + - arch/arm64/kernel/debug-monitors.c | 4 + - arch/arm64/kernel/entry-common.c | 4 + - arch/arm64/kernel/entry.S | 611 ++++++++ - arch/arm64/kernel/fpsimd.c | 4 + - arch/arm64/kernel/head.S | 56 + - arch/arm64/kernel/hibernate.c | 14 + - arch/arm64/kernel/hw_breakpoint.c | 99 ++ - arch/arm64/kernel/iee/Makefile | 1 + - arch/arm64/kernel/iee/iee-func.c | 187 +++ - arch/arm64/kernel/iee/iee-gate.S | 174 +++ - arch/arm64/kernel/iee/iee.c | 1360 +++++++++++++++++ - arch/arm64/kernel/koi/Makefile | 1 + - arch/arm64/kernel/koi/koi.c | 1327 +++++++++++++++++ - arch/arm64/kernel/mte.c | 5 + - arch/arm64/kernel/process.c | 19 +- - arch/arm64/kernel/proton-pack.c | 8 + - arch/arm64/kernel/setup.c | 33 + - arch/arm64/kernel/traps.c | 26 + - arch/arm64/kernel/vmlinux.lds.S | 61 + - arch/arm64/mm/context.c | 91 +- - arch/arm64/mm/fault.c | 9 + - arch/arm64/mm/fixmap.c | 74 +- - arch/arm64/mm/init.c | 34 + - arch/arm64/mm/mmu.c | 1780 +++++++++++++++++++---- - arch/arm64/mm/pgd.c | 39 + - arch/arm64/mm/proc.S | 28 + - arch/arm64/mm/trans_pgd.c | 46 + - drivers/firmware/efi/arm-runtime.c | 4 + - drivers/firmware/efi/memmap.c | 20 + - drivers/tty/serial/earlycon.c | 4 + - drivers/usb/early/ehci-dbgp.c | 4 + - fs/coredump.c | 8 + - fs/exec.c | 20 + - fs/nfs/flexfilelayout/flexfilelayout.c | 9 + - fs/nfs/nfs4idmap.c | 9 + - fs/nfsd/auth.c | 38 + - fs/nfsd/nfs4callback.c | 12 +- - fs/nfsd/nfs4recover.c | 9 + - fs/nfsd/nfsfh.c | 9 + - fs/open.c | 26 + - fs/overlayfs/dir.c | 9 + - fs/overlayfs/super.c | 12 + - fs/smb/client/cifs_spnego.c | 9 + - fs/smb/client/cifsacl.c | 9 + - include/asm-generic/early_ioremap.h | 3 + - include/asm-generic/fixmap.h | 18 + - include/asm-generic/pgalloc.h | 54 + - include/asm-generic/vmlinux.lds.h | 24 +- - include/linux/cred.h | 45 +- - include/linux/efi.h | 9 + - include/linux/iee-func.h | 27 + - include/linux/module.h | 1 + - include/linux/sched.h | 19 + - init/main.c | 28 +- - kernel/cred.c | 182 +++ - kernel/exit.c | 8 + - kernel/fork.c | 316 ++-- - kernel/groups.c | 7 + - kernel/kthread.c | 13 + - kernel/smpboot.c | 9 + - kernel/sys.c | 107 ++ - kernel/umh.c | 10 + - kernel/user_namespace.c | 18 + - mm/Kconfig | 12 + - mm/damon/ops-common.c | 1 + - mm/debug_vm_pgtable.c | 24 + - mm/early_ioremap.c | 57 + - mm/huge_memory.c | 30 +- - mm/init-mm.c | 17 + - mm/memory.c | 14 + - mm/slub.c | 198 ++- - mm/sparse-vmemmap.c | 21 + - mm/vmalloc.c | 2 +- - net/dns_resolver/dns_key.c | 9 + - security/commoncap.c | 169 +++ - security/keys/keyctl.c | 23 + - security/keys/process_keys.c | 53 + - security/security.c | 15 + - 109 files changed, 8945 insertions(+), 397 deletions(-) - create mode 100644 arch/arm64/include/asm/iee-access.h - create mode 100644 arch/arm64/include/asm/iee-cred.h - create mode 100644 arch/arm64/include/asm/iee-def.h - create mode 100644 arch/arm64/include/asm/iee-si.h - create mode 100644 arch/arm64/include/asm/iee-slab.h - create mode 100644 arch/arm64/include/asm/iee-token.h - create mode 100644 arch/arm64/include/asm/iee.h - create mode 100644 arch/arm64/include/asm/koi.h - create mode 100644 arch/arm64/kernel/iee/Makefile - create mode 100644 arch/arm64/kernel/iee/iee-func.c - create mode 100644 arch/arm64/kernel/iee/iee-gate.S - create mode 100644 arch/arm64/kernel/iee/iee.c - create mode 100644 arch/arm64/kernel/koi/Makefile - create mode 100644 arch/arm64/kernel/koi/koi.c - create mode 100644 include/linux/iee-func.h - +diff --git a/.gitignore b/.gitignore +index d1a8ab3f98aa..f87d7b8380ab 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -51,6 +51,7 @@ + *.tar + *.xz + *.zst ++*.log + Module.symvers + modules.order + +@@ -169,3 +170,6 @@ sphinx_*/ + + # Rust analyzer configuration + /rust-project.json ++ ++#command ++command.txt diff --git a/Makefile b/Makefile -index 8e6d9b894b1e..20c367b5957d 100644 +index ee377cec01f3..d36eeeb0c9a8 100644 --- a/Makefile +++ b/Makefile @@ -554,7 +554,7 @@ LINUXINCLUDE := \ @@ -244,19 +30,20 @@ index 8e6d9b894b1e..20c367b5957d 100644 KBUILD_CFLAGS := KBUILD_CFLAGS += -std=gnu11 -@@ -563,6 +563,7 @@ KBUILD_CFLAGS += -funsigned-char +@@ -563,6 +563,8 @@ KBUILD_CFLAGS += -funsigned-char KBUILD_CFLAGS += -fno-common KBUILD_CFLAGS += -fno-PIE KBUILD_CFLAGS += -fno-strict-aliasing +KBUILD_CFLAGS += -march=armv8.1-a ++#KBUILD_CFLAGS += -fPIC KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_RUSTFLAGS := $(rust_common_flags) \ diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig -index 2a875546bdc7..7448afc90c0a 100644 +index 501ec560a939..ae30b4c5d549 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig -@@ -1730,6 +1730,24 @@ config UNMAP_KERNEL_AT_EL0 +@@ -1731,6 +1731,41 @@ config UNMAP_KERNEL_AT_EL0 If unsure, say Y. @@ -277,10 +64,67 @@ index 2a875546bdc7..7448afc90c0a 100644 +config CREDP + depends on IEE + def_bool y ++ ++# Config for kernel module isolation ++config KOI ++ depends on ARM64 ++ depends on ARM64_VA_BITS_48 ++ depends on ARM64_4K_PAGES ++ def_bool y ++ ++config IEE_SELINUX_P ++ depends on IEE ++ depends on SECURITY_SELINUX ++ def_bool y ++ ++# Config for key isolation ++config KEYP ++ depends on IEE ++ def_bool y + config MITIGATE_SPECTRE_BRANCH_HISTORY bool "Mitigate Spectre style attacks against branch history" if EXPERT default y +diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig +index 96ca8b990e22..c576bab62195 100644 +--- a/arch/arm64/configs/openeuler_defconfig ++++ b/arch/arm64/configs/openeuler_defconfig +@@ -1377,7 +1377,7 @@ CONFIG_NETFILTER_NETLINK_ACCT=m + CONFIG_NETFILTER_NETLINK_QUEUE=m + CONFIG_NETFILTER_NETLINK_LOG=m + CONFIG_NETFILTER_NETLINK_OSF=m +-CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK=y + CONFIG_NF_LOG_SYSLOG=m + CONFIG_NETFILTER_CONNCOUNT=m + CONFIG_NF_CONNTRACK_MARK=y +@@ -1408,7 +1408,7 @@ CONFIG_NF_CT_NETLINK=m + CONFIG_NF_CT_NETLINK_TIMEOUT=m + CONFIG_NF_CT_NETLINK_HELPER=m + CONFIG_NETFILTER_NETLINK_GLUE_CT=y +-CONFIG_NF_NAT=m ++CONFIG_NF_NAT=y + CONFIG_NF_NAT_AMANDA=m + CONFIG_NF_NAT_FTP=m + CONFIG_NF_NAT_IRC=m +@@ -1612,7 +1612,7 @@ CONFIG_IP_VS_PE_SIP=m + # + # IP: Netfilter Configuration + # +-CONFIG_NF_DEFRAG_IPV4=m ++CONFIG_NF_DEFRAG_IPV4=y + CONFIG_NF_SOCKET_IPV4=m + CONFIG_NF_TPROXY_IPV4=m + CONFIG_NF_TABLES_IPV4=y +@@ -1684,7 +1684,7 @@ CONFIG_IP6_NF_TARGET_MASQUERADE=m + CONFIG_IP6_NF_TARGET_NPT=m + # end of IPv6: Netfilter Configuration + +-CONFIG_NF_DEFRAG_IPV6=m ++CONFIG_NF_DEFRAG_IPV6=y + CONFIG_NF_TABLES_BRIDGE=m + # CONFIG_NFT_BRIDGE_META is not set + CONFIG_NFT_BRIDGE_REJECT=m diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 38b23786aeb4..6af10d509c2e 100644 --- a/arch/arm64/include/asm/assembler.h @@ -499,13 +343,14 @@ index 84055329cd8b..f72d89bb9a32 100644 struct perf_event_attr; diff --git a/arch/arm64/include/asm/iee-access.h b/arch/arm64/include/asm/iee-access.h new file mode 100644 -index 000000000000..79604c21a510 +index 000000000000..cfa76c140bee --- /dev/null +++ b/arch/arm64/include/asm/iee-access.h -@@ -0,0 +1,36 @@ +@@ -0,0 +1,47 @@ +#ifndef _LINUX_IEE_ACCESS_H +#define _LINUX_IEE_ACCESS_H + ++#include +#include +#include + @@ -522,6 +367,11 @@ index 000000000000..79604c21a510 + iee_rw_gate(IEE_MEMSET, ptr, data, n); +} + ++void iee_memcpy(void *dst, void *src, size_t n) ++{ ++ iee_rw_gate(IEE_MEMCPY, dst, src, n); ++} ++ +void iee_set_track(struct track *ptr, struct track *data) +{ + iee_rw_gate(IEE_OP_SET_TRACK, ptr, data); @@ -532,9 +382,14 @@ index 000000000000..79604c21a510 + iee_rw_gate(IEE_OP_SET_FREEPTR, pptr, ptr); +} + -+void iee_write_entry_task(struct task_struct *tsk) ++void iee_copy_pte_range(pte_t *new_dst, pte_t *old_dst, pte_t *src_pte, struct vm_area_struct *src_vma, unsigned long dst_vm_flags, pte_t *end_pte) +{ -+ iee_rw_gate(IEE_WRITE_ENTRY_TASK, tsk); ++ iee_rw_gate(IEE_COPY_PTE_RANGE, new_dst, old_dst, src_pte, src_vma, dst_vm_flags, end_pte); ++} ++ ++void iee_split_huge_pmd(pmd_t *pmdp, pte_t *pgtable) ++{ ++ iee_rw_gate(IEE_SPLIT_HUGE_PMD, pmdp, pgtable); +} +#endif + @@ -699,72 +554,12 @@ index 000000000000..b8c3bb53f98a \ No newline at end of file diff --git a/arch/arm64/include/asm/iee-def.h b/arch/arm64/include/asm/iee-def.h new file mode 100644 -index 000000000000..76e59259e4d1 +index 000000000000..2d2b4301ebb3 --- /dev/null +++ b/arch/arm64/include/asm/iee-def.h -@@ -0,0 +1,74 @@ -+// Function Identifiers with Parameters Description -+ -+#define IEE_WRITE_IN_BYTE 0 // Parameters: void *ptr, __u64 data, int length -+#define IEE_OP_SET_PTE 1 // Parameters: pte_t *ptep, pte_t pte -+#define IEE_OP_SET_PMD 2 // Parameters: pmd_t *pmdp, pmd_t pmd -+#define IEE_OP_SET_PUD 3 // Parameters: pud_t *pudp, pud_t pud -+#define IEE_OP_SET_P4D 4 // Parameters: p4d_t *p4dp, p4d_t p4d -+#define IEE_OP_SET_BM_PTE 5 // Parameters: pte_t *ptep, pte_t pte -+#define IEE_OP_SET_SWAPPER_PGD 6 // Parameters: pgd_t *pgdp, pgd_t pgd -+#define IEE_OP_SET_TRAMP_PGD 7 // Parameters: pgd_t *pgdp, pgd_t pgd -+#define IEE_OP_SET_CMPXCHG 8 // Parameters: pte_t *ptep, pteval_t old_pteval, pteval_t new_pteval -+#define IEE_OP_SET_XCHG 9 // Parameters: pte_t *ptep, pteval_t pteval -+#define IEE_OP_COPY_CRED 10 // Parameters: struct cred *old, struct cred *new -+#define IEE_OP_SET_CRED_UID 11 // Parameters: struct cred *cred, kuid_t uid -+#define IEE_OP_SET_CRED_GID 12 // Parameters: struct cred *cred, kgid_t gid -+#define IEE_OP_SET_CRED_SUID 13 // Parameters: struct cred *cred, kuid_t suid -+#define IEE_OP_SET_CRED_SGID 14 // Parameters: struct cred *cred, kgid_t sgid -+#define IEE_OP_SET_CRED_EUID 15 // Parameters: struct cred *cred, kuid_t euid -+#define IEE_OP_SET_CRED_EGID 16 // Parameters: struct cred *cred, kgid_t egid -+#define IEE_OP_SET_CRED_FSUID 17 // Parameters: struct cred *cred, kuid_t fsuid -+#define IEE_OP_SET_CRED_FSGID 18 // Parameters: struct cred *cred, kgid_t fsgid -+#define IEE_OP_SET_CRED_USER 19 // Parameters: struct cred *cred, struct user_struct *user -+#define IEE_OP_SET_CRED_USER_NS 20 // Parameters: struct cred *cred, struct user_namespace *user_ns -+#define IEE_OP_SET_CRED_GROUP_INFO 21 // Parameters: struct cred *cred, struct group_info *group_info -+#define IEE_OP_SET_CRED_SECUREBITS 22 // Parameters: struct cred *cred, unsigned securebits -+#define IEE_OP_SET_CRED_CAP_INHER 23 // Parameters: struct cred *cred, kernel_cap_t cap_inheritable -+#define IEE_OP_SET_CRED_CAP_PERM 24 // Parameters: struct cred *cred, kernel_cap_t cap_permitted -+#define IEE_OP_SET_CRED_CAP_EFFECT 25 // Parameters: struct cred *cred, kernel_cap_t cap_effective -+#define IEE_OP_SET_CRED_CAP_BSET 26 // Parameters: struct cred *cred, kernel_cap_t cap_bset -+#define IEE_OP_SET_CRED_CAP_AMBIENT 27 // Parameters: struct cred *cred, kernel_cap_t cap_ambient -+#define IEE_OP_SET_CRED_JIT_KEYRING 28 // Parameters: struct cred *cred, unsigned char jit_keyring -+#define IEE_OP_SET_CRED_SESS_KEYRING 29 // Parameters: struct cred *cred, struct key *session_keyring -+#define IEE_OP_SET_CRED_PROC_KEYRING 30 // Parameters: struct cred *cred, struct key *process_keyring -+#define IEE_OP_SET_CRED_THREAD_KEYRING 31 // Parameters: struct cred *cred, struct key *thread_keyring -+#define IEE_OP_SET_CRED_REQ_KEYRING 32 // Parameters: struct cred *cred, struct key *request_key_auth -+#define IEE_OP_SET_CRED_NON_RCU 33 // Parameters: struct cred *cred, int non_rcu -+#define IEE_OP_SET_CRED_ATSET_USAGE 34 // Parameters: struct cred *cred, int i -+#define IEE_OP_SET_CRED_ATOP_USAGE 35 // Parameters: struct cred *cred, int flag -+#define IEE_OP_SET_CRED_SECURITY 36 // Parameters: struct cred *cred, void *security -+#define IEE_OP_SET_CRED_RCU 37 // Parameters: struct cred *cred, struct rcu_head *rcu -+#define IEE_MEMSET 38 // Parameters: void *ptr, int data, size_t n -+#define IEE_OP_SET_TRACK 39 // Parameters: struct track *ptr, struct track *data -+#define IEE_OP_SET_FREEPTR 40 // Parameters: void **pptr, void *ptr -+#define IEE_OP_SET_PTE_U 41 // Parameters: pte_t *ptep, pte_t pte -+#define IEE_OP_SET_PTE_P 42 // Parameters: pte_t *ptep, pte_t pte -+#define IEE_SET_TOKEN_MM 43 // Parameters: struct task_token *token, struct mm_struct *mm -+#define IEE_SET_TOKEN_PGD 44 // Parameters: struct task_token *token, pgd_t *pgd -+#define IEE_INIT_TOKEN 45 // Parameters: struct task_struct *tsk, void *kernel_stack, void *iee_stack -+#define IEE_FREE_TOKEN 46 // Parameters: struct task_struct *tsk -+#define IEE_READ_TOKEN_STACK 47 // Parameters: struct task_struct *tsk -+#define IEE_WRITE_ENTRY_TASK 48 // Parameters: struct task_struct *tsk -+#define IEE_OP_SET_CRED_UCOUNTS 49 // Parameters: struct cred *cred, struct ucounts *ucounts -+#ifdef CONFIG_KOI -+#define IEE_READ_KOI_STACK 50 // Parameters: struct task_struct *tsk -+#define IEE_WRITE_KOI_STACK 51 // Parameters: struct task_struct *tsk, unsigned long koi_stack -+#define IEE_READ_TOKEN_TTBR1 52 // Parameters: struct task_struct *tsk -+#define IEE_WRITE_TOKEN_TTBR1 53 // Parameters: struct task_struct *tsk, unsigned long current_ttbr1 -+#define IEE_READ_KOI_KERNEL_STACK 54 // Parameters: struct task_struct *tsk -+#define IEE_WRITE_KOI_KERNEL_STACK 55 // Parameters: struct task_struct *tsk, unsigned long kernel_stack -+#define IEE_READ_KOI_STACK_BASE 56 // Parameters: struct task_struct *tsk -+#define IEE_WRITE_KOI_STACK_BASE 57 // Parameters: struct task_struct *tsk, unsigned long koi_stack_base -+#endif +@@ -0,0 +1,37 @@ ++#ifndef _LINUX_IEE_DEF_H ++#define _LINUX_IEE_DEF_H + +/* Add new IEE ops here */ + @@ -773,17 +568,235 @@ index 000000000000..76e59259e4d1 +#define AT_SUB_AND_TEST 3 +/* Atomic ops for atomic_t */ + ++#define REFCOUNT_INC 1 ++#define REFCOUNT_SET 2 ++#define REFCOUNT_DEC_AND_TEST 3 ++#define REFCOUNT_INC_NOT_ZERO 4 ++ ++#define SET_BIT_OP 1 ++#define TEST_AND_CLEAR_BIT 2 ++#define TEST_AND_SET_BIT 3 ++ +#ifdef CONFIG_KOI +#define IEE_SWITCH_TO_KERNEL 7 +#define IEE_SWITCH_TO_KOI 8 +#endif ++ ++#if defined(CONFIG_KOI) && defined(CONFIG_IEE) ++#define IEE_READ_KOI_STACK 24 ++#define IEE_WRITE_KOI_STACK 25 ++#define IEE_READ_TOKEN_TTBR1 26 ++#define IEE_WRITE_TOKEN_TTBR1 27 ++#define IEE_READ_KOI_KERNEL_STACK 28 ++#define IEE_WRITE_KOI_KERNEL_STACK 29 ++#define IEE_READ_KOI_STACK_BASE 30 ++#define IEE_WRITE_KOI_STACK_BASE 31 ++#define IEE_SET_KOI_PGD 32 ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/arch/arm64/include/asm/iee-key.h b/arch/arm64/include/asm/iee-key.h +new file mode 100644 +index 000000000000..eb116bb7604a +--- /dev/null ++++ b/arch/arm64/include/asm/iee-key.h +@@ -0,0 +1,154 @@ ++#ifndef _LINUX_IEE_KEY_H ++#define _LINUX_IEE_KEY_H ++ ++#include ++#include ++ ++extern unsigned long long iee_rw_gate(int flag, ...); ++ ++#ifdef CONFIG_KEYP ++static void __maybe_unused iee_set_key_union(struct key *key, struct key_union *key_union) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_UNION, key, key_union); ++} ++ ++static void __maybe_unused iee_set_key_struct(struct key *key, struct key_struct *key_struct) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_STRUCT, key, key_struct); ++} ++ ++static void __maybe_unused iee_set_key_payload(struct key *key, union key_payload *key_payload) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_PAYLOAD, key, key_payload); ++} ++ ++static void __maybe_unused iee_write_key_payload(struct key *key, union key_payload payload) ++{ ++ iee_rw_gate(IEE_OP_WRITE_KEY_PAYLOAD, key, payload); ++} ++ ++extern bool iee_set_key_usage(struct key *key, int n, int flag); ++ ++static void __maybe_unused iee_set_key_serial(struct key *key, key_serial_t serial) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_SERIAL, key, serial); ++} ++ ++#ifdef CONFIG_KEY_NOTIFICATIONS ++static void __maybe_unused iee_set_key_watchers(struct key *key, struct watch_list *watchers) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_WATCHERS, key, watchers); ++} ++#endif ++ ++static void __maybe_unused iee_set_key_user(struct key *key, struct key_user *user) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_USERS, key, user); ++} ++ ++static void __maybe_unused iee_set_key_security(struct key *key, void *security) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_SECURITY, key, security); ++} ++ ++static void __maybe_unused iee_set_key_expiry(struct key *key, time64_t expiry) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_EXPIRY, key, expiry); ++} ++ ++static void __maybe_unused iee_set_key_revoked_at(struct key *key, time64_t revoked_at) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_REVOKED_AT, key, revoked_at); ++} ++ ++static void __maybe_unused iee_set_key_last_used_at(struct key *key, time64_t last_used_at) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_LAST_USED_AT, key, last_used_at); ++} ++ ++static void __maybe_unused iee_set_key_uid(struct key *key, kuid_t uid) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_UID, key, uid); ++} ++ ++static void __maybe_unused iee_set_key_gid(struct key *key, kgid_t gid) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_GID, key, gid); ++} ++ ++static void __maybe_unused iee_set_key_perm(struct key *key, key_perm_t perm) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_PERM, key, perm); ++} ++ ++static void __maybe_unused iee_set_key_quotalen(struct key *key, unsigned short quotalen) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_QUOTALEN, key, quotalen); ++} ++ ++static void __maybe_unused iee_set_key_datalen(struct key *key, unsigned short datalen) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_DATALEN, key, datalen); ++} ++ ++static void __maybe_unused iee_set_key_state(struct key *key, short state) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_STATE, key, state); ++} ++ ++#ifdef KEY_DEBUGGING ++static void __maybe_unused iee_set_key_magic(struct key *key, unsigned magic) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_MAGIC, key, magic); ++} ++#endif ++ ++static void __maybe_unused iee_set_key_flags(struct key *key, unsigned long flags) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_FLAGS, key, flags); ++} ++ ++static void __maybe_unused iee_set_key_index_key(struct key *key, struct keyring_index_key index_key) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_INDEX_KEY, key, index_key); ++} ++ ++static void __maybe_unused iee_set_key_hash(struct key *key, unsigned long hash) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_HASH, key, hash); ++} ++ ++static void __maybe_unused iee_set_key_len_desc(struct key *key, unsigned long len_desc) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_LEN_DESC, key, len_desc); ++} ++ ++static void __maybe_unused iee_set_key_type(struct key *key, struct key_type *type) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_TYPE, key, type); ++} ++ ++static void __maybe_unused iee_set_key_domain_tag(struct key *key, struct key_tag *domain_tag) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_TAG, key, domain_tag); ++} ++ ++static void __maybe_unused iee_set_key_description(struct key *key, char *description) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_DESCRIPTION, key, description); ++} ++ ++static void __maybe_unused iee_set_key_restrict_link(struct key *key, struct key_restriction *restrict_link) ++{ ++ iee_rw_gate(IEE_OP_SET_KEY_RESTRICT_LINK, key, restrict_link); ++} ++ ++static bool __maybe_unused iee_set_key_flag_bit(struct key *key, long nr, int flag) ++{ ++ bool ret; ++ ret = iee_rw_gate(IEE_OP_SET_KEY_FLAG_BIT, key, nr, flag); ++ return ret; ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/arch/arm64/include/asm/iee-selinuxp.h b/arch/arm64/include/asm/iee-selinuxp.h +new file mode 100644 +index 000000000000..4ea3e614c049 +--- /dev/null ++++ b/arch/arm64/include/asm/iee-selinuxp.h +@@ -0,0 +1,27 @@ ++#ifndef _LINUX_IEE_SELINUX_P_H ++#define _LINUX_IEE_SELINUX_P_H ++ ++#include ++#include ++#include "security.h" ++#include "ss/services.h" ++ ++static inline struct mutex* iee_get_selinux_policy_lock(void) ++{ ++ return (struct mutex*)(selinux_state.policy_mutex.owner.counter); ++} ++ ++static inline struct mutex* iee_get_selinux_status_lock(void) ++{ ++ return (struct mutex*)(selinux_state.status_lock.owner.counter); ++} ++ ++/* APIs for modifying selinux_state */ ++extern void iee_set_selinux_status_pg(struct page* new_page); ++extern void iee_set_sel_policy_cap(unsigned int idx, int cap); ++extern void iee_sel_rcu_assign_policy(struct selinux_policy* new_policy, ++ struct selinux_policy* iee_new_policy); ++ ++extern struct kmem_cache *policy_jar; ++ ++#endif \ No newline at end of file diff --git a/arch/arm64/include/asm/iee-si.h b/arch/arm64/include/asm/iee-si.h new file mode 100644 -index 000000000000..e67d81db66a5 +index 000000000000..8d2f7566e272 --- /dev/null +++ b/arch/arm64/include/asm/iee-si.h -@@ -0,0 +1,64 @@ +@@ -0,0 +1,65 @@ +#ifndef _LINUX_IEE_SI_H +#define _LINUX_IEE_SI_H + @@ -792,6 +805,7 @@ index 000000000000..e67d81db66a5 +#define __iee_si_data __section(".iee.si_data") + +/* Used for copying globals that iee rwx gate needs. */ ++extern unsigned long iee_base_swapper_pg_dir; +extern unsigned long iee_base_idmap_pg_dir; +extern unsigned long iee_base_reserved_pg_dir; +extern unsigned long iee_base__bp_harden_el1_vectors; @@ -801,7 +815,7 @@ index 000000000000..e67d81db66a5 +/* The following are __init functions used for iee si initialization. */ +extern void iee_si_prepare_data(void); + -+extern unsigned long __iee_si_start[]; ++extern unsigned long __iee_si_text_start[]; +// Handler function for sensitive inst +u64 iee_si_handler(int flag, ...); +/* @@ -881,14 +895,15 @@ index 000000000000..4f3c17c7da00 \ No newline at end of file diff --git a/arch/arm64/include/asm/iee-token.h b/arch/arm64/include/asm/iee-token.h new file mode 100644 -index 000000000000..152474e1a187 +index 000000000000..d1b2cdaa0c03 --- /dev/null +++ b/arch/arm64/include/asm/iee-token.h -@@ -0,0 +1,40 @@ +@@ -0,0 +1,34 @@ +#ifndef _LINUX_IEE_TOKEN_H +#define _LINUX_IEE_TOKEN_H + +#include ++#include + +extern unsigned long long iee_rw_gate(int flag, ...); +struct task_token; @@ -896,31 +911,24 @@ index 000000000000..152474e1a187 +struct mm_struct; + +#ifdef CONFIG_IEE -+void iee_set_token_mm(struct task_struct *tsk, struct mm_struct *mm) -+{ -+ iee_rw_gate(IEE_SET_TOKEN_MM, tsk, mm); -+} -+ +void iee_set_token_pgd(struct task_struct *tsk, pgd_t *pgd) +{ + iee_rw_gate(IEE_SET_TOKEN_PGD, tsk, pgd); +} + -+void iee_init_token(struct task_struct *tsk, void *kernel_stack, void *iee_stack) ++void iee_init_token(struct task_struct *tsk, void *iee_stack, void *tmp_page) +{ -+ iee_rw_gate(IEE_INIT_TOKEN, tsk, kernel_stack, iee_stack); ++ iee_rw_gate(IEE_INIT_TOKEN, tsk, iee_stack, tmp_page); +} + -+void iee_free_token(struct task_struct *tsk) ++void iee_invalidate_token(struct task_struct *tsk) +{ -+ iee_rw_gate(IEE_FREE_TOKEN, tsk); ++ iee_rw_gate(IEE_INVALIDATE_TOKEN, tsk); +} + -+unsigned long iee_read_token_stack(struct task_struct *tsk) ++void iee_validate_token(struct task_struct *tsk) +{ -+ unsigned long ret; -+ ret = iee_rw_gate(IEE_READ_TOKEN_STACK, tsk); -+ return ret; ++ iee_rw_gate(IEE_VALIDATE_TOKEN, tsk); +} +#endif + @@ -974,10 +982,10 @@ index 85d26143faa5..e7a3081ce285 100644 #endif /* __ASM_KERNEL_PGTABLE_H */ diff --git a/arch/arm64/include/asm/koi.h b/arch/arm64/include/asm/koi.h new file mode 100644 -index 000000000000..48d9a1378a1d +index 000000000000..a3b0ce0f8019 --- /dev/null +++ b/arch/arm64/include/asm/koi.h -@@ -0,0 +1,335 @@ +@@ -0,0 +1,531 @@ +#include "linux/mm.h" +#include "asm/current.h" +#include "asm/pgtable-hwdef.h" @@ -988,6 +996,7 @@ index 000000000000..48d9a1378a1d +#include "linux/printk.h" +#include "linux/slab.h" +#include "linux/string.h" ++#include +#include +#include "linux/hashtable.h" +#include "linux/module.h" @@ -999,6 +1008,8 @@ index 000000000000..48d9a1378a1d +#include "asm/iee-def.h" +#endif + ++#ifdef CONFIG_KOI ++ +#define HASH_TABLE_BIT 10 +#define HASH_TABLE_LEN (1 << HASH_TABLE_BIT) +#define HASH_KEY_MASK ((1 << HASH_TABLE_BIT) - 1) @@ -1042,6 +1053,8 @@ index 000000000000..48d9a1378a1d + spinlock_t spin_lock; + // used to protect addr hashtable + spinlock_t addr_htbl_spin_lock; ++ bool is_valid; ++ spinlock_t mod_lock; +}; +//describe the global shared var +struct shared_variable_descriptor { @@ -1055,10 +1068,13 @@ index 000000000000..48d9a1378a1d + +int koi_do_switch_to_kernel_pgtbl(void); + ++int koi_share_kstack(struct module *mod); ++ +int koi_copy_pagetable(struct mm_struct *ko_mm, pgd_t *koi_pg_dir, -+ unsigned long addr, unsigned long end); ++ unsigned long addr, unsigned long end, pteval_t prot); + +void koi_create_pagetable(struct module *mod); ++void koi_destroy_pagetable(struct module *mod); + +void koi_map_kostack(struct module *mod); +unsigned long koi_mem_alloc(struct module *mod, unsigned long orig_addr, @@ -1069,16 +1085,17 @@ index 000000000000..48d9a1378a1d +void koi_mem_free_callback(struct module *mod, unsigned long addr, + unsigned long size, void (*func)(void *)); +void koi_map_mem(struct module *mod, unsigned long addr, unsigned long size); ++void koi_unmap_mem(struct module *mod, unsigned long addr, unsigned long size); +void koi_mem_free_to_user(struct module *mod, unsigned long addr, + unsigned long size); + +unsigned long koi_ttbr_ctor(struct module *mod); -+extern void koi_do_switch_to_kernel_stack(void); -+extern void koi_do_switch_to_ko_stack(void); ++ ++// unsigned long koi_get_token_addr(struct task_struct *tsk); + +#define switch_pgtable(ttbr1) \ + do { \ -+ write_sysreg(ttbr1, ttbr1_el1); \ ++ write_sysreg((ttbr1), ttbr1_el1); \ + isb(); \ + asm volatile(ALTERNATIVE("nop; nop; nop", \ + "ic iallu; dsb nsh; isb", \ @@ -1097,11 +1114,11 @@ index 000000000000..48d9a1378a1d + "mov %1, sp\n" \ + : "=r"(flags), "=r"(cur_sp) \ + :); \ -+ if (!on_irq_stack(cur_sp, NULL)) { \ -+ koi_do_switch_to_ko_stack(); \ ++ if (!on_irq_stack(cur_sp, (unsigned long)NULL)) { \ + ko_ttbr1 = koi_ttbr_ctor(THIS_MODULE); \ + token = (struct task_token *)((unsigned long)current + \ -+ koi_offset); \ ++ (unsigned long) \ ++ koi_offset); \ + token->current_ttbr1 = ko_ttbr1 & (~TTBR_ASID_MASK); \ + } else { \ + ko_ttbr1 = koi_ttbr_ctor(THIS_MODULE); \ @@ -1125,17 +1142,15 @@ index 000000000000..48d9a1378a1d + "msr daifset, #2\n" \ + "isb\n" \ + "mov %1, sp\n" \ -+ "mov %2, ttbr0_el1\n" \ -+ : "=r"(flags), "=r"(cur_sp), "=r"(asid) \ ++ : "=r"(flags), "=r"(cur_sp) \ + :); \ -+ asid &= ~USER_ASID_FLAG; \ ++ asid = read_sysreg(ttbr0_el1) & (~USER_ASID_FLAG); \ + asid &= TTBR_ASID_MASK; \ -+ switch_pgtable(koi_swapper_ttbr1); \ -+ if (!on_irq_stack(cur_sp, NULL)) { \ ++ switch_pgtable((koi_swapper_ttbr1 | asid)); \ ++ if (!on_irq_stack(cur_sp, (unsigned long)NULL)) { \ + token = (struct task_token *)((unsigned long)current + \ -+ koi_offset); \ ++ (unsigned long)koi_offset); \ + token->current_ttbr1 = koi_swapper_ttbr1; \ -+ koi_do_switch_to_kernel_stack(); \ + } else { \ + ptr = SHIFT_PERCPU_PTR(koi_irq_current_ttbr1, \ + __kern_my_cpu_offset()); \ @@ -1157,8 +1172,7 @@ index 000000000000..48d9a1378a1d + "mov %1, sp\n" \ + : "=r"(flags), "=r"(cur_sp) \ + :); \ -+ if (!on_irq_stack(cur_sp, NULL)) { \ -+ koi_do_switch_to_ko_stack(); \ ++ if (!on_irq_stack(cur_sp, (unsigned long)NULL)) { \ + ko_ttbr1 = koi_ttbr_ctor(THIS_MODULE); \ + iee_rw_gate(IEE_WRITE_TOKEN_TTBR1, current, \ + ko_ttbr1 &(~TTBR_ASID_MASK)); \ @@ -1185,11 +1199,10 @@ index 000000000000..48d9a1378a1d + "mov %1, sp\n" \ + : "=r"(flags), "=r"(cur_sp) \ + :); \ -+ iee_rwx_gate_entry(IEE_SWITCH_TO_KERNEL); \ -+ if (!on_irq_stack(cur_sp, NULL)) { \ ++ iee_rwx_gate_entry(IEE_SWITCH_TO_KERNEL); \ ++ if (!on_irq_stack(cur_sp, (unsigned long)NULL)) { \ + iee_rw_gate(IEE_WRITE_TOKEN_TTBR1, current, \ + koi_swapper_ttbr1); \ -+ koi_do_switch_to_kernel_stack(); \ + } else { \ + ptr = SHIFT_PERCPU_PTR(koi_irq_current_ttbr1, \ + __kern_my_cpu_offset()); \ @@ -1224,16 +1237,41 @@ index 000000000000..48d9a1378a1d + + addr = kzalloc(size, flags); + koi_copy_pagetable(target->ko_mm, target->pgdp, (unsigned long)addr, -+ (unsigned long)addr + PAGE_SIZE * cnt); ++ (unsigned long)addr + PAGE_SIZE * cnt, 0); + koi_switch_to_ko(); + return addr; +} ++ ++static __maybe_unused noinline void *koi_kzalloc_node_wrapper(struct module *mod, size_t size, gfp_t flags, int node) { ++ int cnt = (size + PAGE_SIZE - 1) / PAGE_SIZE; ++ void *addr = NULL; ++ struct koi_mem_hash_node *target = NULL; ++ koi_switch_to_kernel(); ++ ++ rcu_read_lock(); ++ hash_for_each_possible_rcu(koi_mem_htbl, target, node, (unsigned long)mod) { ++ if (target->mod == mod) ++ break; ++ } ++ rcu_read_unlock(); ++ if (target == NULL) { ++ printk(KERN_ERR "mem node for module: %s not found\n", mod->name); ++ goto ret; ++ } ++ addr = kzalloc_node(cnt * PAGE_SIZE, flags, node); ++ koi_copy_pagetable(target->ko_mm, target->pgdp, (unsigned long)addr, ++ (unsigned long)addr + PAGE_SIZE * cnt, 0); ++ret: ++ koi_switch_to_ko(); ++ return (void *)addr; ++} ++ +//kmalloc function in driver space -+static __maybe_unused __always_inline void * ++static __maybe_unused void * +koi_kmalloc_wrapper(struct module *mod, size_t size, gfp_t flags) +{ + int cnt = (size + PAGE_SIZE - 1) / PAGE_SIZE; -+ void *addr; ++ void *addr = NULL; + struct koi_mem_hash_node *target = NULL; + koi_switch_to_kernel(); + @@ -1246,14 +1284,15 @@ index 000000000000..48d9a1378a1d + } + rcu_read_unlock(); + if (target == NULL) { -+ printk("mem node for module: %s not found\n", mod->name); -+ return 0; ++ printk(KERN_ERR"mem node for module: %s not found\n", mod->name); ++ goto ret; + } + + addr = kmalloc(cnt * PAGE_SIZE, flags); + koi_copy_pagetable(target->ko_mm, target->pgdp, (unsigned long)addr, -+ (unsigned long)addr + PAGE_SIZE * cnt); -+ koi_switch_to_ko(); ++ (unsigned long)addr + PAGE_SIZE * cnt, 0); ++ret: ++ koi_switch_to_ko(); + return (void *)addr; +} +//vmalloc function in driver space @@ -1279,7 +1318,7 @@ index 000000000000..48d9a1378a1d + } + addr = vmalloc(cnt * PAGE_SIZE); + koi_copy_pagetable(target->ko_mm, target->pgdp, (unsigned long)addr, -+ (unsigned long)addr + PAGE_SIZE * cnt); ++ (unsigned long)addr + PAGE_SIZE * cnt, 0); + koi_switch_to_ko(); + return addr; +} @@ -1309,13 +1348,178 @@ index 000000000000..48d9a1378a1d + n = (kpage * PAGE_SIZE) / size; + addr = kmalloc_array(n, size, flags); + koi_copy_pagetable(target->ko_mm, target->pgdp, (unsigned long)addr, -+ (unsigned long)addr + PAGE_SIZE * kpage); ++ (unsigned long)addr + PAGE_SIZE * kpage, 0); + koi_switch_to_ko(); + return addr; +} ++ ++static __maybe_unused noinline void *koi_kcalloc_wrapper(struct module *mod, size_t n, size_t size, gfp_t flags) { ++ return koi_kmalloc_array_wrapper(mod, n, size, flags | __GFP_ZERO); ++} ++#endif ++ ++#ifdef CONFIG_KOI ++ ++#define koi_copy_to_user_wrapper(to, from, n) \ ++({ \ ++ koi_switch_to_kernel(); \ ++ long long ret = copy_to_user(to, from, n); \ ++ koi_switch_to_ko(); \ ++ ret; \ ++}) ++ ++#define koi_copy_from_user_wrapper(to, from, n) \ ++({ \ ++ koi_switch_to_kernel(); \ ++ long long ret = copy_from_user(to, from, n); \ ++ koi_switch_to_ko(); \ ++ ret; \ ++}) ++ ++#define koi_kasprintf_wrapper(gfp, fmt, args...)\ ++ ({ \ ++ koi_switch_to_kernel(); \ ++ void *ret = kasprintf(gfp, fmt, ##args); \ ++ koi_map_mem(THIS_MODULE, (unsigned long)ret, sizeof(void *)); \ ++ koi_switch_to_ko(); \ ++ ret;\ ++ }) ++ ++#define koi_scnprintf_wrapper(buf, size, fmt, args...) \ ++ ({ \ ++ int ret; \ ++ koi_switch_to_kernel(); \ ++ ret = scnprintf(buf, size, fmt, ##args); \ ++ koi_switch_to_ko(); \ ++ ret; \ ++ }) ++ ++#define koi_sscanf_wrapper(buf, fmt, args...) \ ++ ({ \ ++ int ret; \ ++ koi_switch_to_kernel(); \ ++ ret = sscanf(buf, fmt, ##args); \ ++ koi_switch_to_ko(); \ ++ ret; \ ++ }) ++ ++#define koi_rcu_read_lock_wrapper() \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ rcu_read_lock(); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++#define koi_rcu_read_unlock_wrapper() \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ rcu_read_unlock(); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++#define koi_mutex_lock_wrapper(lock) \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ mutex_lock(lock); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++#define koi_mutex_unlock_wrapper(lock) \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ mutex_unlock(lock); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++#define koi_mutex_init_wrapper(lock) \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ mutex_init(lock); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++#define koi_spin_lock_wrapper(lock) \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ spin_lock(lock); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++#define koi_spin_unlock_wrapper(lock) \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ spin_unlock(lock); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++#define koi_spin_lock_irq_wrapper(lock) \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ spin_lock_irq(lock); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++ ++#define koi_spin_unlock_irq_wrapper(lock) \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ spin_unlock_irq(lock); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++#define koi_spin_lock_irqsave_wrapper(lock, flags) \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ spin_lock_irqsave(lock, flags); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++ ++#define koi_spin_lock_irqrestore_wrapper(lock, flags) \ ++ do { \ ++ koi_switch_to_kernel(); \ ++ spin_lock_irqrestore(lock, flags); \ ++ koi_switch_to_ko(); \ ++ } while(0); ++ ++#else ++ ++#define koi_copy_to_user_wrapper copy_to_user ++ ++#define koi_copy_from_user_wrapper copy_from_user ++ ++#define koi_kasprintf_wrapper kasprintf ++ ++#define koi_scnprintf_wrapper scnprintf ++ ++#define koi_sscanf_wrapper sscanf ++ ++#define koi_rcu_read_lock_wrapper rcu_read_lock ++ ++#define koi_rcu_read_unlock_wrapper rcu_read_unlock ++ ++#define koi_mutex_lock_wrapper mutex_lock ++ ++#define koi_mutex_unlock_wrapper mutex_unlock ++ ++#define koi_mutex_init_wrapper mutex_init ++ ++#define koi_spin_lock_irq_wrapper spin_lock_irq ++ ++#define koi_spin_unlock_irq_wrapper spin_unlock_irq ++ ++#define koi_spin_lock_wrapper spin_lock ++ ++#define koi_spin_unlock_wrapper spin_unlock ++ ++#define koi_spin_lock_irqsave_wrapper spin_lock_irqsave ++ ++#define koi_spin_lock_irqrestore_wrapper spin_lock_irqrestore ++ ++#endif \ No newline at end of file diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h -index fde4186cc387..6309e5514a16 100644 +index fde4186cc387..c9e9a5a288bc 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -190,6 +190,13 @@ extern u64 vabits_actual; @@ -1332,12 +1536,12 @@ index fde4186cc387..6309e5514a16 100644 /* PHYS_OFFSET - the physical address of the start of memory. */ #define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; }) -@@ -310,6 +317,23 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x); +@@ -310,6 +317,27 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x); #define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET) #define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset)) +#ifdef CONFIG_KOI -+#define KOI_OFFSET ((unsigned long)BIT(vabits_actual - 2)) ++#define KOI_OFFSET (((unsigned long)BIT(vabits_actual - 2)) - LOGICAL_RANDOM) +#endif + +#ifdef CONFIG_IEE @@ -1353,6 +1557,10 @@ index fde4186cc387..6309e5514a16 100644 +#define SET_NG(x) __pgprot(pgprot_val(x) | PTE_NG) +#endif + ++#if defined(CONFIG_IEE) || defined (CONFIG_KOI) ++#define SET_NG(x) __pgprot(pgprot_val(x) | PTE_NG) ++#define SET_INVALID(x) __pgprot(pgprot_val(x) & (~PTE_VALID)) ++#endif /* * Convert a page to/from a physical address */ @@ -1463,7 +1671,7 @@ index e4944d517c99..7f60e568c964 100644 * TTBR. */ diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h -index 8d68d00de0a4..6f8d5b85bfd7 100644 +index e4d6593dfa66..85b4af2c2122 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -34,6 +34,9 @@ @@ -1476,273 +1684,171 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 #ifdef CONFIG_TRANSPARENT_HUGEPAGE #define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE -@@ -156,6 +159,30 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys) +@@ -156,6 +159,14 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys) #define pud_access_permitted(pud, write) \ (pte_access_permitted(pud_pte(pud), (write))) +#ifdef CONFIG_PTP -+static inline bool in_tramp_pgdir(void *addr); ++extern bool in_tramp_pgdir(void *addr); +extern unsigned long long iee_rw_gate(int flag, ...); -+ -+static void iee_set_tramp_pgd_pre_init(pgd_t *pgdp, pgd_t pgd) -+{ -+ iee_rw_gate(IEE_OP_SET_TRAMP_PGD, pgdp, pgd); -+} -+ -+static noinline pteval_t iee_set_xchg_relaxed(pte_t *ptep, pteval_t pteval) -+{ -+ pteval_t ret; -+ ret = iee_rw_gate(IEE_OP_SET_XCHG, ptep, pteval); -+ return (pteval_t)ret; -+} -+ -+static noinline pteval_t iee_set_cmpxchg_relaxed(pte_t *ptep, pteval_t old_pteval, pteval_t new_pteval) -+{ -+ pteval_t ret; -+ ret = iee_rw_gate(IEE_OP_SET_CMPXCHG, ptep, old_pteval, new_pteval); -+ return (pteval_t)ret; -+} ++extern void iee_set_tramp_pgd_pre_init(pgd_t *pgdp, pgd_t pgd); ++extern pteval_t iee_set_xchg_relaxed(pte_t *ptep, pteval_t pteval); ++extern pteval_t iee_set_cmpxchg_relaxed(pte_t *ptep, pteval_t old_pteval, pteval_t new_pteval); +#endif + static inline pte_t clear_pte_bit(pte_t pte, pgprot_t prot) { pte_val(pte) &= ~pgprot_val(prot); -@@ -262,6 +289,64 @@ static inline pte_t pte_mkdevmap(pte_t pte) +@@ -260,19 +271,35 @@ static inline pte_t pte_mkdevmap(pte_t pte) + return set_pte_bit(pte, __pgprot(PTE_DEVMAP | PTE_SPECIAL)); + } ++#ifdef CONFIG_PTP ++extern void iee_set_bm_pte(pte_t *ptep, pte_t pte); ++extern void iee_set_fixmap_pte_pre_init(pte_t *ptep, pte_t pte); ++#endif ++ ++#ifdef CONFIG_IEE ++extern void __set_pte(pte_t *ptep, pte_t pte); ++#else static inline void __set_pte(pte_t *ptep, pte_t pte) { +#ifdef CONFIG_KOI -+ if (!pte_none(pte)) { ++ if (pte_valid(pte)) { + pte = __pte(pte_val(pte) | PTE_NG); + } +#endif -+#ifdef CONFIG_PTP -+ iee_rw_gate(IEE_OP_SET_PTE, ptep, pte); -+ dsb(ishst); -+ isb(); -+#else -+ WRITE_ONCE(*ptep, pte); -+ -+ /* -+ * Only if the new pte is valid and kernel, otherwise TLB maintenance -+ * or update_mmu_cache() have the necessary barriers. -+ */ -+ if (pte_valid_not_user(pte)) { -+ dsb(ishst); -+ isb(); -+ } + WRITE_ONCE(*ptep, pte); +- +- /* +- * Only if the new pte is valid and kernel, otherwise TLB maintenance +- * or update_mmu_cache() have the necessary barriers. +- */ + if (pte_valid_not_user(pte)) { + dsb(ishst); + isb(); + } + } +#endif -+} + ++#ifdef CONFIG_IEE ++extern void iee_set_stack_pte(pte_t *ptep, int order, int use_block_pmd, unsigned long lm_addr); ++extern void iee_unset_stack_pte(pte_t *ptep, int order, int use_block_pmd, unsigned long lm_addr); ++extern void iee_set_sensitive_pte(pte_t *lm_ptep, pte_t *iee_ptep, int order, int use_block_pmd); ++extern void iee_unset_sensitive_pte(pte_t *lm_ptep, pte_t *iee_ptep, int order, int use_block_pmd); ++#endif + + static inline pte_t __ptep_get(pte_t *ptep) + { +@@ -361,8 +388,15 @@ static inline pte_t pte_advance_pfn(pte_t pte, unsigned long nr) + return pfn_pte(pte_pfn(pte) + nr, pte_pgprot(pte)); + } + +-static inline void __set_ptes(struct mm_struct *mm, +- unsigned long __always_unused addr, ++#ifdef CONFIG_PTP ++extern void iee_set_pte_pre_init(pte_t *ptep, pte_t pte); ++extern void iee_set_pte_at(struct mm_struct *mm, unsigned long addr, ++ pte_t *ptep, pte_t pte); ++extern void iee_set_pte_at_delayed(struct mm_struct *mm, unsigned long addr, ++ pte_t *ptep, pte_t pte); ++#endif + ++static inline void __set_ptes(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pte, unsigned int nr) + { + page_table_check_ptes_set(mm, ptep, pte, nr); +@@ -546,6 +580,44 @@ static inline void __set_pte_at(struct mm_struct *mm, + __set_pte(ptep, pte); + } + +#ifdef CONFIG_PTP -+static inline void iee_set_bm_pte(pte_t *ptep, pte_t pte) ++extern void set_pmd(pmd_t *pmdp, pmd_t pmd); ++extern void set_pud(pud_t *pudp, pud_t pud); ++ ++static inline void __set_pmd_at(struct mm_struct *mm, ++ unsigned long __always_unused addr, ++ pmd_t *pmdp, pmd_t pmd, unsigned int nr) +{ -+ // If it is pre init, write once. -+ // Else, write once will cause exception. So it is safe. -+ unsigned long flags; -+ unsigned long res; -+ local_irq_save(flags); -+ asm volatile("at s1e1r, %0"::"r"(__phys_to_iee(__pa_symbol(ptep)))); -+ isb(); -+ res = read_sysreg(par_el1); -+ local_irq_restore(flags); -+ if(res & 0x1) -+ WRITE_ONCE(*ptep,pte); -+ else -+ iee_rw_gate(IEE_OP_SET_BM_PTE, ptep, pte); -+ -+ /* -+ * Only if the new pte is valid and kernel, otherwise TLB maintenance -+ * or update_mmu_cache() have the necessary barriers. -+ */ -+ if (pte_valid_not_user(pte)) { -+ dsb(ishst); -+ isb(); -+ } -+} -+ -+static inline void iee_set_fixmap_pte_pre_init(pte_t *ptep, pte_t pte) -+{ -+#ifdef CONFIG_KOI -+ if (!pte_none(pte)) { -+ pte = __pte(pte_val(pte) | PTE_NG); -+ } -+#endif - WRITE_ONCE(*ptep, pte); - - /* -@@ -273,6 +358,7 @@ static inline void __set_pte(pte_t *ptep, pte_t pte) - isb(); - } - } -+#endif - - static inline pte_t __ptep_get(pte_t *ptep) - { -@@ -546,6 +632,95 @@ static inline void __set_pte_at(struct mm_struct *mm, - __set_pte(ptep, pte); - } - -+#ifdef CONFIG_IEE -+static inline void iee_set_pte_upage(pte_t *ptep, pte_t pte) -+{ -+#ifdef CONFIG_PTP -+ iee_rw_gate(IEE_OP_SET_PTE_U, ptep, pte); -+ dsb(ishst); -+ isb(); -+#else -+ WRITE_ONCE(*ptep, pte); -+ if (pte_valid_not_user(pte)) { -+ dsb(ishst); -+ isb(); -+ } -+#endif -+} -+ -+static inline void iee_set_pte_ppage(pte_t *ptep, pte_t pte) -+{ -+#ifdef CONFIG_PTP -+ iee_rw_gate(IEE_OP_SET_PTE_P, ptep, pte); -+#else -+ WRITE_ONCE(*ptep, pte); -+#endif -+ if (pte_valid_not_user(pte)) { -+ dsb(ishst); -+ isb(); -+ } ++ __sync_cache_and_tags(pmd_pte(pmd), nr); ++ __check_safe_pte_update(mm, (pte_t *)pmdp, pmd_pte(pmd)); ++ set_pmd(pmdp, pmd); +} -+#endif + -+#ifdef CONFIG_PTP -+static inline void set_pmd(pmd_t *pmdp, pmd_t pmd); -+static inline void __set_pmd_at(struct mm_struct *mm, unsigned long addr, -+ pmd_t *pmdp, pmd_t pmd) ++static inline void __set_pud_at(struct mm_struct *mm, ++ unsigned long __always_unused addr, ++ pud_t *pudp, pud_t pud, unsigned int nr) +{ -+ if (pte_present(pmd_pte(pmd)) && pte_user_exec(pmd_pte(pmd)) && !pte_special(pmd_pte(pmd))) -+ __sync_icache_dcache(pmd_pte(pmd)); -+ -+ /* -+ * If the PTE would provide user space access to the tags associated -+ * with it then ensure that the MTE tags are synchronised. Although -+ * pte_access_permitted() returns false for exec only mappings, they -+ * don't expose tags (instruction fetches don't check tags). -+ */ -+ if (system_supports_mte() && pte_access_permitted(pmd_pte(pmd), false) && -+ !pte_special(pmd_pte(pmd)) && pte_tagged(pmd_pte(pmd))) -+ mte_sync_tags(pmd_pte(pmd), PMD_SIZE >> PAGE_SHIFT); -+ -+ __check_safe_pte_update(mm, (pte_t *)pmdp, pmd_pte(pmd)); -+ -+ set_pmd(pmdp, pmd); ++ __sync_cache_and_tags(pud_pte(pud), nr); ++ __check_safe_pte_update(mm, (pte_t *)pudp, pud_pte(pud)); ++ set_pud(pudp, pud); +} + +static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp, pmd_t pmd) +{ + page_table_check_pmd_set(mm, pmdp, pmd); -+ return __set_pmd_at(mm, addr, pmdp, pmd); -+} -+ -+static inline void set_pud(pud_t *pudp, pud_t pud); -+static inline void __set_pud_at(struct mm_struct *mm, unsigned long addr, -+ pud_t *pudp, pud_t pud) -+{ -+ if (pte_present(pud_pte(pud)) && pte_user_exec(pud_pte(pud)) && !pte_special(pud_pte(pud))) -+ __sync_icache_dcache(pud_pte(pud)); -+ -+ /* -+ * If the PTE would provide user space access to the tags associated -+ * with it then ensure that the MTE tags are synchronised. Although -+ * pte_access_permitted() returns false for exec only mappings, they -+ * don't expose tags (instruction fetches don't check tags). -+ */ -+ if (system_supports_mte() && pte_access_permitted(pud_pte(pud), false) && -+ !pte_special(pud_pte(pud)) && pte_tagged(pud_pte(pud))) -+ mte_sync_tags(pud_pte(pud), PUD_SIZE >> PAGE_SHIFT); -+ -+ __check_safe_pte_update(mm, (pte_t *)pudp, pud_pte(pud)); -+ -+ set_pud(pudp, pud); ++ return __set_pmd_at(mm, addr, pmdp, pmd, ++ PMD_SIZE >> PAGE_SHIFT); +} + +static inline void set_pud_at(struct mm_struct *mm, unsigned long addr, + pud_t *pudp, pud_t pud) +{ + page_table_check_pud_set(mm, pudp, pud); -+ return __set_pud_at(mm, addr, pudp, pud); ++ return __set_pud_at(mm, addr, pudp, pud, ++ PUD_SIZE >> PAGE_SHIFT); +} +#else static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pmd_t pmd) { -@@ -561,7 +736,7 @@ static inline void set_pud_at(struct mm_struct *mm, unsigned long addr, +@@ -561,6 +633,7 @@ static inline void set_pud_at(struct mm_struct *mm, unsigned long addr, return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud), PUD_SIZE >> PAGE_SHIFT); } -- +#endif + #define __p4d_to_phys(p4d) __pte_to_phys(p4d_pte(p4d)) #define __phys_to_p4d_val(phys) __phys_to_pte_val(phys) - -@@ -640,7 +815,14 @@ static inline bool in_swapper_pgdir(void *addr) +@@ -640,6 +713,14 @@ static inline bool in_swapper_pgdir(void *addr) ((unsigned long)swapper_pg_dir & PAGE_MASK); } --static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) +#ifdef CONFIG_PTP -+static inline bool in_tramp_pgdir(void *addr) -+{ -+ return ((unsigned long)addr & PAGE_MASK) == -+ ((unsigned long)tramp_pg_dir & PAGE_MASK); -+} ++extern bool in_tramp_pgdir(void *addr); ++extern void iee_set_fixmap_pmd_pre_init(pmd_t *pmdp, pmd_t pmd); ++#endif + -+static inline void iee_set_fixmap_pmd_pre_init(pmd_t *pmdp, pmd_t pmd) ++#ifdef CONFIG_IEE ++extern void set_pmd(pmd_t *pmdp, pmd_t pmd); ++#else + static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) { #ifdef __PAGETABLE_PMD_FOLDED - if (in_swapper_pgdir(pmdp)) { -@@ -648,7 +830,6 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) +@@ -648,14 +729,19 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) return; } #endif /* __PAGETABLE_PMD_FOLDED */ - - WRITE_ONCE(*pmdp, pmd); - - if (pmd_valid(pmd)) { -@@ -656,6 +837,32 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) - isb(); - } - } -+#endif -+ -+static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) -+{ -+#ifdef __PAGETABLE_PMD_FOLDED -+ if (in_swapper_pgdir(pmdp)) { -+ set_swapper_pgd((pgd_t *)pmdp, __pgd(pmd_val(pmd))); -+ return; -+ } -+#endif /* __PAGETABLE_PMD_FOLDED */ +#ifdef CONFIG_KOI + pmdval_t val = pmd_val(pmd); + if (pmd_valid(pmd) && !(val & PMD_TABLE_BIT)) { + pmd = __pmd(val | PMD_SECT_NG); + } +#endif -+#ifdef CONFIG_PTP -+ iee_rw_gate(IEE_OP_SET_PMD, pmdp, pmd); -+#else -+ WRITE_ONCE(*pmdp, pmd); + WRITE_ONCE(*pmdp, pmd); +- + if (pmd_valid(pmd)) { + dsb(ishst); + isb(); + } + } +#endif -+ if (pmd_valid(pmd)) { -+ dsb(ishst); -+ isb(); -+ } -+} static inline void pmd_clear(pmd_t *pmdp) { -@@ -675,6 +882,12 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) +@@ -675,6 +761,12 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) /* Find an entry in the third-level page table. */ #define pte_offset_phys(dir,addr) (pmd_page_paddr(READ_ONCE(*(dir))) + pte_index(addr) * sizeof(pte_t)) @@ -1755,39 +1861,26 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 #define pte_set_fixmap(addr) ((pte_t *)set_fixmap_offset(FIX_PTE, addr)) #define pte_set_fixmap_offset(pmd, addr) pte_set_fixmap(pte_offset_phys(pmd, addr)) #define pte_clear_fixmap() clear_fixmap(FIX_PTE) -@@ -703,7 +916,9 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) +@@ -703,6 +795,14 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) #define pud_user(pud) pte_user(pud_pte(pud)) #define pud_user_exec(pud) pte_user_exec(pud_pte(pud)) --static inline void set_pud(pud_t *pudp, pud_t pud) + +#ifdef CONFIG_PTP -+static inline void iee_set_fixmap_pud_pre_init(pud_t *pudp, pud_t pud) ++extern void iee_set_fixmap_pud_pre_init(pud_t *pudp, pud_t pud); ++#endif ++ ++#ifdef CONFIG_IEE ++extern void set_pud(pud_t *pudp, pud_t pud); ++#else + static inline void set_pud(pud_t *pudp, pud_t pud) { #ifdef __PAGETABLE_PUD_FOLDED - if (in_swapper_pgdir(pudp)) { -@@ -711,7 +926,6 @@ static inline void set_pud(pud_t *pudp, pud_t pud) +@@ -711,14 +811,20 @@ static inline void set_pud(pud_t *pudp, pud_t pud) return; } #endif /* __PAGETABLE_PUD_FOLDED */ - - WRITE_ONCE(*pudp, pud); - - if (pud_valid(pud)) { -@@ -719,6 +933,33 @@ static inline void set_pud(pud_t *pudp, pud_t pud) - isb(); - } - } -+#endif -+ -+static inline void set_pud(pud_t *pudp, pud_t pud) -+{ -+#ifdef __PAGETABLE_PUD_FOLDED -+ if (in_swapper_pgdir(pudp)) { -+ set_swapper_pgd((pgd_t *)pudp, __pgd(pud_val(pud))); -+ return; -+ } -+#endif /* __PAGETABLE_PUD_FOLDED */ +#ifdef CONFIG_KOI + pudval_t val = pud_val(pud); + if (pud_valid(pud) && !(val & PUD_TABLE_BIT)) { @@ -1795,20 +1888,18 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 + pud = __pud(val | PMD_SECT_NG); + } +#endif -+#ifdef CONFIG_PTP -+ iee_rw_gate(IEE_OP_SET_PUD, pudp, pud); -+#else -+ WRITE_ONCE(*pudp, pud); + WRITE_ONCE(*pudp, pud); +- + if (pud_valid(pud)) { + dsb(ishst); + isb(); + } + } +#endif -+ if (pud_valid(pud)) { -+ dsb(ishst); -+ isb(); -+ } -+} static inline void pud_clear(pud_t *pudp) { -@@ -738,6 +979,12 @@ static inline pmd_t *pud_pgtable(pud_t pud) +@@ -738,6 +844,12 @@ static inline pmd_t *pud_pgtable(pud_t pud) /* Find an entry in the second-level page table. */ #define pmd_offset_phys(dir, addr) (pud_page_paddr(READ_ONCE(*(dir))) + pmd_index(addr) * sizeof(pmd_t)) @@ -1821,12 +1912,15 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 #define pmd_set_fixmap(addr) ((pmd_t *)set_fixmap_offset(FIX_PMD, addr)) #define pmd_set_fixmap_offset(pud, addr) pmd_set_fixmap(pmd_offset_phys(pud, addr)) #define pmd_clear_fixmap() clear_fixmap(FIX_PMD) -@@ -769,15 +1016,26 @@ static inline pmd_t *pud_pgtable(pud_t pud) +@@ -769,10 +881,15 @@ static inline pmd_t *pud_pgtable(pud_t pud) #define p4d_none(p4d) (!p4d_val(p4d)) #define p4d_bad(p4d) (!(p4d_val(p4d) & 2)) #define p4d_present(p4d) (p4d_val(p4d)) +#define p4d_valid(p4d) pte_valid(p4d_pte(p4d)) ++#ifdef CONFIG_IEE ++extern void set_p4d(p4d_t *p4dp, p4d_t p4d); ++#else static inline void set_p4d(p4d_t *p4dp, p4d_t p4d) { - if (in_swapper_pgdir(p4dp)) { @@ -1835,21 +1929,15 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 set_swapper_pgd((pgd_t *)p4dp, __pgd(p4d_val(p4d))); return; } - -+#ifdef CONFIG_PTP -+ if(in_tramp_pgdir(p4dp)) -+ { -+ iee_set_tramp_pgd_pre_init((pgd_t *)p4dp, __pgd(p4d_val(p4d))); -+ return; -+ } -+ iee_rw_gate(IEE_OP_SET_P4D, p4dp, p4d); -+#else - WRITE_ONCE(*p4dp, p4d); -+#endif +@@ -781,6 +898,7 @@ static inline void set_p4d(p4d_t *p4dp, p4d_t p4d) dsb(ishst); isb(); } -@@ -800,6 +1058,12 @@ static inline pud_t *p4d_pgtable(p4d_t p4d) ++#endif + + static inline void p4d_clear(p4d_t *p4dp) + { +@@ -800,6 +918,12 @@ static inline pud_t *p4d_pgtable(p4d_t p4d) /* Find an entry in the first-level page table. */ #define pud_offset_phys(dir, addr) (p4d_page_paddr(READ_ONCE(*(dir))) + pud_index(addr) * sizeof(pud_t)) @@ -1862,7 +1950,7 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 #define pud_set_fixmap(addr) ((pud_t *)set_fixmap_offset(FIX_PUD, addr)) #define pud_set_fixmap_offset(p4d, addr) pud_set_fixmap(pud_offset_phys(p4d, addr)) #define pud_clear_fixmap() clear_fixmap(FIX_PUD) -@@ -826,6 +1090,10 @@ static inline pud_t *p4d_pgtable(p4d_t p4d) +@@ -826,6 +950,10 @@ static inline pud_t *p4d_pgtable(p4d_t p4d) #define pgd_ERROR(e) \ pr_err("%s:%d: bad pgd %016llx.\n", __FILE__, __LINE__, pgd_val(e)) @@ -1873,8 +1961,14 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 #define pgd_set_fixmap(addr) ((pgd_t *)set_fixmap_offset(FIX_PGD, addr)) #define pgd_clear_fixmap() clear_fixmap(FIX_PGD) -@@ -912,8 +1180,13 @@ static inline int __ptep_test_and_clear_young(struct vm_area_struct *vma, +@@ -910,10 +1038,19 @@ static inline int __ptep_test_and_clear_young(struct vm_area_struct *vma, + + pte = __ptep_get(ptep); do { ++ #ifdef CONFIG_KOI ++ if (pte_valid(pte)) ++ pte = __pte(pte_val(pte) | PTE_NG); ++ #endif old_pte = pte; pte = pte_mkold(pte); + #ifdef CONFIG_PTP @@ -1887,7 +1981,7 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 } while (pte_val(pte) != pte_val(old_pte)); return pte_young(pte); -@@ -952,8 +1225,12 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, +@@ -952,8 +1089,12 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, static inline pte_t __ptep_get_and_clear(struct mm_struct *mm, unsigned long address, pte_t *ptep) { @@ -1901,7 +1995,7 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 page_table_check_pte_clear(mm, pte); return pte; -@@ -995,7 +1272,12 @@ static inline pte_t __get_and_clear_full_ptes(struct mm_struct *mm, +@@ -995,7 +1136,12 @@ static inline pte_t __get_and_clear_full_ptes(struct mm_struct *mm, static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, unsigned long address, pmd_t *pmdp) { @@ -1914,8 +2008,15 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 page_table_check_pmd_clear(mm, pmd); -@@ -1012,8 +1294,12 @@ static inline void ___ptep_set_wrprotect(struct mm_struct *mm, +@@ -1010,10 +1156,19 @@ static inline void ___ptep_set_wrprotect(struct mm_struct *mm, + pte_t old_pte; + do { ++ #ifdef CONFIG_KOI ++ if (pte_valid(pte)) { ++ pte = __pte(pte_val(pte) | PTE_NG); ++ } ++ #endif old_pte = pte; pte = pte_wrprotect(pte); + #ifdef CONFIG_PTP @@ -1927,10 +2028,16 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 } while (pte_val(pte) != pte_val(old_pte)); } -@@ -1049,7 +1335,11 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma, +@@ -1089,7 +1244,17 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp, pmd_t pmd) { page_table_check_pmd_set(vma->vm_mm, pmdp, pmd); ++ #ifdef CONFIG_KOI ++ pmdval_t val = pmd_val(pmd); ++ if (pmd_valid(pmd) && !(val & PMD_TABLE_BIT)) { ++ pmd = __pmd(val | PMD_SECT_NG); ++ } ++ #endif + #ifdef CONFIG_PTP + return __pmd((pmdval_t)iee_set_xchg_relaxed((pte_t *)&pmd_val(*pmdp), (pmdval_t)pmd_val(pmd))); + #else @@ -1939,6 +2046,21 @@ index 8d68d00de0a4..6f8d5b85bfd7 100644 } #endif +diff --git a/arch/arm64/include/asm/pgtable_slab.h b/arch/arm64/include/asm/pgtable_slab.h +new file mode 100644 +index 000000000000..0674582a1948 +--- /dev/null ++++ b/arch/arm64/include/asm/pgtable_slab.h +@@ -0,0 +1,8 @@ ++#ifndef _LINUX_PGTABLE_SLAB_H ++#define _LINUX_PGTABLE_SLAB_H ++ ++extern void __init iee_pgtable_init(void); ++extern void *get_iee_pgtable_page(gfp_t gfpflags); ++extern void free_iee_pgtable_page(void *obj); ++ ++#endif +\ No newline at end of file diff --git a/arch/arm64/include/asm/pointer_auth.h b/arch/arm64/include/asm/pointer_auth.h index d2e0306e65d3..8352e92d4536 100644 --- a/arch/arm64/include/asm/pointer_auth.h @@ -1957,6 +2079,20 @@ index d2e0306e65d3..8352e92d4536 100644 isb(); } +diff --git a/arch/arm64/include/asm/stack_slab.h b/arch/arm64/include/asm/stack_slab.h +new file mode 100644 +index 000000000000..0a478828421e +--- /dev/null ++++ b/arch/arm64/include/asm/stack_slab.h +@@ -0,0 +1,8 @@ ++#ifndef _LINUX_STACK_SLAB_H ++#define _LINUX_STACK_SLAB_H ++ ++extern void __init iee_stack_init(void); ++extern void *get_iee_stack(void); ++extern void free_iee_stack(void *obj); ++ ++#endif diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 42358b8d678e..1e2d11e57fe3 100644 --- a/arch/arm64/include/asm/sysreg.h @@ -2027,29 +2163,43 @@ index 42358b8d678e..1e2d11e57fe3 100644 u64 par; \ asm(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412)); \ diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h -index 2c29239d05c3..955f99317790 100644 +index 2c29239d05c3..989c6d23632c 100644 --- a/arch/arm64/include/asm/tlb.h +++ b/arch/arm64/include/asm/tlb.h -@@ -11,8 +11,17 @@ +@@ -11,11 +11,31 @@ #include #include +#ifdef CONFIG_PTP +#include ++#include "pgtable_slab.h" +#endif + static inline void __tlb_remove_table(void *_table) { -+#ifdef CONFIG_PTP -+ unsigned long iee_addr = __phys_to_iee(page_to_phys((struct page *)_table)); -+ set_iee_page_invalid(iee_addr); -+ iee_set_logical_mem_rw((unsigned long)page_address((struct page *)_table)); -+#endif free_page_and_swap_cache((struct page *)_table); } ++#ifdef CONFIG_PTP ++static inline void __iee_tlb_remove_table(void *_table) ++{ ++ struct page *page = (struct page *)_table; ++ ++ if (!is_huge_zero_page(page)) ++ { ++ if (page_ref_dec_return(page) == 1) ++ { ++ free_iee_pgtable_page((void *)page_to_virt(page)); ++ } ++ } ++} ++#endif ++ + #define tlb_flush tlb_flush + static void tlb_flush(struct mmu_gather *tlb); + diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h -index 831c314d75ff..7775628528c6 100644 +index 831c314d75ff..d447a0e35a7c 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -49,6 +49,7 @@ @@ -2082,11 +2232,37 @@ index 831c314d75ff..7775628528c6 100644 } static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, -@@ -366,6 +375,45 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) +@@ -366,6 +375,7 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) * 2. If there is 1 page remaining, flush it through non-range operations. Range * operations can only span an even number of pages. */ +#if defined(CONFIG_IEE) || defined(CONFIG_KOI) + #define __flush_tlb_range_op(op, start, pages, stride, \ + asid, tlb_level, tlbi_user) \ + do { \ +@@ -378,6 +388,8 @@ do { \ + pages == 1) { \ + addr = __TLBI_VADDR(start, asid); \ + __tlbi_level(op, addr, tlb_level); \ ++ if (!arm64_kernel_unmapped_at_el0()) /* added for IEE */ \ ++ __tlbi_level(op, addr | USER_ASID_FLAG, tlb_level); \ + if (tlbi_user) \ + __tlbi_user_level(op, addr, tlb_level); \ + start += stride; \ +@@ -390,6 +402,8 @@ do { \ + addr = __TLBI_VADDR_RANGE(start, asid, scale, \ + num, tlb_level); \ + __tlbi(r##op, addr); \ ++ if (!arm64_kernel_unmapped_at_el0()) /* added for IEE */ \ ++ __tlbi(r##op, addr | USER_ASID_FLAG); \ + if (tlbi_user) \ + __tlbi_user(r##op, addr); \ + start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \ +@@ -399,6 +413,42 @@ do { \ + } \ + } while (0) + ++#else +#define __flush_tlb_range_op(op, start, pages, stride, \ + asid, tlb_level, tlbi_user) \ +do { \ @@ -2099,8 +2275,6 @@ index 831c314d75ff..7775628528c6 100644 + pages % 2 == 1) { \ + addr = __TLBI_VADDR(start, asid); \ + __tlbi_level(op, addr, tlb_level); \ -+ if (!arm64_kernel_unmapped_at_el0()) /* added for IEE */ \ -+ __tlbi_level(op, addr | USER_ASID_FLAG, tlb_level); \ + if (tlbi_user) \ + __tlbi_user_level(op, addr, tlb_level); \ + start += stride; \ @@ -2113,8 +2287,6 @@ index 831c314d75ff..7775628528c6 100644 + addr = __TLBI_VADDR_RANGE(start, asid, scale, \ + num, tlb_level); \ + __tlbi(r##op, addr); \ -+ if (!arm64_kernel_unmapped_at_el0()) /* added for IEE */ \ -+ __tlbi(r##op, addr | USER_ASID_FLAG); \ + if (tlbi_user) \ + __tlbi_user(r##op, addr); \ + start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \ @@ -2124,14 +2296,6 @@ index 831c314d75ff..7775628528c6 100644 + } \ +} while (0) + -+#else - #define __flush_tlb_range_op(op, start, pages, stride, \ - asid, tlb_level, tlbi_user) \ - do { \ -@@ -399,6 +447,8 @@ do { \ - } \ - } while (0) - +#endif //if defined(CONFIG_IEE) || defined(CONFIG_KOI) + #define __flush_s2_tlb_range_op(op, start, pages, stride, tlb_level) \ @@ -2160,7 +2324,7 @@ index 831c314d75ff..7775628528c6 100644 dsb(ish); isb(); diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile -index 21ef9c21a400..44eb76cc54d7 100644 +index 4ce58887302a..81dd446dc8a3 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -36,6 +36,8 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \ @@ -2173,7 +2337,7 @@ index 21ef9c21a400..44eb76cc54d7 100644 sys_compat.o obj-$(CONFIG_AARCH32_EL0) += sigreturn32.o diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c -index fd0f291e215e..c008e46b5fc0 100644 +index 87ac0b9c0b4f..f135db1d9965 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c @@ -306,11 +306,19 @@ static int cp15barrier_handler(struct pt_regs *regs, u32 instr) @@ -2217,27 +2381,29 @@ index fd0f291e215e..c008e46b5fc0 100644 static int __a32_setend_handler(struct pt_regs *regs, u32 big_endian) diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c -index e997ad275afb..e105f633355a 100644 +index e997ad275afb..f584b457a0f4 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c -@@ -97,6 +97,17 @@ int main(void) - DEFINE(FREGS_DIRECT_TRAMP, offsetof(struct ftrace_regs, direct_tramp)); - #endif +@@ -99,6 +99,19 @@ int main(void) DEFINE(FREGS_SIZE, sizeof(struct ftrace_regs)); + BLANK(); + #endif +#ifdef CONFIG_IEE + DEFINE(iee_from_token_offset, offsetof(struct task_token, iee_stack)); ++ DEFINE(tmp_page_from_token_offset, offsetof(struct task_token, tmp_page)); + DEFINE(kernel_from_token_offset, offsetof(struct task_token, kernel_stack)); + DEFINE(mm_from_task_offset, offsetof(struct task_struct, mm)); +#endif +#ifdef CONFIG_KOI + DEFINE(koi_kernel_from_token_offset, offsetof(struct task_token, koi_kernel_stack)); -+ DEFINE(koi_from_token_offset, offsetof(struct task_token, koi_stack)); -+ DEFINE(ttbr1_from_token_offset, offsetof(struct task_token, current_ttbr1)); -+ DEFINE(koi_stack_base_from_token_offset, offsetof(struct task_token, koi_stack_base)); ++ DEFINE(koi_from_token_offset, offsetof(struct task_token, koi_stack)); ++ DEFINE(ttbr1_from_token_offset, offsetof(struct task_token, current_ttbr1)); ++ DEFINE(koi_stack_base_from_token_offset, offsetof(struct task_token, koi_stack_base)); +#endif - BLANK(); - #endif ++ BLANK(); #ifdef CONFIG_AARCH32_EL0 + DEFINE(COMPAT_SIGFRAME_REGS_OFFSET, offsetof(struct a32_sigframe, uc.uc_mcontext.arm_r0)); + DEFINE(COMPAT_RT_SIGFRAME_REGS_OFFSET, offsetof(struct a32_rt_sigframe, sig.uc.uc_mcontext.arm_r0)); diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 46813132a09f..412006aa323c 100644 --- a/arch/arm64/kernel/cpu_errata.c @@ -2279,7 +2445,7 @@ index 46813132a09f..412006aa323c 100644 #ifdef CONFIG_HISILICON_ERRATUM_HIP08_RU_PREFETCH diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c -index 74e445251b51..ebc1e776b175 100644 +index a7b4ccd7983e..3c27722b6bfe 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -94,6 +94,10 @@ @@ -2293,7 +2459,7 @@ index 74e445251b51..ebc1e776b175 100644 /* Kernel representation of AT_HWCAP and AT_HWCAP2 */ static DECLARE_BITMAP(elf_hwcap, MAX_CPU_FEATURES) __read_mostly; -@@ -1612,7 +1616,11 @@ static void cpu_emulate_effective_ctr(const struct arm64_cpu_capabilities *__unu +@@ -1616,7 +1620,11 @@ static void cpu_emulate_effective_ctr(const struct arm64_cpu_capabilities *__unu * value. */ if (!(read_cpuid_cachetype() & BIT(CTR_EL0_IDC_SHIFT))) @@ -2305,7 +2471,7 @@ index 74e445251b51..ebc1e776b175 100644 } static bool has_cache_dic(const struct arm64_cpu_capabilities *entry, -@@ -1873,7 +1881,11 @@ static inline void __cpu_enable_hw_dbm(void) +@@ -1877,7 +1885,11 @@ static inline void __cpu_enable_hw_dbm(void) { u64 tcr = read_sysreg(tcr_el1) | TCR_HD; @@ -2317,7 +2483,7 @@ index 74e445251b51..ebc1e776b175 100644 isb(); local_flush_tlb_all(); } -@@ -2056,7 +2068,9 @@ static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused) +@@ -2060,7 +2072,9 @@ static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused) */ WARN_ON_ONCE(in_interrupt()); @@ -2327,7 +2493,7 @@ index 74e445251b51..ebc1e776b175 100644 set_pstate_pan(1); } #endif /* CONFIG_ARM64_PAN */ -@@ -2121,7 +2135,11 @@ static bool has_generic_auth(const struct arm64_cpu_capabilities *entry, +@@ -2125,7 +2139,11 @@ static bool has_generic_auth(const struct arm64_cpu_capabilities *entry, static void cpu_enable_e0pd(struct arm64_cpu_capabilities const *cap) { if (this_cpu_has_cap(ARM64_HAS_E0PD)) @@ -2339,7 +2505,7 @@ index 74e445251b51..ebc1e776b175 100644 } #endif /* CONFIG_ARM64_E0PD */ -@@ -2214,7 +2232,11 @@ static void nmi_enable(const struct arm64_cpu_capabilities *__unused) +@@ -2220,7 +2238,11 @@ static void nmi_enable(const struct arm64_cpu_capabilities *__unused) * avoid leaving things masked. */ _allint_clear(); @@ -2351,7 +2517,7 @@ index 74e445251b51..ebc1e776b175 100644 isb(); } #endif -@@ -2229,7 +2251,11 @@ static void bti_enable(const struct arm64_cpu_capabilities *__unused) +@@ -2235,7 +2257,11 @@ static void bti_enable(const struct arm64_cpu_capabilities *__unused) * So, be strict and forbid other BRs using other registers to * jump onto a PACIxSP instruction: */ @@ -2363,7 +2529,7 @@ index 74e445251b51..ebc1e776b175 100644 isb(); } #endif /* CONFIG_ARM64_BTI */ -@@ -2237,7 +2263,11 @@ static void bti_enable(const struct arm64_cpu_capabilities *__unused) +@@ -2243,7 +2269,11 @@ static void bti_enable(const struct arm64_cpu_capabilities *__unused) #ifdef CONFIG_ARM64_MTE static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap) { @@ -2375,7 +2541,7 @@ index 74e445251b51..ebc1e776b175 100644 mte_cpu_setup(); -@@ -2271,7 +2301,11 @@ static bool is_kvm_protected_mode(const struct arm64_cpu_capabilities *entry, in +@@ -2277,7 +2307,11 @@ static bool is_kvm_protected_mode(const struct arm64_cpu_capabilities *entry, in static void cpu_trap_el0_impdef(const struct arm64_cpu_capabilities *__unused) { @@ -2387,7 +2553,7 @@ index 74e445251b51..ebc1e776b175 100644 } static void cpu_enable_dit(const struct arm64_cpu_capabilities *__unused) -@@ -2281,7 +2315,11 @@ static void cpu_enable_dit(const struct arm64_cpu_capabilities *__unused) +@@ -2287,7 +2321,11 @@ static void cpu_enable_dit(const struct arm64_cpu_capabilities *__unused) static void cpu_enable_mops(const struct arm64_cpu_capabilities *__unused) { @@ -2399,7 +2565,7 @@ index 74e445251b51..ebc1e776b175 100644 } /* Internal helper functions to match cpu capability type */ -@@ -3475,6 +3513,43 @@ static void __init setup_system_capabilities(void) +@@ -3513,6 +3551,43 @@ static void __init setup_system_capabilities(void) enable_cpu_capabilities(SCOPE_ALL & ~SCOPE_BOOT_CPU); } @@ -2420,13 +2586,13 @@ index 74e445251b51..ebc1e776b175 100644 + // pr_info("IEE: testing iee_exec_entry afsr0...\n"); + // iee_rwx_gate_entry(IEE_WRITE_AFSR0); + #ifdef CONFIG_KOI -+ write_sysreg(read_sysreg(ttbr0_el1)+0x3000000000000, ttbr0_el1); + pr_info("IEE: current TTBR1_EL1:%llx, TTBR0:%llx\n", read_sysreg(ttbr1_el1), read_sysreg(ttbr0_el1)); + pr_info("IEE: testing iee_exec_entry switch to koi...\n"); -+ iee_rwx_gate_entry(IEE_SWITCH_TO_KOI, phys_to_ttbr(__pa_symbol(swapper_pg_dir))); ++ iee_rwx_gate_entry(IEE_SWITCH_TO_KOI, phys_to_ttbr(__pa_symbol(swapper_pg_dir)) | 3UL << 48); + pr_info("IEE: current TTBR1_EL1:%llx, TTBR0:%llx\n", read_sysreg(ttbr1_el1), read_sysreg(ttbr0_el1)); + pr_info("IEE: testing iee_exec_entry switch to kernel...\n"); + iee_rwx_gate_entry(IEE_SWITCH_TO_KERNEL); ++ pr_info("IEE: current TTBR1_EL1:%llx, TTBR0:%llx\n", read_sysreg(ttbr1_el1), read_sysreg(ttbr0_el1)); + #endif +} + @@ -2443,7 +2609,7 @@ index 74e445251b51..ebc1e776b175 100644 void __init setup_cpu_features(void) { u32 cwg; -@@ -3502,6 +3577,10 @@ void __init setup_cpu_features(void) +@@ -3540,6 +3615,10 @@ void __init setup_cpu_features(void) if (!cwg) pr_warn("No Cache Writeback Granule information, assuming %d\n", ARCH_DMA_MINALIGN); @@ -2490,10 +2656,10 @@ index 08274e4317b2..0d259e355c90 100644 regs->lockdep_hardirqs = lockdep_hardirqs_enabled(); diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S -index 7fcbee0f6c0e..dee813ee6aad 100644 +index 7fcbee0f6c0e..8ee531918781 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S -@@ -29,12 +29,391 @@ +@@ -29,12 +29,400 @@ #include #include @@ -2512,6 +2678,7 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 .endr .endm ++ +#ifdef CONFIG_KOI +#ifdef CONFIG_IEE +/* @@ -2588,12 +2755,17 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 + str x17, [sp, #16] + stp x30, x29, [sp] + -+ // current sp stores in x1 -+ add x1, x1, #176 ++ // current sp stores in x2 ++ add x2, x1, #176 + // current sp_el0 stores in x0 ++ mov x1, x0 ++ adrp x0, iee_offset ++ ldr x0, [x0, #:lo12:iee_offset] + bl _iee_write_koi_kernel_stack + -+ mrs x0, sp_el0 ++ adrp x0, iee_offset ++ ldr x0, [x0, #:lo12:iee_offset] ++ mrs x1, sp_el0 + bl _iee_read_koi_stack + + ldr x17, [sp, #16] @@ -2629,11 +2801,15 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 + stp x30, x29, [sp] + str x17, [sp, #16] + -+ mrs x0, sp_el0 -+ add x1, sp, #192 ++ adrp x0, iee_offset ++ ldr x0, [x0, #:lo12:iee_offset] ++ mrs x1, sp_el0 ++ add x2, sp, #192 + bl _iee_write_koi_stack + -+ mrs x0, sp_el0 ++ adrp x0, iee_offset ++ ldr x0, [x0, #:lo12:iee_offset] ++ mrs x1, sp_el0 + bl _iee_read_koi_kernel_stack + + ldr x17, [sp, #16] @@ -2756,7 +2932,7 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 + ret +SYM_FUNC_END(koi_switch_to_kernel_stack) +#endif -+ ++.pushsection ".koi.text", "ax" +SYM_FUNC_START(koi_switch_to_ko_pgtbl) + stp x0, x1, [sp, #16 * 1] + stp x2, x3, [sp, #16 * 2] @@ -2784,7 +2960,6 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 + and x2, x2, #~(THREAD_SIZE - 1) + cbnz x2, 1f + -+ bl koi_switch_to_ko_stack +1: +#ifndef CONFIG_IEE + msr ttbr1_el1, x19 @@ -2812,7 +2987,6 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 + ret +SYM_FUNC_END(koi_switch_to_ko_pgtbl) + -+.pushsection ".koi.text", "ax" +SYM_FUNC_START(koi_switch_to_kernel_pgtbl) + sub sp, sp, #160 + stp x0, x1, [sp, #16 * 0] @@ -2844,7 +3018,7 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 + ldr x1, [x1, #:lo12:koi_offset] + add x0, x0, x1 + mov x16, sp -+ ldr x17, [x0, koi_stack_base_from_token_offset] ++ ldr x17, [x0, #koi_stack_base_from_token_offset] + eor x17, x17, x16 + and x17, x17, #~(THREAD_SIZE - 1) + cbnz x17, 0f @@ -2853,7 +3027,9 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 + mrs x17, pan + // disable pan + msr pan, 0x0 -+ mrs x0, sp_el0 ++ adrp x0, iee_offset ++ ldr x0, [x0, #:lo12:iee_offset] ++ mrs x1, sp_el0 + bl _iee_read_koi_stack_base + // restore pan + msr pan, x17 @@ -2863,7 +3039,6 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 + and x0, x0, #~(THREAD_SIZE - 1) + cbnz x0, 0f +#endif -+ bl koi_switch_to_kernel_stack +0: + + ldp x0, x1, [sp, #16 * 0] @@ -2885,54 +3060,41 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 .macro kernel_ventry, el:req, ht:req, regsize:req, label:req .align 7 .Lventry_start\@: -@@ -151,6 +530,17 @@ alternative_else_nop_endif - #endif - .endm +@@ -53,6 +441,15 @@ + .Lskip_tramp_vectors_cleanup\@: + .endif -+#ifdef CONFIG_IEE -+// SP_EL0 check failed. -+SYM_FUNC_START_LOCAL(sp_el0_check_failed) -+ mov x0, sp -+ mov x1, #BAD_SP_EL0 -+ mrs x2, esr_el1 -+ bl iee_bad_mode -+ ASM_BUG() -+SYM_FUNC_END(sp_el0_check_failed) ++#ifdef CONFIG_KOI ++ .if \el == 1 ++ msr tpidrro_el0, x30 ++ bl koi_switch_to_kernel_pgtbl ++ mrs x30, tpidrro_el0 ++ msr tpidrro_el0, xzr ++ .endif +#endif + - /* Clear the MTE asynchronous tag check faults */ - .macro clear_mte_async_tcf thread_sctlr - #ifdef CONFIG_ARM64_MTE -@@ -224,6 +614,14 @@ alternative_cb_end - ldr_this_cpu tsk, __entry_task, x20 - msr sp_el0, tsk + sub sp, sp, #PT_REGS_SIZE + #ifdef CONFIG_VMAP_STACK + /* +@@ -320,6 +717,17 @@ alternative_else_nop_endif + msr_s SYS_ICC_PMR_EL1, x20 -+#ifdef CONFIG_IEE -+ // tsk check. -+ ldr_this_cpu x19, __entry_task, x20 -+ mrs x20, sp_el0 -+ cmp x19, x20 -+ b.ne sp_el0_check_failed + .Lskip_pmr_save\@: +#endif + - /* - * Ensure MDSCR_EL1.SS is clear, since we can unmask debug exceptions - * when scheduling. -@@ -276,6 +674,13 @@ alternative_else_nop_endif ++#ifndef CONFIG_IEE ++#ifdef CONFIG_KOI ++ // set tcr_el1 to choose asid from ttbr1_el1 or ttbr0_el1 ++ .if \el == 0 ++ mrs x0, tcr_el1 ++ orr x0, x0 ,#0x0000000000400000 ++ msr tcr_el1,x0 ++ .endif ++#endif + #endif - scs_load_current - .else -+#ifdef CONFIG_IEE -+ // tsk check. -+ ldr_this_cpu x19, __entry_task, x20 -+ mrs x20, sp_el0 -+ cmp x19, x20 -+ b.ne sp_el0_check_failed -+#endif - add x21, sp, #PT_REGS_SIZE - get_current_task tsk - .endif /* \el == 0 */ -@@ -333,9 +738,11 @@ alternative_else_nop_endif + /* +@@ -333,9 +741,11 @@ alternative_else_nop_endif .endm .macro kernel_exit, el @@ -2944,7 +3106,7 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 #ifdef CONFIG_ARM64_PSEUDO_NMI alternative_if_not ARM64_HAS_GIC_PRIO_MASKING -@@ -411,6 +818,41 @@ alternative_else_nop_endif +@@ -411,6 +821,41 @@ alternative_else_nop_endif msr elr_el1, x21 // set up the return data msr spsr_el1, x22 @@ -2986,7 +3148,39 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 ldp x0, x1, [sp, #16 * 0] ldp x2, x3, [sp, #16 * 1] ldp x4, x5, [sp, #16 * 2] -@@ -569,12 +1011,167 @@ SYM_CODE_START_LOCAL(__bad_stack) +@@ -451,13 +896,30 @@ alternative_if ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD + dsb nsh + alternative_else_nop_endif + eret ++ ++#ifdef CONFIG_IEE ++5: ++ // ELR_EL1 check fail ++ mov x0, sp ++ mov x1, #BAD_ELR_EL1 ++ mrs x2, esr_el1 ++ bl iee_bad_mode ++ ASM_BUG() ++#endif ++ + .else + ldr lr, [sp, #S_LR] + add sp, sp, #PT_REGS_SIZE // restore sp + + /* Ensure any device/NC reads complete */ + alternative_insn nop, "dmb sy", ARM64_WORKAROUND_1508412 +- ++#ifdef CONFIG_KOI ++ sub sp, sp, #176 ++ stp x30, x19, [sp, #16 * 0] ++ bl koi_switch_to_ko_pgtbl ++ ldp x30, x19, [sp, #16 * 0] ++ add sp, sp, #176 ++#endif + eret + .endif + sb +@@ -569,12 +1031,167 @@ SYM_CODE_START_LOCAL(__bad_stack) SYM_CODE_END(__bad_stack) #endif /* CONFIG_VMAP_STACK */ @@ -2999,7 +3193,7 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 + ldr x1, =__iee_si_no_irq + cmp x1, x22 + b.hi 1148f -+ ldr x1, =__iee_si_end ++ ldr x1, =__iee_si_text_end + cmp x1, x22 + b.lo 1148f + /* ELR check fail */ @@ -3154,34 +3348,22 @@ index 7fcbee0f6c0e..dee813ee6aad 100644 .if \el == 0 b ret_to_user .else -@@ -844,6 +1441,13 @@ SYM_FUNC_START(cpu_switch_to) - ldr lr, [x8] - mov sp, x9 - msr sp_el0, x1 -+#ifdef CONFIG_IEE -+ // tsk check. -+ ldr_this_cpu x8, __entry_task, x9 -+ mrs x9, sp_el0 -+ cmp x8, x9 -+ b.ne sp_el0_check_failed -+#endif - ptrauth_keys_install_kernel x1, x8, x9, x10 - scs_save x0 - scs_load_current -@@ -1033,6 +1637,13 @@ SYM_CODE_START(__sdei_asm_handler) - mrs x28, sp_el0 - ldr_this_cpu dst=x0, sym=__entry_task, tmp=x1 - msr sp_el0, x0 -+#ifdef CONFIG_IEE -+ // tsk check. -+ ldr_this_cpu x0, __entry_task, x1 -+ mrs x1, sp_el0 -+ cmp x0, x1 -+ b.ne sp_el0_check_failed +@@ -606,9 +1223,15 @@ SYM_CODE_END(el\el\ht\()_\regsize\()_\label) + entry_handler 0, t, 32, fiq + entry_handler 0, t, 32, error + ++#ifdef CONFIG_KOI ++.pushsection ".koi.text", "ax" ++#endif + SYM_CODE_START_LOCAL(ret_to_kernel) + kernel_exit 1 + SYM_CODE_END(ret_to_kernel) ++#ifdef CONFIG_KOI ++.popsection +#endif - /* If we interrupted the kernel point to the previous stack/frame. */ - and x0, x3, #0xc + SYM_CODE_START_LOCAL(ret_to_user) + ldr x19, [tsk, #TSK_TI_FLAGS] // re-check for single-step diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 5cdfcc9e3e54..c0af965bd92e 100644 --- a/arch/arm64/kernel/fpsimd.c @@ -3199,84 +3381,18 @@ index 5cdfcc9e3e54..c0af965bd92e 100644 } diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S -index 6517bf2644a0..5c75e069d877 100644 +index 6517bf2644a0..3d0716d59c0b 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S -@@ -464,6 +464,42 @@ SYM_FUNC_END(create_kernel_mapping) - set_this_cpu_offset \tmp1 - .endm - -+#ifdef CONFIG_IEE -+ .macro init_cpu_task_checked tsk, tmp1, tmp2 -+ msr sp_el0, \tsk -+ // tsk check. -+ adrp x29, __per_cpu_offset -+ mrs \tmp1, sp_el0 -+ ldr \tmp2, [\tmp1, #TSK_TI_CPU] /* cpu number */ -+1: -+ cmp \tmp2, #0 -+ b.eq 2f -+ add x29, x29, #8 -+ sub \tmp2, \tmp2, #1 -+ b 1b -+2: -+ ldr \tmp2, [x29, #:lo12:__per_cpu_offset] /* cpu offset */ -+ adr_l x29, __entry_task -+ ldr x29, [x29, \tmp2] -+ cmp x29, \tmp1 -+ b.ne sp_el0_check_failed -+ -+ ldr \tmp1, [\tsk, #TSK_STACK] -+ add sp, \tmp1, #THREAD_SIZE -+ sub sp, sp, #PT_REGS_SIZE -+ -+ stp xzr, xzr, [sp, #S_STACKFRAME] -+ add x29, sp, #S_STACKFRAME -+ -+ scs_load_current -+ -+ adr_l \tmp1, __per_cpu_offset -+ ldr w\tmp2, [\tsk, #TSK_TI_CPU] -+ ldr \tmp1, [\tmp1, \tmp2, lsl #3] -+ set_this_cpu_offset \tmp1 -+ .endm -+#endif -+ - /* - * The following fragment of code is executed with the MMU enabled. - * -@@ -661,6 +697,18 @@ SYM_FUNC_START_LOCAL(secondary_startup) +@@ -661,6 +661,7 @@ SYM_FUNC_START_LOCAL(secondary_startup) SYM_FUNC_END(secondary_startup) .text -+#ifdef CONFIG_IEE -+// SP_EL0 check failed. -+SYM_FUNC_START_LOCAL(sp_el0_check_failed) -+ 1: -+ nop -+ nop -+ nop -+ nop -+ b 1f -+SYM_FUNC_END(sp_el0_check_failed) -+#endif + SYM_FUNC_START_LOCAL(__secondary_switched) mov x0, x20 bl set_cpu_boot_mode_flag -@@ -677,7 +725,11 @@ SYM_FUNC_START_LOCAL(__secondary_switched) - ldr x2, [x0, #CPU_BOOT_TASK] - cbz x2, __secondary_too_slow - -+#ifdef CONFIG_IEE -+ init_cpu_task_checked x2, x1, x3 -+#else - init_cpu_task x2, x1, x3 -+#endif - - #ifdef CONFIG_ARM64_PTR_AUTH - ptrauth_keys_init_cpu x2, x3, x4, x5 -@@ -746,6 +798,10 @@ SYM_FUNC_START(__enable_mmu) +@@ -746,6 +747,10 @@ SYM_FUNC_START(__enable_mmu) cmp x3, #ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX b.gt __no_granule_support phys_to_ttbr x2, x2 @@ -3288,7 +3404,7 @@ index 6517bf2644a0..5c75e069d877 100644 load_ttbr1 x1, x1, x3 diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c -index 02870beb271e..1c14428a3ed4 100644 +index 02870beb271e..76d86b3d71b1 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -34,6 +34,10 @@ @@ -3302,24 +3418,13 @@ index 02870beb271e..1c14428a3ed4 100644 /* * Hibernate core relies on this value being 0 on resume, and marks it * __nosavedata assuming it will keep the resume kernel's '0' value. This -@@ -197,12 +201,22 @@ static int create_safe_exec_page(void *src_start, size_t length, - phys_addr_t trans_ttbr0; - unsigned long t0sz; - int rc; -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; -+ #endif - - if (!page) - return -ENOMEM; +@@ -203,6 +207,11 @@ static int create_safe_exec_page(void *src_start, size_t length, memcpy(page, src_start, length); caches_clean_inval_pou((unsigned long)page, (unsigned long)page + length); + + #ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(page_address(page))); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)page_address(page)); ++ set_iee_page((unsigned long)page_address(page),0); + #endif + rc = trans_pgd_idmap_page(&trans_info, &trans_ttbr0, &t0sz, page); @@ -3474,18 +3579,22 @@ index d39a8787edf2..b5ac4b7670bc 100644 slot = &slots[i]; diff --git a/arch/arm64/kernel/iee/Makefile b/arch/arm64/kernel/iee/Makefile new file mode 100644 -index 000000000000..123c68c5cc4e +index 000000000000..1d4436f06af4 --- /dev/null +++ b/arch/arm64/kernel/iee/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_IEE) += iee.o iee-gate.o iee-func.o +@@ -0,0 +1,5 @@ ++ccflags-$(CONFIG_IEE_SELINUX_P) := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include ++ ++obj-$(CONFIG_IEE) += iee.o iee-gate.o iee-func.o iee-pgtable.o stack_slab.o pgtable_slab.o iee-key.o ++ ++obj-$(CONFIG_IEE_SELINUX_P) += iee-selinuxp.o \ No newline at end of file diff --git a/arch/arm64/kernel/iee/iee-func.c b/arch/arm64/kernel/iee/iee-func.c new file mode 100644 -index 000000000000..7764dbd41555 +index 000000000000..76538e75edd2 --- /dev/null +++ b/arch/arm64/kernel/iee/iee-func.c -@@ -0,0 +1,187 @@ +@@ -0,0 +1,720 @@ +#include "asm/pgtable.h" +#include +#include @@ -3493,118 +3602,555 @@ index 000000000000..7764dbd41555 +#include +#include + -+void set_iee_page_valid(unsigned long addr) ++extern s64 iee_offset; ++extern void iee_memset(void *ptr, int data, size_t n); ++extern void iee_split_huge_pmd(pmd_t *pmdp, pte_t *pgtable); ++#ifdef CONFIG_PTP ++extern phys_addr_t __init early_pgtable_alloc(int shift); ++#endif ++ ++static inline void iee_set_token(pte_t *ptep, void *new, unsigned long order) +{ -+ pgd_t *pgdir = swapper_pg_dir; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++#ifdef CONFIG_PTP ++ pgd_t *pgdir; ++ pgd_t *pgdp; ++ p4d_t *p4dp; ++ pud_t *pudp; ++ pmd_t *pmdp; ++ int use_block_pmd = 0; + -+ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ pgdir = swapper_pg_dir; ++ pgdp = pgd_offset_pgd(pgdir, (unsigned long)new); ++ p4dp = p4d_offset(pgdp, (unsigned long)new); ++ pudp = pud_offset(p4dp, (unsigned long)new); ++ pmdp = pmd_offset(pudp, (unsigned long)new); + -+ pud_t *pudp = pud_offset(p4dp, addr); ++ // Handling cont mapping. ++ if(pmd_val(*pmdp) & PTE_CONT) ++ { ++ // The beginning of cont mapping. ++ int i; ++ pmd_t *pmdp = pmd_offset(pudp, (unsigned long)new & CONT_PMD_MASK); ++ for(i = 0; i < CONT_PMDS; i++) ++ { ++ set_pmd(pmdp,__pmd(pmd_val(*pmdp) & ~PTE_CONT)); ++ pmdp++; ++ } ++ } + -+ pmd_t *pmdp = pmd_offset(pudp, addr); ++ // Use Block Descriptor. ++ if(pmd_leaf(*pmdp)) ++ { ++ #ifndef CONFIG_PTP ++ struct page *page = pmd_page(*pmdp); ++ #endif ++ pte_t *pgtable = pte_alloc_one_kernel(&init_mm); + -+ pte_t *ptep = pte_offset_kernel(pmdp, addr); -+ pte_t pte = READ_ONCE(*ptep); ++ if (!pgtable) ++ panic("Alloc pgtable error.\n"); + -+ if((addr < (PAGE_OFFSET + IEE_OFFSET)) | (addr > (PAGE_OFFSET + BIT(vabits_actual - 1)))) -+ return; ++ iee_split_huge_pmd(pmdp, pgtable); + -+ pte = __pte(pte_val(pte) | 0x1); -+ set_pte(ptep, pte); -+ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); -+ isb(); -+} ++ spinlock_t *ptl = pmd_lock(&init_mm, pmdp); ++ if(pmd_leaf(READ_ONCE(*pmdp))) ++ { ++ smp_wmb(); ++ pmd_populate_kernel(&init_mm, pmdp, pgtable); ++ pgtable = NULL; ++ } ++ spin_unlock(ptl); + -+void set_iee_page_invalid(unsigned long addr) -+{ -+ pgd_t *pgdir = swapper_pg_dir; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ if(pgtable) ++ { ++ #ifdef CONFIG_PTP ++ iee_memset(pgtable, 0, PAGE_SIZE); ++ #endif ++ pte_free_kernel(&init_mm, pgtable); ++ } ++ } ++ else if(pmd_leaf(*pmdp)) ++ { ++ use_block_pmd = 1; ++ } + -+ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ iee_rw_gate(IEE_SET_TOKEN, ptep, new, order, use_block_pmd); ++#else ++ int i; ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, new); ++ p4d_t *p4dp = p4d_offset(pgdp, new); ++ pud_t *pudp = pud_offset(p4dp, new); ++ pmd_t *pmdp; ++ pte_t *lm_ptep; ++ pte_t *iee_ptep; ++ unsigned long iee_addr; ++ int use_block_pmd = 0; + -+ pud_t *pudp = pud_offset(p4dp, addr); ++ pmdp = pmd_offset(pudp, new); + -+ pmd_t *pmdp = pmd_offset(pudp, addr); ++ // Handling cont mapping. ++ if(pmd_val(*pmdp) & PTE_CONT) ++ { ++ // The beginning of cont mapping. ++ int i; ++ pmd_t *pmdp = pmd_offset(pudp, (unsigned long)new & CONT_PMD_MASK); ++ for(i = 0; i < CONT_PMDS; i++) ++ { ++ set_pmd(pmdp,__pmd(pmd_val(*pmdp) & ~PTE_CONT)); ++ pmdp++; ++ } ++ } + -+ pte_t *ptep = pte_offset_kernel(pmdp, addr); -+ pte_t pte = READ_ONCE(*ptep); ++ // Use Block Descriptor. ++ if(pmd_leaf(*pmdp) && order < 9) ++ { ++ struct page *page = pmd_page(*pmdp); ++ pte_t *pgtable = pte_alloc_one_kernel(&init_mm); ++ int i; ++ pte_t *ptep = pgtable; + -+ if((addr < (PAGE_OFFSET + IEE_OFFSET)) | (addr > (PAGE_OFFSET + BIT(vabits_actual - 1)))) -+ return; ++ if (!pgtable) ++ panic("Alloc pgtable error.\n"); + -+ pte = __pte(pte_val(pte) & ~0x1); -+ set_pte(ptep, pte); -+ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); -+ isb(); -+} ++ for (i = 0; i < PMD_SIZE / PAGE_SIZE; i++, ptep++) { ++ pte_t entry; ++ pgprot_t pgprot = PAGE_KERNEL; ++ pgprot = __pgprot(pgprot_val(pgprot) | PTE_CONT); + -+void iee_set_logical_mem_ro(unsigned long addr) -+{ -+ pgd_t *pgdir = swapper_pg_dir; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ entry = mk_pte(page + i, pgprot); ++ set_pte(ptep, entry); ++ } + -+ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ spin_lock(&init_mm.page_table_lock); ++ if(pmd_leaf(READ_ONCE(*pmdp))) ++ { ++ smp_wmb(); ++ pmd_populate_kernel(&init_mm, pmdp, pgtable); ++ pgtable = NULL; ++ } ++ spin_unlock(&init_mm.page_table_lock); + -+ pud_t *pudp = pud_offset(p4dp, addr); ++ if(pgtable) ++ { ++ pte_free_kernel(&init_mm, pgtable); ++ } ++ } ++ else if(pmd_leaf(*pmdp)) ++ { ++ use_block_pmd = 1; ++ } + -+ pmd_t *pmdp = pmd_offset(pudp, addr); ++ if(use_block_pmd) ++ lm_ptep = (pte_t *)pmdp; ++ else ++ lm_ptep = pte_offset_kernel(pmdp, new); + -+ pte_t *ptep = pte_offset_kernel(pmdp, addr); -+ pte_t pte = READ_ONCE(*ptep); ++ // Handling cont mapping. ++ if(pte_val(*lm_ptep) & PTE_CONT) ++ { ++ // The beginning of cont mapping. ++ int i; ++ pte_t *ptep = pte_offset_kernel(pmdp, (unsigned long)new & CONT_PTE_MASK); ++ if(order < CONFIG_ARM64_CONT_PTE_SHIFT) ++ { ++ for(i = 0; i < CONT_PTES; i++) ++ { ++ set_pte(ptep,__pte(pte_val(*ptep) & ~PTE_CONT)); ++ ptep++; ++ } ++ } ++ } ++ ++ iee_addr = ((unsigned long)new + (unsigned long)iee_offset); ++ pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ p4dp = p4d_offset(pgdp, iee_addr); ++ pudp = pud_offset(p4dp, iee_addr); ++ pmdp = pmd_offset(pudp, iee_addr); ++ iee_ptep = pte_offset_kernel(pmdp, iee_addr); ++ ++ if(use_block_pmd) ++ { ++ pmd_t *pmdp = (pmd_t *)lm_ptep; ++ pmd_t pmd = READ_ONCE(*pmdp); ++ pmd = __pmd((pmd_val(pmd) | PMD_SECT_RDONLY) & ~PTE_DBM); ++ WRITE_ONCE(*pmdp, pmd); ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) | 0x1) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(new))); ++ WRITE_ONCE(*ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) | 0x1); ++ WRITE_ONCE(*iee_ptep, pte); ++ ptep++; ++ iee_ptep++; ++ new += PAGE_SIZE; ++ } ++ } ++ else ++ { ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) | 0x1) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(new))); ++ WRITE_ONCE(*ptep, pte); ++ pte = READ_ONCE(*lm_ptep); ++ pte = __pte((pte_val(pte) | PTE_RDONLY) & ~PTE_DBM); ++ WRITE_ONCE(*lm_ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) | 0x1); ++ WRITE_ONCE(*iee_ptep, pte); ++ ptep++; ++ lm_ptep++; ++ iee_ptep++; ++ new += PAGE_SIZE; ++ } ++ } ++#endif ++ dsb(ishst); ++ isb(); ++} + -+ if(addr < PAGE_OFFSET) -+ return; ++static inline void iee_unset_token(pte_t *ptep, void *token_addr, void *token_page, unsigned long order) ++{ ++#ifdef CONFIG_PTP ++ iee_rw_gate(IEE_UNSET_TOKEN, ptep, token_addr, token_page, order); ++#else ++ int i; ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, token_page); ++ p4d_t *p4dp = p4d_offset(pgdp, token_page); ++ pud_t *pudp = pud_offset(p4dp, token_page); ++ pmd_t *pmdp = pmd_offset(pudp, token_page); ++ pte_t *lm_ptep; ++ pte_t *iee_ptep; ++ unsigned long iee_addr; ++ int use_block_pmd = 0; + -+ pte = __pte((pte_val(pte) | PTE_RDONLY) & ~PTE_DBM); -+ set_pte(ptep, pte); -+ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); ++ // Use Block Descriptor. ++ if(pmd_leaf(*pmdp)) ++ { ++ use_block_pmd = 1; ++ lm_ptep = (pte_t *)pmdp; ++ } ++ else ++ lm_ptep = pte_offset_kernel(pmdp, token_page); ++ ++ iee_addr = ((unsigned long)token_page + (unsigned long)iee_offset); ++ pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ p4dp = p4d_offset(pgdp, iee_addr); ++ pudp = pud_offset(p4dp, iee_addr); ++ pmdp = pmd_offset(pudp, iee_addr); ++ iee_ptep = pte_offset_kernel(pmdp, iee_addr); ++ ++ if(use_block_pmd) ++ { ++ pmd_t *pmdp = (pmd_t *)lm_ptep; ++ pmd_t pmd = READ_ONCE(*pmdp); ++ pmd = __pmd(pmd_val(pmd) | PTE_DBM); ++ WRITE_ONCE(*pmdp, pmd); ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) & ~((unsigned long)0x1)) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(token_addr - IEE_OFFSET))); ++ WRITE_ONCE(*ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) & ~0x1); ++ WRITE_ONCE(*iee_ptep, pte); ++ ptep++; ++ iee_ptep++; ++ token_addr += PAGE_SIZE; ++ token_page += PAGE_SIZE; ++ } ++ } ++ else ++ { ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) & ~((unsigned long)0x1)) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(token_addr - IEE_OFFSET))); ++ WRITE_ONCE(*ptep, pte); ++ pte = READ_ONCE(*lm_ptep); ++ pte = __pte(pte_val(pte) | PTE_DBM); ++ WRITE_ONCE(*lm_ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) & ~0x1); ++ WRITE_ONCE(*iee_ptep, pte); ++ ptep++; ++ lm_ptep++; ++ iee_ptep++; ++ token_addr += PAGE_SIZE; ++ token_page += PAGE_SIZE; ++ } ++ } ++#endif ++ dsb(ishst); + isb(); +} + -+void iee_set_logical_mem_rw(unsigned long addr) ++// Input is the lm vaddr of sensitive data. ++void set_iee_page(unsigned long addr, int order) +{ + pgd_t *pgdir = swapper_pg_dir; + pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); -+ + p4d_t *p4dp = p4d_offset(pgdp, addr); -+ + pud_t *pudp = pud_offset(p4dp, addr); ++ pmd_t *pmdp; ++ pte_t *lm_ptep; ++ pte_t *iee_ptep; ++ unsigned long iee_addr; ++ int use_block_pmd = 0; + -+ pmd_t *pmdp = pmd_offset(pudp, addr); ++ pmdp = pmd_offset(pudp, addr); + -+ pte_t *ptep = pte_offset_kernel(pmdp, addr); -+ pte_t pte = READ_ONCE(*ptep); ++ // Handling cont mapping. ++ if(pmd_val(*pmdp) & PTE_CONT) ++ { ++ // The beginning of cont mapping. ++ int i; ++ pmd_t *pmdp = pmd_offset(pudp, addr & CONT_PMD_MASK); ++ for(i = 0; i < CONT_PMDS; i++) ++ { ++ set_pmd(pmdp,__pmd(pmd_val(*pmdp) & ~PTE_CONT)); ++ pmdp++; ++ } ++ } + -+ if((addr < PAGE_OFFSET) | (addr > (PAGE_OFFSET + BIT(vabits_actual - 2)))) -+ return; -+ -+ pte = __pte(pte_val(pte) | PTE_DBM); -+ set_pte(ptep, pte); -+ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); -+ isb(); -+} ++ // Use Block Descriptor. ++ if(pmd_leaf(*pmdp) && order < 9) ++ { ++ #ifndef CONFIG_PTP ++ struct page *page = pmd_page(*pmdp); ++ #endif ++ pte_t *pgtable = pte_alloc_one_kernel(&init_mm); + -+void iee_set_token_page_valid(void *token, void *new) -+{ -+ pgd_t *pgdir = swapper_pg_dir; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, (unsigned long)token); ++ if (!pgtable) ++ panic("Alloc pgtable error.\n"); + -+ p4d_t *p4dp = p4d_offset(pgdp, (unsigned long)token); ++ #ifdef CONFIG_PTP ++ iee_split_huge_pmd(pmdp, pgtable); ++ #else ++ { ++ int i; ++ pte_t *ptep = pgtable; ++ for (i = 0; i < PMD_SIZE / PAGE_SIZE; i++, ptep++) { ++ pte_t entry; ++ pgprot_t pgprot = PAGE_KERNEL; ++ pgprot = __pgprot(pgprot_val(pgprot) | PTE_CONT); ++ ++ entry = mk_pte(page + i, pgprot); ++ set_pte(ptep, entry); ++ } ++ } ++ #endif + -+ pud_t *pudp = pud_offset(p4dp, (unsigned long)token); ++ spinlock_t *ptl = pmd_lock(&init_mm, pmdp); ++ if(pmd_leaf(READ_ONCE(*pmdp))) ++ { ++ smp_wmb(); ++ pmd_populate_kernel(&init_mm, pmdp, pgtable); ++ pgtable = NULL; ++ } ++ spin_unlock(ptl); + -+ pmd_t *pmdp = pmd_offset(pudp, (unsigned long)token); ++ if(pgtable) ++ { ++ #ifdef CONFIG_PTP ++ iee_memset(pgtable, 0, PAGE_SIZE); ++ #endif ++ pte_free_kernel(&init_mm, pgtable); ++ } ++ } ++ else if(pmd_leaf(*pmdp)) ++ { ++ use_block_pmd = 1; ++ } + -+ pte_t *ptep = pte_offset_kernel(pmdp, (unsigned long)token); -+ pte_t pte = READ_ONCE(*ptep); -+ pte = __pte(((pte_val(pte) | 0x1) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(new))); -+ set_pte(ptep, pte); -+ flush_tlb_kernel_range((unsigned long)token, (unsigned long)(token+PAGE_SIZE)); ++ if(use_block_pmd) ++ lm_ptep = (pte_t *)pmdp; ++ else ++ lm_ptep = pte_offset_kernel(pmdp, addr); ++ ++ // Handling cont mapping. ++ if(pte_val(*lm_ptep) & PTE_CONT) ++ { ++ // The beginning of cont mapping. ++ int i; ++ pte_t *ptep = pte_offset_kernel(pmdp, addr & CONT_PTE_MASK); ++ if(order < CONFIG_ARM64_CONT_PTE_SHIFT) ++ { ++ for(i = 0; i < CONT_PTES; i++) ++ { ++ set_pte(ptep,__pte(pte_val(*ptep) & ~PTE_CONT)); ++ ptep++; ++ } ++ } ++ } ++ ++ iee_addr = ((unsigned long)addr + (unsigned long)iee_offset); ++ pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ p4dp = p4d_offset(pgdp, iee_addr); ++ pudp = pud_offset(p4dp, iee_addr); ++ pmdp = pmd_offset(pudp, iee_addr); ++ iee_ptep = pte_offset_kernel(pmdp, iee_addr); ++ iee_set_sensitive_pte(lm_ptep, iee_ptep, order, use_block_pmd); ++ flush_tlb_kernel_range(addr, addr+PAGE_SIZE*(1 << order)); ++ isb(); ++} ++ ++// Input is the lm vaddr of sensitive data. ++void unset_iee_page(unsigned long addr, int order) ++{ ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ pud_t *pudp = pud_offset(p4dp, addr); ++ pmd_t *pmdp = pmd_offset(pudp, addr); ++ pte_t *lm_ptep; ++ pte_t *iee_ptep; ++ unsigned long iee_addr; ++ int use_block_pmd = 0; ++ ++ // Use Block Descriptor. ++ if(pmd_leaf(*pmdp)) ++ { ++ use_block_pmd = 1; ++ lm_ptep = (pte_t *)pmdp; ++ } ++ else ++ lm_ptep = pte_offset_kernel(pmdp, addr); ++ ++ iee_addr = ((unsigned long)addr + (unsigned long)iee_offset); ++ pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ p4dp = p4d_offset(pgdp, iee_addr); ++ pudp = pud_offset(p4dp, iee_addr); ++ pmdp = pmd_offset(pudp, iee_addr); ++ iee_ptep = pte_offset_kernel(pmdp, iee_addr); ++ iee_unset_sensitive_pte(lm_ptep, iee_ptep, order, use_block_pmd); ++ flush_tlb_kernel_range(addr, addr+PAGE_SIZE*(1 << order)); ++ flush_tlb_kernel_range(iee_addr, iee_addr+PAGE_SIZE*(1 << order)); ++ isb(); ++} ++ ++void set_iee_page_valid(unsigned long addr) ++{ ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ ++ pud_t *pudp = pud_offset(p4dp, addr); ++ ++ pmd_t *pmdp = pmd_offset(pudp, addr); ++ ++ pte_t *ptep = pte_offset_kernel(pmdp, addr); ++ pte_t pte = READ_ONCE(*ptep); ++ ++ if((addr < (PAGE_OFFSET + IEE_OFFSET)) | (addr > (PAGE_OFFSET + BIT(vabits_actual - 1)))) ++ return; ++ ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ set_pte(ptep, pte); ++} ++ ++void iee_set_logical_mem_ro(unsigned long addr) ++{ ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ pud_t *pudp = pud_offset(p4dp, addr); ++ pmd_t *pmdp; ++ pte_t *ptep; ++ pte_t pte; ++ ++ pmdp = pmd_offset(pudp, addr); ++ ++ // Handling cont mapping. ++ if(pmd_val(*pmdp) & PTE_CONT) ++ { ++ // The beginning of cont mapping. ++ int i; ++ pmd_t *pmdp = pmd_offset(pudp, addr & CONT_PMD_MASK); ++ for(i = 0; i < CONT_PMDS; i++) ++ { ++ set_pmd(pmdp,__pmd(pmd_val(*pmdp) & ~PTE_CONT)); ++ pmdp++; ++ } ++ } ++ ++ // Use Block Descriptor. ++ if(pmd_leaf(*pmdp)) ++ { ++ #ifndef CONFIG_PTP ++ struct page *page = pmd_page(*pmdp); ++ #endif ++ pte_t *pgtable = pte_alloc_one_kernel(&init_mm); ++ ++ if (!pgtable) ++ panic("Alloc pgtable error.\n"); ++ ++ #ifdef CONFIG_PTP ++ iee_split_huge_pmd(pmdp, pgtable); ++ #else ++ { ++ int i; ++ pte_t *ptep = pgtable; ++ for (i = 0; i < PMD_SIZE / PAGE_SIZE; i++, ptep++) { ++ pte_t entry; ++ pgprot_t pgprot = PAGE_KERNEL; ++ pgprot = __pgprot(pgprot_val(pgprot) | PTE_CONT); ++ ++ entry = mk_pte(page + i, pgprot); ++ set_pte(ptep, entry); ++ } ++ } ++ #endif ++ ++ spinlock_t *ptl = pmd_lock(&init_mm, pmdp); ++ if(pmd_leaf(READ_ONCE(*pmdp))) ++ { ++ smp_wmb(); ++ pmd_populate_kernel(&init_mm, pmdp, pgtable); ++ pgtable = NULL; ++ } ++ spin_unlock(ptl); ++ ++ if(pgtable) ++ { ++ #ifdef CONFIG_PTP ++ iee_memset(pgtable, 0, PAGE_SIZE); ++ #endif ++ pte_free_kernel(&init_mm, pgtable); ++ } ++ } ++ ++ ptep = pte_offset_kernel(pmdp, addr); ++ ++ // Handling cont mapping. ++ if(pte_val(*ptep) & PTE_CONT) ++ { ++ // The beginning of cont mapping. ++ int i; ++ pte_t *ptep = pte_offset_kernel(pmdp, addr & CONT_PTE_MASK); ++ for(i = 0; i < CONT_PTES; i++) ++ { ++ set_pte(ptep,__pte(pte_val(*ptep) & ~PTE_CONT)); ++ ptep++; ++ } ++ } ++ ++ pte = READ_ONCE(*ptep); ++ ++ if(addr < PAGE_OFFSET) ++ return; ++ ++ pte = __pte((pte_val(pte) | PTE_RDONLY) & ~PTE_DBM); ++ set_pte(ptep, pte); ++ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); + isb(); +} + -+void iee_set_token_page_invalid(void *token) ++void iee_set_token_page_valid(void *token, void *new, unsigned int order) +{ + pgd_t *pgdir = swapper_pg_dir; + pgd_t *pgdp = pgd_offset_pgd(pgdir, (unsigned long)token); @@ -3616,77 +4162,281 @@ index 000000000000..7764dbd41555 + pmd_t *pmdp = pmd_offset(pudp, (unsigned long)token); + + pte_t *ptep = pte_offset_kernel(pmdp, (unsigned long)token); -+ pte_t pte = READ_ONCE(*ptep); -+ pte = __pte(((pte_val(pte) & ~((unsigned long)0x1)) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(token - IEE_OFFSET))); -+ set_pte(ptep, pte); -+ flush_tlb_kernel_range((unsigned long)token, (unsigned long)(token+PAGE_SIZE)); ++ iee_set_token(ptep, new, order); ++ ++ flush_tlb_kernel_range((unsigned long)token, (unsigned long)(token + (PAGE_SIZE * (1 << order)))); ++ flush_tlb_kernel_range((unsigned long)new, (unsigned long)(new + (PAGE_SIZE * (1 << order)))); ++ + isb(); +} + -+void iee_set_kernel_ppage(unsigned long addr) ++void iee_set_token_page_invalid(void *token_addr, void *token_page, unsigned long order) +{ ++ unsigned long iee_addr = ((unsigned long)token_page + (unsigned long)iee_offset); + pgd_t *pgdir = swapper_pg_dir; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, (unsigned long)token_addr); ++ p4d_t *p4dp = p4d_offset(pgdp, (unsigned long)token_addr); ++ pud_t *pudp = pud_offset(p4dp, (unsigned long)token_addr); ++ pmd_t *pmdp = pmd_offset(pudp, (unsigned long)token_addr); ++ pte_t *ptep = pte_offset_kernel(pmdp, (unsigned long)token_addr); + -+ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ if(token_page == NULL) ++ panic("Token of task_struct was unset.\n"); + -+ pud_t *pudp = pud_offset(p4dp, addr); ++ iee_unset_token(ptep, token_addr, token_page, order); + -+ pmd_t *pmdp = pmd_offset(pudp, addr); ++ flush_tlb_kernel_range((unsigned long)token_addr, (unsigned long)(token_addr + (PAGE_SIZE * (1 << order)))); ++ flush_tlb_kernel_range((unsigned long)token_page, (unsigned long)(token_page + (PAGE_SIZE * (1 << order)))); ++ flush_tlb_kernel_range(iee_addr, iee_addr + (PAGE_SIZE * (1 << order))); ++ isb(); ++} + -+ pte_t *ptep = pte_offset_kernel(pmdp, addr); ++void unset_iee_stack_page(unsigned long addr, int order) ++{ ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ pud_t *pudp = pud_offset(p4dp, addr); ++ pmd_t *pmdp = pmd_offset(pudp, addr); ++ pte_t *ptep; ++ int use_block_pmd = 0; + -+ int i; -+ for(i = 0; i < 4; i++) ++ // Use Block Descriptor. ++ if(pmd_leaf(*pmdp)) + { -+ pte_t pte = READ_ONCE(*ptep); -+ pte = __pte(pte_val(pte) & ~PTE_USER & ~PTE_NG); -+ iee_set_pte_ppage(ptep, pte); -+ ptep++; ++ use_block_pmd = 1; ++ ptep = (pte_t *)pmdp; + } -+ flush_tlb_kernel_range(addr, addr+4*PAGE_SIZE); ++ else ++ ptep = pte_offset_kernel(pmdp, addr); ++ ++ iee_unset_stack_pte(ptep, order, use_block_pmd, addr); ++ flush_tlb_kernel_range(addr+iee_offset, addr+iee_offset+(1 << order)*PAGE_SIZE); + isb(); +} + -+void iee_set_kernel_upage(unsigned long addr) ++void set_iee_stack_page(unsigned long addr, int order) +{ + pgd_t *pgdir = swapper_pg_dir; + pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); -+ + p4d_t *p4dp = p4d_offset(pgdp, addr); -+ p4d_t p4d = READ_ONCE(*p4dp); -+ + pud_t *pudp = pud_offset(p4dp, addr); ++ pmd_t *pmdp; ++ pte_t *ptep; ++ int use_block_pmd = 0; + -+ pmd_t *pmdp = pmd_offset(pudp, addr); ++ pmdp = pmd_offset(pudp, addr); + -+ pte_t *ptep = pte_offset_kernel(pmdp, addr); ++ // Handling cont mapping. ++ if(pmd_val(*pmdp) & PTE_CONT) ++ { ++ // The beginning of cont mapping. ++ int i; ++ pmd_t *pmdp = pmd_offset(pudp, addr & CONT_PMD_MASK); ++ for(i = 0; i < CONT_PMDS; i++) ++ { ++ set_pmd(pmdp,__pmd(pmd_val(*pmdp) & ~PTE_CONT)); ++ pmdp++; ++ } ++ } + -+ int i; -+ for(i = 0; i < 4; i++) ++ // Use Block Descriptor. ++ if(pmd_leaf(*pmdp) && order < 9) + { -+ pte_t pte = READ_ONCE(*ptep); -+ pte = __pte(pte_val(pte) | PTE_USER | PTE_NG); -+ iee_set_pte_upage(ptep, pte); -+ ptep++; ++ #ifndef CONFIG_PTP ++ struct page *page = pmd_page(*pmdp); ++ #endif ++ pte_t *pgtable = pte_alloc_one_kernel(&init_mm); ++ ++ if (!pgtable) ++ panic("Alloc pgtable error.\n"); ++ ++ #ifdef CONFIG_PTP ++ iee_split_huge_pmd(pmdp, pgtable); ++ #else ++ { ++ int i; ++ pte_t *ptep = pgtable; ++ for (i = 0; i < PMD_SIZE / PAGE_SIZE; i++, ptep++) { ++ pte_t entry; ++ pgprot_t pgprot = PAGE_KERNEL; ++ pgprot = __pgprot(pgprot_val(pgprot) | PTE_CONT); ++ ++ entry = mk_pte(page + i, pgprot); ++ set_pte(ptep, entry); ++ } ++ } ++ #endif ++ ++ spinlock_t *ptl = pmd_lock(&init_mm, pmdp); ++ if(pmd_leaf(READ_ONCE(*pmdp))) ++ { ++ smp_wmb(); ++ pmd_populate_kernel(&init_mm, pmdp, pgtable); ++ pgtable = NULL; ++ } ++ spin_unlock(ptl); ++ ++ if(pgtable) ++ { ++ #ifdef CONFIG_PTP ++ iee_memset(pgtable, 0, PAGE_SIZE); ++ #endif ++ pte_free_kernel(&init_mm, pgtable); ++ } + } -+ flush_tlb_kernel_range(addr, addr+4*PAGE_SIZE); ++ else if(pmd_leaf(*pmdp)) ++ { ++ use_block_pmd = 1; ++ } ++ ++ if(use_block_pmd) ++ ptep = (pte_t *)pmdp; ++ else ++ ptep = pte_offset_kernel(pmdp, addr); ++ ++ // Handling cont mapping. ++ if(pte_val(*ptep) & PTE_CONT) ++ { ++ // The beginning of cont mapping. ++ int i; ++ pte_t *ptep = pte_offset_kernel(pmdp, addr & CONT_PTE_MASK); ++ if(order < CONFIG_ARM64_CONT_PTE_SHIFT) ++ { ++ for(i = 0; i < CONT_PTES; i++) ++ { ++ set_pte(ptep,__pte(pte_val(*ptep) & ~PTE_CONT)); ++ ptep++; ++ } ++ } ++ } ++ ++ iee_set_stack_pte(ptep, order, use_block_pmd, addr); ++ flush_tlb_kernel_range(addr, addr+(1 << order)*PAGE_SIZE); + isb(); +} \ No newline at end of file diff --git a/arch/arm64/kernel/iee/iee-gate.S b/arch/arm64/kernel/iee/iee-gate.S new file mode 100644 -index 000000000000..6de99a018bde +index 000000000000..24a80378191d --- /dev/null +++ b/arch/arm64/kernel/iee/iee-gate.S -@@ -0,0 +1,174 @@ +@@ -0,0 +1,314 @@ +#include +#include +#include +#include ++#include ++#include + +#ifdef CONFIG_IEE + ++SYM_FUNC_START(iee_read_tmp_page) ++ /* save daif, close irq */ ++ mrs x13, daif ++ msr daifset, #0x2 ++ isb ++ /* disable PAN */ ++ msr pan, #0x0 ++ adrp x12, iee_offset ++ ldr x12, [x12, #:lo12:iee_offset] ++ add x11, x0, x12 /* x11 -> task_token(IEE) */ ++ ldr x0, [x11, #tmp_page_from_token_offset] ++ /* enable PAN */ ++ msr pan, #0x1 ++ /* restore daif */ ++ msr daif, x13 ++ ret ++SYM_FUNC_END(iee_read_tmp_page) ++ ++SYM_FUNC_START(iee_read_freeptr) ++ /* save daif, close irq */ ++ mrs x13, daif ++ msr daifset, #0x2 ++ isb ++ /* disable PAN */ ++ msr pan, #0x0 ++ adrp x12, iee_offset ++ ldr x12, [x12, #:lo12:iee_offset] ++ add x0, x0, x12 ++ ldr x0, [x0] ++ /* enable PAN */ ++ msr pan, #0x1 ++ /* restore daif */ ++ msr daif, x13 ++ ret ++SYM_FUNC_END(iee_read_freeptr) ++ ++SYM_FUNC_START(iee_read_token_stack) ++ /* save daif, close irq */ ++ mrs x13, daif ++ msr daifset, #0x2 ++ isb ++ /* disable PAN */ ++ msr pan, #0x0 ++ adrp x12, iee_offset ++ ldr x12, [x12, #:lo12:iee_offset] ++ add x11, x0, x12 /* x11 -> task_token(IEE) */ ++ ldr x0, [x11, #iee_from_token_offset] ++ /* enable PAN */ ++ msr pan, #0x1 ++ /* restore daif */ ++ msr daif, x13 ++ ret ++SYM_FUNC_END(iee_read_token_stack) ++ ++SYM_FUNC_START(iee_set_xchg_relaxed) ++ /* save daif, close irq */ ++ mrs x13, daif ++ msr daifset, #0x2 ++ isb ++ /* disable PAN */ ++ msr pan, #0x0 ++ /* begin */ ++ adrp x2, iee_offset ++ ldr x2, [x2, #:lo12:iee_offset] ++ add x0, x0, x2 ++ prfm pstl1strm, [x0] ++12: ++ ldxr x3, [x0] ++ stxr w4, x1, [x0] ++ cbnz w4, 12b ++ mov x0, x3 ++ /* end */ ++ /* enable PAN */ ++ msr pan, #0x1 ++ /* restore daif */ ++ msr daif, x13 ++ ret ++SYM_FUNC_END(iee_set_xchg_relaxed) ++ ++SYM_FUNC_START(iee_set_cmpxchg_relaxed) ++ /* save daif, close irq */ ++ mrs x13, daif ++ msr daifset, #0x2 ++ isb ++ /* disable PAN */ ++ msr pan, #0x0 ++ /* begin */ ++ adrp x9, iee_offset ++ ldr x9, [x9, #:lo12:iee_offset] ++ add x3, x0, x9 ++ prfm pstl1strm, [x3] ++11: ++ ldxr x0, [x3] ++ eor x4, x0, x1 ++ cbnz w4, 13f ++ stxr w4, x2, [x3] ++ cbnz w4, 11b ++13: ++ /* end */ ++ /* enable PAN */ ++ msr pan, #0x1 ++ /* restore daif */ ++ msr daif, x13 ++ ret ++SYM_FUNC_END(iee_set_cmpxchg_relaxed) ++ +SYM_FUNC_START(iee_rw_gate) + /* save daif, close irq */ + mrs x13, daif @@ -3703,21 +4453,20 @@ index 000000000000..6de99a018bde + msr daif, x13 + ret +SYM_FUNC_END(iee_rw_gate) -+#if defined(CONFIG_CREDP) || defined(CONFIG_KOI) ++#if defined(CONFIG_CREDP) || defined(CONFIG_KOI) || (CONFIG_KEYP) +EXPORT_SYMBOL(iee_rw_gate) +#endif + + .pushsection ".iee.text.header", "ax" + +SYM_FUNC_START(iee_protected_rw_gate) -+ mrs x9, pan + /* disable PAN */ + msr pan, #0x0 + /* switch to iee stack */ + mrs x9, sp_el0 /* x9 -> task_struct */ -+ adrp x12, iee_offset -+ ldr x12, [x12, #:lo12:iee_offset] -+ add x11, x9, x12 /* x11 -> task_token(IEE) */ ++ adrp x7, iee_offset ++ ldr x7, [x7, #:lo12:iee_offset] ++ add x11, x9, x7 /* x11 -> task_token(IEE) */ + // store kernel stack + mov x10, sp + str x10, [x11, #kernel_from_token_offset] @@ -3729,15 +4478,20 @@ index 000000000000..6de99a018bde + /* restore daif */ + msr daif, x13 + sub sp, sp, #16 -+ stp x29, x30, [sp] ++ stp x11, x30, [sp] +#else -+ sub sp, sp, #16 ++ sub sp, sp, #32 ++ stp x11, x7, [sp, #16] + stp x13, x30, [sp] +#endif + /* call iee func */ -+ bl iee_dispatch ++ adrp x12, iee_funcs ++ add x12, x12, x0, lsl #3 ++ ldr x12, [x12, #:lo12:iee_funcs] ++ mov x0, x7 ++ blr x12 +#ifdef CONFIG_IEE_INTERRUPTABLE -+ ldp x29, x30, [sp] ++ ldp x11, x30, [sp] + add sp, sp, #16 + /* store and disable daif */ + mrs x13, daif @@ -3745,16 +4499,10 @@ index 000000000000..6de99a018bde + isb +#else + ldp x13, x30, [sp] -+ add sp, sp, #16 ++ ldp x11, x7, [sp, #16] ++ add sp, sp, #32 +#endif + /* switch to kernel stack */ -+ mrs x9, sp_el0 /* x9 -> task_struct(VA) */ -+ adrp x12, iee_offset -+ ldr x12, [x12, #:lo12:iee_offset] -+ add x11, x9, x12 /* x11 -> task_token(IEE) */ -+ // store iee stack -+ mov x10, sp -+ str x10, [x11, #iee_from_token_offset] + // load kernel stack + ldr x10, [x11, #kernel_from_token_offset] + mov sp, x10 @@ -3789,29 +4537,42 @@ index 000000000000..6de99a018bde + + b iee_rwx_gate_tramp +SYM_FUNC_END(iee_rwx_gate_entry) ++#ifdef CONFIG_KOI ++EXPORT_SYMBOL(iee_rwx_gate_entry) ++#endif + .popsection + ++#define USER_ASID_FLAG (UL(1) << 48) ++ + .pushsection ".iee.si_text", "awx" + +SYM_FUNC_START(iee_rwx_gate_tramp) + /* Check tcr val. */ + mrs x10, tcr_el1 -+ adrp x12, iee_si_tcr // tcr val shall be const after init ++ adrp x12, iee_si_tcr // tcr value shall be const after init + ldr x12, [x12, #:lo12:iee_si_tcr] + cbz x12, 1f + cmp x12, x10 + b.ne 3f +1: + mov x13, sp ++ /* if called by koi, skip stack switch */ ++#ifdef CONFIG_KOI ++ cmp x0, #IEE_SWITCH_TO_KERNEL ++ b.eq 4f ++ cmp x0, #IEE_SWITCH_TO_KOI ++ b.eq 5f ++#endif ++ + /* If iee hasn't been initialized, skip stack switch. */ -+ ldr x11, =iee_init_done -+ ldr x10, [x11] ++ adrp x11, iee_init_done ++ ldr x10, [x11, #:lo12:iee_init_done] + cbz x10, 2f + + /* Switch to iee stack */ + mrs x9, sp_el0 // x9 -> task_struct -+ adrp x12, iee_offset -+ ldr x12, [x12, #:lo12:iee_offset] ++ adrp x12, iee_si_offset ++ ldr x12, [x12, #:lo12:iee_si_offset] + add x11, x9, x12 // x11 -> task_token(IEE) + // load iee stack + ldr x10, [x11, #iee_from_token_offset] @@ -3831,6 +4592,27 @@ index 000000000000..6de99a018bde + mrs x2, esr_el1 + bl iee_bad_mode + ASM_BUG() ++#ifdef CONFIG_KOI ++/* Handle KOI switch gates. */ ++4: ++ /* IEE_SWITCH_TO_KERNEL */ ++ mrs x9, ttbr1_el1 ++ bic x9, x9, #USER_ASID_FLAG // Set new ASID to even ++ adrp x11, iee_base_swapper_pg_dir ++ ldr x11, [x11, #:lo12:iee_base_swapper_pg_dir] ++ ubfx x10, x9, #48, #16 // x10 -> new TTBR1 ASID ++ bfi x11, x10, #48, #16 ++ b 6f ++5: ++ /* IEE_SWITCH_TO_KOI */ ++ tbz x1, #48, 3b // KOI ASID shall be odd. ++ mov x11, x1 ++6: ++ msr ttbr1_el1, x11 ++ isb ++ stp x15, x13, [sp, #-32]! ++ b iee_rwx_gate_exit ++#endif +SYM_FUNC_END(iee_rwx_gate_tramp) + + .popsection @@ -3854,9479 +4636,15248 @@ index 000000000000..6de99a018bde + .popsection + +#endif -diff --git a/arch/arm64/kernel/iee/iee.c b/arch/arm64/kernel/iee/iee.c +diff --git a/arch/arm64/kernel/iee/iee-key.c b/arch/arm64/kernel/iee/iee-key.c new file mode 100644 -index 000000000000..6b9f7d40df67 +index 000000000000..a801f9fdebf0 --- /dev/null -+++ b/arch/arm64/kernel/iee/iee.c -@@ -0,0 +1,1360 @@ -+#include "linux/sched.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++++ b/arch/arm64/kernel/iee/iee-key.c +@@ -0,0 +1,12 @@ ++#include ++#include ++#include + -+#ifdef CONFIG_IEE -+extern struct cred init_cred; -+extern s64 memstart_addr; ++extern unsigned long long iee_rw_gate(int flag, ...); + -+void __iee_code _iee_set_swapper_pgd(pgd_t *pgdp, pgd_t pgd); -+void __iee_code _iee_set_tramp_pgd_pre_init(pgd_t *pgdp, pgd_t pgd); -+void __iee_code _iee_set_pte(pte_t *ptep, pte_t pte); -+void __iee_code _iee_set_pmd(pmd_t *pmdp, pmd_t pmd); -+void __iee_code _iee_set_pud(pud_t *pudp, pud_t pud); -+void __iee_code _iee_set_p4d(p4d_t *p4dp, p4d_t p4d); -+void __iee_code _iee_set_bm_pte(pte_t *ptep, pte_t pte); -+pteval_t __iee_code _iee_set_xchg_relaxed(pte_t *ptep, pteval_t pteval); -+pteval_t __iee_code _iee_set_cmpxchg_relaxed(pte_t *ptep, pteval_t old_pteval, pteval_t new_pteval); -+void __iee_code _iee_write_in_byte(void *ptr, __u64 data, int length); -+void __iee_code _iee_set_cred_uid(struct cred *cred, kuid_t uid); -+void __iee_code _iee_set_cred_gid(struct cred *cred, kgid_t gid); -+void __iee_code _iee_copy_cred(struct cred *old, struct cred *new); -+void __iee_code _iee_set_cred_suid(struct cred *cred, kuid_t suid); -+void __iee_code _iee_set_cred_sgid(struct cred *cred, kgid_t sgid); -+void __iee_code _iee_set_cred_euid(struct cred *cred, kuid_t euid); -+void __iee_code _iee_set_cred_egid(struct cred *cred, kgid_t egid); -+void __iee_code _iee_set_cred_fsuid(struct cred *cred, kuid_t fsuid); -+void __iee_code _iee_set_cred_fsgid(struct cred *cred, kgid_t fsgid); -+void __iee_code _iee_set_cred_user(struct cred *cred, struct user_struct *user); -+void __iee_code _iee_set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns); -+void __iee_code _iee_set_cred_ucounts(struct cred *cred, struct ucounts *ucounts); -+void __iee_code _iee_set_cred_group_info(struct cred *cred, struct group_info *group_info); -+void __iee_code _iee_set_cred_securebits(struct cred *cred, unsigned securebits); -+void __iee_code _iee_set_cred_cap_inheritable(struct cred *cred, kernel_cap_t cap_inheritable); -+void __iee_code _iee_set_cred_cap_permitted(struct cred *cred, kernel_cap_t cap_permitted); -+void __iee_code _iee_set_cred_cap_effective(struct cred *cred, kernel_cap_t cap_effective); -+void __iee_code _iee_set_cred_cap_bset(struct cred *cred, kernel_cap_t cap_bset); -+void __iee_code _iee_set_cred_cap_ambient(struct cred *cred, kernel_cap_t cap_ambient); -+void __iee_code _iee_set_cred_jit_keyring(struct cred *cred, unsigned char jit_keyring); -+void __iee_code _iee_set_cred_session_keyring(struct cred *cred, struct key *session_keyring); -+void __iee_code _iee_set_cred_process_keyring(struct cred *cred, struct key *process_keyring); -+void __iee_code _iee_set_cred_thread_keyring(struct cred *cred, struct key *thread_keyring); -+void __iee_code _iee_set_cred_request_key_auth(struct cred *cred, struct key *request_key_auth); -+void __iee_code _iee_set_cred_non_rcu(struct cred *cred, int non_rcu); -+void __iee_code _iee_set_cred_atomic_set_usage(struct cred *cred, int i); -+bool __iee_code _iee_set_cred_atomic_op_usage(struct cred *cred, int flag, int nr); -+void __iee_code _iee_set_cred_security(struct cred *cred, void *security); -+void __iee_code _iee_set_cred_rcu(struct cred *cred, struct rcu_head *rcu); -+void __iee_code _iee_memset(void *ptr, int data, size_t n); -+void __iee_code _iee_set_track(struct track *ptr, struct track *data); -+void __iee_code _iee_set_freeptr(freeptr_t *pptr, freeptr_t ptr); -+void __iee_code _iee_set_pte_upage(pte_t *ptep, pte_t pte); -+void __iee_code _iee_set_pte_ppage(pte_t *ptep, pte_t pte); -+void __iee_code _iee_set_token_mm(struct task_struct *tsk, struct mm_struct *mm); -+void __iee_code _iee_set_token_pgd(struct task_struct *tsk, pgd_t *pgd); -+void __iee_code _iee_init_token(struct task_struct *tsk, void *kernel_stack, void *iee_stack); -+void __iee_code _iee_free_token(struct task_struct *tsk); -+unsigned long __iee_code _iee_read_token_stack(struct task_struct *tsk); -+void __iee_code _iee_write_entry_task(struct task_struct *tsk); -+#ifdef CONFIG_KOI -+unsigned long __iee_code _iee_read_koi_stack(struct task_struct *tsk); -+void __iee_code _iee_write_koi_stack(struct task_struct *tsk, unsigned long koi_stack); -+unsigned long __iee_code _iee_read_token_ttbr1(struct task_struct *tsk); -+void __iee_code _iee_write_token_ttbr1(struct task_struct *tsk, unsigned long current_ttbr1); -+unsigned long __iee_code _iee_read_koi_kernel_stack(struct task_struct *tsk); -+void __iee_code _iee_write_koi_kernel_stack(struct task_struct *tsk, unsigned long kernel_stack); -+unsigned long __iee_code _iee_read_koi_stack_base(struct task_struct *tsk); -+void __iee_code _iee_write_koi_stack_base(struct task_struct *tsk, unsigned long koi_stack_base); ++#ifdef CONFIG_KEYP ++void iee_write_key_payload_rcu_data0(struct key *key, void *rcu_data0) ++{ ++ iee_rw_gate(IEE_OP_WRITE_KEY_PAYLOAD_RCU_DATA0, key, rcu_data0); ++} +#endif +\ No newline at end of file +diff --git a/arch/arm64/kernel/iee/iee-pgtable.c b/arch/arm64/kernel/iee/iee-pgtable.c +new file mode 100644 +index 000000000000..bd43af6d4eb3 +--- /dev/null ++++ b/arch/arm64/kernel/iee/iee-pgtable.c +@@ -0,0 +1,402 @@ ++#include ++#include ++#include ++#include + -+/* wrapper functions */ -+void __iee_code iee_wrapper_write_in_byte(va_list args) { -+ void *ptr = va_arg(args, void *); -+ __u64 data = va_arg(args, __u64); -+ int length = va_arg(args, int); -+ _iee_write_in_byte(ptr, data, length); -+} ++#ifdef CONFIG_PTP + -+void __iee_code iee_wrapper_set_pte(va_list args) { -+ pte_t *ptep = va_arg(args, pte_t *); -+ pte_t pte = va_arg(args, pte_t); -+ _iee_set_pte(ptep, pte); ++void iee_set_tramp_pgd_pre_init(pgd_t *pgdp, pgd_t pgd) ++{ ++ iee_rw_gate(IEE_OP_SET_TRAMP_PGD, pgdp, pgd); +} + -+void __iee_code iee_wrapper_set_pmd(va_list args) { -+ pmd_t *pmdp = va_arg(args, pmd_t *); -+ pmd_t pmd = va_arg(args, pmd_t); -+ _iee_set_pmd(pmdp, pmd); -+} ++inline void iee_set_bm_pte(pte_t *ptep, pte_t pte) ++{ ++ // If it is pre init, write once. ++ // Else, write once will cause exception. So it is safe. ++ unsigned long flags; ++ unsigned long res; ++ local_irq_save(flags); ++ asm volatile("at s1e1r, %0"::"r"(__phys_to_iee(__pa_symbol(ptep)))); ++ isb(); ++ res = read_sysreg(par_el1); ++ local_irq_restore(flags); ++#ifdef CONFIG_KOI ++ if (pte_valid(pte)) ++ pte = __pte(pte_val(pte) | PTE_NG); ++#endif ++ if(res & 0x1) ++ WRITE_ONCE(*ptep,pte); ++ else ++ iee_rw_gate(IEE_OP_SET_BM_PTE, ptep, pte); + -+void __iee_code iee_wrapper_set_p4d(va_list args) { -+ p4d_t *p4dp = va_arg(args, p4d_t *); -+ p4d_t p4d = va_arg(args, p4d_t); -+ _iee_set_p4d(p4dp, p4d); ++ /* ++ * Only if the new pte is valid and kernel, otherwise TLB maintenance ++ * or update_mmu_cache() have the necessary barriers. ++ */ ++ if (pte_valid_not_user(pte)) { ++ dsb(ishst); ++ isb(); ++ } +} + -+void __iee_code iee_wrapper_set_pud(va_list args) { -+ pud_t *pudp = va_arg(args, pud_t *); -+ pud_t pud = va_arg(args, pud_t); -+ _iee_set_pud(pudp, pud); -+} ++inline void iee_set_fixmap_pte_pre_init(pte_t *ptep, pte_t pte) ++{ ++#ifdef CONFIG_KOI ++ if (pte_valid(pte)) { ++ pte = __pte(pte_val(pte) | PTE_NG); ++ } ++#endif ++ WRITE_ONCE(*ptep, pte); + -+void __iee_code iee_wrapper_set_bm_pte(va_list args) { -+ pte_t *ptep = va_arg(args, pte_t *); -+ pte_t pte = va_arg(args, pte_t); -+ _iee_set_bm_pte(ptep, pte); ++ /* ++ * Only if the new pte is valid and kernel, otherwise TLB maintenance ++ * or update_mmu_cache() have the necessary barriers. ++ */ ++ if (pte_valid_not_user(pte)) { ++ dsb(ishst); ++ isb(); ++ } +} + -+void __iee_code iee_wrapper_set_swapper_pgd(va_list args) { -+ pgd_t *pgdp = va_arg(args, pgd_t *); -+ pgd_t pgd = va_arg(args, pgd_t); -+ _iee_set_swapper_pgd(pgdp, pgd); -+} ++inline void iee_set_pte_at(struct mm_struct *mm, unsigned long addr, ++ pte_t *ptep, pte_t pte) ++{ ++ __sync_cache_and_tags(pte, 1); ++ __check_safe_pte_update(mm, ptep, pte); + -+void __iee_code iee_wrapper_set_tramp_pgd(va_list args) { -+ pgd_t *pgdp = va_arg(args, pgd_t *); -+ pgd_t pgd = va_arg(args, pgd_t); -+ _iee_set_tramp_pgd_pre_init(pgdp, pgd); ++ iee_set_pte_pre_init(ptep, pte); +} + -+pteval_t __iee_code iee_wrapper_set_xchg(va_list args) { -+ pteval_t ret; -+ pte_t *ptep = va_arg(args, pte_t *); -+ pteval_t pteval = va_arg(args, pteval_t); -+ ret = _iee_set_xchg_relaxed(ptep, pteval); -+ return (u64)ret; ++inline void iee_set_pte_at_delayed(struct mm_struct *mm, unsigned long addr, ++ pte_t *ptep, pte_t pte) ++{ ++ __sync_cache_and_tags(pte, 1); ++ __check_safe_pte_update(mm, ptep, pte); +} + -+pteval_t __iee_code iee_wrapper_set_cmpxchg(va_list args) { -+ pteval_t ret; -+ pte_t *ptep = va_arg(args, pte_t *); -+ pteval_t old_pteval = va_arg(args, pteval_t); -+ pteval_t new_pteval = va_arg(args, pteval_t); -+ ret = _iee_set_cmpxchg_relaxed(ptep, old_pteval, new_pteval); -+ return (u64)ret; ++inline bool in_tramp_pgdir(void *addr) ++{ ++ return ((unsigned long)addr & PAGE_MASK) == ++ ((unsigned long)tramp_pg_dir & PAGE_MASK); +} + -+void __iee_code iee_wrapper_set_cred_uid(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kuid_t uid = va_arg(args, kuid_t); -+ _iee_set_cred_uid(cred, uid); -+} ++inline void iee_set_fixmap_pmd_pre_init(pmd_t *pmdp, pmd_t pmd) ++{ ++#ifdef __PAGETABLE_PMD_FOLDED ++ if (in_swapper_pgdir(pmdp)) { ++ set_swapper_pgd((pgd_t *)pmdp, __pgd(pmd_val(pmd))); ++ return; ++ } ++#endif /* __PAGETABLE_PMD_FOLDED */ ++#ifdef CONFIG_KOI ++ pmdval_t val = pmd_val(pmd); ++ if (pmd_valid(pmd) && !(val & PMD_TABLE_BIT)) { ++ pmd = __pmd(val | PMD_SECT_NG); ++ } ++#endif ++ WRITE_ONCE(*pmdp, pmd); + -+void __iee_code iee_wrapper_set_cred_gid(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kgid_t gid = va_arg(args, kgid_t); -+ _iee_set_cred_gid(cred, gid); ++ if (pmd_valid(pmd)) { ++ dsb(ishst); ++ isb(); ++ } +} + -+void __iee_code iee_wrapper_copy_cred(va_list args) { -+ struct cred *old = va_arg(args, struct cred *); -+ struct cred *new = va_arg(args, struct cred *); -+ _iee_copy_cred(old, new); -+} ++inline void iee_set_fixmap_pud_pre_init(pud_t *pudp, pud_t pud) ++{ ++#ifdef __PAGETABLE_PUD_FOLDED ++ if (in_swapper_pgdir(pudp)) { ++ set_swapper_pgd((pgd_t *)pudp, __pgd(pud_val(pud))); ++ return; ++ } ++#endif /* __PAGETABLE_PUD_FOLDED */ ++#ifdef CONFIG_KOI ++ pudval_t val = pud_val(pud); ++ if (pud_valid(pud) && !(val & PUD_TABLE_BIT)) { ++ // There is no PUD_SEC_NG, so we use PMD_SECT_NG instead. ++ pud = __pud(val | PMD_SECT_NG); ++ } ++#endif ++ WRITE_ONCE(*pudp, pud); + -+void __iee_code iee_wrapper_set_cred_suid(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kuid_t suid = va_arg(args, kuid_t); -+ _iee_set_cred_suid(cred, suid); ++ if (pud_valid(pud)) { ++ dsb(ishst); ++ isb(); ++ } +} + -+void __iee_code iee_wrapper_set_cred_sgid(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kgid_t sgid = va_arg(args, kgid_t); -+ _iee_set_cred_sgid(cred, sgid); -+} ++#endif //#ifdef CONFIG_PTP + -+void __iee_code iee_wrapper_set_cred_euid(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kuid_t euid = va_arg(args, kuid_t); -+ _iee_set_cred_euid(cred, euid); ++inline void __set_pte(pte_t *ptep, pte_t pte) ++{ ++#ifdef CONFIG_KOI ++ if (pte_valid(pte)) { ++ pte = __pte(pte_val(pte) | PTE_NG); ++ } ++#endif ++#ifdef CONFIG_PTP ++ iee_rw_gate(IEE_OP_SET_PTE, ptep, pte); ++ dsb(ishst); ++ isb(); ++#else ++ WRITE_ONCE(*ptep, pte); ++ if (pte_valid_not_user(pte)) { ++ dsb(ishst); ++ isb(); ++ } ++#endif +} + -+void __iee_code iee_wrapper_set_cred_egid(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kgid_t egid = va_arg(args, kgid_t); -+ _iee_set_cred_egid(cred, egid); ++inline void set_pmd(pmd_t *pmdp, pmd_t pmd) ++{ ++#ifdef __PAGETABLE_PMD_FOLDED ++ if (in_swapper_pgdir(pmdp)) { ++ set_swapper_pgd((pgd_t *)pmdp, __pgd(pmd_val(pmd))); ++ return; ++ } ++#endif /* __PAGETABLE_PMD_FOLDED */ ++#ifdef CONFIG_KOI ++ pmdval_t val = pmd_val(pmd); ++ if (pmd_valid(pmd) && !(val & PMD_TABLE_BIT)) { ++ pmd = __pmd(val | PMD_SECT_NG); ++ } ++#endif ++#ifdef CONFIG_PTP ++ iee_rw_gate(IEE_OP_SET_PMD, pmdp, pmd); ++#else ++ WRITE_ONCE(*pmdp, pmd); ++#endif ++ if (pmd_valid(pmd)) { ++ dsb(ishst); ++ isb(); ++ } +} + -+void __iee_code iee_wrapper_set_cred_fsuid(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kuid_t fsuid = va_arg(args, kuid_t); -+ _iee_set_cred_fsuid(cred, fsuid); ++inline void set_pud(pud_t *pudp, pud_t pud) ++{ ++#ifdef __PAGETABLE_PUD_FOLDED ++ if (in_swapper_pgdir(pudp)) { ++ set_swapper_pgd((pgd_t *)pudp, __pgd(pud_val(pud))); ++ return; ++ } ++#endif /* __PAGETABLE_PUD_FOLDED */ ++#ifdef CONFIG_KOI ++ pudval_t val = pud_val(pud); ++ if (pud_valid(pud) && !(val & PUD_TABLE_BIT)) { ++ // There is no PUD_SEC_NG, so we use PMD_SECT_NG instead. ++ pud = __pud(val | PMD_SECT_NG); ++ } ++#endif ++#ifdef CONFIG_PTP ++ iee_rw_gate(IEE_OP_SET_PUD, pudp, pud); ++#else ++ WRITE_ONCE(*pudp, pud); ++#endif ++ if (pud_valid(pud)) { ++ dsb(ishst); ++ isb(); ++ } +} + -+void __iee_code iee_wrapper_set_cred_fsgid(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kgid_t fsgid = va_arg(args, kgid_t); -+ _iee_set_cred_fsgid(cred, fsgid); -+} ++inline void set_p4d(p4d_t *p4dp, p4d_t p4d) ++{ ++ if (in_swapper_pgdir(p4dp)) ++ { ++ set_swapper_pgd((pgd_t *)p4dp, __pgd(p4d_val(p4d))); ++ return; ++ } + -+void __iee_code iee_wrapper_set_cred_user(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ struct user_struct *user = va_arg(args, struct user_struct *); -+ _iee_set_cred_user(cred, user); ++#ifdef CONFIG_PTP ++ if(in_tramp_pgdir(p4dp)) ++ { ++ iee_set_tramp_pgd_pre_init((pgd_t *)p4dp, __pgd(p4d_val(p4d))); ++ return; ++ } ++ iee_rw_gate(IEE_OP_SET_P4D, p4dp, p4d); ++#else ++ WRITE_ONCE(*p4dp, p4d); ++#endif ++ dsb(ishst); ++ isb(); +} + -+void __iee_code iee_wrapper_set_cred_user_ns(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ struct user_namespace *user_ns = va_arg(args, struct user_namespace *); -+ _iee_set_cred_user_ns(cred, user_ns); -+} ++#ifdef CONFIG_IEE ++inline void iee_set_stack_pte(pte_t *ptep, int order, int use_block_pmd, unsigned long lm_addr) ++{ ++#ifdef CONFIG_PTP ++ iee_rw_gate(IEE_OP_SET_PTE_U, ptep, order, use_block_pmd, lm_addr); ++#else ++ int i; ++ unsigned long iee_addr = lm_addr + iee_offset; ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ p4d_t *p4dp = p4d_offset(pgdp, iee_addr); ++ pud_t *pudp = pud_offset(p4dp, iee_addr); ++ pmd_t *pmdp = pmd_offset(pudp, iee_addr); ++ pte_t *iee_ptep = pte_offset_kernel(pmdp, iee_addr); ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ iee_ptep++; ++ } + -+void __iee_code iee_wrapper_set_cred_ucounts(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ struct ucounts *ucounts = va_arg(args, struct ucounts *); -+ _iee_set_cred_ucounts(cred, ucounts); ++ if(use_block_pmd) ++ { ++ pmd_t *pmdp = (pmd_t *)ptep; ++ pmd_t pmd = READ_ONCE(*pmdp); ++ pmd = __pmd(pmd_val(pmd) & ~PTE_VALID); ++ WRITE_ONCE(*pmdp, pmd); ++ } ++ else ++ { ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ WRITE_ONCE(*ptep, pte); ++ ptep++; ++ } ++ } ++#endif ++ dsb(ishst); ++ isb(); +} + -+void __iee_code iee_wrapper_set_cred_group_info(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ struct group_info *group_info = va_arg(args, struct group_info *); -+ _iee_set_cred_group_info(cred, group_info); -+} ++inline void iee_unset_stack_pte(pte_t *ptep, int order, int use_block_pmd, unsigned long lm_addr) ++{ ++#ifdef CONFIG_PTP ++ iee_rw_gate(IEE_OP_SET_PTE_P, ptep, order, use_block_pmd, lm_addr); ++#else ++ int i; ++ unsigned long iee_addr = lm_addr + iee_offset; ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ p4d_t *p4dp = p4d_offset(pgdp, iee_addr); ++ pud_t *pudp = pud_offset(p4dp, iee_addr); ++ pmd_t *pmdp = pmd_offset(pudp, iee_addr); ++ pte_t *iee_ptep = pte_offset_kernel(pmdp, iee_addr); ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ iee_ptep++; ++ } + -+void __iee_code iee_wrapper_set_cred_securebits(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ unsigned securebits = va_arg(args, unsigned); -+ _iee_set_cred_securebits(cred, securebits); ++ if(use_block_pmd) ++ { ++ pmd_t *pmdp = (pmd_t *)ptep; ++ pmd_t pmd = READ_ONCE(*pmdp); ++ pmd = __pmd(pmd_val(pmd) | PTE_VALID); ++ WRITE_ONCE(*pmdp, pmd); ++ } ++ else ++ { ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ #ifdef CONFIG_KOI ++ if (pte_valid(pte)) ++ pte = __pte(pte_val(pte) | PTE_NG); ++ #endif ++ WRITE_ONCE(*ptep, pte); ++ ptep++; ++ } ++ } ++#endif ++ dsb(ishst); ++ isb(); +} + -+void __iee_code iee_wrapper_set_cred_cap_inheritable(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kernel_cap_t cap_inheritable = va_arg(args, kernel_cap_t); -+ _iee_set_cred_cap_inheritable(cred, cap_inheritable); ++inline void iee_set_sensitive_pte(pte_t *lm_ptep, pte_t *iee_ptep, int order, int use_block_pmd) ++{ ++#ifdef CONFIG_PTP ++ iee_rw_gate(IEE_SET_SENSITIVE_PTE, lm_ptep, iee_ptep, order, use_block_pmd); ++#else ++ int i; ++ if(use_block_pmd) ++ { ++ pmd_t pmd = __pmd(pte_val(READ_ONCE(*lm_ptep))); ++ pmd = __pmd((pmd_val(pmd) | PMD_SECT_RDONLY) & ~PTE_DBM); ++ WRITE_ONCE(*lm_ptep, __pte(pmd_val(pmd))); ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*iee_ptep); ++ #ifdef CONFIG_KOI ++ pte = __pte(pte_val(pte) | PTE_VALID | PTE_NG); ++ #else ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ #endif ++ WRITE_ONCE(*iee_ptep, pte); ++ iee_ptep++; ++ } ++ } ++ else ++ { ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*lm_ptep); ++ pte = __pte((pte_val(pte) | PTE_RDONLY) & ~PTE_DBM); ++ #ifdef CONFIG_KOI ++ if (pte_valid(pte)) ++ pte = __pte(pte_val(pte) | PTE_NG); ++ #endif ++ WRITE_ONCE(*lm_ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ #ifdef CONFIG_KOI ++ if (pte_valid(pte)) ++ pte = __pte(pte_val(pte) | PTE_NG); ++ #endif ++ WRITE_ONCE(*iee_ptep, pte); ++ lm_ptep++; ++ iee_ptep++; ++ } ++ } ++#endif ++ dsb(ishst); ++ isb(); +} + -+void __iee_code iee_wrapper_set_cred_cap_permitted(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kernel_cap_t cap_permitted = va_arg(args, kernel_cap_t); -+ _iee_set_cred_cap_permitted(cred, cap_permitted); -+} -+ -+void __iee_code iee_wrapper_set_cred_cap_effective(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kernel_cap_t cap_effective = va_arg(args, kernel_cap_t); -+ _iee_set_cred_cap_effective(cred, cap_effective); -+} -+ -+void __iee_code iee_wrapper_set_cred_cap_bset(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kernel_cap_t cap_bset = va_arg(args, kernel_cap_t); -+ _iee_set_cred_cap_bset(cred, cap_bset); -+} -+ -+void __iee_code iee_wrapper_set_cred_cap_ambient(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ kernel_cap_t cap_ambient = va_arg(args, kernel_cap_t); -+ _iee_set_cred_cap_ambient(cred, cap_ambient); -+} -+ -+void __iee_code iee_wrapper_set_cred_jit_keyring(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ unsigned long jit_keyring = va_arg(args, unsigned long); -+ _iee_set_cred_jit_keyring(cred, (unsigned char)jit_keyring); -+} -+ -+void __iee_code iee_wrapper_set_cred_session_keyring(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ struct key *session_keyring = va_arg(args, struct key *); -+ _iee_set_cred_session_keyring(cred, session_keyring); -+} -+ -+void __iee_code iee_wrapper_set_cred_process_keyring(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ struct key *process_keyring = va_arg(args, struct key *); -+ _iee_set_cred_process_keyring(cred, process_keyring); -+} -+ -+void __iee_code iee_wrapper_set_cred_thread_keyring(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ struct key *thread_keyring = va_arg(args, struct key *); -+ _iee_set_cred_thread_keyring(cred, thread_keyring); -+} -+ -+void __iee_code iee_wrapper_set_cred_request_key_auth(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ struct key *request_key_auth = va_arg(args, struct key *); -+ _iee_set_cred_request_key_auth(cred, request_key_auth); -+} -+ -+void __iee_code iee_wrapper_set_cred_non_rcu(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ int non_rcu = va_arg(args, int); -+ _iee_set_cred_non_rcu(cred, non_rcu); -+} -+ -+void __iee_code iee_wrapper_set_cred_atomic_set_usage(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ int i = va_arg(args, int); -+ _iee_set_cred_atomic_set_usage(cred, i); -+} -+ -+u64 __iee_code iee_wrapper_set_cred_atomic_op_usage(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ int flag = va_arg(args, int); -+ int nr = va_arg(args, int); -+ return (u64)_iee_set_cred_atomic_op_usage(cred, flag, nr); -+} -+ -+void __iee_code iee_wrapper_set_cred_security(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ void *security = va_arg(args, void *); -+ _iee_set_cred_security(cred, security); -+} -+ -+void __iee_code iee_wrapper_set_cred_rcu(va_list args) { -+ struct cred *cred = va_arg(args, struct cred *); -+ struct rcu_head *rcu = va_arg(args, struct rcu_head *); -+ _iee_set_cred_rcu(cred, rcu); -+} -+ -+void __iee_code iee_wrapper_memset(va_list args) { -+ void *ptr = va_arg(args, void *); -+ int data = va_arg(args, int); -+ size_t n = va_arg(args, size_t); -+ _iee_memset(ptr, data, n); -+} -+ -+void __iee_code iee_wrapper_set_track(va_list args) { -+ struct track *ptr = va_arg(args, struct track *); -+ struct track *data = va_arg(args, struct track *); -+ _iee_set_track(ptr, data); -+} -+ -+void __iee_code iee_wrapper_set_freeptr(va_list args) { -+ freeptr_t *pptr = va_arg(args, freeptr_t *); -+ freeptr_t ptr = va_arg(args, freeptr_t); -+ _iee_set_freeptr(pptr, ptr); -+} -+ -+void __iee_code iee_wrapper_set_pte_upage(va_list args) { -+ pte_t *ptep = va_arg(args, pte_t *); -+ pte_t pte = va_arg(args, pte_t); -+ _iee_set_pte_upage(ptep, pte); ++inline void iee_unset_sensitive_pte(pte_t *lm_ptep, pte_t *iee_ptep, int order, int use_block_pmd) ++{ ++#ifdef CONFIG_PTP ++ iee_rw_gate(IEE_UNSET_SENSITIVE_PTE, lm_ptep, iee_ptep, order, use_block_pmd); ++#else ++ int i; ++ if(use_block_pmd) ++ { ++ pmd_t pmd = __pmd(pte_val(READ_ONCE(*lm_ptep))); ++ pmd = __pmd(pmd_val(pmd) | PTE_DBM); ++ WRITE_ONCE(*lm_ptep, __pte(pmd_val(pmd))); ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ iee_ptep++; ++ } ++ } ++ else ++ { ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*lm_ptep); ++ pte = __pte(pte_val(pte) | PTE_DBM); ++ WRITE_ONCE(*lm_ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ lm_ptep++; ++ iee_ptep++; ++ } ++ } ++#endif ++ dsb(ishst); ++ isb(); +} ++#endif //#ifdef CONFIG_IEE +diff --git a/arch/arm64/kernel/iee/iee-selinuxp.c b/arch/arm64/kernel/iee/iee-selinuxp.c +new file mode 100644 +index 000000000000..394f99f3f574 +--- /dev/null ++++ b/arch/arm64/kernel/iee/iee-selinuxp.c +@@ -0,0 +1,36 @@ ++#include + -+void __iee_code iee_wrapper_set_pte_ppage(va_list args) { -+ pte_t *ptep = va_arg(args, pte_t *); -+ pte_t pte = va_arg(args, pte_t); -+ _iee_set_pte_ppage(ptep, pte); -+} ++extern unsigned long long iee_rw_gate(int flag, ...); + -+void __iee_code iee_wrapper_set_token_mm(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ struct mm_struct *mm = va_arg(args, struct mm_struct *); -+ _iee_set_token_mm(tsk, mm); ++#ifdef CONFIG_IEE_SELINUX_P ++inline void iee_set_selinux_status_pg(struct page* new_page) ++{ ++ iee_rw_gate(IEE_SEL_SET_STATUS_PG, new_page); +} + -+void __iee_code iee_wrapper_set_token_pgd(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ pgd_t *pgd = va_arg(args, pgd_t *); -+ _iee_set_token_pgd(tsk, pgd); ++inline void enforcing_set(bool value) ++{ ++ iee_rw_gate(IEE_SEL_SET_ENFORCING, value); +} + -+void __iee_code iee_wrapper_init_token(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ void *kernel_stack = va_arg(args, void *); -+ void *iee_stack = va_arg(args, void *); -+ _iee_init_token(tsk, kernel_stack, iee_stack); ++inline void selinux_mark_initialized(void) ++{ ++ iee_rw_gate(IEE_SEL_SET_INITIALIZED); +} + -+void __iee_code iee_wrapper_free_token(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ _iee_free_token(tsk); ++inline void iee_set_sel_policy_cap(unsigned int idx, int cap) ++{ ++ iee_rw_gate(IEE_SEL_SET_POLICY_CAP, idx, cap); +} + -+u64 __iee_code iee_wrapper_read_token_stack(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ return (u64)_iee_read_token_stack(tsk); ++/* ++ * Please make sure param iee_new_policy is from policy_jar memcache. ++ * Need to free new_policy after calling this func as it's only used to ++ * trans data from kernel. ++ */ ++inline void iee_sel_rcu_assign_policy(struct selinux_policy* new_policy, ++ struct selinux_policy* iee_new_policy) ++{ ++ iee_rw_gate(IEE_SEL_RCU_ASSIGN_POLICY, new_policy, iee_new_policy); +} ++#endif +diff --git a/arch/arm64/kernel/iee/iee.c b/arch/arm64/kernel/iee/iee.c +new file mode 100644 +index 000000000000..2c7882d4f5be +--- /dev/null ++++ b/arch/arm64/kernel/iee/iee.c +@@ -0,0 +1,1734 @@ ++#include "linux/sched.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+void __iee_code iee_wrapper_write_entry_task(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ _iee_write_entry_task(tsk); -+} ++#define is_cow_mapping(flags) (((flags) & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE) + ++#ifdef CONFIG_IEE ++extern struct cred init_cred; ++extern s64 memstart_addr; ++extern unsigned long highest_memmap_pfn; ++ ++struct watch_list; ++ ++void __iee_code _iee_set_swapper_pgd(unsigned long iee_offset, pgd_t *pgdp, pgd_t pgd); ++void __iee_code _iee_set_tramp_pgd(unsigned long iee_offset, pgd_t *pgdp, pgd_t pgd); ++void __iee_code _iee_set_pte(unsigned long iee_offset, pte_t *ptep, pte_t pte); ++void __iee_code _iee_set_pmd(unsigned long iee_offset, pmd_t *pmdp, pmd_t pmd); ++void __iee_code _iee_set_pud(unsigned long iee_offset, pud_t *pudp, pud_t pud); ++void __iee_code _iee_set_p4d(unsigned long iee_offset, p4d_t *p4dp, p4d_t p4d); ++void __iee_code _iee_set_bm_pte(unsigned long iee_offset, pte_t *ptep, pte_t pte); ++void __iee_code _iee_write_in_byte(unsigned long iee_offset, void *ptr, __u64 data, int length); ++void __iee_code _iee_set_cred_uid(unsigned long iee_offset, struct cred *cred, kuid_t uid); ++void __iee_code _iee_set_cred_gid(unsigned long iee_offset, struct cred *cred, kgid_t gid); ++void __iee_code _iee_copy_cred(unsigned long iee_offset, struct cred *old, struct cred *new); ++void __iee_code _iee_set_cred_suid(unsigned long iee_offset, struct cred *cred, kuid_t suid); ++void __iee_code _iee_set_cred_sgid(unsigned long iee_offset, struct cred *cred, kgid_t sgid); ++void __iee_code _iee_set_cred_euid(unsigned long iee_offset, struct cred *cred, kuid_t euid); ++void __iee_code _iee_set_cred_egid(unsigned long iee_offset, struct cred *cred, kgid_t egid); ++void __iee_code _iee_set_cred_fsuid(unsigned long iee_offset, struct cred *cred, kuid_t fsuid); ++void __iee_code _iee_set_cred_fsgid(unsigned long iee_offset, struct cred *cred, kgid_t fsgid); ++void __iee_code _iee_set_cred_user(unsigned long iee_offset, struct cred *cred, struct user_struct *user); ++void __iee_code _iee_set_cred_user_ns(unsigned long iee_offset, struct cred *cred, struct user_namespace *user_ns); ++void __iee_code _iee_set_cred_group_info(unsigned long iee_offset, struct cred *cred, struct group_info *group_info); ++void __iee_code _iee_set_cred_securebits(unsigned long iee_offset, struct cred *cred, unsigned securebits); ++void __iee_code _iee_set_cred_cap_inheritable(unsigned long iee_offset, struct cred *cred, kernel_cap_t cap_inheritable); ++void __iee_code _iee_set_cred_cap_permitted(unsigned long iee_offset, struct cred *cred, kernel_cap_t cap_permitted); ++void __iee_code _iee_set_cred_cap_effective(unsigned long iee_offset, struct cred *cred, kernel_cap_t cap_effective); ++void __iee_code _iee_set_cred_cap_bset(unsigned long iee_offset, struct cred *cred, kernel_cap_t cap_bset); ++void __iee_code _iee_set_cred_cap_ambient(unsigned long iee_offset, struct cred *cred, kernel_cap_t cap_ambient); ++void __iee_code _iee_set_cred_jit_keyring(unsigned long iee_offset, struct cred *cred, unsigned char jit_keyring); ++void __iee_code _iee_set_cred_session_keyring(unsigned long iee_offset, struct cred *cred, struct key *session_keyring); ++void __iee_code _iee_set_cred_process_keyring(unsigned long iee_offset, struct cred *cred, struct key *process_keyring); ++void __iee_code _iee_set_cred_thread_keyring(unsigned long iee_offset, struct cred *cred, struct key *thread_keyring); ++void __iee_code _iee_set_cred_request_key_auth(unsigned long iee_offset, struct cred *cred, struct key *request_key_auth); ++void __iee_code _iee_set_cred_non_rcu(unsigned long iee_offset, struct cred *cred, int non_rcu); ++void __iee_code _iee_set_cred_atomic_set_usage(unsigned long iee_offset, struct cred *cred, int i); ++bool __iee_code _iee_set_cred_atomic_op_usage(unsigned long iee_offset, struct cred *cred, int flag, int nr); ++void __iee_code _iee_set_cred_security(unsigned long iee_offset, struct cred *cred, void *security); ++void __iee_code _iee_set_cred_rcu(unsigned long iee_offset, struct cred *cred, struct rcu_head *rcu); ++void __iee_code _iee_memset(unsigned long iee_offset, void *ptr, int data, size_t n); ++void __iee_code _iee_set_track(unsigned long iee_offset, struct track *ptr, struct track *data); ++void __iee_code _iee_set_freeptr(unsigned long iee_offset, void **pptr, void *ptr); ++void __iee_code _iee_set_stack_pte(unsigned long iee_offset, pte_t *ptep, int order, int use_block_pmd, unsigned long lm_addr); ++void __iee_code _iee_unset_stack_pte(unsigned long iee_offset, pte_t *ptep, int order, int use_block_pmd, unsigned long lm_addr); ++void __iee_code _iee_set_token_pgd(unsigned long iee_offset, struct task_struct *tsk, pgd_t *pgd); ++void __iee_code _iee_init_token(unsigned long iee_offset, struct task_struct *tsk, void *iee_stack, void *tmp_page); ++void __iee_code _iee_invalidate_token(unsigned long iee_offset, struct task_struct *tsk); ++void __iee_code _iee_validate_token(unsigned long iee_offset, struct task_struct *tsk); ++void __iee_code _iee_set_sensitive_pte(unsigned long iee_offset, pte_t *lm_ptep, pte_t *iee_ptep, int order, int use_block_pmd); ++void __iee_code _iee_unset_sensitive_pte(unsigned long iee_offset, pte_t *lm_ptep, pte_t *iee_ptep, int order, int use_block_pmd); ++void __iee_code _iee_set_token(unsigned long iee_offset, pte_t *ptep, void *new, unsigned long order, int use_block_pmd); ++void __iee_code _iee_unset_token(unsigned long iee_offset, pte_t *ptep, void *token_addr, void *token_page, unsigned long order); ++void __iee_code _iee_copy_pte_range(unsigned long iee_offset, pte_t *new_dst, pte_t *old_dst, pte_t *src_pte, struct vm_area_struct *src_vma, unsigned long dst_vm_flags, pte_t *end_pte); ++void __iee_code _iee_split_huge_pmd(unsigned long iee_offset, pmd_t *pmdp, pte_t *pgtable); ++void __iee_code _iee_set_cred_ucounts(unsigned long iee_offset, struct cred *cred, struct ucounts *ucounts); ++void __iee_code _iee_set_key_union(unsigned long iee_offset, struct key *key, struct key_union *key_union); ++void __iee_code _iee_set_key_struct(unsigned long iee_offset, struct key *key, struct key_struct *key_struct); ++void __iee_code _iee_set_key_payload(unsigned long iee_offset, struct key *key, union key_payload *key_payload); ++void __iee_code _iee_write_key_payload(unsigned long iee_offset, struct key *key, union key_payload payload); ++void __iee_code _iee_memcpy(unsigned long iee_offset, void *dst, void *src, size_t n); ++void __iee_code _iee_write_key_payload_rcu_data0(unsigned long iee_offset, struct key *key, void *rcu_data0); ++bool __iee_code _iee_set_key_usage(unsigned long iee_offset, struct key *key, int n, int flag); ++void __iee_code _iee_set_key_serial(unsigned long iee_offset, struct key *key, key_serial_t serial); ++void __iee_code _iee_set_key_watchers(unsigned long iee_offset, struct key *key, struct watch_list *watchers); ++void __iee_code _iee_set_key_user(unsigned long iee_offset, struct key *key, struct key_user *user); ++void __iee_code _iee_set_key_security(unsigned long iee_offset, struct key *key, void *security); ++void __iee_code _iee_set_key_expiry(unsigned long iee_offset, struct key *key, time64_t expiry); ++void __iee_code _iee_set_key_revoked_at(unsigned long iee_offset, struct key *key, time64_t revoked_at); ++void __iee_code _iee_set_key_last_used_at(unsigned long iee_offset, struct key *key, time64_t last_used_at); ++void __iee_code _iee_set_key_uid(unsigned long iee_offset, struct key *key, kuid_t uid); ++void __iee_code _iee_set_key_gid(unsigned long iee_offset, struct key *key, kgid_t gid); ++void __iee_code _iee_set_key_perm(unsigned long iee_offset, struct key *key, key_perm_t perm); ++void __iee_code _iee_set_key_quotalen(unsigned long iee_offset, struct key *key, unsigned short quotalen); ++void __iee_code _iee_set_key_datalen(unsigned long iee_offset, struct key *key, unsigned short datalen); ++void __iee_code _iee_set_key_state(unsigned long iee_offset, struct key *key, short state); ++void __iee_code _iee_set_key_magic(unsigned long iee_offset, struct key *key, unsigned magic); ++void __iee_code _iee_set_key_flags(unsigned long iee_offset, struct key *key, unsigned long flags); ++void __iee_code _iee_set_key_index_key(unsigned long iee_offset, struct key *key, struct keyring_index_key index_key); ++void __iee_code _iee_set_key_hash(unsigned long iee_offset, struct key *key, unsigned long hash); ++void __iee_code _iee_set_key_len_desc(unsigned long iee_offset, struct key *key, unsigned long len_desc); ++void __iee_code _iee_set_key_type(unsigned long iee_offset, struct key *key, struct key_type *type); ++void __iee_code _iee_set_key_domain_tag(unsigned long iee_offset, struct key *key, struct key_tag *domain_tag); ++void __iee_code _iee_set_key_description(unsigned long iee_offset, struct key *key, char *description); ++void __iee_code _iee_set_key_restrict_link(unsigned long iee_offset, struct key *key, struct key_restriction *restrict_link); ++bool __iee_code _iee_set_key_flag_bit(unsigned long iee_offset, struct key *key, long nr, int flag); +#ifdef CONFIG_KOI -+u64 __iee_code iee_wrapper_read_koi_stack(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ return (u64)_iee_read_koi_stack(tsk); -+} -+ -+void __iee_code iee_wrapper_write_koi_stack(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ unsigned long koi_stack = va_arg(args, unsigned long); -+ _iee_write_koi_stack(tsk, koi_stack); -+} -+ -+u64 __iee_code iee_wrapper_read_token_ttbr1(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ return (u64)_iee_read_token_ttbr1(tsk); -+} -+ -+void __iee_code iee_wrapper_write_token_ttbr1(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ unsigned long current_ttbr1 = va_arg(args, unsigned long); -+ _iee_write_token_ttbr1(tsk, current_ttbr1); -+} -+ -+u64 __iee_code iee_wrapper_read_koi_kernel_stack(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ return (u64)_iee_read_koi_kernel_stack(tsk); -+} ++unsigned long __iee_code _iee_read_koi_stack(unsigned long iee_offset, struct task_struct *tsk); ++void __iee_code _iee_write_koi_stack(unsigned long iee_offset, struct task_struct *tsk, unsigned long koi_stack); ++unsigned long __iee_code _iee_read_token_ttbr1(unsigned long iee_offset, struct task_struct *tsk); ++void __iee_code _iee_write_token_ttbr1(unsigned long iee_offset, struct task_struct *tsk, unsigned long current_ttbr1); ++unsigned long __iee_code _iee_read_koi_kernel_stack(unsigned long iee_offset, struct task_struct *tsk); ++void __iee_code _iee_write_koi_kernel_stack(unsigned long iee_offset, struct task_struct *tsk, unsigned long kernel_stack); ++unsigned long __iee_code _iee_read_koi_stack_base(unsigned long iee_offset, struct task_struct *tsk); ++void __iee_code _iee_write_koi_stack_base(unsigned long iee_offset, struct task_struct *tsk, unsigned long koi_stack_base); ++void __iee_code _iee_set_koi_pgd(unsigned long iee_offset, unsigned long koi_pgd_addr); ++#endif + -+void __iee_code iee_wrapper_write_koi_kernel_stack(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ unsigned long kernel_stack = va_arg(args, unsigned long); -+ _iee_write_koi_kernel_stack(tsk, kernel_stack); -+} ++#ifdef CONFIG_IEE_SELINUX_P ++#include ++void __iee_code _iee_set_selinux_status_pg(unsigned long iee_offset, struct page* new_page); ++void __iee_code _iee_set_selinux_enforcing(unsigned long iee_offset, bool value); ++void __iee_code _iee_mark_selinux_initialized(unsigned long iee_offset); ++void __iee_code _iee_set_sel_policy_cap(unsigned long iee_offset, unsigned int idx, int cap); ++void __iee_code _iee_sel_rcu_assign_policy(unsigned long iee_offset, ++ struct selinux_policy* new_policy, struct selinux_policy* iee_new_policy); ++#endif + -+u64 __iee_code iee_wrapper_read_koi_stack_base(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ return (u64)_iee_read_koi_stack_base(tsk); -+} ++static void inline _iee_set_pte_single(pte_t *ptep, pte_t pte, unsigned long iee_offset); ++static pteval_t inline _iee_set_cmpxchg_relaxed(pte_t *ptep, pteval_t old_pteval, pteval_t new_pteval, unsigned long iee_offset); + -+void __iee_code iee_wrapper_write_koi_stack_base(va_list args) { -+ struct task_struct *tsk = va_arg(args, struct task_struct *); -+ unsigned long koi_stack_base = va_arg(args, unsigned long); -+ _iee_write_koi_stack_base(tsk, koi_stack_base); -+} -+#endif +// Define the function pointer type for wrapper functions. +// Each function pointer conforms to a standardized calling convention +// using a variable argument list (va_list) as its parameter. +// This allows dynamic invocation of different functions with various arguments. -+typedef void (*iee_wrapper_func)(va_list args); -+iee_wrapper_func iee_wrappers[] = { -+ iee_wrapper_write_in_byte, -+ iee_wrapper_set_pte, -+ iee_wrapper_set_pmd, -+ iee_wrapper_set_pud, -+ iee_wrapper_set_p4d, -+ iee_wrapper_set_bm_pte, -+ iee_wrapper_set_swapper_pgd, -+ iee_wrapper_set_tramp_pgd, -+ (iee_wrapper_func)iee_wrapper_set_cmpxchg, -+ (iee_wrapper_func)iee_wrapper_set_xchg, -+ iee_wrapper_copy_cred, -+ iee_wrapper_set_cred_uid, -+ iee_wrapper_set_cred_gid, -+ iee_wrapper_set_cred_suid, -+ iee_wrapper_set_cred_sgid, -+ iee_wrapper_set_cred_euid, -+ iee_wrapper_set_cred_egid, -+ iee_wrapper_set_cred_fsuid, -+ iee_wrapper_set_cred_fsgid, -+ iee_wrapper_set_cred_user, -+ iee_wrapper_set_cred_user_ns, -+ iee_wrapper_set_cred_group_info, -+ iee_wrapper_set_cred_securebits, -+ iee_wrapper_set_cred_cap_inheritable, -+ iee_wrapper_set_cred_cap_permitted, -+ iee_wrapper_set_cred_cap_effective, -+ iee_wrapper_set_cred_cap_bset, -+ iee_wrapper_set_cred_cap_ambient, -+ iee_wrapper_set_cred_jit_keyring, -+ iee_wrapper_set_cred_session_keyring, -+ iee_wrapper_set_cred_process_keyring, -+ iee_wrapper_set_cred_thread_keyring, -+ iee_wrapper_set_cred_request_key_auth, -+ iee_wrapper_set_cred_non_rcu, -+ iee_wrapper_set_cred_atomic_set_usage, -+ (iee_wrapper_func)iee_wrapper_set_cred_atomic_op_usage, -+ iee_wrapper_set_cred_security, -+ iee_wrapper_set_cred_rcu, -+ iee_wrapper_memset, -+ iee_wrapper_set_track, -+ iee_wrapper_set_freeptr, -+ iee_wrapper_set_pte_upage, -+ iee_wrapper_set_pte_ppage, -+ iee_wrapper_set_token_mm, -+ iee_wrapper_set_token_pgd, -+ iee_wrapper_init_token, -+ iee_wrapper_free_token, -+ (iee_wrapper_func)iee_wrapper_read_token_stack, -+ iee_wrapper_write_entry_task, -+ iee_wrapper_set_cred_ucounts, ++typedef void (*iee_func)(void); ++iee_func iee_funcs[] = { ++ (iee_func)_iee_write_in_byte, ++ (iee_func)_iee_set_pte, ++ (iee_func)_iee_set_pmd, ++ (iee_func)_iee_set_pud, ++ (iee_func)_iee_set_p4d, ++ (iee_func)_iee_set_bm_pte, ++ (iee_func)_iee_set_swapper_pgd, ++ (iee_func)_iee_set_tramp_pgd, ++ (iee_func)_iee_memset, ++ (iee_func)_iee_set_track, ++ (iee_func)_iee_set_freeptr, ++ (iee_func)_iee_set_stack_pte, ++ (iee_func)_iee_unset_stack_pte, ++ (iee_func)_iee_set_token_pgd, ++ (iee_func)_iee_init_token, ++ (iee_func)_iee_invalidate_token, ++ (iee_func)_iee_set_sensitive_pte, ++ (iee_func)_iee_unset_sensitive_pte, ++ (iee_func)_iee_set_token, ++ (iee_func)_iee_unset_token, ++ (iee_func)_iee_copy_pte_range, ++ (iee_func)_iee_split_huge_pmd, ++ (iee_func)_iee_validate_token, ++ (iee_func)_iee_memcpy, +#ifdef CONFIG_KOI -+ (iee_wrapper_func)iee_wrapper_read_koi_stack, -+ iee_wrapper_write_koi_stack, -+ (iee_wrapper_func)iee_wrapper_read_token_ttbr1, -+ iee_wrapper_write_token_ttbr1, -+ (iee_wrapper_func)iee_wrapper_read_koi_kernel_stack, -+ iee_wrapper_write_koi_kernel_stack, -+ (iee_wrapper_func)iee_wrapper_read_koi_stack_base, -+ iee_wrapper_write_koi_stack_base ++ (iee_func)_iee_read_koi_stack, ++ (iee_func)_iee_write_koi_stack, ++ (iee_func)_iee_read_token_ttbr1, ++ (iee_func)_iee_write_token_ttbr1, ++ (iee_func)_iee_read_koi_kernel_stack, ++ (iee_func)_iee_write_koi_kernel_stack, ++ (iee_func)_iee_read_koi_stack_base, ++ (iee_func)_iee_write_koi_stack_base, ++ (iee_func)_iee_set_koi_pgd, +#endif -+}; -+ -+u64 __iee_code iee_dispatch(int flag, ...){ -+ va_list pArgs; -+ -+ va_start(pArgs, flag); -+ -+ switch(flag) -+ { -+ case IEE_OP_SET_CMPXCHG: -+ { -+ pteval_t ret = iee_wrapper_set_cmpxchg(pArgs); -+ va_end(pArgs); -+ return (u64)ret; -+ } -+ case IEE_OP_SET_XCHG: -+ { -+ pteval_t ret = iee_wrapper_set_xchg(pArgs); -+ va_end(pArgs); -+ return (u64)ret; -+ } -+ case IEE_OP_SET_CRED_ATOP_USAGE: -+ { -+ u64 ret = iee_wrapper_set_cred_atomic_op_usage(pArgs); -+ va_end(pArgs); -+ return ret; -+ } -+ case IEE_READ_TOKEN_STACK: -+ { -+ u64 ret = iee_wrapper_read_token_stack(pArgs); -+ va_end(pArgs); -+ return ret; -+ } -+#ifdef CONFIG_KOI -+ case IEE_READ_KOI_STACK: -+ { -+ u64 ret = iee_wrapper_read_koi_stack(pArgs); -+ va_end(pArgs); -+ return ret; -+ } -+ case IEE_READ_TOKEN_TTBR1: -+ { -+ u64 ret = iee_wrapper_read_token_ttbr1(pArgs); -+ va_end(pArgs); -+ return ret; -+ } -+ case IEE_READ_KOI_KERNEL_STACK: -+ { -+ u64 ret = iee_wrapper_read_koi_kernel_stack(pArgs); -+ va_end(pArgs); -+ return ret; -+ } -+ case IEE_READ_KOI_STACK_BASE: -+ { -+ u64 ret = iee_wrapper_read_koi_stack_base(pArgs); -+ va_end(pArgs); -+ return ret; -+ } ++#ifdef CONFIG_CREDP ++ (iee_func)_iee_copy_cred, ++ (iee_func)_iee_set_cred_uid, ++ (iee_func)_iee_set_cred_gid, ++ (iee_func)_iee_set_cred_suid, ++ (iee_func)_iee_set_cred_sgid, ++ (iee_func)_iee_set_cred_euid, ++ (iee_func)_iee_set_cred_egid, ++ (iee_func)_iee_set_cred_fsuid, ++ (iee_func)_iee_set_cred_fsgid, ++ (iee_func)_iee_set_cred_user, ++ (iee_func)_iee_set_cred_user_ns, ++ (iee_func)_iee_set_cred_group_info, ++ (iee_func)_iee_set_cred_securebits, ++ (iee_func)_iee_set_cred_cap_inheritable, ++ (iee_func)_iee_set_cred_cap_permitted, ++ (iee_func)_iee_set_cred_cap_effective, ++ (iee_func)_iee_set_cred_cap_bset, ++ (iee_func)_iee_set_cred_cap_ambient, ++ (iee_func)_iee_set_cred_jit_keyring, ++ (iee_func)_iee_set_cred_session_keyring, ++ (iee_func)_iee_set_cred_process_keyring, ++ (iee_func)_iee_set_cred_thread_keyring, ++ (iee_func)_iee_set_cred_request_key_auth, ++ (iee_func)_iee_set_cred_non_rcu, ++ (iee_func)_iee_set_cred_atomic_set_usage, ++ (iee_func)_iee_set_cred_atomic_op_usage, ++ (iee_func)_iee_set_cred_security, ++ (iee_func)_iee_set_cred_rcu, ++ (iee_func)_iee_set_cred_ucounts, +#endif -+ default: -+ { -+ #ifndef CONFIG_KOI -+ if((flag < IEE_WRITE_IN_BYTE) | (flag > IEE_OP_SET_CRED_UCOUNTS)) -+ panic("Invalid iee flag.\n"); -+ #else -+ if((flag < IEE_WRITE_IN_BYTE) | (flag > IEE_WRITE_KOI_STACK_BASE)) -+ panic("Invalid iee flag.\n"); -+ #endif -+ iee_wrappers[flag](pArgs); -+ break; -+ } -+ } -+ -+ va_end(pArgs); -+ return 0; -+} ++#ifdef CONFIG_KEYP ++ (iee_func)_iee_set_key_union, ++ (iee_func)_iee_set_key_struct, ++ (iee_func)_iee_set_key_payload, ++ (iee_func)_iee_write_key_payload, ++ (iee_func)_iee_write_key_payload_rcu_data0, ++ (iee_func)_iee_set_key_usage, ++ (iee_func)_iee_set_key_serial, ++ (iee_func)_iee_set_key_watchers, ++ (iee_func)_iee_set_key_user, ++ (iee_func)_iee_set_key_security, ++ (iee_func)_iee_set_key_expiry, ++ (iee_func)_iee_set_key_revoked_at, ++ (iee_func)_iee_set_key_last_used_at, ++ (iee_func)_iee_set_key_uid, ++ (iee_func)_iee_set_key_gid, ++ (iee_func)_iee_set_key_perm, ++ (iee_func)_iee_set_key_quotalen, ++ (iee_func)_iee_set_key_datalen, ++ (iee_func)_iee_set_key_state, ++ (iee_func)_iee_set_key_magic, ++ (iee_func)_iee_set_key_flags, ++ (iee_func)_iee_set_key_index_key, ++ (iee_func)_iee_set_key_hash, ++ (iee_func)_iee_set_key_len_desc, ++ (iee_func)_iee_set_key_type, ++ (iee_func)_iee_set_key_domain_tag, ++ (iee_func)_iee_set_key_description, ++ (iee_func)_iee_set_key_restrict_link, ++ (iee_func)_iee_set_key_flag_bit, ++#endif ++#ifdef CONFIG_IEE_SELINUX_P ++ (iee_func)_iee_set_selinux_status_pg, ++ (iee_func)_iee_set_selinux_enforcing, ++ (iee_func)_iee_mark_selinux_initialized, ++ (iee_func)_iee_set_sel_policy_cap, ++ (iee_func)_iee_sel_rcu_assign_policy, ++#endif ++ NULL ++}; + +#ifdef CONFIG_KOI -+unsigned long __iee_code _iee_read_koi_stack(struct task_struct *tsk) ++unsigned long __iee_code _iee_read_koi_stack(unsigned long iee_offset, struct task_struct *tsk) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); + return (unsigned long)token->koi_stack; +} + -+void __iee_code _iee_write_koi_stack(struct task_struct *tsk, unsigned long koi_stack) ++void __iee_code _iee_write_koi_stack(unsigned long iee_offset, struct task_struct *tsk, unsigned long koi_stack) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); + token->koi_stack = koi_stack; +} + -+unsigned long __iee_code _iee_read_token_ttbr1(struct task_struct *tsk) ++unsigned long __iee_code _iee_read_token_ttbr1(unsigned long iee_offset, struct task_struct *tsk) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); + return token->current_ttbr1; +} + -+void __iee_code _iee_write_token_ttbr1(struct task_struct *tsk, unsigned long current_ttbr1) ++void __iee_code _iee_write_token_ttbr1(unsigned long iee_offset, struct task_struct *tsk, unsigned long current_ttbr1) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); + token->current_ttbr1 = current_ttbr1; +} + -+unsigned long __iee_code _iee_read_koi_kernel_stack(struct task_struct *tsk) ++unsigned long __iee_code _iee_read_koi_kernel_stack(unsigned long iee_offset, struct task_struct *tsk) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); + return token->koi_kernel_stack; +} + -+void __iee_code _iee_write_koi_kernel_stack(struct task_struct *tsk, unsigned long kernel_stack) ++void __iee_code _iee_write_koi_kernel_stack(unsigned long iee_offset, struct task_struct *tsk, unsigned long kernel_stack) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); + token->koi_kernel_stack = kernel_stack; +} + -+unsigned long __iee_code _iee_read_koi_stack_base(struct task_struct *tsk) ++unsigned long __iee_code _iee_read_koi_stack_base(unsigned long iee_offset, struct task_struct *tsk) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); + return (unsigned long)token->koi_stack_base; +} + -+void __iee_code _iee_write_koi_stack_base(struct task_struct *tsk, unsigned long koi_stack_base) ++void __iee_code _iee_write_koi_stack_base(unsigned long iee_offset, struct task_struct *tsk, unsigned long koi_stack_base) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); + token->koi_stack_base = koi_stack_base; +} -+#endif + -+// Protect the __entry_task. -+__attribute__((aligned(PAGE_SIZE))) DECLARE_PER_CPU(struct task_struct *[PAGE_SIZE/sizeof(struct task_struct *)], __entry_task); -+void __iee_code _iee_write_entry_task(struct task_struct *tsk) ++static inline void iee_set_koi_pgd_writeable(unsigned long koi_pgd_addr, unsigned long iee_si_addr) +{ -+ // Add check of tsk. -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); -+ -+ unsigned long flags; -+ unsigned long res; -+ struct task_struct **entry_addr; -+ local_irq_save(flags); -+ asm volatile("at s1e1r, %0"::"r"(token)); -+ isb(); -+ res = read_sysreg(par_el1); -+ local_irq_restore(flags); -+ -+ // If it is logical map, that means it is not a token. -+ if(__phys_to_iee(res & PTE_ADDR_MASK) == (((unsigned long)token) & PTE_ADDR_MASK)) -+ panic("Trying to forge a token.\n"); -+ -+ if(!token->valid) -+ panic("Trying to write a wrong task into __entry_task.\n"); -+ entry_addr = (struct task_struct **)__phys_to_iee(__pa(SHIFT_PERCPU_PTR(__entry_task,__kern_my_cpu_offset()))); -+ *entry_addr = tsk; ++ pgd_t *pgdir = (pgd_t *)koi_pgd_addr; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, iee_si_addr); ++ p4d_t *p4dp = p4d_offset(pgdp, iee_si_addr); ++ pud_t *pudp = pud_offset(p4dp, iee_si_addr); ++ pmd_t *pmdp = pmd_offset(pudp, iee_si_addr); ++ pte_t *ptep = pte_offset_kernel(pmdp, iee_si_addr); ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(pte_val(pte) | PTE_DBM); ++ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa(ptep)))), pte); +} -+ -+unsigned long __iee_code _iee_read_token_stack(struct task_struct *tsk) ++/* ++ * Set IEE SI codes U RWX here to avoid IEE DEP checking fault. ++ * Mark koi pgd in the same time. ++ */ ++void __iee_code _iee_set_koi_pgd(unsigned long iee_offset, unsigned long koi_pgd_addr) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); -+ return (unsigned long)token->iee_stack; ++ // IEE SI codes are 2 pages starting at __iee_si_text_start. ++ unsigned long iee_si_addr = (unsigned long)__iee_si_text_start; ++ iee_set_koi_pgd_writeable(koi_pgd_addr, iee_si_addr); ++ iee_si_addr += PAGE_SIZE; ++ iee_set_koi_pgd_writeable(koi_pgd_addr, iee_si_addr); ++ // Use DBM=0, AP[7]=0 to mark this page as a koi pgd in IEE. +} ++#endif + -+void __iee_code _iee_free_token(struct task_struct *tsk) ++#ifdef CONFIG_IEE_SELINUX_P ++void __iee_code _iee_set_selinux_status_pg(unsigned long iee_offset, struct page* new_page) +{ -+ _iee_memset(tsk, 0, sizeof(struct task_token)); ++ struct page** iee_addr = (struct page**)__phys_to_iee(__pa_symbol(&(selinux_state.status_page))); ++ *iee_addr = new_page; +} + -+#ifdef CONFIG_KOI -+extern unsigned long koi_swapper_ttbr1; -+#endif -+void __iee_code _iee_init_token(struct task_struct *tsk, void *kernel_stack, void *iee_stack) ++void __iee_code _iee_set_selinux_enforcing(unsigned long iee_offset, bool value) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); -+ token->kernel_stack = kernel_stack; -+ token->iee_stack = iee_stack; -+ token->valid = true; -+#ifdef CONFIG_KOI -+ token->koi_kernel_stack = NULL; -+ token->koi_stack = NULL; -+ token->koi_stack_base = NULL; -+ token->current_ttbr1 = 0; -+#endif ++ *(bool*)__phys_to_iee(__pa_symbol(&(selinux_state.enforcing))) = value; +} + -+void __iee_code _iee_set_token_mm(struct task_struct *tsk, struct mm_struct *mm) ++void __iee_code _iee_mark_selinux_initialized(unsigned long iee_offset) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); -+ token->mm = mm; ++ smp_store_release(((bool*)__phys_to_iee(__pa_symbol(&(selinux_state.initialized)))), true); ++ printk("IEE: Mark selinux initialized."); +} + -+void __iee_code _iee_set_token_pgd(struct task_struct *tsk, pgd_t *pgd) ++void __iee_code _iee_set_sel_policy_cap(unsigned long iee_offset, unsigned int idx, int cap) +{ -+ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); -+ token->pgd = pgd; ++ *(bool*)__phys_to_iee(__pa_symbol(&(selinux_state.policycap[idx]))) = cap; +} + -+void __iee_code _iee_set_freeptr(freeptr_t *pptr, freeptr_t ptr) ++/* ++ * Please make sure param iee_new_policy is from policy_jar memcache. ++ * Need to free new_policy after calling this func as it's only used to ++ * trans data from kernel. ++ */ ++void __iee_code _iee_sel_rcu_assign_policy(unsigned long iee_offset, struct selinux_policy* new_policy, ++ struct selinux_policy* iee_new_policy) +{ -+ pptr = (freeptr_t *)__phys_to_iee(__pa(pptr)); -+ *pptr = ptr; ++ /* TODO: Verify informations from incoming policy. */ ++ // /* Make sure iee_new_policy is from policy_jar memcache. */ ++ // struct slab* policy_pg = (struct slab*)pfn_to_page(__pa(iee_new_policy) >> PAGE_SHIFT); ++ // if (policy_pg->slab_cache != policy_jar) ++ // printk("IEE SELINUXP ERROR: new policy is not from iee memcache."); ++ /* Copy data from kernel to new allocated policy struct inside iee. */ ++ struct selinux_policy* iee_addr = (struct selinux_policy *)((unsigned long)iee_new_policy + iee_offset); ++ memcpy(iee_addr, new_policy, sizeof(struct selinux_policy)); ++ ++ rcu_assign_pointer(*((struct selinux_policy**)__phys_to_iee(__pa_symbol(&(selinux_state.policy)))), ++ iee_new_policy); ++ printk("IEE: assigned rcu pointer selinux_state.policy."); +} ++#endif + -+#pragma GCC push_options -+#pragma GCC optimize("O0") -+void __iee_code _iee_memset(void *ptr, int data, size_t n) ++bool __iee_code _iee_set_key_flag_bit(unsigned long iee_offset, struct key *key, long nr, int flag) +{ -+ char *_ptr = (char *)__phys_to_iee(__pa(ptr)); -+ -+ while (n--) -+ *_ptr++ = data; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ switch(flag) ++ { ++ case SET_BIT_OP: ++ { ++ set_bit(nr, &key->flags); ++ break; ++ } ++ case TEST_AND_CLEAR_BIT: ++ { ++ return test_and_clear_bit(nr, &key->flags); ++ } ++ case TEST_AND_SET_BIT: ++ { ++ return test_and_set_bit(nr, &key->flags); ++ } ++ } ++ return 0; +} + -+void __iee_code _iee_memcpy(void *dst, void *src, size_t n) ++void __iee_code _iee_set_key_restrict_link(unsigned long iee_offset, struct key *key, struct key_restriction *restrict_link) +{ -+ char *_dst = (char *)__phys_to_iee(__pa(dst)); -+ char *_src = (char *)src; -+ -+ while(n--) -+ *_dst++ = *_src++; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->restrict_link = restrict_link; +} -+#pragma GCC pop_options + -+void __iee_code _iee_set_track(struct track *ptr, struct track *data) ++void __iee_code _iee_set_key_magic(unsigned long iee_offset, struct key *key, unsigned magic) +{ -+ _iee_memcpy(ptr, data, sizeof(struct track)); ++ #ifdef KEY_DEBUGGING ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->magic = magic; ++ #endif +} + -+void __iee_code _iee_set_cred_rcu(struct cred *cred, struct rcu_head *rcu) ++void __iee_code _iee_set_key_flags(unsigned long iee_offset, struct key *key, unsigned long flags) +{ -+ if(cred == &init_cred) -+ cred = (struct cred *)__phys_to_iee(__pa_symbol(cred)); -+ else -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ #ifdef CONFIG_CREDP -+ *((struct rcu_head **)(&(cred->rcu.func))) = rcu; -+ #endif ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->flags = flags; +} + -+void __iee_code _iee_set_cred_security(struct cred *cred, void *security) ++void __iee_code _iee_set_key_index_key(unsigned long iee_offset, struct key *key, struct keyring_index_key index_key) +{ -+ if(cred == &init_cred) -+ cred = (struct cred *)__phys_to_iee(__pa_symbol(cred)); -+ else -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->security = security; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->index_key = index_key; +} + -+bool __iee_code _iee_set_cred_atomic_op_usage(struct cred *cred, int flag, int nr) ++void __iee_code _iee_set_key_hash(unsigned long iee_offset, struct key *key, unsigned long hash) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ switch (flag) -+ { -+ case AT_ADD: { -+ atomic_long_add(nr, &cred->usage); -+ return 0; -+ } -+ case AT_INC_NOT_ZERO: { -+ return atomic_long_inc_not_zero(&cred->usage); -+ } -+ case AT_SUB_AND_TEST: { -+ return atomic_long_sub_and_test(nr, &cred->usage); -+ } -+ } -+ return 0; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->hash = hash; +} + -+void __iee_code _iee_set_cred_atomic_set_usage(struct cred *cred, int i) ++void __iee_code _iee_set_key_len_desc(unsigned long iee_offset, struct key *key, unsigned long len_desc) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ atomic_long_set(&cred->usage,i); ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->len_desc = len_desc; +} + -+void __iee_code _iee_set_cred_non_rcu(struct cred *cred, int non_rcu) ++void __iee_code _iee_set_key_type(unsigned long iee_offset, struct key *key, struct key_type *type) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->non_rcu = non_rcu; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->type = type; +} + -+void __iee_code _iee_set_cred_session_keyring(struct cred *cred, struct key *session_keyring) ++void __iee_code _iee_set_key_domain_tag(unsigned long iee_offset, struct key *key, struct key_tag *domain_tag) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->session_keyring = session_keyring; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->domain_tag = domain_tag; +} + -+void __iee_code _iee_set_cred_process_keyring(struct cred *cred, struct key *process_keyring) ++void __iee_code _iee_set_key_description(unsigned long iee_offset, struct key *key, char *description) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->process_keyring = process_keyring; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->description = description; +} + -+void __iee_code _iee_set_cred_thread_keyring(struct cred *cred, struct key *thread_keyring) ++void __iee_code _iee_set_key_uid(unsigned long iee_offset, struct key *key, kuid_t uid) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->thread_keyring = thread_keyring; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->uid = uid; +} + -+void __iee_code _iee_set_cred_request_key_auth(struct cred *cred, struct key *request_key_auth) ++void __iee_code _iee_set_key_gid(unsigned long iee_offset, struct key *key, kgid_t gid) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->request_key_auth = request_key_auth; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->gid = gid; +} + -+void __iee_code _iee_set_cred_jit_keyring(struct cred *cred, unsigned char jit_keyring) ++void __iee_code _iee_set_key_perm(unsigned long iee_offset, struct key *key, key_perm_t perm) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->jit_keyring = jit_keyring; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->perm = perm; +} + -+void __iee_code _iee_set_cred_cap_inheritable(struct cred *cred, kernel_cap_t cap_inheritable) ++void __iee_code _iee_set_key_quotalen(unsigned long iee_offset, struct key *key, unsigned short quotalen) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->cap_inheritable = cap_inheritable; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->quotalen = quotalen; +} + -+void __iee_code _iee_set_cred_cap_permitted(struct cred *cred, kernel_cap_t cap_permitted) ++void __iee_code _iee_set_key_datalen(unsigned long iee_offset, struct key *key, unsigned short datalen) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->cap_permitted = cap_permitted; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->datalen = datalen; +} + -+void __iee_code _iee_set_cred_cap_effective(struct cred *cred, kernel_cap_t cap_effective) ++void __iee_code _iee_set_key_state(unsigned long iee_offset, struct key *key, short state) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->cap_effective = cap_effective; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ WRITE_ONCE(key->state, state); +} + -+void __iee_code _iee_set_cred_cap_bset(struct cred *cred, kernel_cap_t cap_bset) ++void __iee_code _iee_set_key_user(unsigned long iee_offset, struct key *key, struct key_user *user) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->cap_bset = cap_bset; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->user = user; +} + -+void __iee_code _iee_set_cred_cap_ambient(struct cred *cred, kernel_cap_t cap_ambient) ++void __iee_code _iee_set_key_security(unsigned long iee_offset, struct key *key, void *security) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->cap_ambient = cap_ambient; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->security = security; +} + -+void __iee_code _iee_set_cred_securebits(struct cred *cred, unsigned securebits) ++void __iee_code _iee_set_key_expiry(unsigned long iee_offset, struct key *key, time64_t expiry) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->securebits = securebits; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->expiry = expiry; +} + -+void __iee_code _iee_set_cred_group_info(struct cred *cred, struct group_info *group_info) ++void __iee_code _iee_set_key_revoked_at(unsigned long iee_offset, struct key *key, time64_t revoked_at) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->group_info = group_info; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->revoked_at = revoked_at; +} + -+void __iee_code _iee_set_cred_ucounts(struct cred *cred, struct ucounts *ucounts) ++void __iee_code _iee_set_key_last_used_at(unsigned long iee_offset, struct key *key, time64_t last_used_at) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->ucounts = ucounts; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->last_used_at = last_used_at; +} + -+void __iee_code _iee_set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) ++bool __iee_code _iee_set_key_usage(unsigned long iee_offset, struct key *key, int n, int flag) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->user_ns = user_ns; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ switch(flag) ++ { ++ case REFCOUNT_INC: ++ { ++ refcount_inc(&key->usage); ++ break; ++ } ++ case REFCOUNT_SET: ++ { ++ refcount_set(&key->usage, n); ++ break; ++ } ++ case REFCOUNT_DEC_AND_TEST: ++ { ++ return refcount_dec_and_test(&key->usage); ++ } ++ case REFCOUNT_INC_NOT_ZERO: ++ { ++ return refcount_inc_not_zero(&key->usage); ++ } ++ } ++ return 0; +} + -+void __iee_code _iee_set_cred_user(struct cred *cred, struct user_struct *user) ++void __iee_code _iee_set_key_serial(unsigned long iee_offset, struct key *key, key_serial_t serial) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->user = user; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->serial = serial; +} + -+void __iee_code _iee_set_cred_fsgid(struct cred *cred, kgid_t fsgid) ++void __iee_code _iee_set_key_watchers(unsigned long iee_offset, struct key *key, struct watch_list *watchers) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->fsgid = fsgid; ++ #ifdef CONFIG_KEY_NOTIFICATIONS ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->watchers = watchers; ++ #endif +} + -+void __iee_code _iee_set_cred_fsuid(struct cred *cred, kuid_t fsuid) ++void __iee_code _iee_write_key_payload_rcu_data0(unsigned long iee_offset, struct key *key, void *rcu_data0) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->fsuid = fsuid; ++ union key_payload *key_payload = (union key_payload *)__phys_to_iee(__pa(key->name_link.next)); ++ WRITE_ONCE(key_payload->rcu_data0, rcu_data0); +} + -+void __iee_code _iee_set_cred_egid(struct cred *cred, kgid_t egid) ++void __iee_code _iee_write_key_payload(unsigned long iee_offset, struct key *key, union key_payload payload) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->egid = egid; ++ union key_payload *key_payload = (union key_payload *)__phys_to_iee(__pa(key->name_link.next)); ++ *key_payload = payload; +} + -+void __iee_code _iee_set_cred_euid(struct cred *cred, kuid_t euid) ++void __iee_code _iee_set_key_union(unsigned long iee_offset, struct key *key, struct key_union *key_union) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->euid = euid; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->graveyard_link.next = (struct list_head *)key_union; +} + -+void __iee_code _iee_set_cred_sgid(struct cred *cred, kgid_t sgid) ++void __iee_code _iee_set_key_struct(unsigned long iee_offset, struct key *key, struct key_struct *key_struct) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->sgid = sgid; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->name_link.prev = (struct list_head *)key_struct; +} + -+void __iee_code _iee_set_cred_suid(struct cred *cred, kuid_t suid) ++void __iee_code _iee_set_key_payload(unsigned long iee_offset, struct key *key, union key_payload *key_payload) +{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->suid = suid; ++ key = (struct key *)((unsigned long)key + iee_offset); ++ key->name_link.next = (struct list_head *)key_payload; +} + -+void __iee_code _iee_copy_cred(struct cred *old, struct cred *new) ++void __iee_code _iee_split_huge_pmd(unsigned long iee_offset, pmd_t *pmdp, pte_t *pgtable) +{ -+ #ifdef CONFIG_CREDP -+ struct rcu_head *rcu = (struct rcu_head *)(new->rcu.func); -+ struct cred *_new = (struct cred *)__phys_to_iee(__pa(new)); -+ _iee_memcpy(new,old,sizeof(struct cred)); -+ *(struct rcu_head **)(&(_new->rcu.func)) = rcu; -+ *(struct rcu_head *)(_new->rcu.func) = *(struct rcu_head *)(old->rcu.func); -+ #endif -+} -+ -+void __iee_code _iee_set_cred_gid(struct cred *cred, kgid_t gid) -+{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->gid = gid; -+} -+ -+void __iee_code _iee_set_cred_uid(struct cred *cred, kuid_t uid) -+{ -+ cred = (struct cred *)__phys_to_iee(__pa(cred)); -+ cred->uid = uid; ++ int i; ++ struct page *page = pmd_page(*pmdp); ++ pte_t *ptep = (pte_t *)((unsigned long)pgtable + (unsigned long)iee_offset); ++ ++ for (i = 0; i < PMD_SIZE / PAGE_SIZE; i++, ptep++) { ++ pte_t entry; ++ pgprot_t pgprot = PAGE_KERNEL; ++ #ifdef CONFIG_KOI ++ pgprot = __pgprot(pgprot_val(pgprot) | PTE_CONT | PTE_NG); ++ #else ++ pgprot = __pgprot(pgprot_val(pgprot) | PTE_CONT); ++ #endif ++ entry = mk_pte(page + i, pgprot); ++ WRITE_ONCE(*ptep, entry); ++ } +} + -+void __iee_code _iee_write_in_byte(void *ptr, __u64 data, int length) ++void __iee_code _iee_copy_pte_range(unsigned long iee_offset, pte_t *new_dst, pte_t *old_dst, pte_t *src_pte, struct vm_area_struct *src_vma, unsigned long dst_vm_flags, pte_t *end_pte) +{ -+ ptr = (void *)__phys_to_iee(__pa(ptr)); -+ switch(length) { -+ case 8: { -+ *(__u64 *)ptr = data; -+ break; -+ } -+ case 4: { -+ *(__u32 *)ptr = (__u32)data; -+ break; ++ pte_t pte, tmp; ++ swp_entry_t entry; ++ tmp = __pte(0); ++ while(src_pte < end_pte) ++ { ++ if (!pte_none(*src_pte) && unlikely(!pte_present(*src_pte))) ++ { ++ pte = *src_pte; ++ entry = pte_to_swp_entry(pte); ++ if (likely(!non_swap_entry(entry))) ++ ; ++ else if(is_migration_entry(entry)) ++ { ++ if (is_readable_migration_entry(entry) && ++ is_cow_mapping(dst_vm_flags)) ++ { ++ entry = make_readable_migration_entry(swp_offset(entry)); ++ pte = swp_entry_to_pte(entry); ++ if (pte_swp_soft_dirty(*src_pte)) ++ pte = pte_swp_mksoft_dirty(pte); ++ if (pte_swp_uffd_wp(*src_pte)) ++ pte = pte_swp_mkuffd_wp(pte); ++ _iee_set_pte_single(src_pte, pte, iee_offset); ++ } ++ } ++ else if (is_device_private_entry(entry)) ++ { ++ if (is_writable_device_private_entry(entry) && ++ is_cow_mapping(dst_vm_flags)) { ++ entry = make_readable_device_private_entry( ++ swp_offset(entry)); ++ pte = swp_entry_to_pte(entry); ++ if (pte_swp_uffd_wp(*src_pte)) ++ pte = pte_swp_mkuffd_wp(pte); ++ _iee_set_pte_single(src_pte, pte, iee_offset); ++ } ++ } + } -+ case 2: { -+ *(__u16 *)ptr = (__u16)data; -+ break; ++ else if(!pte_none(*src_pte) && likely(pte_present(*src_pte))) ++ { ++ struct page *page = NULL; ++ #ifdef CONFIG_ARCH_HAS_PTE_SPECIAL ++ if (likely(!pte_special(*src_pte))) ++ if (unlikely(pte_pfn(*src_pte) > highest_memmap_pfn)) ++ page = NULL; ++ else ++ page = pte_page(*src_pte); ++ #else ++ if((!unlikely(src_vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) || ((src_vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pte_pfn(*src_pte))) || (!(src_vma->vm_flags & VM_MIXEDMAP) && !(pfn == src_vma->vm_pgoff + off) && is_cow_mapping(src_vma->vm_flags))) && !is_zero_pfn(pte_pfn(*src_pte)) && !unlikely(pte_pfn(*src_pte) > highest_memmap_pfn)) ++ page = pte_page(*src_pte); ++ #endif ++ if(!(page && folio_test_anon(page_folio(page))) || likely(!PageAnonExclusive(page) || !(likely(!is_device_private_page(page) && unlikely(folio_needs_cow_for_dma(src_vma, page_folio(page))))))) ++ { ++ if (is_cow_mapping(src_vma->vm_flags) && pte_write(*src_pte)) ++ { ++ pte_t old_pte, new_pte; ++ ++ new_pte = READ_ONCE(*src_pte); ++ do { ++ old_pte = new_pte; ++ new_pte = pte_wrprotect(new_pte); ++ _iee_set_cmpxchg_relaxed(src_pte, pte_val(old_pte), pte_val(new_pte), iee_offset); ++ } while (pte_val(new_pte) != pte_val(old_pte)); ++ } ++ } + } -+ case 1: { -+ *(__u8 *)ptr = (__u8)data; -+ break; ++ if(!pte_none(*new_dst)) ++ { ++ _iee_set_pte_single(old_dst, *new_dst, iee_offset); ++ WRITE_ONCE(*new_dst, __pte(0)); + } ++ old_dst++; ++ src_pte++; ++ new_dst++; + } +} + -+pteval_t __iee_code _iee_set_xchg_relaxed(pte_t *ptep, pteval_t pteval) -+{ -+ pteval_t ret = xchg_relaxed((pteval_t *)(__phys_to_iee(__pa(ptep))), pteval); -+ return ret; -+} -+ -+pteval_t __iee_code _iee_set_cmpxchg_relaxed(pte_t *ptep, pteval_t old_pteval, pteval_t new_pteval) -+{ -+ pteval_t pteval = cmpxchg_relaxed((pteval_t *)(__phys_to_iee(__pa(ptep))), old_pteval, new_pteval); -+ return pteval; -+} -+ -+/* Check if addr is allocated in IEE page */ -+static inline bool check_addr_in_iee_valid(unsigned long addr) -+{ -+ unsigned long flags; -+ unsigned long res; -+ local_irq_save(flags); -+ asm volatile("at s1e1r, %0"::"r"(addr)); -+ isb(); -+ res = read_sysreg(par_el1); -+ local_irq_restore(flags); -+ -+ // If it is not logical map, that means it is a token. -+ if(__phys_to_iee(res & PTE_ADDR_MASK) != addr) -+ return false; -+ -+ return !(res & 0x1); -+} -+ -+void __iee_code _iee_set_tramp_pgd_pre_init(pgd_t *pgdp, pgd_t pgd) ++void __iee_code _iee_set_sensitive_pte(unsigned long iee_offset, pte_t *lm_ptep, pte_t *iee_ptep, int order, int use_block_pmd) +{ -+ WRITE_ONCE(*((pgd_t *)(__phys_to_iee(__pa_symbol(pgdp)))), pgd); -+} ++ int i; + -+void __iee_code _iee_set_swapper_pgd(pgd_t *pgdp, pgd_t pgd) -+{ -+ if(!(pgd_val(pgd) & PMD_SECT_VALID)) ++ lm_ptep = (pte_t *)((unsigned long)lm_ptep + iee_offset); ++ iee_ptep = (pte_t *)((unsigned long)iee_ptep + iee_offset); ++ if(use_block_pmd) + { -+ WRITE_ONCE(*((pgd_t *)(__phys_to_iee(__pa_symbol(pgdp)))), pgd); -+ return; ++ pmd_t pmd = __pmd(pte_val(READ_ONCE(*lm_ptep))); ++ pmd = __pmd((pmd_val(pmd) | PMD_SECT_RDONLY) & ~PTE_DBM); ++ WRITE_ONCE(*lm_ptep, __pte(pmd_val(pmd))); ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ iee_ptep++; ++ } + } -+ -+ if ((pgd_val(pgd) & PMD_TABLE_BIT) && !check_addr_in_iee_valid(__phys_to_iee(__pgd_to_phys(pgd)))) -+ panic("You can't use non-iee-pgtable\n"); -+ -+ if((pgdp >= pgd_offset_pgd((pgd_t *)swapper_pg_dir, PAGE_OFFSET + BIT(vabits_actual - 2))) && (pgdp < pgd_offset_pgd((pgd_t *)swapper_pg_dir, PAGE_OFFSET + BIT(vabits_actual - 1))) && !(pgd_val(pgd) & PGD_APT)) -+ panic("Set IEE pgd U page.\n"); -+ -+ WRITE_ONCE(*((pgd_t *)(__phys_to_iee(__pa_symbol(pgdp)))), pgd); -+} -+ -+void __iee_code _iee_set_p4d(p4d_t *p4dp, p4d_t p4d) -+{ -+ if(!(p4d_val(p4d) & PMD_SECT_VALID)) ++ else + { -+ WRITE_ONCE(*((p4d_t *)(__phys_to_iee(__pa(p4dp)))), p4d); -+ return; ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*lm_ptep); ++ pte = __pte((pte_val(pte) | PTE_RDONLY) & ~PTE_DBM); ++ WRITE_ONCE(*lm_ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ lm_ptep++; ++ iee_ptep++; ++ } + } -+ -+ if ((p4d_val(p4d) & PMD_TABLE_BIT) && !check_addr_in_iee_valid(__phys_to_iee(__p4d_to_phys(p4d)))) -+ panic("You can't use non-iee-pgtable\n"); -+ -+ WRITE_ONCE(*((p4d_t *)(__phys_to_iee(__pa(p4dp)))), p4d); +} + -+void __iee_code _iee_set_pud(pud_t *pudp, pud_t pud) ++void __iee_code _iee_unset_sensitive_pte(unsigned long iee_offset, pte_t *lm_ptep, pte_t *iee_ptep, int order, int use_block_pmd) +{ -+ if(!(pud_val(pud) & PMD_SECT_VALID)) ++ int i; ++ ++ lm_ptep = (pte_t *)((unsigned long)lm_ptep + iee_offset); ++ iee_ptep = (pte_t *)((unsigned long)iee_ptep + iee_offset); ++ if(use_block_pmd) + { -+ WRITE_ONCE(*((pud_t *)(__phys_to_iee(__pa(pudp)))), pud); -+ return; ++ pmd_t pmd = __pmd(pte_val(READ_ONCE(*lm_ptep))); ++ pmd = __pmd(pmd_val(pmd) | PTE_DBM); ++ WRITE_ONCE(*lm_ptep, __pte(pmd_val(pmd))); ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ iee_ptep++; ++ } + } -+ -+ if ((pud_val(pud) & PMD_TABLE_BIT) && !check_addr_in_iee_valid(__phys_to_iee(__pud_to_phys(pud)))) -+ panic("You can't use non-iee-pgtable\n"); -+ -+ WRITE_ONCE(*((pud_t *)(__phys_to_iee(__pa(pudp)))), pud); -+} -+ -+// Return true if the modify does not break DEP. -+static inline bool check_pmd_dep(char *addr, pmd_t pmd) -+{ -+ // DEP for kernel code and readonly data -+ // _text: .text start addr, __init_begin: .rodata end addr -+ if (addr >= _stext && addr < _etext) ++ else + { -+ if ((PTE_WRITE & pmd_val(pmd)) || // DBM == 1 --> writable -+ !(PTE_RDONLY & pmd_val(pmd))) // DBM == 0 && AP[2] = 0 --> writable ++ for(i = 0; i < (1 << order); i++) + { -+ panic("Can't make kernel's text/readonly page as writable!\n" -+ "addr = 0x%16llx, pmd_val = 0x%16llx", -+ (u64)addr, pmd_val(pmd)); ++ pte_t pte = READ_ONCE(*lm_ptep); ++ pte = __pte(pte_val(pte) | PTE_DBM); ++ WRITE_ONCE(*lm_ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ lm_ptep++; ++ iee_ptep++; + } + } -+ return true; +} + -+// Return true if the pmd table is a part of kernel page table. -+// TODO : Optimize to get lower overhead. -+static inline bool is_kernel_pmd_table(pmd_t *pmdp, pmd_t pmd) ++void __iee_code _iee_set_token(unsigned long iee_offset, pte_t *ptep, void *new, unsigned long order, int use_block_pmd) +{ -+ int i = 0,j = 0; -+ for(i = 0; i < PAGE_SIZE/sizeof(pgd_t); i++) ++ int i; ++ pgd_t *pgdir; ++ pgd_t *pgdp; ++ p4d_t *p4dp; ++ pud_t *pudp; ++ pmd_t *pmdp; ++ pte_t *lm_ptep; ++ pte_t *iee_ptep; ++ unsigned long iee_addr; ++ ++ pgdir = swapper_pg_dir; ++ ++ pgdp = pgd_offset_pgd(pgdir, (unsigned long)new); ++ p4dp = p4d_offset(pgdp, (unsigned long)new); ++ pudp = pud_offset(p4dp, (unsigned long)new); ++ pmdp = pmd_offset(pudp, (unsigned long)new); ++ if(use_block_pmd) ++ lm_ptep = (pte_t *)pmdp; ++ else ++ lm_ptep = pte_offset_kernel(pmdp, (unsigned long)new); ++ // Handling cont mapping. ++ if(pte_val(*lm_ptep) & PTE_CONT) + { -+ pgd_t *pgdp = (pgd_t *)swapper_pg_dir + i; -+ if((pgd_val(*pgdp) & PMD_SECT_VALID) && (pgd_val(*pgdp) & PMD_TABLE_BIT)) ++ // The beginning of cont mapping. ++ int i; ++ pte_t *ptep = (pte_t *)((unsigned long)pte_offset_kernel(pmdp, (unsigned long)new & CONT_PTE_MASK) + iee_offset); ++ if(order < CONFIG_ARM64_CONT_PTE_SHIFT) + { -+ for(j = 0; j < PAGE_SIZE/sizeof(pud_t); j++) ++ for(i = 0; i < CONT_PTES; i++) + { -+ pud_t *pudp = (pud_t *)__va(__pgd_to_phys(*pgdp)) + i; -+ if((pud_val(*pudp) & PMD_SECT_VALID) && (pud_val(*pudp) & PMD_TABLE_BIT)) -+ { -+ pmd_t *current_pmdp = __va(__pud_to_phys(*pudp)); -+ if((unsigned long)current_pmdp == ((unsigned long)pmdp & PAGE_MASK)) -+ return true; -+ } ++ WRITE_ONCE(*ptep,__pte(pte_val(*ptep) & ~PTE_CONT)); ++ ptep++; + } + } + } -+ return false; -+} -+ -+// Return true if it is mapped to a physical range containing IEE page. -+// TODO : Optimize to get lower overhead. -+static inline bool check_addr_range_in_iee_valid(pmd_t pmd) -+{ -+ int i = 0; -+ unsigned long addr = __phys_to_iee(__pmd_to_phys(pmd)); -+ for(i = 0; i < PAGE_SIZE/sizeof(pmd_t); i++) ++ ++ iee_addr = ((unsigned long)new + (unsigned long)iee_offset); ++ pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ p4dp = p4d_offset(pgdp, iee_addr); ++ pudp = pud_offset(p4dp, iee_addr); ++ pmdp = pmd_offset(pudp, iee_addr); ++ iee_ptep = pte_offset_kernel(pmdp, iee_addr); ++ ++ ptep = (pte_t *)((unsigned long)ptep + iee_offset); ++ lm_ptep = (pte_t *)((unsigned long)lm_ptep + iee_offset); ++ iee_ptep = (pte_t *)((unsigned long)iee_ptep + iee_offset); ++ if(use_block_pmd) + { -+ if(check_addr_in_iee_valid(addr + PAGE_SIZE * i)) -+ return true; ++ pmd_t *pmdp = (pmd_t *)lm_ptep; ++ pmd_t pmd = READ_ONCE(*pmdp); ++ pmd = __pmd((pmd_val(pmd) | PMD_SECT_RDONLY) & ~PTE_DBM); ++ WRITE_ONCE(*pmdp, pmd); ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) | PTE_VALID) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(new))); ++ WRITE_ONCE(*ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ ptep++; ++ iee_ptep++; ++ new += PAGE_SIZE; ++ } + } -+ return false; -+} -+ -+void __iee_code _iee_set_pmd(pmd_t *pmdp, pmd_t pmd) -+{ -+ char * addr = (char *)__phys_to_kimg(__pmd_to_phys(pmd)); -+ -+ if(!(pmd_val(pmd) & PMD_SECT_VALID)) ++ else + { -+ WRITE_ONCE(*((pmd_t *)(__phys_to_iee(__pa(pmdp)))), pmd); -+ return; ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) | PTE_VALID) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(new))); ++ WRITE_ONCE(*ptep, pte); ++ pte = READ_ONCE(*lm_ptep); ++ pte = __pte((pte_val(pte) | PTE_RDONLY) & ~PTE_DBM); ++ WRITE_ONCE(*lm_ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ ptep++; ++ lm_ptep++; ++ iee_ptep++; ++ new += PAGE_SIZE; ++ } + } -+ -+ // Check if the pte table is legally allocated. -+ if ((pmd_val(pmd) & PMD_TABLE_BIT) && !check_addr_in_iee_valid(__phys_to_iee(__pmd_to_phys(pmd)))) -+ panic("You can't use non-iee-pgtable\n"); -+ -+ // Avoid mapping a huge pmd as U page. -+ if(!(pmd_val(pmd) & PMD_TABLE_BIT) && (pmd_val(pmd) & PMD_SECT_USER) && is_kernel_pmd_table(pmdp, pmd)) -+ panic("Set a block descriptor in kernel space U page.\n"); -+ -+ // Avoid mapping a huge pmd to IEE physical page. -+ if(!(pmd_val(pmd) & PMD_TABLE_BIT) && check_addr_range_in_iee_valid(pmd)) -+ panic("Mapping IEE physical page to a huge pmd.\n"); -+ -+ if(!check_pmd_dep(addr, pmd)) -+ return; -+ -+ WRITE_ONCE(*((pmd_t *)(__phys_to_iee(__pa(pmdp)))), pmd); +} + -+// Return true if the pte table is a part of kernel page table. -+// TODO : Optimize to get lower overhead. -+static inline bool is_kernel_pte_table(pte_t *ptep, pte_t pte) ++void __iee_code _iee_unset_token(unsigned long iee_offset, pte_t *ptep, void *token_addr, void *token_page, unsigned long order) +{ -+ return false; -+} ++ int i; ++ pgd_t *pgdir; ++ pgd_t *pgdp; ++ p4d_t *p4dp; ++ pud_t *pudp; ++ pmd_t *pmdp; ++ pte_t *lm_ptep; ++ pte_t *iee_ptep; ++ unsigned long iee_addr; ++ int use_block_pmd = 0; + -+// Return true if it does not change the privilage or add new U page in kernel. -+static inline bool check_privilage_safe(pte_t *ptep, pte_t pte) -+{ -+ if(!(pte_val(pte) & PTE_VALID)) -+ return true; ++ pgdir = swapper_pg_dir; ++ ++ pgdp = pgd_offset_pgd(pgdir, (unsigned long)token_page); ++ p4dp = p4d_offset(pgdp, (unsigned long)token_page); ++ pudp = pud_offset(p4dp, (unsigned long)token_page); ++ pmdp = pmd_offset(pudp, (unsigned long)token_page); ++ // Use Block Descriptor. ++ if(pmd_leaf(*pmdp)) ++ { ++ use_block_pmd = 1; ++ lm_ptep = (pte_t *)pmdp; ++ } ++ else ++ lm_ptep = pte_offset_kernel(pmdp, (unsigned long)token_page); + -+ if((pte_val(*ptep) & PTE_VALID)) ++ iee_addr = ((unsigned long)token_page + (unsigned long)iee_offset); ++ pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ p4dp = p4d_offset(pgdp, iee_addr); ++ pudp = pud_offset(p4dp, iee_addr); ++ pmdp = pmd_offset(pudp, iee_addr); ++ iee_ptep = pte_offset_kernel(pmdp, iee_addr); ++ ++ ptep = (pte_t *)((unsigned long)ptep + iee_offset); ++ lm_ptep = (pte_t *)((unsigned long)lm_ptep + iee_offset); ++ iee_ptep = (pte_t *)((unsigned long)iee_ptep + iee_offset); ++ if(use_block_pmd) + { -+ if((pte_val(*ptep) & PTE_USER) != (pte_val(pte) & PTE_USER)) -+ panic("Incorrectly change privilage.\n"); ++ pmd_t *pmdp = (pmd_t *)lm_ptep; ++ pmd_t pmd = READ_ONCE(*pmdp); ++ pmd = __pmd(pmd_val(pmd) | PTE_DBM); ++ WRITE_ONCE(*pmdp, pmd); ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) & ~PTE_VALID) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(token_addr - IEE_OFFSET))); ++ WRITE_ONCE(*ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ ptep++; ++ iee_ptep++; ++ token_addr += PAGE_SIZE; ++ token_page += PAGE_SIZE; ++ } + } + else + { -+ if((pte_val(pte) & PTE_USER) && is_kernel_pte_table(ptep, pte)) -+ panic("Add new U page in kernel space.\n"); ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) & ~PTE_VALID) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(token_addr - IEE_OFFSET))); ++ WRITE_ONCE(*ptep, pte); ++ pte = READ_ONCE(*lm_ptep); ++ pte = __pte(pte_val(pte) | PTE_DBM); ++ WRITE_ONCE(*lm_ptep, pte); ++ pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ ptep++; ++ lm_ptep++; ++ iee_ptep++; ++ token_addr += PAGE_SIZE; ++ token_page += PAGE_SIZE; ++ } + } -+ return true; +} + -+// TODO : When adding a new executable page, check it for DEP. -+static inline bool safely_adding_new_exec_page(pte_t *ptep, pte_t pte) ++void __iee_code _iee_invalidate_token(unsigned long iee_offset, struct task_struct *tsk) +{ -+ return true; ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); ++ token->pgd = NULL; ++ token->valid = false; ++ token->kernel_stack = NULL; +} + -+// Return true if it is only changing prot of a pte. -+static inline bool is_changing_pte_prot(pte_t *ptep, pte_t pte) ++void __iee_code _iee_validate_token(unsigned long iee_offset, struct task_struct *tsk) +{ -+ if(((pte_val(*ptep) ^ pte_val(pte)) & PTE_ADDR_MASK) == 0) -+ return true; -+ else -+ return false; ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); ++ token->valid = true; +} + -+// Return true if the modify does not break DEP. -+static inline bool check_pte_dep(char *addr, pte_t pte) ++#ifdef CONFIG_KOI ++extern unsigned long koi_swapper_ttbr1; ++#endif ++void __iee_code _iee_init_token(unsigned long iee_offset, struct task_struct *tsk, void *iee_stack, void *tmp_page) +{ -+ // DEP for kernel code and readonly data -+ // _text: .text start addr, __init_begin: .rodata end addr -+ if (addr >= _stext && addr < _etext) -+ { -+ if ((PTE_WRITE & pte_val(pte)) // DBM == 1 --> writable -+ || !(PTE_RDONLY & pte_val(pte))) // DBM == 0 && AP[2] = 0 --> writable -+ { -+ panic("Can't make kernel's text/readonly page as writable!\n" -+ "addr = 0x%16llx, pte_val = 0x%16llx", -+ (u64)addr, pte_val(pte)); -+ } -+ } -+ return true; ++ struct task_token *token; ++ ++ token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); ++ token->iee_stack = iee_stack; ++ token->tmp_page = tmp_page; ++#ifdef CONFIG_KOI ++ token->koi_kernel_stack = NULL; ++ token->koi_stack = NULL; ++ token->koi_stack_base = NULL; ++ token->current_ttbr1 = 0; ++#endif +} + -+void __iee_code _iee_set_pte(pte_t *ptep, pte_t pte) ++void __iee_code _iee_set_token_pgd(unsigned long iee_offset, struct task_struct *tsk, pgd_t *pgd) +{ -+ char * addr = (char *)__phys_to_kimg(__pte_to_phys(pte)); ++ struct task_token *token; + -+ if(!(pte_val(pte) & PTE_VALID)) ++ token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); ++ token->pgd = pgd; ++} ++ ++void __iee_code _iee_set_freeptr(unsigned long iee_offset, void **pptr, void *ptr) ++{ ++ pptr = (void **)((unsigned long)pptr + (unsigned long)iee_offset); ++ *pptr = ptr; ++} ++ ++#pragma GCC push_options ++#pragma GCC optimize("O0") ++void __iee_code _iee_memset(unsigned long iee_offset, void *ptr, int data, size_t n) ++{ ++ char *_ptr; ++ ++ _ptr = (char *)((unsigned long)ptr + (unsigned long)iee_offset); ++ ++ while (n--) ++ *_ptr++ = data; ++} ++ ++void __iee_code _iee_memcpy(unsigned long iee_offset, void *dst, void *src, size_t n) ++{ ++ char *_dst, *_src; ++ ++ _dst = (char *)((unsigned long)dst + (unsigned long)iee_offset); ++ _src = (char *)src; ++ ++ while(n--) ++ *_dst++ = *_src++; ++} ++#pragma GCC pop_options ++ ++void __iee_code _iee_set_track(unsigned long iee_offset, struct track *ptr, struct track *data) ++{ ++ _iee_memcpy(iee_offset, ptr, data, sizeof(struct track)); ++} ++ ++void __iee_code _iee_set_cred_rcu(unsigned long iee_offset, struct cred *cred, struct rcu_head *rcu) ++{ ++ if(cred == &init_cred) ++ cred = (struct cred *)__phys_to_iee(__pa_symbol(cred)); ++ else ++ cred = (struct cred *)((unsigned long)cred + (unsigned long)iee_offset); ++ #ifdef CONFIG_CREDP ++ *((struct rcu_head **)(&(cred->rcu.func))) = rcu; ++ #endif ++} ++ ++void __iee_code _iee_set_cred_security(unsigned long iee_offset, struct cred *cred, void *security) ++{ ++ if(cred == &init_cred) ++ cred = (struct cred *)__phys_to_iee(__pa_symbol(cred)); ++ else ++ cred = (struct cred *)((unsigned long)cred + (unsigned long)iee_offset); ++ cred->security = security; ++} ++ ++bool __iee_code _iee_set_cred_atomic_op_usage(unsigned long iee_offset, struct cred *cred, int flag, int nr) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ switch (flag) + { -+ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa(ptep)))), pte); -+ return; ++ case AT_ADD: { ++ atomic_long_add(nr, &cred->usage); ++ return 0; ++ } ++ case AT_INC_NOT_ZERO: { ++ return atomic_long_inc_not_zero(&cred->usage); + } ++ case AT_SUB_AND_TEST: { ++ return atomic_long_sub_and_test(nr, &cred->usage); ++ } ++ } ++ return 0; ++} + -+ // Avoid modify privilage unsafely. -+ if(!check_privilage_safe(ptep, pte)) -+ panic("You are modify privilage unsafely.\n"); ++void __iee_code _iee_set_cred_atomic_set_usage(unsigned long iee_offset, struct cred *cred, int i) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ atomic_long_set(&cred->usage,i); ++} + -+ // Avoid mapping a new executable page. -+ if(!safely_adding_new_exec_page(ptep, pte)) -+ panic("You are adding a new executable page unsafely.\n"); ++void __iee_code _iee_set_cred_non_rcu(unsigned long iee_offset, struct cred *cred, int non_rcu) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->non_rcu = non_rcu; ++} + -+ // Avoid mapping a new VA to IEE PA. -+ if(!is_changing_pte_prot(ptep, pte) && -+ check_addr_in_iee_valid(__phys_to_iee(__pte_to_phys(pte)))) -+ panic("You are remmaping IEE page to other VA.\n"); ++void __iee_code _iee_set_cred_session_keyring(unsigned long iee_offset, struct cred *cred, struct key *session_keyring) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->session_keyring = session_keyring; ++} + -+ // Avoid mapping a writable VA to kernel code PA. -+ if(!check_pte_dep(addr, pte)) -+ return; ++void __iee_code _iee_set_cred_process_keyring(unsigned long iee_offset, struct cred *cred, struct key *process_keyring) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->process_keyring = process_keyring; ++} + -+ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa(ptep)))), pte); ++void __iee_code _iee_set_cred_thread_keyring(unsigned long iee_offset, struct cred *cred, struct key *thread_keyring) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->thread_keyring = thread_keyring; +} + -+// Return true if it only sets U page and modify NG. -+static inline bool is_setting_upage(pte_t *ptep, pte_t pte) ++void __iee_code _iee_set_cred_request_key_auth(unsigned long iee_offset, struct cred *cred, struct key *request_key_auth) +{ -+ if(((pte_val(*ptep) ^ pte_val(pte)) & ~(PTE_USER | PTE_NG)) != 0) -+ panic("Incorrectly setting U page.\n"); -+ if((pte_val(pte) & PTE_USER) != PTE_USER) -+ panic("Using error interface to set P page.\n"); -+ return true; ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->request_key_auth = request_key_auth; +} + -+void __iee_code _iee_set_pte_upage(pte_t *ptep, pte_t pte) ++void __iee_code _iee_set_cred_jit_keyring(unsigned long iee_offset, struct cred *cred, unsigned char jit_keyring) +{ -+ // Check if it only change the prot. -+ if(!is_setting_upage(ptep,pte)) -+ panic("Incorrectly setting U page.\n"); ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->jit_keyring = jit_keyring; ++} + -+ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa(ptep)))), pte); ++void __iee_code _iee_set_cred_cap_inheritable(unsigned long iee_offset, struct cred *cred, kernel_cap_t cap_inheritable) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->cap_inheritable = cap_inheritable; +} + -+// Return true if it only sets P page and modify NG. -+static inline bool is_setting_ppage(pte_t *ptep, pte_t pte) ++void __iee_code _iee_set_cred_cap_permitted(unsigned long iee_offset, struct cred *cred, kernel_cap_t cap_permitted) +{ -+ if(((pte_val(*ptep) ^ pte_val(pte)) & ~(PTE_USER | PTE_NG)) != 0) -+ panic("Incorrectly setting P page.\n"); -+ if((pte_val(pte) & PTE_USER) != 0) -+ panic("Using error interface to set U page.\n"); -+ return true; ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->cap_permitted = cap_permitted; +} + -+void __iee_code _iee_set_pte_ppage(pte_t *ptep, pte_t pte) ++void __iee_code _iee_set_cred_cap_effective(unsigned long iee_offset, struct cred *cred, kernel_cap_t cap_effective) +{ -+ // Check if it only change the prot. -+ if(!is_setting_ppage(ptep,pte)) -+ panic("Incorrectly setting P page.\n"); ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->cap_effective = cap_effective; ++} + -+ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa(ptep)))), pte); ++void __iee_code _iee_set_cred_cap_bset(unsigned long iee_offset, struct cred *cred, kernel_cap_t cap_bset) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->cap_bset = cap_bset; +} + -+void __iee_code _iee_set_bm_pte(pte_t *ptep, pte_t pte) ++void __iee_code _iee_set_cred_cap_ambient(unsigned long iee_offset, struct cred *cred, kernel_cap_t cap_ambient) +{ -+ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa_symbol(ptep)))), pte); ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->cap_ambient = cap_ambient; +} + -+/* Data in iee_si_base is visible to all pgd while iee_si_data is private. */ -+unsigned long iee_base_idmap_pg_dir __iee_si_data; -+unsigned long iee_base_reserved_pg_dir __iee_si_data; -+unsigned long iee_base__bp_harden_el1_vectors __iee_si_data; -+bool iee_init_done __iee_si_data; -+unsigned long iee_si_tcr __iee_si_data; ++void __iee_code _iee_set_cred_securebits(unsigned long iee_offset, struct cred *cred, unsigned securebits) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->securebits = securebits; ++} + -+static u64 __iee_si_code inline iee_si_mask(unsigned long mask, unsigned long new_val, unsigned long old_val) ++void __iee_code _iee_set_cred_group_info(unsigned long iee_offset, struct cred *cred, struct group_info *group_info) +{ -+ return (new_val & mask) | (old_val & ~mask); ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->group_info = group_info; +} -+/* -+ * handler function for requests of executing sensitive instrutions. -+ */ -+u64 __iee_si_code iee_si_handler(int flag, ...) ++ ++void __iee_code _iee_set_cred_ucounts(unsigned long iee_offset, struct cred *cred, struct ucounts *ucounts) +{ -+ va_list pArgs; -+ u64 old_val, new_val; ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->ucounts = ucounts; ++} + -+ // BUG_ON(flag > IEE_WRITE_MDSCR); -+ va_start(pArgs, flag); -+ switch (flag) { -+ case IEE_SI_TEST: -+ break; -+ case IEE_WRITE_SCTLR: { -+ old_val = read_sysreg(sctlr_el1); -+ new_val = va_arg(pArgs, u64); -+ new_val = iee_si_mask(IEE_SCTLR_MASK, new_val, old_val); -+ write_sysreg(new_val, sctlr_el1); -+ break; -+ } -+ case IEE_WRITE_TTBR0: -+ case IEE_CONTEXT_SWITCH: { -+ u64 new_asid, new_phys, old_phys, token_phys; -+ struct task_struct *tsk; -+ struct task_token *token; -+ new_val = va_arg(pArgs, u64); -+ new_phys = (new_val & PAGE_MASK) & ~TTBR_ASID_MASK; -+ new_asid = new_val >> 48; ++void __iee_code _iee_set_cred_user_ns(unsigned long iee_offset, struct cred *cred, struct user_namespace *user_ns) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->user_ns = user_ns; ++} + -+ // Check ASID first -+ if (new_phys == iee_base_reserved_pg_dir){ -+ if (new_asid != 1) -+ panic("IEE SI warning: reserved_pg_dir ASID invalid: %llx:%llx", new_asid, new_val); -+ } -+ // Already reserved asid 1 for iee rwx gate. -+ else if (new_asid == 0){ -+ new_val |= FIELD_PREP(TTBR_ASID_MASK, 1); -+ printk("IEE SI: Modify ASID of %llx to 1.", new_val); -+ } -+ // TO DO: operations to protect idmap_pg_dir -+ else if (new_phys == iee_base_idmap_pg_dir) -+ { -+ // printk("IEE SI: switch to idmap_pg_dir.); -+ } -+ else if (new_asid % 2 ==0) -+ panic("IEE SI warning: TTBR0 ASID invalid: %llx:%llx", new_asid, new_val); ++void __iee_code _iee_set_cred_user(unsigned long iee_offset, struct cred *cred, struct user_struct *user) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->user = user; ++} + -+ /* Skip verification if iee hasn't been initialized. */ -+ if (iee_init_done){ -+ // Verify current sp_el0 with iee token info -+ asm volatile("mrs %x0, sp_el0":"=r"(tsk)); -+ token = (struct task_token *)__phys_to_iee(__pa(tsk)); -+ -+ /* -+ * token->pgd != NULL means it is a user task, then we need to check whether current ttbr0 is correct. -+ */ -+ if (token->pgd){ -+ old_val = read_sysreg(ttbr0_el1); -+ // When TTBR0 is reserved_pg_dir then no checking is available. -+ if (old_val != iee_base_reserved_pg_dir){ -+ old_phys = (old_val & PAGE_MASK) & ~TTBR_ASID_MASK; -+ token_phys = __pa(token->pgd); -+ if (old_phys != token_phys) -+ panic("IEE SI warning: Pgd set error. old ttbr0:%lx, token ttbr0:%lx, token pgd:%lx", -+ (unsigned long)old_phys, (unsigned long)token_phys, (unsigned long)(token->pgd)); -+ } -+ } -+ } -+ // all checks are done. -+ write_sysreg(new_val, ttbr0_el1); -+ -+ // SET ASID in TTBR1 when context switch -+ if (flag == IEE_CONTEXT_SWITCH){ -+ new_val = (read_sysreg(ttbr1_el1) & ~TTBR_ASID_MASK) | FIELD_PREP(TTBR_ASID_MASK, new_asid-1); -+ write_sysreg(new_val, ttbr1_el1); -+ } -+ break; -+ } -+ case IEE_WRITE_VBAR: { -+ u64 el1_vector; -+ new_val = va_arg(pArgs, u64); -+ el1_vector = iee_base__bp_harden_el1_vectors; -+ if(new_val == el1_vector || new_val == el1_vector+SZ_2K || -+ new_val == el1_vector+SZ_2K*2 || new_val == el1_vector+SZ_2K*3) -+ write_sysreg(new_val, vbar_el1); -+ break; -+ } -+ case IEE_WRITE_TCR: { -+ old_val = read_sysreg(tcr_el1); -+ new_val = va_arg(pArgs, u64); -+ new_val = iee_si_mask(IEE_TCR_MASK, new_val, old_val); -+ write_sysreg(new_val, tcr_el1); -+ break; -+ } -+ case IEE_WRITE_MDSCR: { -+ old_val = read_sysreg(mdscr_el1); -+ new_val = va_arg(pArgs, u64); -+ new_val = iee_si_mask(IEE_MDSCR_MASK, new_val, old_val); -+ write_sysreg(new_val, mdscr_el1); -+ break; -+ } -+ } -+ va_end(pArgs); -+ return 0; ++void __iee_code _iee_set_cred_fsgid(unsigned long iee_offset, struct cred *cred, kgid_t fsgid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->fsgid = fsgid; +} -+/* -+ * TODO: scan a page to check whether it contains sensitive instructions -+ * return 1 when finding sensitive inst, 0 on safe page. -+ */ -+int iee_si_scan_page(unsigned long addr); -+#endif -\ No newline at end of file -diff --git a/arch/arm64/kernel/koi/Makefile b/arch/arm64/kernel/koi/Makefile -new file mode 100644 -index 000000000000..9be8710b714a ---- /dev/null -+++ b/arch/arm64/kernel/koi/Makefile -@@ -0,0 +1 @@ -+obj-y += koi.o -\ No newline at end of file -diff --git a/arch/arm64/kernel/koi/koi.c b/arch/arm64/kernel/koi/koi.c -new file mode 100644 -index 000000000000..716ba16ab358 ---- /dev/null -+++ b/arch/arm64/kernel/koi/koi.c -@@ -0,0 +1,1327 @@ -+#include "asm/koi.h" -+#include "linux/compiler_attributes.h" -+#include "linux/compiler_types.h" -+#include "asm/barrier.h" -+#include "asm-generic/bug.h" -+#include "asm-generic/errno-base.h" -+#include "asm-generic/memory_model.h" -+#include "asm-generic/pgtable-nop4d.h" -+#include "asm-generic/rwonce.h" -+#include "asm/pgalloc.h" -+#include "asm/memory.h" -+#include "linux/bitfield.h" -+#include "linux/compiler.h" -+#include "linux/types.h" -+#include "linux/spinlock.h" -+#include "linux/spinlock_types.h" -+#include "linux/kernel.h" -+#include "linux/rculist.h" -+#include "linux/rcupdate.h" -+#include "linux/list.h" -+#include "asm/current.h" -+#include "linux/compiler_types.h" -+#include "asm-generic/barrier.h" -+#include "asm-generic/rwonce.h" -+#include "asm-generic/pgalloc.h" -+#include "asm/cpufeature.h" -+#include "asm/kvm_hyp.h" -+#include "asm/mmu.h" -+#include "asm/mmu_context.h" -+#include "asm/page-def.h" -+#include "asm/pgalloc.h" -+#include "asm/pgtable-hwdef.h" -+#include "asm/pgtable-types.h" -+#include "asm/pgtable.h" -+#include "asm/string.h" -+#include "asm/sysreg.h" -+#include "linux/bitfield.h" -+#include "linux/compiler.h" -+#include "linux/export.h" -+#include "linux/gfp.h" -+#include "linux/huge_mm.h" -+#include "linux/kallsyms.h" -+#include "linux/kconfig.h" -+#include "linux/kern_levels.h" -+#include "linux/kernel.h" -+#include "linux/list.h" -+#include "linux/lockdep.h" -+#include "linux/mm.h" -+#include "linux/mm_types.h" -+#include "linux/pgtable.h" -+#include "linux/printk.h" -+#include "linux/rculist.h" -+#include "linux/rcupdate.h" -+#include "linux/rmap.h" -+#include "linux/sched.h" -+#include "linux/stddef.h" -+#include "linux/string.h" -+#include "linux/swap.h" -+#include "linux/swapops.h" -+#include "linux/types.h" -+#include "linux/slab.h" -+#include "linux/string.h" -+#include "linux/hashtable.h" + -+#define __koi_code __section(".koi.text") -+#define __koi_data __section(".data..koi") ++void __iee_code _iee_set_cred_fsuid(unsigned long iee_offset, struct cred *cred, kuid_t fsuid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->fsuid = fsuid; ++} + -+extern unsigned long __koi_code_start[]; -+extern unsigned long __koi_code_end[]; -+extern unsigned long __koi_data_start[]; -+extern unsigned long __koi_data_end[]; -+#ifdef CONFIG_IEE -+extern unsigned long __iee_si_base_start[]; -+extern unsigned long __iee_exec_entry_start[]; -+extern unsigned long __iee_exec_entry_end[]; -+#endif ++void __iee_code _iee_set_cred_egid(unsigned long iee_offset, struct cred *cred, kgid_t egid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->egid = egid; ++} + -+__koi_data unsigned long koi_swapper_ttbr1 = 0; -+EXPORT_SYMBOL(koi_swapper_ttbr1); -+#define KOI_SWAPPER_MASK 0x0000fffffffffff0 ++void __iee_code _iee_set_cred_euid(unsigned long iee_offset, struct cred *cred, kuid_t euid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->euid = euid; ++} + -+__attribute__((aligned(PAGE_SIZE))) -+DEFINE_PER_CPU(unsigned long[PAGE_SIZE / sizeof(unsigned long)], -+ koi_irq_current_ttbr1); -+EXPORT_SYMBOL(koi_irq_current_ttbr1); ++void __iee_code _iee_set_cred_sgid(unsigned long iee_offset, struct cred *cred, kgid_t sgid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->sgid = sgid; ++} + -+extern void koi_switch_to_ko_stack(unsigned long stack_top); -+extern void init_ko_mm(struct mm_struct *ko_mm, pgd_t *pgdp); -+extern void koi_check_and_switch_context(struct mm_struct *mm); -+extern int koi_add_page_mapping(unsigned long dst, unsigned long src); -+extern unsigned long _iee_read_token_ttbr1(struct task_struct *tsk); -+/** -+*struct koi_mem_list - maintain a linked list of free memory in the kernel -+*@addr: stating address of this memory -+*@size: the size of the memory -+*@list: the head of the koi_mem_list -+*@rcu: for rcu -+*/ -+struct koi_mem_list { -+ unsigned long addr; -+ unsigned long size; -+ struct list_head list; -+ struct rcu_head rcu; -+}; -+//mapping parameter pointer to copy -+struct koi_addr_map { -+ unsigned long buffer_addr; -+ unsigned long orig_addr; -+ int offset; -+ struct hlist_node node; -+ struct rcu_head rcu; -+}; ++void __iee_code _iee_set_cred_suid(unsigned long iee_offset, struct cred *cred, kuid_t suid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->suid = suid; ++} + -+DEFINE_HASHTABLE(koi_mem_htbl, HASH_TABLE_BIT); -+EXPORT_SYMBOL(koi_mem_htbl); -+DEFINE_SPINLOCK(koi_mem_htbl_spin_lock); -+EXPORT_SYMBOL(koi_mem_htbl_spin_lock); ++void __iee_code _iee_copy_cred(unsigned long iee_offset, struct cred *old, struct cred *new) ++{ ++ #ifdef CONFIG_CREDP ++ struct rcu_head *rcu = (struct rcu_head *)(new->rcu.func); ++ struct cred *_new = (struct cred *)__phys_to_iee(__pa(new)); ++ _iee_memcpy(iee_offset, new, old, sizeof(struct cred)); ++ *(struct rcu_head **)(&(_new->rcu.func)) = rcu; ++ *(struct rcu_head *)(_new->rcu.func) = *(struct rcu_head *)(old->rcu.func); ++ #endif ++} + -+EXPORT_SYMBOL(koi_do_switch_to_ko_stack); -+EXPORT_SYMBOL(koi_do_switch_to_kernel_stack); ++void __iee_code _iee_set_cred_gid(unsigned long iee_offset, struct cred *cred, kgid_t gid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->gid = gid; ++} + -+extern unsigned long long iee_rw_gate(int flag, ...); ++void __iee_code _iee_set_cred_uid(unsigned long iee_offset, struct cred *cred, kuid_t uid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->uid = uid; ++} + -+/** -+* koi_ttbr_ctor - return ttbr1 for the given driver module -+*/ -+unsigned long koi_ttbr_ctor(struct module *mod) ++void __iee_code _iee_write_in_byte(unsigned long iee_offset, void *ptr, __u64 data, int length) +{ -+ struct koi_mem_hash_node *ko; -+ struct mm_struct *ko_mm; -+ unsigned long ttbr1; -+ unsigned long asid; -+ int bkt; -+ rcu_read_lock(); -+ hash_for_each_rcu (koi_mem_htbl, bkt, ko, node) { -+ if (ko->mod == mod) { -+ ko_mm = ko->ko_mm; ++ ptr = (void *)((unsigned long)ptr + (unsigned long)iee_offset); ++ switch(length) { ++ case 8: { ++ *(__u64 *)ptr = data; ++ break; ++ } ++ case 4: { ++ *(__u32 *)ptr = (__u32)data; ++ break; ++ } ++ case 2: { ++ *(__u16 *)ptr = (__u16)data; ++ break; ++ } ++ case 1: { ++ *(__u8 *)ptr = (__u8)data; + break; + } + } -+ rcu_read_unlock(); -+ if (!ko_mm) { -+ printk(KERN_ERR "cannot found module %s in koi_mem_htbl", -+ mod->name); -+ return 0; -+ } -+ asm volatile("mrs %0, ttbr0_el1\n":"=r"(asid):); -+ asid &= TTBR_ASID_MASK; -+ ttbr1 = ko->ko_ttbr1 | asid; -+ // koi_check_and_switch_context(ko_mm); -+ // asid = ASID(ko_mm); -+ // ttbr1 = ko->ko_ttbr1 | FIELD_PREP(TTBR_ASID_MASK, asid); -+ return ttbr1; +} -+EXPORT_SYMBOL(koi_ttbr_ctor); -+//release the hash node -+static __maybe_unused void koi_mem_hash_node_free(struct rcu_head *rcu) ++ ++static pteval_t inline _iee_set_cmpxchg_relaxed(pte_t *ptep, pteval_t old_pteval, pteval_t new_pteval, unsigned long iee_offset) +{ -+ struct koi_mem_hash_node *node = -+ container_of(rcu, struct koi_mem_hash_node, rcu); -+ kfree(node); ++ pteval_t pteval = cmpxchg_relaxed((pteval_t *)((unsigned long)ptep + iee_offset), old_pteval, new_pteval); ++ return pteval; +} -+//release free memory linked list nodes -+static void koi_mem_node_free(struct rcu_head *rcu) ++ ++/* Check if addr is allocated in IEE page */ ++static inline bool check_addr_in_iee_valid(unsigned long addr) +{ -+ struct koi_mem_list *mem_node = -+ container_of(rcu, struct koi_mem_list, rcu); -+ kfree(mem_node); ++ pgd_t *pgdir = swapper_pg_dir; ++ ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ pud_t *pudp; ++ pmd_t *pmdp; ++ pte_t *ptep; ++ ++ if(!(p4d_val(READ_ONCE(*p4dp)) & PTE_VALID)) ++ return false; ++ ++ pudp = pud_offset(p4dp, addr); ++ ++ if(!(pud_val(READ_ONCE(*pudp)) & PTE_VALID)) ++ return false; ++ ++ pmdp = pmd_offset(pudp, addr); ++ ++ if(!(pmd_val(READ_ONCE(*pmdp)) & PTE_VALID)) ++ return false; ++ ++ ptep = pte_offset_kernel(pmdp, addr); ++ ++ return (pte_val(READ_ONCE(*ptep)) & PTE_VALID); +} -+//release the node in koi_addr_map -+static void koi_addr_map_node_free(struct rcu_head *rcu) ++ ++void __iee_code _iee_set_tramp_pgd(unsigned long iee_offset, pgd_t *pgdp, pgd_t pgd) +{ -+ struct koi_addr_map *addr_map_node = -+ container_of(rcu, struct koi_addr_map, rcu); -+ kfree(addr_map_node); ++ WRITE_ONCE(*((pgd_t *)(__phys_to_iee(__pa_symbol(pgdp)))), pgd); +} + -+#ifndef CONFIG_IEE -+/* -+ * This function is used to switch to ko's pgtable. -+ */ -+__koi_code noinline unsigned long koi_do_switch_to_ko_pgtbl(void) ++void __iee_code _iee_set_swapper_pgd(unsigned long iee_offset, pgd_t *pgdp, pgd_t pgd) +{ -+ struct koi_mem_hash_node *ko; -+ // struct mm_struct *ko_mm; -+ unsigned long addr; -+ unsigned long ttbr1, asid; -+ unsigned long *ptr; -+ struct task_token *token_addr = -+ (struct task_token *)((unsigned long)current + -+ (unsigned long)koi_offset); -+ int bkt; -+ asm volatile(" mrs %0, elr_el1\n" : "=r"(addr)); -+ ptr = SHIFT_PERCPU_PTR(koi_irq_current_ttbr1, __kern_my_cpu_offset()); -+ rcu_read_lock(); -+ hash_for_each_rcu (koi_mem_htbl, bkt, ko, node) { -+ if (ko->mod->init_layout.base != NULL) { -+ if (addr >= (unsigned long)ko->mod->init_layout.base && -+ addr < (unsigned long)(ko->mod->init_layout.base + -+ ko->mod->init_layout.size)) { -+ if (token_addr->current_ttbr1 == ko->ko_ttbr1 || -+ *ptr == ko->ko_ttbr1) { -+ // ko_mm = ko->ko_mm; -+ // koi_check_and_switch_context(ko_mm); -+ // asid = ASID(ko_mm); -+ // ttbr1 = ko->ko_ttbr1; -+ // ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); -+ asm volatile("mrs %0, ttbr0_el1\n":"=r"(asid):); -+ asid &= TTBR_ASID_MASK; -+ ttbr1 = ko->ko_ttbr1 | asid; -+ rcu_read_unlock(); -+ return ttbr1; -+ } -+ rcu_read_unlock(); -+ return 0; -+ } -+ } -+ if (addr >= (unsigned long)ko->mod->core_layout.base && -+ addr < (unsigned long)ko->mod->core_layout.base + -+ ko->mod->core_layout.size) { -+ if (token_addr->current_ttbr1 == ko->ko_ttbr1 || -+ *ptr == ko->ko_ttbr1) { -+ // ko_mm = ko->ko_mm; -+ // koi_check_and_switch_context(ko_mm); -+ // asid = ASID(ko_mm); -+ // ttbr1 = ko->ko_ttbr1; -+ // ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); -+ asm volatile("mrs %0, ttbr0_el1\n":"=r"(asid):); -+ asid &= TTBR_ASID_MASK; -+ ttbr1 = ko->ko_ttbr1 | asid; -+ rcu_read_unlock(); -+ return ttbr1; -+ } -+ rcu_read_unlock(); -+ return 0; -+ } ++ if(!(pgd_val(pgd) & PMD_SECT_VALID)) ++ { ++ WRITE_ONCE(*((pgd_t *)(__phys_to_iee(__pa_symbol(pgdp)))), pgd); ++ return; + } -+ rcu_read_unlock(); -+ return 0; ++ ++ if ((pgd_val(pgd) & PMD_TABLE_BIT) && !check_addr_in_iee_valid(__phys_to_iee(__pgd_to_phys(pgd)))) ++ panic("You can't use non-iee-pgtable\n"); ++ ++ if((pgdp >= pgd_offset_pgd((pgd_t *)swapper_pg_dir, PAGE_OFFSET + BIT(vabits_actual - 2))) && (pgdp < pgd_offset_pgd((pgd_t *)swapper_pg_dir, PAGE_OFFSET + BIT(vabits_actual - 1))) && !(pgd_val(pgd) & PGD_APT)) ++ panic("Set IEE pgd U page.\n"); ++ ++ WRITE_ONCE(*((pgd_t *)(__phys_to_iee(__pa_symbol(pgdp)))), pgd); +} -+/** -+* koi_do_switch_to_kernel_pgtbl - switch to kernel pagetable -+*/ -+__koi_code noinline int koi_do_switch_to_kernel_pgtbl(void) ++ ++void __iee_code _iee_set_p4d(unsigned long iee_offset, p4d_t *p4dp, p4d_t p4d) +{ -+ unsigned long curr_ttbr1, asid; -+ // if (!cpu_online(smp_processor_id())) -+ // return 0; -+ asm volatile(" mrs %0, ttbr1_el1\n" : "=r"(curr_ttbr1)); -+ if ((curr_ttbr1 & KOI_SWAPPER_MASK) == -+ (koi_swapper_ttbr1 & KOI_SWAPPER_MASK)) { -+ return 0; -+ } -+ if (((curr_ttbr1 & TTBR_ASID_MASK) >> 48) <= 1) { -+ return 0; ++ if(!(p4d_val(p4d) & PMD_SECT_VALID)) ++ { ++ WRITE_ONCE(*((p4d_t *)((unsigned long)p4dp + (unsigned long)iee_offset)), p4d); ++ return; + } -+ asm volatile("mrs %0, ttbr0_el1\n":"=r"(asid):); -+ asid &= ~USER_ASID_FLAG; -+ asid &= TTBR_ASID_MASK; -+ write_sysreg(koi_swapper_ttbr1 | asid, ttbr1_el1); -+ isb(); -+ asm volatile(ALTERNATIVE("nop; nop; nop", "ic iallu; dsb nsh; isb", -+ ARM64_WORKAROUND_CAVIUM_27456)); -+ return 1; ++ ++ if ((p4d_val(p4d) & PMD_TABLE_BIT) && !check_addr_in_iee_valid(__phys_to_iee(__p4d_to_phys(p4d)))) ++ panic("You can't use non-iee-pgtable\n"); ++ ++ WRITE_ONCE(*((p4d_t *)((unsigned long)p4dp + (unsigned long)iee_offset)), p4d); +} -+#else -+__koi_code noinline unsigned long koi_do_switch_to_ko_pgtbl(void) ++ ++void __iee_code _iee_set_pud(unsigned long iee_offset, pud_t *pudp, pud_t pud) +{ -+ struct koi_mem_hash_node *ko; -+ struct mm_struct *ko_mm; -+ unsigned long addr, ttbr1, asid, pan_flag, current_ttbr1; -+ unsigned long *ptr; -+ int bkt; -+ asm volatile("mrs %0, pan\n" -+ "msr pan, 0x0\n" -+ : "=r"(pan_flag) -+ :); -+ current_ttbr1 = _iee_read_token_ttbr1(current); -+ asm volatile("msr pan, %0\n" : : "r"(pan_flag)); -+ ptr = SHIFT_PERCPU_PTR(koi_irq_current_ttbr1, __kern_my_cpu_offset()); -+ if (current_ttbr1 == 0 && *ptr == 0) -+ return 0; -+ asm volatile(" mrs %0, elr_el1\n" : "=r"(addr)); -+ rcu_read_lock(); -+ hash_for_each_rcu (koi_mem_htbl, bkt, ko, node) { -+ if (ko->mod->init_layout.base != NULL) { -+ if (addr >= (unsigned long)ko->mod->init_layout.base && -+ addr < (unsigned long)(ko->mod->init_layout.base + -+ ko->mod->init_layout.size)) { -+ rcu_read_unlock(); -+ if (current_ttbr1 == ko->ko_ttbr1 || *ptr == ko->ko_ttbr1) { -+ // ko_mm = ko->ko_mm; -+ // koi_check_and_switch_context(ko_mm); -+ // asid = ASID(ko_mm); -+ // ttbr1 = ko->ko_ttbr1; -+ // ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, -+ // asid); -+ return ko->ko_ttbr1; -+ } -+ return 0; -+ } -+ } -+ if (addr >= (unsigned long)ko->mod->core_layout.base && -+ addr < (unsigned long)ko->mod->core_layout.base + -+ ko->mod->core_layout.size) { -+ rcu_read_unlock(); -+ if (current_ttbr1 == ko->ko_ttbr1 || *ptr == ko->ko_ttbr1) { -+ // ko_mm = ko->ko_mm; -+ // koi_check_and_switch_context(ko_mm); -+ // asid = ASID(ko_mm); -+ // ttbr1 = ko->ko_ttbr1; -+ // ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); -+ return ko->ko_ttbr1; -+ } -+ return 0; -+ } ++ if(!(pud_val(pud) & PMD_SECT_VALID)) ++ { ++ WRITE_ONCE(*((pud_t *)((unsigned long)pudp + (unsigned long)iee_offset)), pud); ++ return; + } -+ rcu_read_unlock(); -+ return 0; ++ ++ if ((pud_val(pud) & PMD_TABLE_BIT) && !check_addr_in_iee_valid(__phys_to_iee(__pud_to_phys(pud)))) ++ panic("You can't use non-iee-pgtable\n"); ++ ++ WRITE_ONCE(*((pud_t *)((unsigned long)pudp + (unsigned long)iee_offset)), pud); +} + -+__koi_code noinline int koi_do_switch_to_kernel_pgtbl(void) ++// Return true if the modify does not break DEP. ++static inline bool check_pmd_dep(char *addr, pmd_t pmd) +{ -+ unsigned long curr_ttbr1; -+ // if (!cpu_online(smp_processor_id())) -+ // return 0; -+ asm volatile(" mrs %0, ttbr1_el1\n" : "=r"(curr_ttbr1)); -+ if ((curr_ttbr1 & KOI_SWAPPER_MASK) == -+ (koi_swapper_ttbr1 & KOI_SWAPPER_MASK)) { -+ return 0; -+ } -+ if (((curr_ttbr1 & TTBR_ASID_MASK) >> 48) <= 1) { -+ return 0; ++ // DEP for kernel code and readonly data ++ // _text: .text start addr, __init_begin: .rodata end addr ++ if (addr >= _stext && addr < _etext) ++ { ++ if ((PTE_WRITE & pmd_val(pmd)) || // DBM == 1 --> writable ++ !(PTE_RDONLY & pmd_val(pmd))) // DBM == 0 && AP[2] = 0 --> writable ++ { ++ panic("Can't make kernel's text/readonly page as writable!\n" ++ "addr = 0x%16llx, pmd_val = 0x%16llx", ++ (u64)addr, pmd_val(pmd)); ++ } + } -+ iee_rwx_gate_entry(IEE_SWITCH_TO_KERNEL); -+ return 1; -+} -+#endif -+/** -+* koi_save_ttbr - save ttbr of each driver module -+* @mod: driver module -+* @pgdp:pointer to driver module top page table,pgd -+*/ -+static void koi_save_ttbr(struct module *mod, pgd_t *pgdp, -+ struct koi_mem_hash_node *node) -+{ -+ phys_addr_t ttbr1 = phys_to_ttbr(virt_to_phys(pgdp)); -+ if (system_supports_cnp()) -+ ttbr1 |= TTBR_CNP_BIT; -+ node->ko_ttbr1 = ttbr1; ++ return true; +} -+/** -+*kio_normal_page - to obtain the pointer of the corresponding struct page structure -+*from a given page table entry(pte) -+*/ -+struct page *koi_normal_page(pte_t pte) -+{ -+ unsigned long pfn = pte_pfn(pte); + -+ if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL)) { -+ if (likely(!pte_special(pte))) -+ goto check_pfn; -+ if (is_zero_pfn(pfn)) { -+ printk(KERN_ERR "zero pfn found! pte=0x%16lx\n", pte); -+ return NULL; -+ } -+ if (pte_devmap(pte)) { -+ printk(KERN_ERR "pte for dev found! pte=0x%16lx\n", -+ pte); -+ return NULL; ++// Return true if the pmd table is a part of kernel page table. ++// TODO : Optimize to get lower overhead. ++static inline bool is_kernel_pmd_table(pmd_t *pmdp, pmd_t pmd) ++{ ++ int i = 0,j = 0; ++ for(i = 0; i < PAGE_SIZE/sizeof(pgd_t); i++) ++ { ++ pgd_t *pgdp = (pgd_t *)swapper_pg_dir + i; ++ if((pgd_val(*pgdp) & PMD_SECT_VALID) && (pgd_val(*pgdp) & PMD_TABLE_BIT)) ++ { ++ for(j = 0; j < PAGE_SIZE/sizeof(pud_t); j++) ++ { ++ pud_t *pudp = (pud_t *)__va(__pgd_to_phys(*pgdp)) + i; ++ if((pud_val(*pudp) & PMD_SECT_VALID) && (pud_val(*pudp) & PMD_TABLE_BIT)) ++ { ++ pmd_t *current_pmdp = __va(__pud_to_phys(*pudp)); ++ if((unsigned long)current_pmdp == ((unsigned long)pmdp & PAGE_MASK)) ++ return true; ++ } ++ } + } -+ return NULL; + } -+ -+check_pfn: -+ return pfn_to_page(pfn); ++ return false; +} + -+/** -+ * Copy one pte. Returns 0 if succeeded, or -EAGAIN if one preallocated page -+ * is required to copy this pte. -+*/ -+static inline int koi_copy_present_pte(pte_t *dst_pte, pte_t *src_pte, -+ unsigned long addr, -+ struct page **prealloc) ++// Return true if it is mapped to a physical range containing IEE page. ++// TODO : Optimize to get lower overhead. ++static inline bool check_addr_range_in_iee_valid(pmd_t pmd) +{ -+ pte_t pte = *src_pte; -+ struct page *page; ++ int i = 0; ++ unsigned long addr = __phys_to_iee(__pmd_to_phys(pmd)); ++ pgd_t *pgdir = swapper_pg_dir; + -+ page = koi_normal_page(pte); -+ if (!page) { -+ printk(KERN_ERR "pte_page unavailable. Impossible.....\n"); -+ return -1; -+ } ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ pud_t *pudp; ++ pmd_t *pmdp; ++ pte_t *ptep; + -+ set_pte(dst_pte, pte); -+ return 0; -+} -+/** -+* copy huge pmd from kernel space to driver space. -+*/ -+static int koi_copy_huge_pmd(struct mm_struct *ko_mm, pmd_t *dst_pmd, -+ pmd_t *src_pmd, unsigned long addr) -+{ -+ spinlock_t *src_ptl; -+ pmd_t pmd; -+ int ret = -ENOMEM; ++ if(!(p4d_val(READ_ONCE(*p4dp)) & PTE_VALID)) ++ return false; + -+ src_ptl = pmd_lockptr(&init_mm, src_pmd); -+ spin_lock_bh(src_ptl); ++ pudp = pud_offset(p4dp, addr); + -+ ret = -EAGAIN; -+ pmd = *src_pmd; ++ if(!(pud_val(READ_ONCE(*pudp)) & PTE_VALID)) ++ return false; + -+ set_pte((pte_t *)dst_pmd, pmd_pte(pmd)); -+ ret = 0; -+ spin_unlock_bh(src_ptl); -+ return ret; -+} ++ pmdp = pmd_offset(pudp, addr); + -+int __koi_pte_alloc(struct mm_struct *mm, pmd_t *pmd) -+{ -+ spinlock_t *ptl; -+ pgtable_t new = pte_alloc_one(mm); -+ if (!new) -+ return -ENOMEM; ++ if(!(pmd_val(READ_ONCE(*pmdp)) & PTE_VALID)) ++ return false; + -+ /* -+ * Ensure all pte setup (eg. pte page lock and page clearing) are -+ * visible before the pte is made visible to other CPUs by being -+ * put into page tables. -+ * -+ * The other side of the story is the pointer chasing in the page -+ * table walking code (when walking the page table without locking; -+ * ie. most of the time). Fortunately, these data accesses consist -+ * of a chain of data-dependent loads, meaning most CPUs (alpha -+ * being the notable exception) will already guarantee loads are -+ * seen in-order. See the alpha page table accessors for the -+ * smp_rmb() barriers in page table walking code. -+ */ -+ smp_wmb(); /* Could be smp_wmb__xxx(before|after)_spin_lock */ ++ ptep = pte_offset_kernel(pmdp, addr); + -+ ptl = pmd_lockptr(mm, pmd); -+ spin_lock_bh(ptl); -+ if (likely(pmd_none(*pmd))) { /* Has another populated it ? */ -+ #ifdef CONFIG_PTP -+ pte_t *pte = (pte_t *)page_address(new); -+ unsigned long iee_addr = __phys_to_iee(__pa(pte)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)pte); -+ #endif -+ mm_inc_nr_ptes(mm); -+ pmd_populate(mm, pmd, new); -+ new = NULL; ++ for(i = 0; i < PAGE_SIZE/sizeof(pte_t); i++) ++ { ++ if(pte_val(READ_ONCE(*ptep)) & PTE_VALID) ++ return true; ++ ptep++; + } -+ spin_unlock_bh(ptl); -+ if (new) -+ pte_free(mm, new); -+ return 0; ++ return false; +} + -+#define koi_pte_alloc(mm, pmd) (unlikely(pmd_none(*(pmd))) && __koi_pte_alloc(mm, pmd)) ++void __iee_code _iee_set_pmd(unsigned long iee_offset, pmd_t *pmdp, pmd_t pmd) ++{ ++ char * addr = (char *)__phys_to_kimg(__pmd_to_phys(pmd)); + -+#define koi_pte_offset_map_lock(mm, pmd, address, ptlp) \ -+({ \ -+ spinlock_t *__ptl = pte_lockptr(mm, pmd); \ -+ pte_t *__pte = pte_offset_map(pmd, address); \ -+ *(ptlp) = __ptl; \ -+ spin_lock_bh(__ptl); \ -+ __pte; \ -+}) ++ if(!(pmd_val(pmd) & PMD_SECT_VALID)) ++ { ++ WRITE_ONCE(*((pmd_t *)((unsigned long)pmdp + (unsigned long)iee_offset)), pmd); ++ return; ++ } + -+#define koi_pte_alloc_map_lock(mm, pmd, address, ptlp) \ -+ (koi_pte_alloc(mm, pmd) ? \ -+ NULL : koi_pte_offset_map_lock(mm, pmd, address, ptlp)) ++ // Check if the pte table is legally allocated. ++ if ((pmd_val(pmd) & PMD_TABLE_BIT) && !check_addr_in_iee_valid(__phys_to_iee(__pmd_to_phys(pmd)))) ++ panic("You can't use non-iee-pgtable\n"); + -+/** -+*koi_copy_pte_range - copy pte from kernel space to driver space -+*/ -+static int koi_copy_pte_range(struct mm_struct *ko_mm, pmd_t *dst_pmd, -+ pmd_t *src_pmd, unsigned long addr, -+ unsigned long end) -+{ -+ pte_t *src_pte, *dst_pte; -+ spinlock_t *src_ptl, *dst_ptl; -+ int ret = 0; -+ struct page *prealloc = NULL; -+again: -+ dst_pte = koi_pte_alloc_map_lock(ko_mm, dst_pmd, addr, &dst_ptl); -+ if (!dst_pte) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ src_pte = pte_offset_map(src_pmd, addr); -+ src_ptl = pte_lockptr(&init_mm, src_pmd); -+ spin_lock_bh(src_ptl); -+ arch_enter_lazy_mmu_mode(); ++ // Avoid mapping a huge pmd as U page. ++ // if(!(pmd_val(pmd) & PMD_TABLE_BIT) && (pmd_val(pmd) & PMD_SECT_USER) && is_kernel_pmd_table(pmdp, pmd)) ++ // panic("Set a block descriptor in kernel space U page.\n"); + -+ do { -+ if (pte_none(*src_pte)) -+ continue; -+ if (unlikely(!pte_present(*src_pte))) { -+ continue; -+ } -+ /* koi_copy_present_pte() will clear `*prealloc` if consumed */ -+ ret = koi_copy_present_pte(dst_pte, src_pte, addr, &prealloc); -+ if (unlikely(ret == -EAGAIN)) -+ break; -+ if (unlikely(prealloc)) { -+ put_page(prealloc); -+ prealloc = NULL; -+ } -+ } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end); -+ arch_leave_lazy_mmu_mode(); -+ spin_unlock_bh(src_ptl); -+ spin_unlock_bh(dst_ptl); -+ -+ if (ret) { -+ WARN_ON_ONCE(ret != -EAGAIN); -+ ret = 0; -+ } -+ if (addr != end) -+ goto again; -+out: -+ if (unlikely(prealloc)) -+ put_page(prealloc); -+ return ret; -+} -+ -+int __koi_pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) -+{ -+ spinlock_t *ptl; -+ pmd_t *new = pmd_alloc_one(mm, address); -+ if (!new) -+ return -ENOMEM; ++ // Avoid mapping a huge pmd to IEE physical page. ++ // if(!(pmd_val(pmd) & PMD_TABLE_BIT) && check_addr_range_in_iee_valid(pmd)) ++ // panic("Mapping IEE physical page to a huge pmd.\n"); + -+ smp_wmb(); /* See comment in __pte_alloc */ ++ if(!check_pmd_dep(addr, pmd)) ++ return; + -+ ptl = pud_lockptr(mm, pud); -+ spin_lock_bh(ptl); -+ if (!pud_present(*pud)) { -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr = __phys_to_iee(__pa(new)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)new); -+ #endif -+ mm_inc_nr_pmds(mm); -+ pud_populate(mm, pud, new); -+ } else /* Another has populated it */ -+ pmd_free(mm, new); -+ spin_unlock_bh(ptl); -+ return 0; ++ WRITE_ONCE(*((pmd_t *)((unsigned long)pmdp + (unsigned long)iee_offset)), pmd); +} + -+static inline pmd_t *koi_pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) ++// Return true if the pte table is a part of kernel page table. ++// TODO : Optimize to get lower overhead. ++static inline bool is_kernel_pte_table(pte_t *ptep, pte_t pte) +{ -+ return (unlikely(pud_none(*pud)) && __koi_pmd_alloc(mm, pud, address))? -+ NULL: pmd_offset(pud, address); ++ return false; +} + -+/** -+*kio_copy_pmd_range - copy pmd from kernel to driver space -+*/ -+static inline int koi_copy_pmd_range(struct mm_struct *ko_mm, pud_t *dst_pud, -+ pud_t *src_pud, unsigned long addr, -+ unsigned long end) ++// Return true if it does not change the privilage or add new U page in kernel. ++static inline bool check_privilage_safe(pte_t *ptep, pte_t pte) +{ -+ pmd_t *src_pmd, *dst_pmd; -+ unsigned long next; -+ int err; -+ -+ dst_pmd = koi_pmd_alloc(ko_mm, dst_pud, addr); -+ if (!dst_pmd) { -+ return -ENOMEM; ++ if(!(pte_val(pte) & PTE_VALID)) ++ return true; ++ ++ if((pte_val(*ptep) & PTE_VALID)) ++ { ++ if((pte_val(*ptep) & PTE_USER) != (pte_val(pte) & PTE_USER)) ++ panic("Incorrectly change privilage.\n"); + } -+ src_pmd = pmd_offset(src_pud, addr); -+ do { -+ next = pmd_addr_end(addr, end); -+ // CONFIG_TRANSPARENT_HUGEPAGE is enabled, so we must add copy_huge_pmd -+ if (is_swap_pmd(*src_pmd) || pmd_trans_huge(*src_pmd) || -+ (pmd_devmap(*src_pmd))) { -+ err = koi_copy_huge_pmd(ko_mm, dst_pmd, src_pmd, addr); -+ if (err == -ENOMEM) -+ return -ENOMEM; -+ if (!err) -+ continue; -+ } -+ if (pmd_none_or_clear_bad(src_pmd)) { -+ continue; -+ } -+ if (koi_copy_pte_range(ko_mm, dst_pmd, src_pmd, addr, next)) -+ return -ENOMEM; -+ } while (dst_pmd++, src_pmd++, addr = next, addr != end); -+ return 0; ++ else ++ { ++ if((pte_val(pte) & PTE_USER) && is_kernel_pte_table(ptep, pte)) ++ panic("Add new U page in kernel space.\n"); ++ } ++ return true; +} + -+int __koi_pud_alloc(struct mm_struct *mm, p4d_t *p4d, unsigned long address) ++// TODO : When adding a new executable page, check it for DEP. ++static inline bool safely_adding_new_exec_page(pte_t *ptep, pte_t pte) +{ -+ pud_t *new = pud_alloc_one(mm, address); -+ if (!new) -+ return -ENOMEM; -+ -+ smp_wmb(); /* See comment in __pte_alloc */ -+ -+ spin_lock_bh(&mm->page_table_lock); -+ if (!p4d_present(*p4d)) { -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr = __phys_to_iee(__pa(new)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)new); -+ #endif -+ mm_inc_nr_puds(mm); -+ p4d_populate(mm, p4d, new); -+ } else /* Another has populated it */ -+ pud_free(mm, new); -+ spin_unlock_bh(&mm->page_table_lock); -+ return 0; ++ return true; +} + -+static inline pud_t *koi_pud_alloc(struct mm_struct *mm, p4d_t *p4d, -+ unsigned long address) ++// Return true if it is only changing prot of a pte. ++static inline bool is_changing_pte_prot(pte_t *ptep, pte_t pte) +{ -+ return (unlikely(p4d_none(*p4d)) && __koi_pud_alloc(mm, p4d, address)) ? -+ NULL : pud_offset(p4d, address); ++ if(((pte_val(*ptep) ^ pte_val(pte)) & PTE_ADDR_MASK) == 0) ++ return true; ++ else ++ return false; +} + -+/** -+*koi_copy_pud_range - copy pud from kernel to driver -+*/ -+static inline int koi_copy_pud_range(struct mm_struct *ko_mm, p4d_t *dst_p4d, -+ p4d_t *src_p4d, unsigned long addr, -+ unsigned long end) ++// Return true if the modify does not break DEP. ++static inline bool check_pte_dep(char *addr, pte_t pte) +{ -+ pud_t *src_pud, *dst_pud; -+ unsigned long next; -+ dst_pud = koi_pud_alloc(ko_mm, dst_p4d, addr); -+ if (!dst_pud) -+ return -ENOMEM; -+ src_pud = pud_offset(src_p4d, addr); -+ do { -+ next = pud_addr_end(addr, end); -+ if (pud_trans_huge(*src_pud) || pud_devmap(*src_pud)) { -+ continue; -+ /* fall through */ ++ // DEP for kernel code and readonly data ++ // _text: .text start addr, __init_begin: .rodata end addr ++ if (addr >= _stext && addr < _etext) ++ { ++ if ((PTE_WRITE & pte_val(pte)) // DBM == 1 --> writable ++ || !(PTE_RDONLY & pte_val(pte))) // DBM == 0 && AP[2] = 0 --> writable ++ { ++ panic("Can't make kernel's text/readonly page as writable!\n" ++ "addr = 0x%16llx, pte_val = 0x%16llx", ++ (u64)addr, pte_val(pte)); + } -+ if (pud_none_or_clear_bad(src_pud)) -+ continue; -+ if (koi_copy_pmd_range(ko_mm, dst_pud, src_pud, addr, next)) -+ return -ENOMEM; -+ } while (dst_pud++, src_pud++, addr = next, addr != end); -+ return 0; ++ } ++ return true; +} + -+/** -+* koi_copy_p4d_range - map the kernel pagetable to the driver space level by level -+* @ko_mm: the mm_struct of driver module -+* @dst_pgd: destination pgd -+* @src_pgd: source pgd -+* @addr: the start of address -+* @end: the end of address -+*/ -+static inline int koi_copy_p4d_range(struct mm_struct *ko_mm, pgd_t *dst_pgd, -+ pgd_t *src_pgd, unsigned long addr, -+ unsigned long end) ++void __iee_code _iee_set_pte(unsigned long iee_offset, pte_t *ptep, pte_t pte) +{ -+ p4d_t *src_p4d, *dst_p4d; -+ unsigned long next; -+ dst_p4d = p4d_alloc(ko_mm, dst_pgd, addr); -+ if (!dst_p4d) -+ return -ENOMEM; -+ src_p4d = p4d_offset(src_pgd, addr); -+ do { -+ next = p4d_addr_end(addr, end); -+ if (p4d_none_or_clear_bad(src_p4d)) -+ continue; -+ if (koi_copy_pud_range(ko_mm, dst_p4d, src_p4d, addr, next)) { -+ return -ENOMEM; -+ } -+ } while (dst_p4d++, src_p4d++, addr = next, addr != end); -+ return 0; -+} ++ char * addr = (char *)__phys_to_kimg(__pte_to_phys(pte)); + -+/** -+*int koi_copy_pagetable - map the address range from "addr" to "end" to the driver pagetable -+*@ko_mm: the mm_struct of the driver module -+*@koi_pg_dir: koi_pg_dir, related to the driver module, the entry for driver pagetable -+*@addr: the starting address of mapping zone -+*@end: the end address of mapping zone -+*/ -+int koi_copy_pagetable(struct mm_struct *ko_mm, pgd_t *koi_pg_dir, -+ unsigned long addr, unsigned long end) -+{ -+ int ret = 0; -+ unsigned long next; ++ if(!(pte_val(pte) & PTE_VALID)) ++ { ++ WRITE_ONCE(*((pte_t *)((unsigned long)ptep + (unsigned long)iee_offset)), pte); ++ return; ++ } + -+ pgd_t *src_pgd, *dst_pgd; ++ // Avoid modify privilage unsafely. ++ if(!check_privilage_safe(ptep, pte)) ++ panic("You are modify privilage unsafely.\n"); + -+ src_pgd = pgd_offset_pgd(swapper_pg_dir, addr); -+ dst_pgd = pgd_offset_pgd(koi_pg_dir, addr); -+ do { -+ next = pgd_addr_end(addr, end); -+ if (pgd_none_or_clear_bad(src_pgd)) -+ continue; -+ if (unlikely(koi_copy_p4d_range(ko_mm, dst_pgd, src_pgd, addr, -+ next))) { -+ ret = -ENOMEM; -+ break; -+ } -+ } while (dst_pgd++, src_pgd++, addr = next, addr != end); ++ // Avoid mapping a new executable page. ++ if(!safely_adding_new_exec_page(ptep, pte)) ++ panic("You are adding a new executable page unsafely.\n"); + -+ return ret; ++ // Avoid mapping a new VA to IEE PA. ++ if(!is_changing_pte_prot(ptep, pte) && ++ check_addr_in_iee_valid(__phys_to_iee(__pte_to_phys(pte)))) ++ panic("You are remmaping IEE page to other VA.\n"); ++ ++ // Avoid mapping a writable VA to kernel code PA. ++ if(!check_pte_dep(addr, pte)) ++ return; ++#ifdef CONFIG_KOI ++ if (pte_valid(pte)) ++ pte = __pte(pte_val(pte) | PTE_NG); ++#endif ++ WRITE_ONCE(*((pte_t *)((unsigned long)ptep + (unsigned long)iee_offset)), pte); +} + -+void koi_set_rdonly(unsigned long addr, pgd_t *pgdir) ++static void inline _iee_set_pte_single(pte_t *ptep, pte_t pte, unsigned long iee_offset) +{ -+ p4d_t *p4dp; -+ pud_t *pudp; -+ pmd_t *pmdp; -+ pte_t *ptep; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); -+ if (pgd_none(*pgdp) || pgd_bad(*pgdp)) { ++ char * addr = (char *)__phys_to_kimg(__pte_to_phys(pte)); ++ ++ if(!(pte_val(pte) & PTE_VALID)) ++ { ++ WRITE_ONCE(*((pte_t *)((unsigned long)ptep + (unsigned long)iee_offset)), pte); + return; + } + -+ p4dp = p4d_offset(pgdp, addr); -+ if (p4d_none(*p4dp) || p4d_bad(*p4dp)) { ++ // Avoid modify privilage unsafely. ++ if(!check_privilage_safe(ptep, pte)) ++ panic("You are modify privilage unsafely.\n"); ++ ++ // Avoid mapping a new executable page. ++ if(!safely_adding_new_exec_page(ptep, pte)) ++ panic("You are adding a new executable page unsafely.\n"); ++ ++ // Avoid mapping a new VA to IEE PA. ++ if(!is_changing_pte_prot(ptep, pte) && ++ check_addr_in_iee_valid(__phys_to_iee(__pte_to_phys(pte)))) ++ panic("You are remmaping IEE page to other VA.\n"); ++ ++ // Avoid mapping a writable VA to kernel code PA. ++ if(!check_pte_dep(addr, pte)) + return; ++ ++ WRITE_ONCE(*((pte_t *)((unsigned long)ptep + (unsigned long)iee_offset)), pte); ++} ++ ++void __iee_code _iee_set_stack_pte(unsigned long iee_offset, pte_t *ptep, int order, int use_block_pmd, unsigned long lm_addr) ++{ ++ int i; ++ unsigned long iee_addr = lm_addr + iee_offset; ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ p4d_t *p4dp = p4d_offset(pgdp, iee_addr); ++ pud_t *pudp = pud_offset(p4dp, iee_addr); ++ pmd_t *pmdp = pmd_offset(pudp, iee_addr); ++ pte_t *iee_ptep = (pte_t *)(((unsigned long)pte_offset_kernel(pmdp, iee_addr)) + iee_offset); ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ iee_ptep++; + } + -+ pudp = pud_offset(p4dp, addr); -+ if (pud_none(*pudp) || pud_bad(*pudp)) { -+ return; ++ ptep = (pte_t *)((unsigned long)ptep + iee_offset); ++ if(use_block_pmd) ++ { ++ pmd_t *pmdp = (pmd_t *)ptep; ++ pmd_t pmd = READ_ONCE(*pmdp); ++ pmd = __pmd(pmd_val(pmd) & ~PTE_VALID); ++ WRITE_ONCE(*pmdp, pmd); + } -+ pmdp = pmd_offset(pudp, addr); -+ if (pmd_none(*pmdp) || pmd_bad(*pmdp)) { -+ return; ++ else ++ { ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ WRITE_ONCE(*ptep, pte); ++ ptep++; ++ } + } ++} + -+ ptep = pte_offset_kernel(pmdp, addr); -+ if (pte_none(*ptep)) { -+ printk(KERN_ERR "ptep 0x%llx not available\n", ptep); -+ return; ++void __iee_code _iee_unset_stack_pte(unsigned long iee_offset, pte_t *ptep, int order, int use_block_pmd, unsigned long lm_addr) ++{ ++ int i; ++ unsigned long iee_addr = lm_addr + iee_offset; ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ p4d_t *p4dp = p4d_offset(pgdp, iee_addr); ++ pud_t *pudp = pud_offset(p4dp, iee_addr); ++ pmd_t *pmdp = pmd_offset(pudp, iee_addr); ++ pte_t *iee_ptep = (pte_t *)(((unsigned long)pte_offset_kernel(pmdp, iee_addr)) + iee_offset); ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*iee_ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ WRITE_ONCE(*iee_ptep, pte); ++ iee_ptep++; ++ } ++ ++ ptep = (pte_t *)((unsigned long)ptep + iee_offset); ++ if(use_block_pmd) ++ { ++ pmd_t *pmdp = (pmd_t *)ptep; ++ pmd_t pmd = READ_ONCE(*pmdp); ++ pmd = __pmd(pmd_val(pmd) | PTE_VALID); ++ WRITE_ONCE(*pmdp, pmd); ++ } ++ else ++ { ++ for(i = 0; i < (1 << order); i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ WRITE_ONCE(*ptep, pte); ++ ptep++; ++ } + } -+ set_pte(ptep, __pte(pte_val(*ptep) | PTE_RDONLY)); -+ printk(KERN_ERR "set_readonly successfully\n"); -+ return; +} + -+/** -+* koi_create_pagetable - create pagetable for driver -+* @mod: driver module -+* 1.create a new koi_mem_hash_node new_node -+* 2.create page table return the pgd address, init the new_node->pgdp -+* 3.create and init the new_node->ko_mm -+* 4.map swapper_ttbr1 to the newly created pagetable -+* 5.map the interrupt vector table to the newly created pagetable -+* 6.map the init_layout of the module -+* 7.map the core_layout of the module -+* 8.map switch_to_kernel_pgtable into driver view -+* 9.map share memory -+*/ -+void koi_create_pagetable(struct module *mod) ++void __iee_code _iee_set_bm_pte(unsigned long iee_offset, pte_t *ptep, pte_t pte) +{ -+ int ret = 0, cpu; -+ unsigned long vbar, addr, ttbr1; -+ pgd_t *pgdp; -+ unsigned long *ptr; -+ struct koi_mem_list *new_mem_node; -+ struct koi_mem_hash_node *new_node = -+ kzalloc(sizeof(struct koi_mem_hash_node), GFP_KERNEL); -+ if (!new_node) { -+ printk(KERN_ERR "NULL new_node\n"); -+ return; -+ }; -+ if (koi_swapper_ttbr1 == 0) { -+ pgdp = lm_alias(swapper_pg_dir); -+ ttbr1 = phys_to_ttbr(virt_to_phys(pgdp)); -+ if (system_supports_cnp() && -+ !WARN_ON(pgdp != lm_alias(swapper_pg_dir))) -+ ttbr1 |= TTBR_CNP_BIT; -+#ifdef CONFIG_IEE -+ ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, 1); ++#ifdef CONFIG_KOI ++ if (pte_valid(pte)) ++ pte = __pte(pte_val(pte) | PTE_NG); +#endif -+ koi_swapper_ttbr1 = ttbr1; -+ // __WRITE_ONCE(koi_swapper_ttbr1, ttbr1); -+ // koi_set_rdonly(&koi_swapper_ttbr1, swapper_pg_dir); -+ } -+ new_node->pgdp = koi_pgd_alloc(); -+ new_node->ko_mm = -+ kzalloc(sizeof(struct mm_struct) + -+ sizeof(unsigned long) * BITS_TO_LONGS(NR_CPUS), -+ GFP_KERNEL); -+ init_ko_mm(new_node->ko_mm, new_node->pgdp); -+ new_node->mod = mod; -+ koi_save_ttbr(mod, new_node->pgdp, new_node); -+ printk(KERN_ERR "copying koi_data, start=0x%16llx, end=0x%16llx\n", -+ (unsigned long)__koi_data_start, (unsigned long)__koi_data_end); -+ // copy koi_swapper_ttbr1, which records page dir base for kernel view -+ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, -+ (unsigned long)__koi_data_start, -+ (unsigned long)__koi_data_end); -+ asm volatile("mrs %0, VBAR_EL1\n" : "=r"(vbar) :); -+ -+ // copy interrupt vectors -+ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, vbar & PAGE_MASK, -+ (vbar + PAGE_SIZE) & PAGE_MASK); -+ -+ // copy module init_layout, which contains init data and text in driver -+ ret = koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, -+ (unsigned long)mod->init_layout.base, -+ (unsigned long)mod->init_layout.base + -+ mod->init_layout.size); -+ if (ret != 0) -+ printk(KERN_ERR -+ "\033[33mError occur when copying init_layout, Eno:%d\033[0m\n", -+ ret); ++ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa_symbol(ptep)))), pte); ++} + -+ // copy module core_layout, which contains non-init data and text in driver -+ ret = koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, -+ (unsigned long)mod->core_layout.base, -+ (unsigned long)mod->core_layout.base + -+ mod->core_layout.size); -+ if (ret != 0) -+ printk(KERN_ERR -+ "\033[33mError occur when copying core_layout, Eno: %d\033[0m\n", -+ ret); ++/* Data in iee_si_base is visible to all pgd while iee_si_data is private. */ ++unsigned long iee_base_swapper_pg_dir __iee_si_data; ++unsigned long iee_base_idmap_pg_dir __iee_si_data; ++unsigned long iee_base_reserved_pg_dir __iee_si_data; ++unsigned long iee_base__bp_harden_el1_vectors __iee_si_data; ++bool iee_init_done __iee_si_data; ++unsigned long iee_si_tcr __iee_si_data; ++s64 iee_si_offset __iee_si_data; + -+ // mapping switch_to_kernel_pgtable into driver view, which is used to switch to kernel view when entering INT -+ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, -+ (unsigned long)__koi_code_start, -+ (unsigned long)__koi_code_end); ++static u64 __iee_si_code inline iee_si_mask(unsigned long mask, unsigned long new_val, unsigned long old_val) ++{ ++ return (new_val & mask) | (old_val & ~mask); ++} ++/* ++ * handler function for requests of executing sensitive instrutions. ++ */ ++u64 __iee_si_code iee_si_handler(int flag, ...) ++{ ++ va_list pArgs; ++ u64 old_val, new_val; + -+ for_each_possible_cpu (cpu) { -+ ptr = per_cpu(irq_stack_ptr, cpu); -+ printk(KERN_ERR -+ "\033[33mirq_stack_ptr on cpu %d addr=0x%16llx, end=0x%16llx\033[0m\n", -+ cpu, (unsigned long)ptr, -+ (unsigned long)ptr + IRQ_STACK_SIZE); -+ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, -+ (unsigned long)ptr, -+ (unsigned long)ptr + IRQ_STACK_SIZE); -+ } ++ // BUG_ON(flag > IEE_WRITE_MDSCR); ++ va_start(pArgs, flag); ++ switch (flag) { ++ case IEE_SI_TEST: ++ break; ++ case IEE_WRITE_SCTLR: { ++ old_val = read_sysreg(sctlr_el1); ++ new_val = va_arg(pArgs, u64); ++ new_val = iee_si_mask(IEE_SCTLR_MASK, new_val, old_val); ++ write_sysreg(new_val, sctlr_el1); ++ break; ++ } ++ case IEE_WRITE_TTBR0: ++ case IEE_CONTEXT_SWITCH: { ++ u64 new_asid, new_phys, old_phys, token_phys; ++ struct task_struct *tsk; ++ struct task_token *token; ++ new_val = va_arg(pArgs, u64); ++ new_phys = (new_val & PAGE_MASK) & ~TTBR_ASID_MASK; ++ new_asid = new_val >> 48; + -+ for_each_possible_cpu (cpu) { -+ ptr = per_cpu(koi_irq_current_ttbr1, cpu); -+ printk(KERN_ERR -+ "\033[33mirq_current_ptr on cpu %d addr=0x%16llx, end=0x%16llx\033[0m\n", -+ cpu, (unsigned long)ptr, (unsigned long)ptr + PAGE_SIZE); -+ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, -+ (unsigned long)ptr, -+ (unsigned long)ptr + PAGE_SIZE); -+ } ++ // Check ASID first ++ if (new_phys == iee_base_reserved_pg_dir){ ++ if (new_asid != 1) ++ panic("IEE SI warning: reserved_pg_dir ASID invalid: %llx:%llx", new_asid, new_val); ++ } ++ // Already reserved asid 1 for iee rwx gate. ++ else if (new_asid == 0){ ++ new_val |= FIELD_PREP(TTBR_ASID_MASK, 1); ++ printk("IEE SI: Modify ASID of %llx to 1.", new_val); ++ } ++ // TO DO: operations to protect idmap_pg_dir ++ else if (new_phys == iee_base_idmap_pg_dir) ++ { ++ // printk("IEE SI: switch to idmap_pg_dir.); ++ } ++ else if (new_asid % 2 ==0) ++ panic("IEE SI warning: TTBR0 ASID invalid: %llx:%llx", new_asid, new_val); + -+#ifdef CONFIG_IEE -+ // mapping iee_rwx_gate_entry and iee_si_base to ko's pagetable -+ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, -+ (unsigned long)__iee_si_base_start, -+ (unsigned long)__iee_exec_entry_end); ++ /* Skip verification if iee hasn't been initialized. */ ++ if (iee_init_done){ ++ // Verify current sp_el0 with iee token info ++ asm volatile("mrs %x0, sp_el0":"=r"(tsk)); ++ token = (struct task_token *)((unsigned long)tsk + (unsigned long)iee_offset); ++ ++ /* ++ * token->pgd != NULL means it is a user task, then we need to check whether current ttbr0 is correct. ++ */ ++ if (token->pgd){ ++ old_val = read_sysreg(ttbr0_el1); ++ // When TTBR0 is reserved_pg_dir then no checking is available. ++ if (old_val != iee_base_reserved_pg_dir){ ++ old_phys = (old_val & PAGE_MASK) & ~TTBR_ASID_MASK; ++ token_phys = __pa(token->pgd); ++ if (old_phys != token_phys) ++ panic("IEE SI warning: Pgd set error. old ttbr0:%lx, token ttbr0:%lx, token pgd:%lx", ++ (unsigned long)old_phys, (unsigned long)token_phys, (unsigned long)(token->pgd)); ++ } ++ } ++ } ++ // all checks are done. ++ write_sysreg(new_val, ttbr0_el1); ++ ++ // SET ASID in TTBR1 when context switch ++ if (flag == IEE_CONTEXT_SWITCH){ ++ new_val = (read_sysreg(ttbr1_el1) & ~TTBR_ASID_MASK) | FIELD_PREP(TTBR_ASID_MASK, new_asid-1); ++ write_sysreg(new_val, ttbr1_el1); ++ } ++ break; ++ } ++ case IEE_WRITE_VBAR: { ++ u64 el1_vector; ++ new_val = va_arg(pArgs, u64); ++ el1_vector = iee_base__bp_harden_el1_vectors; ++ if(new_val == el1_vector || new_val == el1_vector+SZ_2K || ++ new_val == el1_vector+SZ_2K*2 || new_val == el1_vector+SZ_2K*3) ++ write_sysreg(new_val, vbar_el1); ++ break; ++ } ++ case IEE_WRITE_TCR: { ++ old_val = read_sysreg(tcr_el1); ++ new_val = va_arg(pArgs, u64); ++ new_val = iee_si_mask(IEE_TCR_MASK, new_val, old_val); ++ write_sysreg(new_val, tcr_el1); ++ break; ++ } ++ } ++ va_end(pArgs); ++ return 0; ++} ++/* ++ * TODO: scan a page to check whether it contains sensitive instructions ++ * return 1 when finding sensitive inst, 0 on safe page. ++ */ ++int iee_si_scan_page(unsigned long addr); +#endif +\ No newline at end of file +diff --git a/arch/arm64/kernel/iee/pgtable_slab.c b/arch/arm64/kernel/iee/pgtable_slab.c +new file mode 100644 +index 000000000000..1f98d639a315 +--- /dev/null ++++ b/arch/arm64/kernel/iee/pgtable_slab.c +@@ -0,0 +1,97 @@ ++#include ++#include + -+ // alloc 16KB memory for new ko, and add it into hashtable -+ addr = (unsigned long)kmalloc(THREAD_SIZE, GFP_KERNEL); -+ if ((void *)addr == NULL) { -+ printk(KERN_ERR "alloc buffer error\n"); -+ } -+ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, addr, -+ addr + THREAD_SIZE); ++#define PGTABLE_INIT_ORDER 7 ++struct kmem_cache *pgtable_jar; ++struct kmem_cache *ptdesc_jar; ++extern void iee_set_freeptr(void **pptr, void *ptr); ++unsigned long pgtable_jar_offset; + -+ new_mem_node = kmalloc(sizeof(struct koi_mem_list), GFP_KERNEL); -+ if (new_mem_node == NULL) { -+ printk(KERN_ERR "alloc new_mem_node error\n"); -+ } -+ new_mem_node->addr = addr; -+ new_mem_node->size = THREAD_SIZE; ++#ifdef CONFIG_PTP ++extern void early_pgtable_jar_alloc(struct kmem_cache *pgtable_jar); ++void __init iee_pmd_pgtable_init(pud_t *pud) { ++ struct page *page; ++ struct ptdesc_t *tmp; ++ pmd_t *orig_pmd = pud_pgtable(*pud); ++ pmd_t *pmd; ++ int i; ++ ++ for (i = 0; i < PTRS_PER_PMD; i++) { ++ pmd = orig_pmd + i; ++ if (pmd_none(*pmd) || pmd_bad(*pmd)) ++ continue; ++ page = pmd_page(*pmd); ++ tmp = kmem_cache_alloc(ptdesc_jar, GFP_KERNEL | __GFP_ZERO); ++ spin_lock_init(&tmp->ptl); ++ ((struct slab_t *)page)->slab_cache = (struct kmem_cache *)tmp; ++ ((struct ptdesc_t *)(((struct slab_t *)page)->slab_cache))->slab = (struct slab_t *)page; ++ } ++} + -+ new_node->mem_list_head = -+ (struct list_head)LIST_HEAD_INIT(new_node->mem_list_head); -+ hash_init(new_node->addr_htbl); -+ spin_lock_init(&new_node->addr_htbl_spin_lock); -+ spin_lock_init(&new_node->spin_lock); ++void __init iee_pud_pgtable_init(p4d_t *p4d) { ++ struct page *page; ++ struct ptdesc_t *tmp; ++ pud_t *orig_pud = p4d_pgtable(*p4d); ++ pud_t *pud; ++ int i; ++ ++ for (i = 0; i < PTRS_PER_PUD; i++) { ++ pud = orig_pud + i; ++ if (pud_none(*pud) || pud_bad(*pud)) ++ continue; ++ iee_pmd_pgtable_init(pud); ++ page = pud_page(*pud); ++ tmp = kmem_cache_alloc(ptdesc_jar, GFP_KERNEL | __GFP_ZERO); ++ spin_lock_init(&tmp->ptl); ++ ((struct slab_t *)page)->slab_cache = (struct kmem_cache *)tmp; ++ ((struct ptdesc_t *)(((struct slab_t *)page)->slab_cache))->slab = (struct slab_t *)page; ++ } ++} + -+ spin_lock(&new_node->spin_lock); -+ list_add_rcu(&new_mem_node->list, &new_node->mem_list_head); -+ spin_unlock(&new_node->spin_lock); ++void __init iee_pgtable_init(void) ++{ ++ int i; ++ pgd_t *pgd; ++ struct page* page; ++ struct ptdesc_t *tmp; + -+ spin_lock(&koi_mem_htbl_spin_lock); -+ hash_add_rcu(koi_mem_htbl, &new_node->node, -+ (unsigned long)new_node->mod); -+ spin_unlock(&koi_mem_htbl_spin_lock); ++ ptdesc_jar = kmem_cache_create("ptdesc_jar", sizeof(struct ptdesc_t), 0, SLAB_PANIC|SLAB_RED_ZONE, NULL); ++ pgtable_jar = kmem_cache_create("pgtable_jar", PAGE_SIZE, PAGE_SIZE, ++ SLAB_PANIC, NULL); ++ for(i = 0; i < ((1 << (PGTABLE_INIT_ORDER))/nr_cpu_ids); i++) ++ { ++ early_pgtable_jar_alloc(pgtable_jar); ++ } ++ for (i = 0; i < PTRS_PER_PGD; i++) { ++ pgd = swapper_pg_dir + i; ++ if (p4d_none_or_clear_bad((p4d_t *)pgd)) ++ continue; ++ iee_pud_pgtable_init((p4d_t *)pgd); ++ page = pgd_page(*pgd); ++ tmp = kmem_cache_alloc(ptdesc_jar, GFP_KERNEL | __GFP_ZERO); ++ spin_lock_init(&tmp->ptl); ++ ((struct slab_t *)page)->slab_cache = (struct kmem_cache *)tmp; ++ ((struct ptdesc_t *)(((struct slab_t *)page)->slab_cache))->slab = (struct slab_t *)page; ++ } +} -+/** -+* koi_mem_alloc -+*@mod: driver module -+*@orig_addr: the starting address of the parameter in kernel -+*@size: the size of the parameter -+*/ -+unsigned long koi_mem_alloc(struct module *mod, unsigned long orig_addr, -+ unsigned long size) ++#else ++void __init iee_pgtable_init(void) +{ -+ struct koi_mem_hash_node *target = NULL; -+ struct koi_mem_list *mem_node; -+ struct koi_addr_map *new_addr_node; -+ unsigned long addr = 0, flags; -+ struct koi_mem_list *new_mem_node; -+ rcu_read_lock(); -+ hash_for_each_possible_rcu (koi_mem_htbl, target, node, -+ (unsigned long)mod) { -+ if (target->mod == mod) { -+ break; -+ } -+ } -+ rcu_read_unlock(); -+ if (target == NULL) { -+ printk(KERN_ERR "mem node for module: %s not found\n", -+ mod->name); -+ return 0; -+ } -+ spin_lock_irqsave(&target->spin_lock, flags); -+ list_for_each_entry_rcu (mem_node, &target->mem_list_head, list) { -+ if (mem_node->size >= size) { -+ addr = mem_node->addr; -+ mem_node->size -= size; -+ if (mem_node->size == 0) { -+ list_del_rcu(&mem_node->list); -+ } else { -+ new_mem_node = -+ kmalloc(sizeof(struct koi_mem_list), -+ GFP_ATOMIC); -+ new_mem_node->addr = addr + size; -+ new_mem_node->size = mem_node->size; -+ list_replace_rcu(&mem_node->list, -+ &new_mem_node->list); -+ } -+ call_rcu(&mem_node->rcu, koi_mem_node_free); -+ } -+ } -+ spin_unlock_irqrestore(&target->spin_lock, flags); -+ if (!addr) { -+ addr = (unsigned long)kmalloc(THREAD_SIZE, GFP_KERNEL); -+ if ((void *)addr == NULL) { -+ return 0; -+ } -+ koi_copy_pagetable(target->ko_mm, target->pgdp, addr, -+ addr + THREAD_SIZE); -+ mem_node = kmalloc(sizeof(struct koi_mem_list), GFP_KERNEL); -+ if (!mem_node) { -+ printk(KERN_ERR "NULL mem_node\n"); -+ } -+ if (size > THREAD_SIZE) { -+ return 0; -+ } -+ mem_node->addr = addr + size; -+ mem_node->size = THREAD_SIZE - size; -+ spin_lock_irqsave(&target->spin_lock, flags); -+ list_add_tail_rcu(&mem_node->list, &target->mem_list_head); -+ spin_unlock_irqrestore(&target->spin_lock, flags); -+ } ++ ; ++} ++#endif + -+ new_addr_node = kzalloc(sizeof(struct koi_addr_map), GFP_KERNEL); -+ new_addr_node->buffer_addr = addr; -+ new_addr_node->orig_addr = orig_addr; -+ spin_lock_irqsave(&target->addr_htbl_spin_lock, flags); -+ hash_add_rcu(target->addr_htbl, &new_addr_node->node, -+ new_addr_node->buffer_addr); -+ spin_unlock_irqrestore(&target->addr_htbl_spin_lock, flags); -+ return addr; ++void *get_iee_pgtable_page(gfp_t gfpflags) ++{ ++ struct page *page; ++ void *res = kmem_cache_alloc(pgtable_jar, gfpflags); ++ iee_set_freeptr((void **)((unsigned long)res + pgtable_jar_offset), NULL); ++ page = virt_to_page(res); ++ page_ref_inc(page); ++ return res; +} -+EXPORT_SYMBOL(koi_mem_alloc); -+// find the parameter pointer corresponding to the copy -+noinline void *koi_mem_lookup(struct module *mod, unsigned long addr) ++ ++void free_iee_pgtable_page(void *obj) +{ -+ struct koi_mem_hash_node *target = NULL; -+ struct koi_addr_map *addr_map_node; -+ unsigned long orig_addr = addr; -+ rcu_read_lock(); -+ hash_for_each_possible_rcu (koi_mem_htbl, target, node, -+ (unsigned long)mod) { -+ if (target->mod == mod) { -+ break; -+ } -+ } -+ rcu_read_unlock(); -+ if (target == NULL) { -+ printk(KERN_ERR "mem node for module: %s not found\n", -+ mod->name); -+ return NULL; -+ } ++ kmem_cache_free(pgtable_jar, obj); ++} +\ No newline at end of file +diff --git a/arch/arm64/kernel/iee/stack_slab.c b/arch/arm64/kernel/iee/stack_slab.c +new file mode 100644 +index 000000000000..c52a11d67415 +--- /dev/null ++++ b/arch/arm64/kernel/iee/stack_slab.c +@@ -0,0 +1,19 @@ ++#include ++#include ++ ++struct kmem_cache *iee_stack_jar; ++ ++void __init iee_stack_init(void) ++{ ++ iee_stack_jar = kmem_cache_create("iee_stack_jar", (PAGE_SIZE << 3), (PAGE_SIZE << 3), SLAB_PANIC, NULL); ++} ++ ++void *get_iee_stack(void) ++{ ++ return kmem_cache_alloc(iee_stack_jar, GFP_KERNEL) + iee_offset; ++} ++ ++void free_iee_stack(void *obj) ++{ ++ kmem_cache_free(iee_stack_jar, obj - iee_offset); ++} +diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c +index b1f2a9b49039..7b86a1047278 100644 +--- a/arch/arm64/kernel/irq.c ++++ b/arch/arm64/kernel/irq.c +@@ -31,7 +31,9 @@ + DEFINE_PER_CPU(struct nmi_ctx, nmi_contexts); + + DEFINE_PER_CPU(unsigned long *, irq_stack_ptr); +- ++#ifdef CONFIG_KOI ++EXPORT_SYMBOL(irq_stack_ptr); ++#endif + + DECLARE_PER_CPU(unsigned long *, irq_shadow_call_stack_ptr); + +diff --git a/arch/arm64/kernel/koi/Makefile b/arch/arm64/kernel/koi/Makefile +new file mode 100644 +index 000000000000..9be8710b714a +--- /dev/null ++++ b/arch/arm64/kernel/koi/Makefile +@@ -0,0 +1 @@ ++obj-y += koi.o +\ No newline at end of file +diff --git a/arch/arm64/kernel/koi/koi.c b/arch/arm64/kernel/koi/koi.c +new file mode 100644 +index 000000000000..aece03f85564 +--- /dev/null ++++ b/arch/arm64/kernel/koi/koi.c +@@ -0,0 +1,1688 @@ ++#include "asm/koi.h" ++#include "linux/compiler_attributes.h" ++#include "linux/compiler_types.h" ++#include "asm/barrier.h" ++#include "asm-generic/bug.h" ++#include "asm-generic/errno-base.h" ++#include "asm-generic/memory_model.h" ++#include "asm-generic/pgtable-nop4d.h" ++#include "asm-generic/rwonce.h" ++#include "asm/pgalloc.h" ++#include "asm/memory.h" ++#include "linux/bitfield.h" ++#include "linux/compiler.h" ++#include "linux/types.h" ++#include "linux/module.h" ++#include "linux/spinlock.h" ++#include "linux/spinlock_types.h" ++#include "linux/kernel.h" ++#include "linux/rculist.h" ++#include "linux/rcupdate.h" ++#include "linux/list.h" ++#include "asm/current.h" ++#include "linux/compiler_types.h" ++#include "asm-generic/barrier.h" ++#include "asm-generic/rwonce.h" ++#include "asm-generic/pgalloc.h" ++#include "asm/cpufeature.h" ++#include "asm/kvm_hyp.h" ++#include "asm/mmu.h" ++#include "asm/mmu_context.h" ++#include "asm/page-def.h" ++#include "asm/pgalloc.h" ++#include "asm/pgtable-hwdef.h" ++#include "asm/pgtable-types.h" ++#include "asm/pgtable.h" ++#include "asm/string.h" ++#include "asm/sysreg.h" ++#include "linux/bitfield.h" ++#include "linux/compiler.h" ++#include "linux/export.h" ++#include "linux/gfp.h" ++#include "linux/huge_mm.h" ++#include "linux/kallsyms.h" ++#include "linux/kconfig.h" ++#include "linux/kern_levels.h" ++#include "linux/kernel.h" ++#include "linux/list.h" ++#include "linux/lockdep.h" ++#include "linux/mm.h" ++#include "linux/mm_types.h" ++#include "linux/pgtable.h" ++#include "linux/printk.h" ++#include "linux/rculist.h" ++#include "linux/rcupdate.h" ++#include "linux/rmap.h" ++#include "linux/sched.h" ++#include "linux/stddef.h" ++#include "linux/string.h" ++#include "linux/swap.h" ++#include "linux/swapops.h" ++#include "linux/types.h" ++#include "linux/slab.h" ++#include "linux/string.h" ++#include "linux/hashtable.h" ++ ++// #define DEBUG ++ ++#ifdef DEBUG ++#define debug_printk(...) printk(KERN_ERR __VA_ARGS__) ++#else ++#define debug_printk(...) ++#endif ++ ++#define __koi_code __section(".koi.text") ++#define __koi_data __section(".data..koi") ++ ++#define KOI_FLAG_MASK 0xffff000000000fff ++ ++extern unsigned long __koi_code_start[]; ++extern unsigned long __koi_code_end[]; ++extern unsigned long __koi_data_start[]; ++extern unsigned long __koi_data_end[]; ++#ifdef CONFIG_IEE ++extern unsigned long __iee_si_data_start[]; ++extern unsigned long __iee_si_text_start[]; ++#endif + ++__koi_data unsigned long koi_swapper_ttbr1 = 0; ++EXPORT_SYMBOL(koi_swapper_ttbr1); ++#define KOI_SWAPPER_MASK 0x0000fffffffffff0 ++ ++__attribute__((aligned(PAGE_SIZE))) ++DEFINE_PER_CPU(unsigned long[PAGE_SIZE / sizeof(unsigned long)], ++ koi_irq_current_ttbr1); ++EXPORT_SYMBOL(koi_irq_current_ttbr1); ++ ++extern void koi_switch_to_ko_stack(unsigned long stack_top); ++extern void init_ko_mm(struct mm_struct *ko_mm, pgd_t *pgdp); ++extern void koi_check_and_switch_context(struct mm_struct *mm); ++extern void koi_add_page_mapping(unsigned long dst, unsigned long src); ++extern unsigned long _iee_read_token_ttbr1(unsigned long iee_offset, ++ struct task_struct *tsk); ++/** ++*struct koi_mem_list - maintain a linked list of free memory in the kernel ++*@addr: stating address of this memory ++*@size: the size of the memory ++*@list: the head of the koi_mem_list ++*@rcu: for rcu ++*/ ++struct koi_mem_list { ++ unsigned long addr; ++ unsigned long size; ++ struct list_head list; ++ struct rcu_head rcu; ++}; ++//mapping parameter pointer to copy ++struct koi_addr_map { ++ unsigned long buffer_addr; ++ unsigned long orig_addr; ++ int offset; ++ struct hlist_node node; ++ struct rcu_head rcu; ++}; ++ ++DEFINE_HASHTABLE(koi_mem_htbl, HASH_TABLE_BIT); ++EXPORT_SYMBOL(koi_mem_htbl); ++DEFINE_SPINLOCK(koi_mem_htbl_spin_lock); ++EXPORT_SYMBOL(koi_mem_htbl_spin_lock); ++ ++// EXPORT_SYMBOL(koi_do_switch_to_kernel_stack); ++// EXPORT_SYMBOL(koi_do_switch_to_ko_stack); ++ ++/** ++* koi_ttbr_ctor - return ttbr1 for the given driver module ++*/ ++unsigned long koi_ttbr_ctor(struct module *mod) ++{ ++ struct koi_mem_hash_node *ko; ++ struct mm_struct *ko_mm; ++ unsigned long ttbr1; ++ unsigned long asid; ++ int bkt; + rcu_read_lock(); -+ hash_for_each_possible_rcu (target->addr_htbl, addr_map_node, node, -+ orig_addr) { -+ if (addr_map_node->buffer_addr == addr) { ++ hash_for_each_rcu (koi_mem_htbl, bkt, ko, node) { ++ if (ko->mod == mod) { ++ ko_mm = ko->ko_mm; + break; + } + } + rcu_read_unlock(); -+ if (addr_map_node) { -+ return (void *)(addr_map_node->orig_addr); -+ } else { -+ return NULL; ++ if (!ko_mm) { ++ printk(KERN_ERR "cannot found module %s in koi_mem_htbl", ++ mod->name); ++ return 0; + } ++ koi_check_and_switch_context(ko_mm); ++ asid = ASID(ko_mm) | USER_ASID_FLAG; ++ ttbr1 = ko->ko_ttbr1 | FIELD_PREP(TTBR_ASID_MASK, asid); ++ return ttbr1; +} -+EXPORT_SYMBOL(koi_mem_lookup); -+/** -+* kio_mem_free - recycle a copy of the copied parameters and synchronize the parameters -+* @mod: driver module -+* @addr: the starting addr of parameter -+* @size: the size of the parameter -+* @is_const: const pointers or not -+* @count: contry the number of parameters -+*/ -+noinline void koi_mem_free(struct module *mod, unsigned long addr, -+ unsigned long size, bool is_const, int count, ...) ++EXPORT_SYMBOL(koi_ttbr_ctor); ++//release the hash node ++static __maybe_unused void koi_mem_hash_node_free(struct rcu_head *rcu) +{ -+ struct koi_mem_hash_node *target = NULL; -+ struct koi_mem_list *mem_node; -+ struct list_head *pos = NULL; -+ struct koi_addr_map *addr_map_node; -+ unsigned long orig_size = size; -+ unsigned long orig_addr = addr; -+ va_list valist; -+ int i; -+ unsigned int offset; ++ struct koi_mem_hash_node *node = ++ container_of(rcu, struct koi_mem_hash_node, rcu); ++ kfree(node); ++} ++//release free memory linked list nodes ++static void koi_mem_node_free(struct rcu_head *rcu) ++{ ++ struct koi_mem_list *mem_node = ++ container_of(rcu, struct koi_mem_list, rcu); ++ kfree(mem_node); ++} ++//release the node in koi_addr_map ++static void koi_addr_map_node_free(struct rcu_head *rcu) ++{ ++ struct koi_addr_map *addr_map_node = ++ container_of(rcu, struct koi_addr_map, rcu); ++ kfree(addr_map_node); ++} ++ ++static __koi_code noinline unsigned int koi_ldtrh_wrapper(unsigned long src_addr) ++{ ++ unsigned int ret; ++ asm volatile("ldtrh w0, [%1]\n" : "=r"(ret) : "r"(src_addr)); ++ return ret; ++} ++ ++static __koi_code noinline unsigned long koi_ldtr_wrapper(unsigned long src_addr) ++{ ++ unsigned long ret; ++ asm volatile("ldtr x0, [%1]\n" : "=r"(ret) : "r"(src_addr)); ++ return ret; ++} ++ ++static __koi_code noinline void koi_sttr_wrapper(unsigned long src, ++ unsigned long dst_addr) ++{ ++ asm volatile("sttr x0, [x1]\n" : :); ++} ++ ++static __koi_code noinline void koi_sttrh_wrapper(unsigned int src, ++ unsigned long dst_addr) ++{ ++ asm volatile("sttrh w0, [x1]\n" : :); ++} ++ ++#ifndef CONFIG_IEE ++/* ++ * This function is used to switch to ko's pgtable. ++ */ ++__koi_code noinline unsigned long koi_do_switch_to_ko_pgtbl(void) ++{ ++ struct koi_mem_hash_node *ko; ++ // struct mm_struct *ko_mm; ++ unsigned long addr; ++ unsigned long ttbr1, asid; ++ unsigned long *ptr; ++ struct task_token *token_addr = ++ (struct task_token *)((unsigned long)current + ++ (unsigned long)koi_offset); ++ int bkt; + unsigned long flags; ++ asm volatile(" mrs %0, elr_el1\n" : "=r"(addr)); ++ ptr = SHIFT_PERCPU_PTR(koi_irq_current_ttbr1, __kern_my_cpu_offset()); + rcu_read_lock(); -+ hash_for_each_possible_rcu (koi_mem_htbl, target, node, -+ (unsigned long)mod) { -+ if (target->mod == mod) { -+ break; ++ hash_for_each_rcu (koi_mem_htbl, bkt, ko, node) { ++ spin_lock_irqsave(&ko->mod_lock, flags); ++ if (!ko->is_valid) { ++ spin_unlock_irqrestore(&ko->mod_lock, flags); ++ goto out; + } -+ } -+ rcu_read_unlock(); -+ if (target == NULL) { -+ printk(KERN_ERR "mem node for module: %s not found\n", -+ mod->name); -+ return; -+ } -+ -+ rcu_read_lock(); -+ hash_for_each_possible_rcu (target->addr_htbl, addr_map_node, node, -+ orig_addr) { -+ if (addr_map_node->buffer_addr == orig_addr) { -+ break; ++ if (ko->mod != NULL && ko->mod->mem[MOD_INIT_TEXT].base != NULL) { ++ if (addr >= (unsigned long)ko->mod->mem[MOD_INIT_TEXT].base && ++ addr < (unsigned long)ko->mod->mem[MOD_INIT_TEXT].base + ko->mod->mem[MOD_INIT_TEXT].size) { ++ spin_unlock_irqrestore(&ko->mod_lock, flags); ++ if (token_addr->current_ttbr1 == ko->ko_ttbr1 || ++ *ptr == ko->ko_ttbr1) { ++ // ko_mm = ko->ko_mm; ++ // koi_check_and_switch_context(ko_mm); ++ // asid = ASID(ko_mm); ++ // ttbr1 = ko->ko_ttbr1; ++ // ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); ++ asm volatile("mrs %0, ttbr0_el1\n" ++ : "=r"(asid) ++ :); ++ asid &= TTBR_ASID_MASK; ++ ttbr1 = ko->ko_ttbr1 | asid; ++ rcu_read_unlock(); ++ return ttbr1; ++ } ++ goto out; ++ } + } -+ } -+ rcu_read_unlock(); -+ va_start(valist, count); -+ for (i = 0; i < count; i++) { -+ offset = va_arg(valist, int); -+ *(unsigned long *)(addr_map_node->buffer_addr + offset) = -+ *(unsigned long *)(addr_map_node->orig_addr + offset); -+ } -+ va_end(valist); -+ memcpy((void *)addr_map_node->orig_addr, -+ (void *)addr_map_node->buffer_addr, orig_size); -+ -+ spin_lock_irqsave(&target->addr_htbl_spin_lock, flags); -+ hlist_del_init_rcu(&addr_map_node->node); -+ call_rcu(&addr_map_node->rcu, koi_addr_map_node_free); -+ spin_unlock_irqrestore(&target->addr_htbl_spin_lock, flags); -+ -+ spin_lock_irqsave(&target->spin_lock, flags); -+ list_for_each_entry_rcu (mem_node, &target->mem_list_head, list) { -+ if (mem_node->addr + mem_node->size == addr) { -+ pos = mem_node->list.prev; -+ addr = mem_node->addr; -+ size += mem_node->size; -+ list_del_rcu(&mem_node->list); -+ call_rcu(&mem_node->rcu, koi_mem_node_free); -+ } else if (addr + size == mem_node->addr) { -+ if (!pos) -+ pos = mem_node->list.prev; -+ size += mem_node->size; -+ list_del_rcu(&mem_node->list); -+ call_rcu(&mem_node->rcu, koi_mem_node_free); -+ } else if (addr + size < mem_node->addr) { -+ if (!pos) -+ pos = mem_node->list.prev; -+ break; ++ if (addr >= (unsigned long)ko->mod->mem[MOD_TEXT].base && ++ addr < (unsigned long)ko->mod->mem[MOD_TEXT].base + ko->mod->mem[MOD_TEXT].size) { ++ spin_unlock_irqrestore(&ko->mod_lock, flags); ++ if (token_addr->current_ttbr1 == ko->ko_ttbr1 || ++ *ptr == ko->ko_ttbr1) { ++ // ko_mm = ko->ko_mm; ++ // koi_check_and_switch_context(ko_mm); ++ // asid = ASID(ko_mm); ++ // ttbr1 = ko->ko_ttbr1; ++ // ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); ++ asm volatile("mrs %0, ttbr0_el1\n" ++ : "=r"(asid) ++ :); ++ asid &= TTBR_ASID_MASK; ++ ttbr1 = ko->ko_ttbr1 | asid; ++ rcu_read_unlock(); ++ return ttbr1; ++ } ++ goto out; + } ++ spin_unlock_irqrestore(&ko->mod_lock, flags); + } -+ mem_node = kzalloc(sizeof(struct koi_mem_list), GFP_ATOMIC); -+ mem_node->addr = addr; -+ mem_node->size = size; -+ if (pos) -+ list_add_rcu(&mem_node->list, pos); -+ else -+ list_add_tail_rcu(&mem_node->list, &target->mem_list_head); -+ spin_unlock_irqrestore(&target->spin_lock, flags); ++out: ++ rcu_read_unlock(); ++ return 0; +} -+EXPORT_SYMBOL(koi_mem_free); +/** -+* koi_mem_free_callback - used to recycle the copy of parameter. -+*@addr: the address of the parameter -+*@(*func)(void*): callback func, used to release the copy of the parameter pointer ++* koi_do_switch_to_kernel_pgtbl - switch to kernel pagetable +*/ -+noinline void koi_mem_free_callback(struct module *mod, unsigned long addr, -+ unsigned long size, void (*func)(void *)) ++__koi_code noinline int koi_do_switch_to_kernel_pgtbl(void) +{ -+ struct koi_mem_hash_node *target = NULL; -+ struct koi_mem_list *mem_node; -+ struct list_head *pos = NULL; -+ struct koi_addr_map *addr_map_node; -+ unsigned long flags; -+ unsigned long orig_size = size; -+ unsigned long orig_addr = addr; ++ unsigned long curr_ttbr1, asid; ++ // if (!cpu_online(smp_processor_id())) ++ // return 0; ++ asm volatile(" mrs %0, ttbr1_el1\n" : "=r"(curr_ttbr1)); ++ if ((curr_ttbr1 & KOI_SWAPPER_MASK) == ++ (koi_swapper_ttbr1 & KOI_SWAPPER_MASK)) { ++ return 0; ++ } ++ // if (((curr_ttbr1 & TTBR_ASID_MASK) >> 48) <= 1) { ++ // return 0; ++ // } ++ asm volatile("mrs %0, ttbr0_el1\n" : "=r"(asid) :); ++ asid &= ~USER_ASID_FLAG; ++ asid &= TTBR_ASID_MASK; ++ write_sysreg(koi_swapper_ttbr1 | asid, ttbr1_el1); ++ isb(); ++ asm volatile(ALTERNATIVE("nop; nop; nop", "ic iallu; dsb nsh; isb", ++ ARM64_WORKAROUND_CAVIUM_27456)); ++ return 1; ++} ++#else ++__koi_code noinline unsigned long koi_do_switch_to_ko_pgtbl(void) ++{ ++ struct koi_mem_hash_node *ko; ++ unsigned long addr, pan_flag, current_ttbr1, asid, ttbr1, flags; ++ unsigned long *ptr; ++ struct mm_struct *ko_mm; ++ int bkt; ++ asm volatile("mrs %0, pan\n" ++ "msr pan, 0x0\n" ++ : "=r"(pan_flag) ++ :); ++ current_ttbr1 = _iee_read_token_ttbr1(iee_offset, current); ++ asm volatile("msr pan, %0\n" : : "r"(pan_flag)); ++ ptr = SHIFT_PERCPU_PTR(koi_irq_current_ttbr1, __kern_my_cpu_offset()); ++ if (current_ttbr1 == 0 && *ptr == 0) ++ return 0; ++ asm volatile(" mrs %0, elr_el1\n" : "=r"(addr)); + rcu_read_lock(); -+ hash_for_each_possible_rcu (koi_mem_htbl, target, node, -+ (unsigned long)mod) { -+ if (target->mod == mod) { -+ break; ++ hash_for_each_rcu (koi_mem_htbl, bkt, ko, node) { ++ spin_lock_irqsave(&ko->mod_lock, flags); ++ if (!ko->is_valid) { ++ spin_unlock_irqrestore(&ko->mod_lock, flags); ++ goto out; ++ } ++ if (ko->mod != NULL && ko->mod->mem[MOD_INIT_TEXT].base != NULL) { ++ if (addr >= (unsigned long)ko->mod->mem[MOD_INIT_TEXT].base && ++ addr < (unsigned long)ko->mod->mem[MOD_INIT_TEXT].base + ko->mod->mem[MOD_INIT_TEXT].size) { ++ spin_unlock_irqrestore(&ko->mod_lock, flags); ++ if (current_ttbr1 == ko->ko_ttbr1 || *ptr == ko->ko_ttbr1) { ++ asm volatile("mrs %0, ttbr0_el1\n" ++ : "=r"(asid) ++ :); ++ asid &= TTBR_ASID_MASK; ++ ttbr1 = ko->ko_ttbr1 | asid; ++ rcu_read_unlock(); ++ return ttbr1; ++ } ++ goto out; ++ } ++ } ++ if (addr >= (unsigned long)ko->mod->mem[MOD_TEXT].base && ++ addr < (unsigned long)ko->mod->mem[MOD_TEXT].base + ko->mod->mem[MOD_TEXT].size) { ++ spin_unlock_irqrestore(&ko->mod_lock, flags); ++ if (current_ttbr1 == ko->ko_ttbr1 || *ptr == ko->ko_ttbr1) { ++ asm volatile("mrs %0, ttbr0_el1\n" ++ : "=r"(asid) ++ :); ++ asid &= TTBR_ASID_MASK; ++ ttbr1 = ko->ko_ttbr1 | asid; ++ rcu_read_unlock(); ++ return ttbr1; ++ } ++ goto out; + } ++ spin_unlock_irqrestore(&ko->mod_lock, flags); + } ++out: + rcu_read_unlock(); -+ if (target == NULL) { -+ printk("mem node for module: %s not found\n", mod->name); -+ return; -+ } ++ return 0; ++} + -+ rcu_read_lock(); -+ hash_for_each_possible_rcu (target->addr_htbl, addr_map_node, node, -+ orig_addr) { -+ if (addr_map_node->buffer_addr == orig_addr) { -+ break; -+ } ++__koi_code noinline int koi_do_switch_to_kernel_pgtbl(void) ++{ ++ unsigned long curr_ttbr1, asid, error_addr; ++ // if (!cpu_online(smp_processor_id())) ++ // return 0; ++ asm volatile(" mrs %0, ttbr1_el1\n" : "=r"(curr_ttbr1)); ++ if ((curr_ttbr1 & KOI_SWAPPER_MASK) == ++ (koi_swapper_ttbr1 & KOI_SWAPPER_MASK)) { ++ return 0; + } -+ rcu_read_unlock(); -+ if (addr_map_node != NULL) { -+ memcpy((void *)addr_map_node->orig_addr, -+ (void *)addr_map_node->buffer_addr, orig_size); -+ func((void *)addr_map_node->orig_addr); ++ // if (((curr_ttbr1 & TTBR_ASID_MASK) >> 48) <= 1) { ++ // return 0; ++ // } ++ error_addr = read_sysreg(elr_el1); ++ if ((error_addr >= (unsigned long)__iee_si_data_start) && ++ (error_addr <= (unsigned long)__iee_si_text_start)) { ++ unsigned long esr = read_sysreg(esr_el1); ++ asm volatile("mrs %0, ttbr1_el1\n" : "=r"(asid) :); ++ asid &= ~USER_ASID_FLAG; ++ asid &= TTBR_ASID_MASK; ++ write_sysreg(koi_swapper_ttbr1 | asid, ttbr1_el1); ++ isb(); ++ printk(KERN_ERR ++ "IEE SI: Error on switch to kernel. ELR_EL1:0x%llx, ESR_EL1:0x%llx, TTBR1:0x%llx", ++ error_addr, esr, curr_ttbr1); + } else { -+ printk("Cannot find addr_map_node in addr_htbl, maybe addr is in kernel space!!\n"); -+ func((void *)orig_addr); -+ } -+ -+ spin_lock_irqsave(&target->addr_htbl_spin_lock, flags); -+ if (addr_map_node != NULL) { -+ hlist_del_init_rcu(&addr_map_node->node); -+ call_rcu(&addr_map_node->rcu, koi_addr_map_node_free); ++ iee_rwx_gate_entry(IEE_SWITCH_TO_KERNEL); + } -+ spin_unlock_irqrestore(&target->addr_htbl_spin_lock, flags); -+ spin_lock_irqsave(&target->spin_lock, flags); -+ list_for_each_entry_rcu (mem_node, &target->mem_list_head, list) { -+ if (mem_node->addr + mem_node->size == addr) { -+ pos = mem_node->list.prev; -+ addr = mem_node->addr; -+ size += mem_node->size; -+ list_del_rcu(&mem_node->list); -+ call_rcu(&mem_node->rcu, koi_mem_node_free); -+ } else if (addr + size == mem_node->addr) { -+ if (!pos) -+ pos = mem_node->list.prev; -+ size += mem_node->size; -+ list_del_rcu(&mem_node->list); -+ call_rcu(&mem_node->rcu, koi_mem_node_free); -+ } else if (addr + size < mem_node->addr) { -+ if (!pos) -+ pos = mem_node->list.prev; -+ break; -+ } -+ } -+ mem_node = kzalloc(sizeof(struct koi_mem_list), GFP_ATOMIC); -+ mem_node->addr = addr; -+ mem_node->size = size; -+ if (pos) -+ list_add_rcu(&mem_node->list, pos); -+ else -+ list_add_tail_rcu(&mem_node->list, &target->mem_list_head); -+ spin_unlock_irqrestore(&target->spin_lock, flags); ++ return 1; ++} ++#endif ++/** ++* koi_save_ttbr - save ttbr of each driver module ++* @mod: driver module ++* @pgdp:pointer to driver module top page table,pgd ++*/ ++static void koi_save_ttbr(struct module *mod, pgd_t *pgdp, ++ struct koi_mem_hash_node *node) ++{ ++ phys_addr_t ttbr1 = phys_to_ttbr(virt_to_phys(pgdp)); ++ if (system_supports_cnp()) ++ ttbr1 |= TTBR_CNP_BIT; ++ node->ko_ttbr1 = ttbr1; +} -+EXPORT_SYMBOL(koi_mem_free_callback); + -+void koi_map_mem(struct module *mod, unsigned long addr, unsigned long size) ++/** ++ * Copy one pte. Returns 0 if succeeded, or -EAGAIN if one preallocated page ++ * is required to copy this pte. ++*/ ++static inline int koi_copy_present_pte(struct mm_struct *ko_mm, pte_t *dst_pte, ++ pte_t *src_pte, unsigned long addr) +{ -+ struct koi_mem_hash_node *target = NULL; -+ rcu_read_lock(); -+ hash_for_each_possible_rcu (koi_mem_htbl, target, node, -+ (unsigned long)mod) { -+ if (target->mod == mod) -+ break; -+ } -+ rcu_read_unlock(); ++ pte_t pte = *src_pte; ++ struct page *page; + -+ if (target == NULL) { -+ printk(KERN_ERR "mem node for module: %s not found\n", -+ mod->name); -+ return; ++ debug_printk("addr=0x%16llx, dst_pte=0x%16llx\n", addr, dst_pte); ++#ifdef CONFIG_IEE ++ if ((pte_val(pte) & PTE_USER) && (pte_val(pte) & PTE_DBM) && ++ !(pte_val(pte) & PTE_PXN)) { ++ set_pte(dst_pte, __pte(pte_val(pte) & (~PTE_DBM) | PTE_RDONLY)); ++ } else { ++#endif ++ set_pte(dst_pte, pte); ++#ifdef CONFIG_IEE + } -+ koi_copy_pagetable(target->ko_mm, target->pgdp, addr & PAGE_MASK, -+ (addr + size + PAGE_SIZE) & PAGE_MASK); ++#endif ++ return 0; +} -+EXPORT_SYMBOL(koi_map_mem); +/** -+* koi_mem_free_to_user - function 'copy_to_user' in driver space ++* copy huge pmd from kernel space to driver space. +*/ -+void koi_mem_free_to_user(struct module *mod, unsigned long addr, -+ unsigned long size) ++static int koi_copy_huge_pmd(struct mm_struct *ko_mm, pmd_t *dst_pmd, ++ pmd_t *src_pmd, unsigned long addr, pteval_t prot) +{ -+ struct koi_mem_hash_node *target = NULL; -+ struct koi_mem_list *mem_node; -+ struct list_head *pos = NULL; -+ struct koi_addr_map *addr_map_node; -+ unsigned long flags; -+ unsigned long orig_size = size; -+ unsigned long orig_addr = addr; -+ rcu_read_lock(); -+ hash_for_each_possible_rcu (koi_mem_htbl, target, node, -+ (unsigned long)mod) { -+ if (target->mod == mod) { -+ break; -+ } ++ spinlock_t *src_ptl, *dst_ptl; ++ pmd_t pmd; ++ int ret = -ENOMEM; ++ debug_printk( ++ "hugepmd: src_pmd=0x%16llx, dst_pmd=0x%16llx, src_pmd_val=0x%16llx, dst_pmd_val=0x%16llx, addr=0x%16llx\n", ++ src_pmd, dst_pmd, pmd_val(*src_pmd), pmd_val(*dst_pmd), addr); ++ dst_ptl = pmd_lockptr(ko_mm, dst_pmd); ++ src_ptl = pmd_lockptr(&init_mm, src_pmd); ++ spin_lock_bh(dst_ptl); ++ spin_lock_bh(src_ptl); ++ ++ set_pmd(dst_pmd, __pmd(pmd_val(*src_pmd) | prot)); ++ ret = 0; ++ spin_unlock_bh(src_ptl); ++ spin_unlock_bh(dst_ptl); ++ return ret; ++} ++ ++int __koi_pte_alloc(struct mm_struct *mm, pmd_t *pmd) ++{ ++ spinlock_t *ptl; ++ // pgtable_t new = alloc_page(GFP_PGTABLE_KERNEL); ++ pte_t *new = pte_alloc_one_kernel(mm); ++ printk(KERN_ERR "alloc new=0x%16llx\n", new); ++ if (!new) ++ return -ENOMEM; ++ ++ /* ++ * Ensure all pte setup (eg. pte page lock and page clearing) are ++ * visible before the pte is made visible to other CPUs by being ++ * put into page tables. ++ * ++ * The other side of the story is the pointer chasing in the page ++ * table walking code (when walking the page table without locking; ++ * ie. most of the time). Fortunately, these data accesses consist ++ * of a chain of data-dependent loads, meaning most CPUs (alpha ++ * being the notable exception) will already guarantee loads are ++ * seen in-order. See the alpha page table accessors for the ++ * smp_rmb() barriers in page table walking code. ++ */ ++ smp_wmb(); /* Could be smp_wmb__xxx(before|after)_spin_lock */ ++ ++ ptl = pmd_lockptr(mm, pmd); ++ spin_lock_bh(ptl); ++ if (likely(pmd_none(*pmd))) { /* Has another populated it ? */ ++ mm_inc_nr_ptes(mm); ++ pmd_populate_kernel(mm, pmd, new); ++ new = NULL; + } -+ rcu_read_unlock(); -+ if (target == NULL) { -+ printk(KERN_ERR "mem node for module: %s not found\n", -+ mod->name); -+ return; ++ spin_unlock_bh(ptl); ++ if (new) { ++ pte_free_kernel(mm, new); + } ++ return 0; ++} + -+ rcu_read_lock(); -+ hash_for_each_possible_rcu (target->addr_htbl, addr_map_node, node, -+ orig_addr) { -+ if (addr_map_node->buffer_addr == orig_addr) { -+ break; -+ } ++#define koi_pte_alloc(mm, pmd) \ ++ (unlikely(pmd_none(*(pmd))) && __koi_pte_alloc(mm, pmd)) ++ ++#define koi_pte_offset_map_lock(mm, pmd, address, ptlp) \ ++ ({ \ ++ spinlock_t *__ptl = pte_lockptr(mm, pmd); \ ++ pte_t *__pte = pte_offset_kernel(pmd, address); \ ++ *(ptlp) = __ptl; \ ++ spin_lock_bh(__ptl); \ ++ __pte; \ ++ }) ++ ++#define koi_pte_alloc_map_lock(mm, pmd, address, ptlp) \ ++ (koi_pte_alloc(mm, pmd) ? \ ++ NULL : \ ++ koi_pte_offset_map_lock(mm, pmd, address, ptlp)) ++ ++/** ++*koi_copy_pte_range - copy pte from kernel space to driver space ++*/ ++static int koi_copy_pte_range(struct mm_struct *ko_mm, pmd_t *dst_pmd, ++ pmd_t *src_pmd, unsigned long addr, ++ unsigned long end, pteval_t prot) ++{ ++ pte_t *src_pte, *dst_pte; ++ spinlock_t *src_ptl, *dst_ptl; ++ ++ int ret = 0; ++again: ++ dst_pte = koi_pte_alloc_map_lock(ko_mm, dst_pmd, addr, &dst_ptl); ++ if (!dst_pte) { ++ ret = -ENOMEM; ++ goto unlock; + } -+ rcu_read_unlock(); -+ if (copy_to_user((void *)addr_map_node->orig_addr, -+ (void *)addr_map_node->buffer_addr, orig_size)) { -+ return; ++ src_pte = pte_offset_kernel(src_pmd, addr); ++ src_ptl = pte_lockptr(&init_mm, src_pmd); ++ spin_lock_bh(src_ptl); ++ do { ++ if (pte_none(*src_pte)) ++ continue; ++ if (unlikely(!pte_present(*src_pte))) { ++ printk(KERN_ERR ++ "present pte found: addr=0x%16llx, end=0x%16llx\n", ++ addr, end); ++ continue; ++ } ++ if (pte_valid(*dst_pte)) { ++ continue; ++ } ++ /* koi_copy_present_pte() will clear `*prealloc` if consumed */ ++ ret = koi_copy_present_pte(ko_mm, dst_pte, src_pte, addr); ++ debug_printk( ++ "dst_pte=0x%16llx, dst_pte_val=0x%16llx, src_pte=0x%16llx, src_pte_val=0x%16llx, addr=0x%16llx\n", ++ dst_pte, pte_val(*dst_pte), src_pte, pte_val(*src_pte), ++ addr); ++ if (unlikely(ret == -EAGAIN)) ++ break; ++ } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end); ++ spin_unlock_bh(src_ptl); ++ spin_unlock_bh(dst_ptl); ++ ++ if (ret) { ++ WARN_ON_ONCE(ret != -EAGAIN); ++ ret = 0; + } ++ if (addr != end) ++ goto again; + -+ spin_lock_irqsave(&target->addr_htbl_spin_lock, flags); -+ hlist_del_init_rcu(&addr_map_node->node); -+ call_rcu(&addr_map_node->rcu, koi_addr_map_node_free); -+ spin_unlock_irqrestore(&target->addr_htbl_spin_lock, flags); -+ spin_lock_irqsave(&target->spin_lock, flags); -+ list_for_each_entry_rcu (mem_node, &target->mem_list_head, list) { -+ if (mem_node->addr + mem_node->size == addr) { -+ pos = mem_node->list.prev; -+ addr = mem_node->addr; -+ size += mem_node->size; -+ list_del_rcu(&mem_node->list); -+ call_rcu(&mem_node->rcu, koi_mem_node_free); -+ } else if (addr + size == mem_node->addr) { -+ if (!pos) -+ pos = mem_node->list.prev; -+ size += mem_node->size; -+ list_del_rcu(&mem_node->list); -+ call_rcu(&mem_node->rcu, koi_mem_node_free); -+ } else if (addr + size < mem_node->addr) { -+ if (!pos) -+ pos = mem_node->list.prev; -+ break; -+ } ++ return ret; ++unlock: ++ spin_unlock_bh(dst_ptl); ++ return ret; ++} ++ ++int __koi_pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) ++{ ++ spinlock_t *ptl; ++ // struct page* page = alloc_page(GFP_PGTABLE_KERNEL); ++ // pmd_t *new = (pmd_t *)page_address(page); ++ pmd_t *new = pmd_alloc_one(mm, address); ++ if (!new) ++ return -ENOMEM; ++ ++ smp_wmb(); /* See comment in __pte_alloc */ ++ ++ ptl = pud_lockptr(mm, pud); ++ spin_lock_bh(ptl); ++ if (!pud_present(*pud)) { ++ mm_inc_nr_pmds(mm); ++ pud_populate(mm, pud, new); ++ } else { /* Another has populated it */ ++ pmd_free(mm, new); ++ // free_page((unsigned long)new); + } -+ mem_node = kzalloc(sizeof(struct koi_mem_list), GFP_ATOMIC); -+ mem_node->addr = addr; -+ mem_node->size = size; -+ if (pos) -+ list_add_rcu(&mem_node->list, pos); -+ else -+ list_add_tail_rcu(&mem_node->list, &target->mem_list_head); -+ spin_unlock_irqrestore(&target->spin_lock, flags); ++ spin_unlock_bh(ptl); ++ return 0; +} -+EXPORT_SYMBOL(koi_mem_free_to_user); -+// map the driver stack to kernel -+void koi_map_kostack(struct module *mod) ++ ++static inline pmd_t *koi_pmd_alloc(struct mm_struct *mm, pud_t *pud, ++ unsigned long address) +{ -+ struct koi_mem_hash_node *target = NULL; -+ void *koi_stack; -+ unsigned long cur_sp; -+ asm volatile("mov %0, sp\n" : "=r"(cur_sp) :); -+ if (on_irq_stack(cur_sp, NULL)) { -+ return; ++ return (unlikely(pud_none(*pud)) && __koi_pmd_alloc(mm, pud, address)) ? ++ NULL : ++ pmd_offset(pud, address); ++} ++ ++/** ++*kio_copy_pmd_range - copy pmd from kernel to driver space ++*/ ++static inline int koi_copy_pmd_range(struct mm_struct *ko_mm, pud_t *dst_pud, ++ pud_t *src_pud, unsigned long addr, ++ unsigned long end, pteval_t prot) ++{ ++ pmd_t *src_pmd, *dst_pmd; ++ unsigned long next, flag; ++ int err; ++ debug_printk( ++ "copy_pud_range src_pud=0x%16llx, dst_pud=0x%16llx, addr=0x%16llx, end=0x%16llx\n", ++ src_pud, dst_pud, addr, end); ++ dst_pmd = koi_pmd_alloc(ko_mm, dst_pud, addr); ++ if (!dst_pmd) { ++ return -ENOMEM; + } -+#ifndef CONFIG_IEE -+ unsigned long res, alloc_token; -+ struct task_token *token_addr = -+ (struct task_token *)((unsigned long)current + -+ (unsigned long)koi_offset); -+ if (token_addr->koi_stack_base != NULL) -+ return; -+#else -+ koi_stack = iee_rw_gate(IEE_READ_KOI_STACK, current); -+ if (koi_stack != NULL) -+ return; -+#endif -+ koi_stack = -+ (void *)__get_free_pages(THREADINFO_GFP & ~__GFP_ACCOUNT, 3); -+ free_pages(koi_stack + 4 * PAGE_SIZE, 2); -+ printk(KERN_ERR "alloc dstack start=0x%16llx, end=0x%16llx\n", -+ koi_stack, koi_stack + THREAD_SIZE); -+#ifndef CONFIG_IEE -+ token_addr->koi_stack = -+ (struct pt_regs *)(THREAD_SIZE + (unsigned long)koi_stack) - 1; -+ token_addr->koi_stack_base = koi_stack; -+#else -+ iee_rw_gate( -+ IEE_WRITE_KOI_STACK, current, -+ (unsigned long)((struct pt_regs *)(THREAD_SIZE + -+ (unsigned long)koi_stack) - -+ 1)); -+ iee_rw_gate(IEE_WRITE_KOI_STACK_BASE, current, -+ (unsigned long)koi_stack); -+#endif -+ rcu_read_lock(); -+ hash_for_each_possible_rcu (koi_mem_htbl, target, node, -+ (unsigned long)mod) { -+ if (target->mod == mod) { -+ break; ++ src_pmd = pmd_offset(src_pud, addr); ++ do { ++ next = pmd_addr_end(addr, end); ++ flag = pmd_val(*src_pmd) & KOI_FLAG_MASK; ++ // debug_printk("src_pmd=0x%16llx, dst_pmd=0x%16llx, addr=0x%16llx\n", src_pmd, dst_pmd, next); ++ // CONFIG_TRANSPARENT_HUGEPAGE is enabled, so we must add copy_huge_pmd ++ if (pmd_none(*src_pmd)) ++ continue; ++ if (!(pmd_val(*src_pmd) & PMD_TABLE_BIT)) { ++ // if src_pmd is huge page ++ debug_printk( ++ "src_pmd=0x%16llx, dst_pmd=0x%16llx, addr=0x%16llx\n", ++ src_pmd, dst_pmd, addr); ++ err = koi_copy_huge_pmd(ko_mm, dst_pmd, src_pmd, addr, prot); ++ if (err == -ENOMEM) ++ return -ENOMEM; ++ continue; + } -+ } -+ rcu_read_unlock(); -+ if (target == NULL) { -+ printk(KERN_ERR "mem node for module: %s not found\n", -+ mod->name); -+ return; -+ } -+ koi_copy_pagetable(target->ko_mm, target->pgdp, -+ (unsigned long)koi_stack, -+ (unsigned long)koi_stack + THREAD_SIZE); -+ printk(KERN_ERR "create ko stack: 0x%16llx\n", -+ (unsigned long)koi_stack); ++ if (koi_copy_pte_range(ko_mm, dst_pmd, src_pmd, addr, next, prot)) ++ return -ENOMEM; ++ set_pmd(dst_pmd, __pmd((pmd_val(*dst_pmd) & (~KOI_FLAG_MASK)) | flag)); ++ debug_printk( ++ "src_pmd_val=0x%16llx, dst_pmd_val=0x%16llx, addr=0x%16llx\n", ++ pmd_val(*src_pmd), pmd_val(*dst_pmd), addr); ++ } while (dst_pmd++, src_pmd++, addr = next, addr != end); ++ return 0; +} -+EXPORT_SYMBOL(koi_map_kostack); -\ No newline at end of file -diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c -index cea96ee75d22..cbddc8e464e4 100644 ---- a/arch/arm64/kernel/mte.c -+++ b/arch/arm64/kernel/mte.c -@@ -79,8 +79,13 @@ int memcmp_pages(struct page *page1, struct page *page2) - static inline void __mte_enable_kernel(const char *mode, unsigned long tcf) - { - /* Enable MTE Sync Mode for EL1. */ -+#ifdef CONFIG_IEE -+ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_EL1_TCF_MASK, -+ SYS_FIELD_PREP(SCTLR_EL1, TCF, tcf)); -+#else - sysreg_clear_set(sctlr_el1, SCTLR_EL1_TCF_MASK, - SYS_FIELD_PREP(SCTLR_EL1, TCF, tcf)); -+#endif - isb(); - - pr_info_once("MTE: enabled in %s mode at EL1\n", mode); -diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c -index 068e5bb2661b..c98bc1a24fc7 100644 ---- a/arch/arm64/kernel/process.c -+++ b/arch/arm64/kernel/process.c -@@ -467,11 +467,24 @@ static void ssbs_thread_switch(struct task_struct *next) - * This is *only* for exception entry from EL0, and is not valid until we - * __switch_to() a user task. - */ -+#ifdef CONFIG_IEE -+// Put __entry_task in a isolated page to protect it. -+__attribute__((aligned(PAGE_SIZE))) DEFINE_PER_CPU(struct task_struct *[PAGE_SIZE/sizeof(struct task_struct *)], __entry_task); -+extern void iee_write_entry_task(struct task_struct *tsk); -+#else - DEFINE_PER_CPU(struct task_struct *, __entry_task); -+#endif - - static void entry_task_switch(struct task_struct *next) - { -+ #ifdef CONFIG_IEE -+ if(next == &init_task) -+ iee_write_entry_task((struct task_struct *)__va(__pa_symbol(next))); -+ else -+ iee_write_entry_task(next); -+ #else - __this_cpu_write(__entry_task, next); -+ #endif - } - - /* -@@ -506,11 +519,15 @@ static void erratum_1418040_new_exec(void) - */ - void update_sctlr_el1(u64 sctlr) - { -- /* -+ /* - * EnIA must not be cleared while in the kernel as this is necessary for - * in-kernel PAC. It will be cleared on kernel exit if needed. - */ -+ #ifdef CONFIG_IEE -+ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_USER_MASK & ~SCTLR_ELx_ENIA, sctlr); -+ #else - sysreg_clear_set(sctlr_el1, SCTLR_USER_MASK & ~SCTLR_ELx_ENIA, sctlr); -+ #endif - - /* ISB required for the kernel uaccess routines when setting TCF0. */ - isb(); -diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c -index 58a97861bfc5..c7839247327d 100644 ---- a/arch/arm64/kernel/proton-pack.c -+++ b/arch/arm64/kernel/proton-pack.c -@@ -551,7 +551,11 @@ static enum mitigation_state spectre_v4_enable_hw_mitigation(void) - return state; - - if (spectre_v4_mitigations_off()) { -+#ifdef CONFIG_IEE -+ sysreg_clear_set_iee_si(sctlr_el1, 0, SCTLR_ELx_DSSBS); -+#else - sysreg_clear_set(sctlr_el1, 0, SCTLR_ELx_DSSBS); -+#endif - set_pstate_ssbs(1); - return SPECTRE_VULNERABLE; - } -@@ -975,7 +979,11 @@ static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot) - if (arm64_kernel_unmapped_at_el0()) - return; - -+#ifdef CONFIG_IEE -+ iee_rwx_gate_entry(IEE_WRITE_vbar_el1, v); -+#else - write_sysreg(v, vbar_el1); -+#endif - isb(); - } - -diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c -index 95cb22c083c8..df73a583a733 100644 ---- a/arch/arm64/kernel/setup.c -+++ b/arch/arm64/kernel/setup.c -@@ -33,6 +33,11 @@ - #include - #include - -+#ifdef CONFIG_IEE -+#include -+#include -+#endif + - #include - #include - #include -@@ -335,10 +340,30 @@ u64 cpu_logical_map(unsigned int cpu) - return __cpu_logical_map[cpu]; - } - -+#ifdef CONFIG_IEE -+/* used for secure modification of vbar*/ -+extern char __bp_harden_el1_vectors[]; -+/* prepare iee rwx gate for senario of ttbr1=init_pg_dir */ -+static void __init iee_si_init_early(void) ++int __koi_pud_alloc(struct mm_struct *mm, p4d_t *p4d, unsigned long address) +{ -+ /* prepare data used for iee rwx gate. */ -+ iee_base_idmap_pg_dir = phys_to_ttbr(__pa_symbol(idmap_pg_dir)); -+ iee_base_reserved_pg_dir = phys_to_ttbr(__pa_symbol(reserved_pg_dir)) -+ | FIELD_PREP(TTBR_ASID_MASK, 1); -+ iee_base__bp_harden_el1_vectors = (unsigned long)__bp_harden_el1_vectors; -+ iee_si_tcr = 0; -+} -+#endif ++ // pud_t *new = pud_alloc_one(mm, address); + - void __init __no_sanitize_address setup_arch(char **cmdline_p) - { - setup_initial_init_mm(_stext, _etext, _edata, _end); - -+ #ifdef CONFIG_IEE -+ init_new_context(&init_task, &init_mm); -+ atomic64_set(&init_mm.context.id, (1UL << get_cpu_asid_bits()) | INIT_ASID); -+ #endif ++ // struct page *page = alloc_page(GFP_PGTABLE_KERNEL); ++ // pud_t *new = (pud_t *)page_address(page); ++ pud_t *new = pud_alloc_one(mm, address); ++ printk(KERN_ERR "pud alloc pud=0x%16llx\n", new); ++ if (!new) ++ return -ENOMEM; + - *cmdline_p = boot_command_line; - - kaslr_init(); -@@ -371,6 +396,14 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p) - */ - local_daif_restore(DAIF_PROCCTX_NOIRQ); - -+#ifdef CONFIG_IEE -+ /* -+ * Map iee si codes to init_pg_dir to run the following -+ * cpu_uninstall_idmap() which writes ttbr0. -+ */ -+ iee_si_init_early(); -+#endif ++ smp_wmb(); /* See comment in __pte_alloc */ + - /* - * TTBR0 is only used for the identity mapping at this stage. Make it - * point to zero page to avoid speculatively fetching new entries. -diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c -index b7b7afb4a8c7..168a9390d6e9 100644 ---- a/arch/arm64/kernel/traps.c -+++ b/arch/arm64/kernel/traps.c -@@ -902,6 +902,32 @@ const char *esr_get_class_string(unsigned long esr) - return esr_class_str[ESR_ELx_EC(esr)]; - } - -+#ifdef CONFIG_IEE -+extern void arm64_enter_nmi(struct pt_regs *regs); -+static const char *handler[]= { -+ "SP_EL0", -+ "ELR_EL1", -+ "TCR_EL1", -+ "TTBR0 ASID" -+ "IEE_SI" -+}; ++ spin_lock_bh(&mm->page_table_lock); ++ if (!p4d_present(*p4d)) { ++ mm_inc_nr_puds(mm); ++ p4d_populate(mm, p4d, new); ++ } else {/* Another has populated it */ ++ pud_free(mm, new); ++ // free_page((unsigned long)new); ++ } ++ spin_unlock_bh(&mm->page_table_lock); ++ return 0; ++} + -+asmlinkage void notrace iee_bad_mode(struct pt_regs *regs, int reason, unsigned int esr) ++static inline pud_t *koi_pud_alloc(struct mm_struct *mm, p4d_t *p4d, ++ unsigned long address) +{ -+ arm64_enter_nmi(regs); -+ -+ console_verbose(); ++ return (unlikely(p4d_none(*p4d)) && __koi_pud_alloc(mm, p4d, address)) ? ++ NULL : ++ pud_offset(p4d, address); ++} + -+ pr_crit("IEE : Bad mode in %s check detected on CPU%d, code 0x%08x -- %s\n", -+ handler[reason], smp_processor_id(), esr, -+ esr_get_class_string(esr)); ++static int koi_copy_huge_pud(struct mm_struct *ko_mm, pud_t *dst_pud, ++ pud_t *src_pud, unsigned long addr, pteval_t prot) ++{ ++ spinlock_t *src_ptl, *dst_ptl; ++ // pmd_t pmd; ++ int ret = -ENOMEM; ++ debug_printk("src_pud=0x%16llx, dst_pud=0x%16llx, addr=0x%16llx\n", ++ src_pud, dst_pud, addr); ++ dst_ptl = pud_lockptr(ko_mm, dst_pud); ++ src_ptl = pud_lockptr(&init_mm, src_pud); ++ spin_lock_bh(dst_ptl); ++ spin_lock_bh(src_ptl); ++ set_pte((pte_t *)dst_pud, __pte(pud_val(*src_pud) | prot)); ++ spin_unlock_bh(src_ptl); ++ spin_unlock_bh(dst_ptl); ++ ret = 0; ++ return ret; ++} + -+ __show_regs(regs); -+ local_daif_mask(); -+ panic("bad mode"); ++/** ++*koi_copy_pud_range - copy pud from kernel to driver ++*/ ++static inline int koi_copy_pud_range(struct mm_struct *ko_mm, p4d_t *dst_p4d, ++ p4d_t *src_p4d, unsigned long addr, ++ unsigned long end, pteval_t prot) ++{ ++ pud_t *src_pud, *dst_pud; ++ unsigned long next, flag; ++ dst_pud = koi_pud_alloc(ko_mm, dst_p4d, addr); ++ if (!dst_pud) ++ return -ENOMEM; ++ src_pud = pud_offset(src_p4d, addr); ++ do { ++ next = pud_addr_end(addr, end); ++ flag = pud_val(*src_pud) & KOI_FLAG_MASK; ++ debug_printk( ++ "src_pud=0x%16llx, dst_pud=0x%16llx, addr=0x%16llx\n", ++ src_pud, dst_pud, next); ++ if (pud_none(*src_pud)) { ++ continue; ++ } ++ if (!(pud_val(*src_pud) & PMD_TABLE_BIT)) { ++ // indicates that the src_pud maps to a huge page ++ koi_copy_huge_pud(ko_mm, dst_pud, src_pud, addr, prot); ++ continue; ++ } ++ // if (pud_trans_huge(*src_pud) || pud_devmap(*src_pud)) { ++ // debug_printk("pud_trans_huge=%d, pud_devmap=%d, src_pud=0x%16llx\n", pud_trans_huge(*src_pud) , pud_devmap(*src_pud), src_pud); ++ // continue; ++ // /* fall through */ ++ // } ++ if (koi_copy_pmd_range(ko_mm, dst_pud, src_pud, addr, next, prot)) ++ return -ENOMEM; ++ set_pud(dst_pud, __pud((pud_val(*dst_pud) & (~KOI_FLAG_MASK)) | flag)); ++ } while (dst_pud++, src_pud++, addr = next, addr != end); ++ return 0; +} -+#endif + - /* - * bad_el0_sync handles unexpected, but potentially recoverable synchronous - * exceptions taken from EL0. -diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S -index 3cd7e76cc562..287eaba7a15b 100644 ---- a/arch/arm64/kernel/vmlinux.lds.S -+++ b/arch/arm64/kernel/vmlinux.lds.S -@@ -134,6 +134,52 @@ jiffies = jiffies_64; - #define UNWIND_DATA_SECTIONS - #endif - -+#ifdef CONFIG_IEE -+#define IEE_TEXT \ -+ . = ALIGN(PAGE_SIZE); \ -+ __iee_code_start = .; \ -+ *(.iee.text.header) \ -+ *(.iee.text) \ -+ . = ALIGN(PAGE_SIZE); \ -+ __iee_code_end = .; -+#else -+#define IEE_TEXT -+#endif -+ -+#ifdef CONFIG_IEE -+#define IEE_SI_TEXT \ -+ . = ALIGN(PAGE_SIZE); \ -+ __iee_si_data_start = .; \ -+ *(.iee.si_data) \ -+ . = ALIGN(PAGE_SIZE); \ -+ __iee_exec_entry_start = .; \ -+ __iee_si_no_irq = . + (16); \ -+ *(.iee.exec_entry) \ -+ . = ALIGN(PAGE_SIZE); \ -+ __iee_si_start = .; \ -+ *(.iee.si_text) \ -+ . = ALIGN(PAGE_SIZE); \ -+ . += PAGE_SIZE - (24); \ -+ __iee_si_end = . + (24); \ -+ __iee_exec_exit = .; \ -+ *(.iee.exec_exit) \ -+ . = ALIGN(PAGE_SIZE); -+ -+#else -+#define IEE_SI_TEXT -+#endif ++/** ++* koi_copy_p4d_range - map the kernel pagetable to the driver space level by level ++* @ko_mm: the mm_struct of driver module ++* @dst_pgd: destination pgd ++* @src_pgd: source pgd ++* @addr: the start of address ++* @end: the end of address ++*/ ++static inline int koi_copy_p4d_range(struct mm_struct *ko_mm, pgd_t *dst_pgd, ++ pgd_t *src_pgd, unsigned long addr, ++ unsigned long end, pteval_t prot) ++{ ++ p4d_t *src_p4d, *dst_p4d; ++ unsigned long next; ++ dst_p4d = p4d_alloc(ko_mm, dst_pgd, addr); ++ if (!dst_p4d) ++ return -ENOMEM; ++ src_p4d = p4d_offset(src_pgd, addr); ++ do { ++ next = p4d_addr_end(addr, end); ++ if (p4d_none(*src_p4d) || p4d_bad(*src_p4d)) ++ continue; ++ debug_printk( ++ "dst_p4d=0x%16llx, dst_p4d_val=0x%16llx\n", ++ dst_p4d, p4d_val(*dst_p4d)); ++ if (koi_copy_pud_range(ko_mm, dst_p4d, src_p4d, addr, next, prot)) { ++ return -ENOMEM; ++ } ++ } while (dst_p4d++, src_p4d++, addr = next, addr != end); ++ return 0; ++} ++int koi_share_kstack(struct module *mod) ++{ ++ unsigned long kstack_start; ++ struct koi_mem_hash_node *target = NULL; ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) { ++ break; ++ } ++ } ++ kstack_start = (unsigned long)current->stack; + -+#ifdef CONFIG_KOI -+#define KOI_TEXT \ -+ . = ALIGN(PAGE_SIZE); \ -+ __koi_code_start = .; \ -+ *(.koi.text) \ -+ . = ALIGN(PAGE_SIZE); \ -+ __koi_code_end = .; -+#else -+#define KOI_TEXT -+#endif ++ return koi_copy_pagetable(target->ko_mm, target->pgdp, kstack_start, ++ kstack_start + THREAD_SIZE, (0)); ++} ++EXPORT_SYMBOL(koi_share_kstack); ++/** ++*int koi_copy_pagetable - map the address range from "addr" to "end" to the driver pagetable ++*@ko_mm: the mm_struct of the driver module ++*@koi_pg_dir: koi_pg_dir, related to the driver module, the entry for driver pagetable ++*@addr: the starting address of mapping zone ++*@end: the end address of mapping zone ++*/ ++int koi_copy_pagetable(struct mm_struct *ko_mm, pgd_t *koi_pg_dir, ++ unsigned long addr, unsigned long end, pteval_t prot) ++{ ++ int ret = 0; ++ unsigned long next; + - /* - * The size of the PE/COFF section that covers the kernel image, which - * runs from _stext to _edata, must be a round multiple of the PE/COFF -@@ -176,10 +222,13 @@ SECTIONS - SOFTIRQENTRY_TEXT - ENTRY_TEXT - TEXT_TEXT -+ IEE_TEXT - SCHED_TEXT - LOCK_TEXT - KPROBES_TEXT - HYPERVISOR_TEXT -+ IEE_SI_TEXT -+ KOI_TEXT - *(.gnu.warning) - } - -@@ -318,6 +367,18 @@ SECTIONS - . += INIT_DIR_SIZE; - init_pg_end = .; - -+ #ifdef CONFIG_IEE -+ . = ALIGN(PAGE_SIZE*8); -+ init_iee_stack_begin = .; -+ . += PAGE_SIZE*4; -+ init_iee_stack_end = .; ++ pgd_t *src_pgd, *dst_pgd; ++ unsigned long flag; ++ src_pgd = pgd_offset_pgd(swapper_pg_dir, addr); ++ dst_pgd = pgd_offset_pgd(koi_pg_dir, addr); ++ do { ++ flag = pgd_val(*src_pgd) & KOI_FLAG_MASK; ++ next = pgd_addr_end(addr, end); ++ if (pgd_none(*src_pgd) || pgd_bad(*src_pgd)) ++ continue; ++ if (unlikely(koi_copy_p4d_range(ko_mm, dst_pgd, src_pgd, addr, ++ next, prot))) { ++ ret = -ENOMEM; ++ break; ++ } ++ set_pgd(dst_pgd, __pgd((pgd_val(*dst_pgd) & (~KOI_FLAG_MASK)) | flag)); ++ } while (dst_pgd++, src_pgd++, addr = next, addr != end); + -+ . = ALIGN(PAGE_SIZE); -+ init_iee_si_stack_begin = .; -+ . += PAGE_SIZE*4; -+ init_iee_si_stack_end = .; -+ #endif ++ return ret; ++} ++EXPORT_SYMBOL(koi_copy_pagetable); ++void koi_set_rdonly(unsigned long addr, pgd_t *pgdir) ++{ ++ p4d_t *p4dp; ++ pud_t *pudp; ++ pmd_t *pmdp; ++ pte_t *ptep; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ if (pgd_none(*pgdp) || pgd_bad(*pgdp)) { ++ return; ++ } + - . = ALIGN(SEGMENT_ALIGN); - __pecoff_data_size = ABSOLUTE(. - __initdata_begin); - _end = .; -diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c -index 188197590fc9..97e1f86046cf 100644 ---- a/arch/arm64/mm/context.c -+++ b/arch/arm64/mm/context.c -@@ -17,6 +17,10 @@ - #include - #include - -+#ifdef CONFIG_IEE -+#include -+#endif ++ p4dp = p4d_offset(pgdp, addr); ++ if (p4d_none(*p4dp) || p4d_bad(*p4dp)) { ++ return; ++ } + - static u32 asid_bits; - static DEFINE_RAW_SPINLOCK(cpu_asid_lock); - -@@ -39,7 +43,11 @@ static unsigned long *pinned_asid_map; - #define asid2ctxid(asid, genid) ((asid) | (genid)) - - /* Get the ASIDBits supported by the current CPU */ -+#ifdef CONFIG_IEE -+u32 get_cpu_asid_bits(void) -+#else - static u32 get_cpu_asid_bits(void) -+#endif - { - u32 asid; - int fld = cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64MMFR0_EL1), -@@ -212,6 +220,38 @@ static u64 new_context(struct mm_struct *mm) - return asid2ctxid(asid, generation); - } - -+#ifdef CONFIG_KOI -+/* -+ * This function is used to check and allocate ASID for ko's pgd -+ * The mm MUST point to the isolated kos' mm_struct, other behaviours are undefined. -+ */ -+void koi_check_and_switch_context(struct mm_struct *mm) { -+ u64 asid = atomic64_read(&mm->context.id); -+ u64 old_active_asid; -+ unsigned long flags; -+ unsigned int cpu; ++ pudp = pud_offset(p4dp, addr); ++ if (pud_none(*pudp) || pud_bad(*pudp)) { ++ return; ++ } ++ pmdp = pmd_offset(pudp, addr); ++ if (pmd_none(*pmdp) || pmd_bad(*pmdp)) { ++ return; ++ } + -+ old_active_asid = atomic64_read(this_cpu_ptr(&active_asids)); -+ if (old_active_asid && asid_gen_match(asid) && atomic64_cmpxchg_relaxed(this_cpu_ptr(&active_asids), old_active_asid, asid)) { ++ ptep = pte_offset_kernel(pmdp, addr); ++ if (pte_none(*ptep)) { ++ // printk(KERN_ERR "ptep 0x%16llx not available\n", ptep); + return; + } -+ -+ raw_spin_lock_irqsave(&cpu_asid_lock, flags); -+ asid = atomic64_read(&mm->context.id); -+ if (!asid_gen_match(asid)) { -+ asid = new_context(mm); -+ atomic64_set(&mm->context.id, asid); ++ set_pte(ptep, __pte(pte_val(*ptep) | PTE_RDONLY)); ++ // printk(KERN_ERR "set_readonly successfully\n"); ++ return; ++} ++ ++void koi_set_upage(struct module *mod, unsigned long addr, unsigned long size) { ++ struct koi_mem_hash_node *target = NULL; ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) { ++ break; ++ } + } + -+ cpu = smp_processor_id(); -+ if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) -+ local_flush_tlb_all(); ++ koi_copy_pagetable(target->ko_mm, target->pgdp, addr & PAGE_MASK, ++ (addr + size + PAGE_SIZE) & PAGE_MASK, PTE_USER); ++} ++EXPORT_SYMBOL(koi_set_upage); + -+ atomic64_set(this_cpu_ptr(&active_asids), asid); -+ raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); ++void koi_unmap_pte_table(struct mm_struct *ko_mm, pmd_t *pmd, ++ unsigned long addr, unsigned long end) ++{ ++ pte_t *pte; ++ if (!pmd) ++ return; ++ debug_printk("pmd=0x%16llx, addr=0x%16llx, end=0x%16llx\n", pmd, addr, ++ end); ++ ++ // struct page *page = pte_page(*pte); ++ // printk(KERN_ERR "pte=0x%16llx, pte_val=0x%16llx\n", pte, pte_val(*pte)); ++ // debug_printk("free pte table 0x%16llx, pmd=0x%16llx, page=0x%16llx, pmd points to page=0x%16llx\n", pte, pmd, page, pte_page(pmd_pte(*pmd))); ++ // printk(KERN_ERR "pmd_pfn=0x%16llx, pte_pfn=0x%16llx\n", pmd_pfn(*pmd), pte_pfn(*pte)); ++ // pte_free(ko_mm, pte_page(pmd_pte(*pmd))); ++ do { ++ pte = pte_offset_kernel(pmd, addr); ++ debug_printk("pte=0x%16llx, pte_val=0x%16llx\n", pte, ++ pte_val(*pte)); ++ set_pte(pte, __pte(0)); ++ } while (addr += PAGE_SIZE, addr != end); +} -+#endif + - void check_and_switch_context(struct mm_struct *mm) - { - unsigned long flags; -@@ -348,7 +388,9 @@ asmlinkage void post_ttbr_update_workaround(void) - - void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm) - { -+ #ifndef CONFIG_IEE - unsigned long ttbr1 = read_sysreg(ttbr1_el1); -+ #endif - unsigned long asid = ASID(mm); - unsigned long ttbr0 = phys_to_ttbr(pgd_phys); - -@@ -360,14 +402,28 @@ void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm) - if (IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN)) - ttbr0 |= FIELD_PREP(TTBR_ASID_MASK, asid); - -- /* Set ASID in TTBR1 since TCR.A1 is set */ -+ #ifdef CONFIG_IEE -+ ttbr0 |= FIELD_PREP(TTBR_ASID_MASK, asid+1); -+ iee_rwx_gate_entry(IEE_CONTEXT_SWITCH, ttbr0); -+ // TODO : if defined CONFIG_IEE and defined CONFIG_KOI -+ #else -+ /* Set ASID in TTBR0 since TCR.A1 is set 0*/ ++void koi_unmap_pmd_range(struct mm_struct *ko_mm, pud_t *pud, ++ unsigned long addr, unsigned long end) ++{ ++ pmd_t *pmd, *orig_pmd; ++ unsigned long next; ++ if (!pud) ++ return; ++ orig_pmd = pmd_offset(pud, addr); ++ pmd = orig_pmd; ++ debug_printk("pud=0x%16llx, addr=0x%16llx, end=0x%16llx\n", pud, addr, ++ end); ++ // printk(KERN_ERR "pud_pfn=0x%16llx, pmd_pfn=0x%16llx\n", pud_pfn(*pud), pmd_pfn(*pmd)); ++ do { ++ debug_printk(KERN_ERR "pmd=0x%16llx, pmd_val=0x%16llx\n", pmd, pmd_val(*pmd)); ++ next = pmd_addr_end(addr, end); ++ if (pmd_none(*pmd)) ++ continue; ++ if (pmd_bad(*pmd)) { ++ set_pmd(pmd, __pmd(0)); ++ continue; ++ } ++ koi_unmap_pte_table(ko_mm, pmd, addr, next); ++ } while (pmd++, addr = next, addr != end); ++} + -+ #ifdef CONFIG_KOI -+ ttbr0 |= FIELD_PREP(TTBR_ASID_MASK, asid+1); -+ ttbr1 &= ~TTBR_ASID_MASK; -+ ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); -+ #else - ttbr1 &= ~TTBR_ASID_MASK; - ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); -- -+ -+ #endif - cpu_set_reserved_ttbr0_nosync(); - write_sysreg(ttbr1, ttbr1_el1); - write_sysreg(ttbr0, ttbr0_el1); - isb(); -+ #endif -+ - post_ttbr_update_workaround(); - } - -@@ -375,11 +431,21 @@ static int asids_update_limit(void) - { - unsigned long num_available_asids = NUM_USER_ASIDS; - -- if (arm64_kernel_unmapped_at_el0()) { -- num_available_asids /= 2; -- if (pinned_asid_map) -- set_kpti_asid_bits(pinned_asid_map); -- } -+ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) -+ num_available_asids /= 2; -+ if (pinned_asid_map) { -+ unsigned int len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long); -+ memset(pinned_asid_map, 0xaa, len); -+ __set_bit(INIT_ASID, pinned_asid_map); ++void koi_unmap_pud_range(struct mm_struct *ko_mm, p4d_t *p4d, ++ unsigned long addr, unsigned long end) ++{ ++ pud_t *pud, *orig_pud; ++ unsigned long next; ++ if (!p4d) ++ return; ++ orig_pud = pud_offset(p4d, addr); ++ pud = orig_pud; ++ debug_printk("p4d=0x%16llx, addr=0x%16llx, end=0x%16llx\n", p4d, addr, ++ end); ++ do { ++ // printk(KERN_ERR "pud=0x%16llx, pud_val=0x%16llx\n", pud, pud_val(*pud)); ++ next = pud_addr_end(addr, end); ++ if (pud_none(*pud)) ++ continue; ++ if (pud_bad(*pud)) { ++ set_pud(pud, __pud(0)); ++ continue; + } -+ #else -+ if (arm64_kernel_unmapped_at_el0()) { -+ num_available_asids /= 2; -+ if (pinned_asid_map) -+ set_kpti_asid_bits(pinned_asid_map); -+ } -+ #endif ++ koi_unmap_pmd_range(ko_mm, pud, addr, next); ++ } while (pud++, addr = next, addr != end); ++ debug_printk("free pud 0x%16llx, p4d=0x%16llx, orig_pud=0x%16llx\n", ++ pud, p4d, orig_pud); ++ // pud_free(ko_mm, (unsigned long)orig_pud & PAGE_MASK); ++} + - /* - * Expect allocation after rollover to fail if we don't have at least - * one more ASID than CPUs. ASID #0 is reserved for init_mm. -@@ -400,6 +466,10 @@ arch_initcall(asids_update_limit); - - static int asids_init(void) - { -+ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) -+ unsigned int len; -+ #endif ++void koi_unmap_p4d_range(struct mm_struct *ko_mm, pgd_t *pgd, ++ unsigned long addr, unsigned long end) ++{ ++ p4d_t *p4d, *orig_p4d; ++ unsigned long next; ++ if (!pgd) ++ return; ++ debug_printk("pgd=0x%16llx, addr=0x%16llx, end=0x%16llx\n", pgd, addr, ++ end); ++ orig_p4d = p4d_offset(pgd, addr); ++ p4d = orig_p4d; ++ do { ++ next = p4d_addr_end(addr, end); ++ debug_printk(KERN_ERR "p4d=0x%16llx, p4d_val=0x%16llx, p4d_none=%d\n", p4d, p4d_val(*p4d), p4d_none(*p4d)); ++ if (p4d_none_or_clear_bad(p4d)) { ++ // printk(KERN_ERR "p4d none=%d, p4d_bad=%d\n", p4d_none(*p4d), p4d_bad(*p4d)); ++ continue; ++ } ++ koi_unmap_pud_range(ko_mm, p4d, addr, next); ++ } while (p4d++, addr = next, addr != end); ++} + - asid_bits = get_cpu_asid_bits(); - atomic64_set(&asid_generation, ASID_FIRST_VERSION); - asid_map = bitmap_zalloc(NUM_USER_ASIDS, GFP_KERNEL); -@@ -410,6 +480,11 @@ static int asids_init(void) - pinned_asid_map = bitmap_zalloc(NUM_USER_ASIDS, GFP_KERNEL); - nr_pinned_asids = 0; - -+ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) -+ len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long); -+ memset(asid_map, 0xaa, len); -+ __set_bit(INIT_ASID, asid_map); -+ #else - /* - * We cannot call set_reserved_asid_bits() here because CPU - * caps are not finalized yet, so it is safer to assume KPTI -@@ -417,6 +492,8 @@ static int asids_init(void) - */ - if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) - set_kpti_asid_bits(asid_map); -+ #endif ++void koi_unmap_pagetable(struct mm_struct *ko_mm, pgd_t *ko_pg_dir, ++ unsigned long addr, unsigned long end) ++{ ++ unsigned long next; ++ pgd_t *pgd = pgd_offset_pgd(ko_pg_dir, addr); ++ debug_printk("freepagetable addr=0x%16llx, end=0x%16llx\n", addr, end); ++ do { ++ next = pgd_addr_end(addr, end); ++ // printk(KERN_ERR "pgd=0x%16llx, pgd_val=0x%16llx\n", pgd, pgd_val(*pgd)); ++ if (pgd_none_or_clear_bad(pgd)) { ++ // printk(KERN_ERR "pgd none\n"); ++ continue; ++ } ++ koi_unmap_p4d_range(ko_mm, pgd, addr, next); ++ } while (pgd++, addr = next, addr != end); ++} + - return 0; - } - early_initcall(asids_init); -diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c -index 4ea07caba71c..de1d57c2b30f 100644 ---- a/arch/arm64/mm/fault.c -+++ b/arch/arm64/mm/fault.c -@@ -261,7 +261,11 @@ int __ptep_set_access_flags(struct vm_area_struct *vma, - pteval ^= PTE_RDONLY; - pteval |= pte_val(entry); - pteval ^= PTE_RDONLY; -+ #ifdef CONFIG_PTP -+ pteval = iee_set_cmpxchg_relaxed(ptep, old_pteval, pteval); -+ #else - pteval = cmpxchg_relaxed(&pte_val(*ptep), old_pteval, pteval); -+ #endif - } while (pteval != old_pteval); - - /* Invalidate a stale read-only entry */ -@@ -376,8 +380,13 @@ static void do_tag_recovery(unsigned long addr, unsigned long esr, - * It will be done lazily on the other CPUs when they will hit a - * tag fault. - */ -+ #ifdef CONFIG_IEE -+ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_EL1_TCF_MASK, -+ SYS_FIELD_PREP_ENUM(SCTLR_EL1, TCF, NONE)); -+ #else - sysreg_clear_set(sctlr_el1, SCTLR_EL1_TCF_MASK, - SYS_FIELD_PREP_ENUM(SCTLR_EL1, TCF, NONE)); -+ #endif - isb(); - } - -diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c -index bfc02568805a..580ecb596d2d 100644 ---- a/arch/arm64/mm/fixmap.c -+++ b/arch/arm64/mm/fixmap.c -@@ -32,6 +32,22 @@ static pte_t bm_pte[NR_BM_PTE_TABLES][PTRS_PER_PTE] __page_aligned_bss; - static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused; - static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused; - -+#ifdef CONFIG_IEE -+void *bm_pte_addr = (void *)bm_pte; -+void *bm_pmd_addr = (void *)bm_pmd; -+void *bm_pud_addr = (void *)bm_pud; -+#endif ++void koi_remove_pte_range(struct mm_struct *ko_mm, pgd_t *ko_pg_dir, pmd_t *pmd) ++{ ++ pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd); ++ debug_printk( ++ "pte=0x%16llx, page=0x%16llx, pmd=0x%16llx, pmd_val=0x%16llx\n", ++ pte, pte_page(pmd_pte(*pmd)), pmd, pmd_val(*pmd)); ++ // printk(KERN_ERR "pte=0x%16llx, pte_val=0x%16llx, pte_page=0x%16llx\n", pte, pte_val(*pte), pte_page(*pte)); ++ printk(KERN_ERR "free orig_pte=0x%16llx\n", pte); ++ pte_free_kernel(ko_mm, pte); ++ // __free_page((unsigned long)pte_page(pmd_pte(*pmd))); ++ // free_page((unsigned long)pte); ++} ++ ++void koi_remove_pmd_range(struct mm_struct *ko_mm, pgd_t *ko_pg_dir, pud_t *pud) ++{ ++ pmd_t *orig_pmd = pud_pgtable(*pud); ++ pmd_t *pmd; ++ int i; ++ for (i = 0; i < PTRS_PER_PMD; i++) { ++ pmd = orig_pmd + i; ++ if (pmd_none(*pmd) || pmd_bad(*pmd)) ++ continue; ++ debug_printk("pmd=0x%16llx, pmd_val=0x%16llx\n", pmd, ++ pmd_val(*pmd)); ++ koi_remove_pte_range(ko_mm, ko_pg_dir, pmd); ++ } ++ debug_printk("free pmd=0x%16llx, page=0x%16llx\n", orig_pmd, ++ pte_page(pud_pte(*pud))); ++ printk(KERN_ERR "free orig_pmd=0x%16llx\n", orig_pmd); ++ pmd_free(ko_mm, orig_pmd); ++ // free_page((unsigned long)orig_pmd); ++} + -+#ifdef CONFIG_PTP -+extern void __iee_p4d_populate_pre_init(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot); -+extern void __iee_pud_populate_pre_init(pud_t *pudp, phys_addr_t pmdp, pudval_t prot); -+extern void __iee_pmd_populate_pre_init(pmd_t *pmdp, phys_addr_t ptep, -+ pmdval_t prot); ++void koi_remove_pud_range(struct mm_struct *ko_mm, pgd_t *ko_pg_dir, p4d_t *p4d) ++{ ++ pud_t *orig_pud = p4d_pgtable(*p4d); ++ pud_t *pud; ++ int i; ++ for (i = 0; i < PTRS_PER_PUD; i++) { ++ pud = orig_pud + i; ++ if (pud_none(*pud) || pud_bad(*pud)) ++ continue; ++ debug_printk("pud=0x%16llx, pud_val=0x%16llx\n", pud, ++ pud_val(*pud)); ++ koi_remove_pmd_range(ko_mm, ko_pg_dir, pud); ++ } ++ debug_printk("free pud=0x%16llx, page=0x%16llx\n", orig_pud, ++ pte_page(p4d_pte(*p4d))); ++ printk(KERN_ERR "free orig_pud=0x%16llx\n", orig_pud); ++ pud_free(ko_mm, orig_pud); ++ // free_page((unsigned long)orig_pud); ++} + -+extern void iee_set_p4d_pre_init(p4d_t *p4dp, p4d_t p4d); -+#define set_pgd_init(pgdptr, pgdval) iee_set_p4d_pre_init((p4d_t *)(pgdptr), (p4d_t) { pgdval }) -+#endif ++void koi_remove_pagetable(struct mm_struct *ko_mm, pgd_t *ko_pg_dir) ++{ ++ pgd_t *pgd; ++ int i; ++ for (i = 0; i < PTRS_PER_PGD; i++) { ++ pgd = ko_pg_dir + i; ++ if (p4d_none(*(p4d_t *)pgd) || p4d_bad(*(p4d_t *)pgd)) ++ continue; ++ debug_printk("pgd=0x%16llx, pgd_val=0x%16llx\n", pgd, ++ pgd_val(*pgd)); ++ koi_remove_pud_range(ko_mm, ko_pg_dir, (p4d_t *)pgd); ++ } ++ debug_printk("free pgd=0x%16llx\n", ko_pg_dir); ++ pgd_free(ko_mm, ko_pg_dir); ++ flush_tlb_all(); ++} + - static inline pte_t *fixmap_pte(unsigned long addr) - { - return &bm_pte[BM_PTE_TABLE_IDX(addr)][pte_index(addr)]; -@@ -44,7 +60,11 @@ static void __init early_fixmap_init_pte(pmd_t *pmdp, unsigned long addr) - - if (pmd_none(pmd)) { - ptep = bm_pte[BM_PTE_TABLE_IDX(addr)]; -+ #ifdef CONFIG_PTP -+ __iee_pmd_populate_pre_init(pmdp, __pa_symbol(ptep), PMD_TYPE_TABLE); -+ #else - __pmd_populate(pmdp, __pa_symbol(ptep), PMD_TYPE_TABLE); -+ #endif - } - } - -@@ -55,8 +75,13 @@ static void __init early_fixmap_init_pmd(pud_t *pudp, unsigned long addr, - pud_t pud = READ_ONCE(*pudp); - pmd_t *pmdp; - -- if (pud_none(pud)) -+ if (pud_none(pud)) { -+ #ifdef CONFIG_PTP -+ __iee_pud_populate_pre_init(pudp, __pa_symbol(bm_pmd), PUD_TYPE_TABLE); -+ #else - __pud_populate(pudp, __pa_symbol(bm_pmd), PUD_TYPE_TABLE); -+ #endif ++void koi_destroy_pagetable(struct module *mod) ++{ ++ // int cpu; ++ // unsigned long *ptr; ++ struct koi_mem_hash_node *target = NULL; ++ struct koi_mem_list *mem_node; ++ struct koi_addr_map *addr_map_node; ++ unsigned long bkt; ++ unsigned long vbar; ++ unsigned long flags; ++ asm volatile("mrs %0, VBAR_EL1\n" : "=r"(vbar) :); ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) { ++ break; ++ } + } - - pmdp = pmd_offset_kimg(pudp, addr); - do { -@@ -82,8 +107,13 @@ static void __init early_fixmap_init_pud(p4d_t *p4dp, unsigned long addr, - BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES)); - } - -- if (p4d_none(p4d)) -+ if (p4d_none(p4d)) { -+ #ifdef CONFIG_PTP -+ __iee_p4d_populate_pre_init(p4dp, __pa_symbol(bm_pud), P4D_TYPE_TABLE); -+ #else - __p4d_populate(p4dp, __pa_symbol(bm_pud), P4D_TYPE_TABLE); -+ #endif ++ rcu_read_unlock(); ++ if (target == NULL) { ++ // printk(KERN_ERR "mem node for module: %s not found, maybe destroyed before?\n", ++ // mod->name); ++ return; + } - - pudp = pud_offset_kimg(p4dp, addr); - early_fixmap_init_pmd(pudp, addr, end); -@@ -106,6 +136,27 @@ void __init early_fixmap_init(void) - early_fixmap_init_pud(p4dp, addr, end); - } - -+#ifdef CONFIG_PTP -+extern void iee_set_pte_pre_init(pte_t *ptep, pte_t pte); -+void __iee_set_fixmap_pre_init(enum fixed_addresses idx, -+ phys_addr_t phys, pgprot_t flags) -+{ -+ unsigned long addr = __fix_to_virt(idx); -+ pte_t *ptep; ++ spin_lock_irqsave(&target->mod_lock, flags); ++ target->is_valid = false; ++ spin_unlock_irqrestore(&target->mod_lock, flags); ++ ++ spin_lock_irqsave(&koi_mem_htbl_spin_lock, flags); ++ hash_del_rcu(&target->node); ++ call_rcu(&target->rcu, koi_mem_hash_node_free); ++ spin_unlock_irqrestore(&koi_mem_htbl_spin_lock, flags); ++ ++ // free addr_htbl ++ spin_lock(&target->addr_htbl_spin_lock); ++ hash_for_each_rcu (target->addr_htbl, bkt, addr_map_node, node) { ++ hash_del_rcu(&addr_map_node->node); ++ call_rcu(&addr_map_node->rcu, koi_addr_map_node_free); ++ } ++ spin_unlock(&target->addr_htbl_spin_lock); ++ // free free mem list ++ spin_lock(&target->spin_lock); ++ list_for_each_entry_rcu (mem_node, &target->mem_list_head, list) { ++ list_del_rcu(&mem_node->list); ++ call_rcu(&mem_node->rcu, koi_mem_node_free); ++ } ++ spin_unlock(&target->spin_lock); + -+ BUG_ON(idx <= FIX_HOLE || idx >= __end_of_fixed_addresses); ++ koi_remove_pagetable(target->ko_mm, target->ko_mm->pgd); ++ kfree(target->ko_mm); ++} + -+ ptep = fixmap_pte(addr); ++/** ++* koi_create_pagetable - create pagetable for driver ++* @mod: driver module ++* 1.create a new koi_mem_hash_node new_node ++* 2.create page table return the pgd address, init the new_node->pgdp ++* 3.create and init the new_node->ko_mm ++* 4.map swapper_ttbr1 to the newly created pagetable ++* 5.map the interrupt vector table to the newly created pagetable ++* 6.map the init_layout of the module ++* 7.map the core_layout of the module ++* 8.map switch_to_kernel_pgtable into driver view ++* 9.map share memory ++*/ ++void koi_create_pagetable(struct module *mod) ++{ ++ int ret = 0, cpu; ++ unsigned long vbar, addr, ttbr1; ++ pgd_t *pgdp; ++ unsigned long *ptr; ++ struct koi_mem_list *new_mem_node; ++ struct koi_mem_hash_node *new_node = ++ kzalloc(sizeof(struct koi_mem_hash_node), GFP_KERNEL); ++ if (!new_node) { ++ // printk(KERN_ERR "NULL new_node\n"); ++ return; ++ }; ++ if (koi_swapper_ttbr1 == 0) { ++ pgdp = lm_alias(swapper_pg_dir); ++ ttbr1 = phys_to_ttbr(virt_to_phys(pgdp)); ++ if (system_supports_cnp() && ++ !WARN_ON(pgdp != lm_alias(swapper_pg_dir))) ++ ttbr1 |= TTBR_CNP_BIT; + -+ if (pgprot_val(flags)) { -+ iee_set_pte_pre_init(ptep, pfn_pte(phys >> PAGE_SHIFT, flags)); -+ } else { -+ iee_set_pte_pre_init(ptep, __pte(0)); -+ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); ++ koi_swapper_ttbr1 = ttbr1; ++ // __WRITE_ONCE(koi_swapper_ttbr1, ttbr1); ++ // koi_set_rdonly(&koi_swapper_ttbr1, swapper_pg_dir); + } -+} -+#endif -+ - /* - * Unusually, this is also called in IRQ context (ghes_iounmap_irq) so if we - * ever need to use IPIs for TLB broadcasting, then we're in trouble here. -@@ -121,9 +172,17 @@ void __set_fixmap(enum fixed_addresses idx, - ptep = fixmap_pte(addr); - - if (pgprot_val(flags)) { -+ #ifdef CONFIG_PTP -+ iee_set_bm_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, flags)); -+ #else - __set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, flags)); -+ #endif - } else { -+ #ifdef CONFIG_PTP -+ iee_set_bm_pte(ptep, __pte(0)); -+ #else - __pte_clear(&init_mm, addr, ptep); -+ #endif - flush_tlb_kernel_range(addr, addr+PAGE_SIZE); - } - } -@@ -179,8 +238,13 @@ void __init fixmap_copy(pgd_t *pgdir) - * live in the carveout for the swapper_pg_dir. We can simply - * re-use the existing dir for the fixmap. - */ -+ #ifdef CONFIG_PTP -+ set_pgd_init(pgd_offset_pgd(pgdir, FIXADDR_TOT_START), -+ READ_ONCE(*pgd_offset_k(FIXADDR_TOT_START))); -+ #else - set_pgd(pgd_offset_pgd(pgdir, FIXADDR_TOT_START), - READ_ONCE(*pgd_offset_k(FIXADDR_TOT_START))); -+ #endif - } else if (CONFIG_PGTABLE_LEVELS > 3) { - pgd_t *bm_pgdp; - p4d_t *bm_p4dp; -@@ -194,9 +258,15 @@ void __init fixmap_copy(pgd_t *pgdir) - BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES)); - bm_pgdp = pgd_offset_pgd(pgdir, FIXADDR_TOT_START); - bm_p4dp = p4d_offset(bm_pgdp, FIXADDR_TOT_START); -+ #ifdef CONFIG_PTP -+ bm_pudp = pud_set_fixmap_offset_init(bm_p4dp, FIXADDR_TOT_START); -+ __iee_pud_populate_pre_init(bm_pudp, __pa(lm_alias(bm_pmd)), PMD_TYPE_TABLE); -+ pud_clear_fixmap_init(); -+ #else - bm_pudp = pud_set_fixmap_offset(bm_p4dp, FIXADDR_TOT_START); - pud_populate(&init_mm, bm_pudp, lm_alias(bm_pmd)); - pud_clear_fixmap(); -+ #endif - } else { - BUG(); - } -diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c -index 8c8d7653ba84..4190f5c10d68 100644 ---- a/arch/arm64/mm/init.c -+++ b/arch/arm64/mm/init.c -@@ -55,8 +55,19 @@ - * that cannot be mistaken for a real physical address. - */ - s64 memstart_addr __ro_after_init = -1; -+#if defined(CONFIG_IEE) || defined(CONFIG_KOI) -+s64 memstart_addr_init __ro_after_init = -1; -+#endif -+#ifdef CONFIG_KOI -+s64 koi_offset __ro_after_init = -1; -+EXPORT_SYMBOL(koi_offset); -+#endif ++ new_node->pgdp = koi_pgd_alloc(); ++ new_node->ko_mm = ++ kzalloc(sizeof(struct mm_struct) + ++ sizeof(unsigned long) * BITS_TO_LONGS(NR_CPUS), ++ GFP_KERNEL); ++ init_ko_mm(new_node->ko_mm, new_node->pgdp); ++ new_node->mod = mod; ++ koi_save_ttbr(mod, new_node->pgdp, new_node); ++ debug_printk("copying koi_data, start=0x%16llx, end=0x%16llx\n", ++ (unsigned long)__koi_data_start, ++ (unsigned long)__koi_data_end); ++ // copy koi_swapper_ttbr1, which records page dir base for kernel view ++ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, ++ (unsigned long)__koi_data_start, ++ (unsigned long)__koi_data_end, (0)); ++ asm volatile("mrs %0, VBAR_EL1\n" : "=r"(vbar) :); ++ ++ // copy interrupt vectors ++ printk(KERN_ERR ++ "\033[33mcopying interrupt vectors, start=0x%16llx, end=0x%16llx, vbar=0x%16llx\033[0m\n", ++ vbar & PAGE_MASK, (vbar + PAGE_SIZE) & PAGE_MASK, vbar); ++ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, vbar & PAGE_MASK, ++ (vbar + PAGE_SIZE) & PAGE_MASK, (0)); ++ ++ for_each_mod_mem_type(type) { ++ printk(KERN_ERR "\033[33mcopying mem range, start=0x%16llx, end=0x%16llx\033[0m\n", ++ (unsigned long)mod->mem[type].base, ++ (unsigned long)mod->mem[type].base + mod->mem[type].size); ++ if (!mod->mem[type].base || !mod->mem[type].size) { ++ continue; ++ } ++ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, (unsigned long)mod->mem[type].base, (unsigned long)mod->mem[type].base + mod->mem[type].size, (0)); ++ if (ret != 0) ++ printk(KERN_ERR ++ "\033[33mError occured when copying range from 0x%llx to 0x%llx, Eno:%d\033[0m\n", ++ (unsigned long)mod->mem[type].base, ++ (unsigned long)mod->mem[type].base + mod->mem[type].size, ++ ret); ++ } ++ ++ // mapping switch_to_kernel_pgtable into driver view, which is used to switch to kernel view when entering INT ++ printk(KERN_ERR "\033[33mcopying koi_code_range, start=0x%16llx, end=0x%16llx\033[0m\n", ++ (unsigned long)__koi_code_start, ++ (unsigned long)__koi_code_end); ++ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, ++ (unsigned long)__koi_code_start, ++ (unsigned long)__koi_code_end, (0)); ++ ++ for_each_possible_cpu (cpu) { ++ ptr = per_cpu(irq_stack_ptr, cpu); ++ debug_printk( ++ "\033[33mirq_stack_ptr on cpu %d addr=0x%16llx, end=0x%16llx\033[0m\n", ++ cpu, (unsigned long)ptr, ++ (unsigned long)ptr + IRQ_STACK_SIZE); ++ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, ++ (unsigned long)ptr, ++ (unsigned long)ptr + IRQ_STACK_SIZE, (0)); ++ } ++ ++ for_each_possible_cpu (cpu) { ++ ptr = per_cpu(koi_irq_current_ttbr1, cpu); ++ debug_printk( ++ "\033[33mirq_current_ptr on cpu %d addr=0x%16llx, end=0x%16llx\033[0m\n", ++ cpu, (unsigned long)ptr, ++ (unsigned long)ptr + PAGE_SIZE); ++ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, ++ (unsigned long)ptr, ++ (unsigned long)ptr + PAGE_SIZE, (0)); ++ } ++ +#ifdef CONFIG_IEE -+s64 iee_offset __ro_after_init = -1; ++ debug_printk("\033[33miee_si addr=0x%16llx, end=0x%16llx\033[0m\n", ++ (unsigned long)__iee_si_data_start, ++ (unsigned long)__iee_si_text_start); ++ // mapping iee_rwx_gate_entry and iee_si_base to ko's pagetable ++ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, ++ (unsigned long)__iee_si_data_start, ++ (unsigned long)__iee_si_text_start, (0)); ++ debug_printk("\033[33miee_si mapping finished\n"); +#endif - EXPORT_SYMBOL(memstart_addr); - + - /* - * If the corresponding config options are enabled, we create both ZONE_DMA - * and ZONE_DMA32. By default ZONE_DMA covers the 32-bit addressable memory -@@ -421,7 +432,11 @@ early_param("memmap", parse_memmap_opt); - - void __init arm64_memblock_init(void) - { -+ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) -+ s64 linear_region_size = BIT(vabits_actual - 2); -+ #else - s64 linear_region_size = PAGE_END - _PAGE_OFFSET(vabits_actual); -+ #endif - - /* - * Corner case: 52-bit VA capable systems running KVM in nVHE mode may -@@ -438,13 +453,24 @@ void __init arm64_memblock_init(void) - } - - /* Remove memory above our supported physical address size */ -+ #ifdef CONFIG_IEE -+ // If config iee, phys size can not be above 0x400000000000 -+ if(__pa_symbol(_end) > BIT_ULL(vabits_actual - 2)) -+ panic("Image on too high phys mem.\n"); -+ else -+ memblock_remove(BIT_ULL(vabits_actual - 2), ULLONG_MAX); -+ #else - memblock_remove(1ULL << PHYS_MASK_SHIFT, ULLONG_MAX); -+ #endif - - /* - * Select a suitable value for the base of physical memory. - */ - memstart_addr = round_down(memblock_start_of_DRAM(), - ARM64_MEMSTART_ALIGN); -+ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) -+ memstart_addr_init = memstart_addr; -+ #endif - - if ((memblock_end_of_DRAM() - memstart_addr) > linear_region_size) - pr_warn("Memory doesn't fit in the linear mapping, VA_BITS too small\n"); -@@ -531,6 +557,14 @@ void __init arm64_memblock_init(void) - ((range * memstart_offset_seed) >> 16); - } - } -+ -+ #ifdef CONFIG_KOI -+ koi_offset = memstart_addr - memstart_addr_init + KOI_OFFSET; -+ #endif -+ #ifdef CONFIG_IEE -+ iee_offset = memstart_addr - memstart_addr_init + ((unsigned long)BIT(vabits_actual - 2)); -+ #endif -+ //printk(KERN_ERR "koi_offset: 0x%16llx\n", koi_offset); - - /* - * Register the kernel text, kernel data, initrd, and initial -diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c -index 4142a75a414e..094f3798441d 100644 ---- a/arch/arm64/mm/mmu.c -+++ b/arch/arm64/mm/mmu.c -@@ -6,6 +6,7 @@ - * Copyright (C) 2012 ARM Ltd. - */ - -+#include "asm/pgtable.h" - #include - #include - #include -@@ -40,6 +41,11 @@ - #include - #include - #include ++ // alloc 16KB memory for new ko, and add it into hashtable ++ addr = (unsigned long)kmalloc(THREAD_SIZE, GFP_KERNEL); ++ if ((void *)addr == NULL) { ++ printk(KERN_ERR "alloc buffer error\n"); ++ } ++ debug_printk( ++ "\033[33mcopying buffer, start=0x%16llx, end=0x%16llx\033[0m\n", ++ addr, addr + THREAD_SIZE); ++ koi_copy_pagetable(new_node->ko_mm, new_node->pgdp, addr, ++ addr + THREAD_SIZE, (0)); +#ifdef CONFIG_IEE -+#include -+#include -+#include ++ iee_rw_gate(IEE_SET_KOI_PGD, new_node->ko_mm->pgd); +#endif - - #define NO_BLOCK_MAPPINGS BIT(0) - #define NO_CONT_MAPPINGS BIT(1) -@@ -76,8 +82,282 @@ EXPORT_SYMBOL(empty_zero_page); - static DEFINE_SPINLOCK(swapper_pgdir_lock); - static DEFINE_MUTEX(fixmap_lock); - -+#ifdef CONFIG_IEE -+extern struct cred init_cred; -+ -+extern unsigned long init_iee_stack_begin[]; -+extern unsigned long init_iee_stack_end[]; -+extern unsigned long __iee_si_data_start[]; -+extern unsigned long __iee_exec_entry_start[]; -+extern unsigned long __iee_si_start[]; -+extern unsigned long __iee_si_end[]; ++ new_mem_node = kmalloc(sizeof(struct koi_mem_list), GFP_KERNEL); ++ if (new_mem_node == NULL) { ++ printk(KERN_ERR "alloc new_mem_node error\n"); ++ } ++ new_mem_node->addr = addr; ++ new_mem_node->size = THREAD_SIZE; + -+extern void *bm_pte_addr; -+extern void *bm_pmd_addr; -+extern void *bm_pud_addr; ++ new_node->mem_list_head = ++ (struct list_head)LIST_HEAD_INIT(new_node->mem_list_head); ++ hash_init(new_node->addr_htbl); ++ spin_lock_init(&new_node->addr_htbl_spin_lock); ++ spin_lock_init(&new_node->spin_lock); ++ spin_lock_init(&new_node->mod_lock); ++ new_node->is_valid = true; + -+#ifdef CONFIG_PTP ++ spin_lock(&new_node->spin_lock); ++ list_add_rcu(&new_mem_node->list, &new_node->mem_list_head); ++ spin_unlock(&new_node->spin_lock); + -+/* Funcs to set pgtable before iee initialized. */ -+static void iee_set_swapper_pgd_pre_init(pgd_t *pgdp, pgd_t pgd) -+{ -+ pgd_t *fixmap_pgdp; ++ spin_lock(&koi_mem_htbl_spin_lock); ++ hash_add_rcu(koi_mem_htbl, &new_node->node, ++ (unsigned long)new_node->mod); ++ spin_unlock(&koi_mem_htbl_spin_lock); + -+ spin_lock(&swapper_pgdir_lock); -+ fixmap_pgdp = pgd_set_fixmap_init(__pa_symbol(pgdp)); -+ WRITE_ONCE(*fixmap_pgdp, pgd); -+ /* -+ * We need dsb(ishst) here to ensure the page-table-walker sees -+ * our new entry before set_p?d() returns. The fixmap's -+ * flush_tlb_kernel_range() via clear_fixmap() does this for us. -+ */ -+ pgd_clear_fixmap_init(); -+ spin_unlock(&swapper_pgdir_lock); ++ // printk(KERN_DEBUG "mod=0x%16llx, end=0x16llx\n", mod, (unsigned long)mod + sizeof(struct module)); ++ printk(KERN_ERR "[KOI] create pagetable pgd=0x%16llx for module %s\n", new_node->pgdp, mod->name); ++ // printk(KERN_ERR "koi mm=0x%16llx\n", (unsigned long)(new_node->ko_mm)); +} -+ -+void iee_set_p4d_pre_init(p4d_t *p4dp, p4d_t p4d) ++/** ++* koi_mem_alloc ++*@mod: driver module ++*@orig_addr: the starting address of the parameter in kernel ++*@size: the size of the parameter ++*/ ++unsigned long koi_mem_alloc(struct module *mod, unsigned long orig_addr, ++ unsigned long size) +{ -+ if (in_swapper_pgdir(p4dp)) { -+ iee_set_swapper_pgd_pre_init((pgd_t *)p4dp, __pgd(p4d_val(p4d))); -+ return; ++ struct koi_mem_hash_node *target = NULL; ++ struct koi_mem_list *mem_node; ++ struct koi_addr_map *new_addr_node; ++ unsigned long addr = 0, flags; ++ struct koi_mem_list *new_mem_node; ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) { ++ break; ++ } + } -+ -+ WRITE_ONCE(*p4dp, p4d); -+ dsb(ishst); -+ isb(); -+} -+ -+static inline void iee_set_pud_pre_init(pud_t *pudp, pud_t pud) -+{ -+#ifdef __PAGETABLE_PUD_FOLDED -+ if (in_swapper_pgdir(pudp)) { -+ iee_set_swapper_pgd_pre_init((pgd_t *)pudp, __pgd(pud_val(pud))); -+ return; ++ rcu_read_unlock(); ++ if (target == NULL) { ++ printk(KERN_ERR "mem node for module: %s not found\n", ++ mod->name); ++ return 0; + } -+#endif /* __PAGETABLE_PUD_FOLDED */ -+#ifdef CONFIG_KOI -+ pudval_t val = pud_val(pud); -+ if (pud_valid(pud) && !(val & PUD_TABLE_BIT)) { -+ // There is no PUD_SEC_NG, so we use PMD_SECT_NG instead. -+ pud = __pud(val | PMD_SECT_NG); -+ } -+#endif -+ WRITE_ONCE(*pudp, pud); -+ -+ if (pud_valid(pud)) { -+ dsb(ishst); -+ isb(); ++ spin_lock_irqsave(&target->spin_lock, flags); ++ list_for_each_entry_rcu (mem_node, &target->mem_list_head, list) { ++ if (mem_node->size >= size) { ++ addr = mem_node->addr; ++ mem_node->size -= size; ++ if (mem_node->size == 0) { ++ list_del_rcu(&mem_node->list); ++ } else { ++ new_mem_node = ++ kmalloc(sizeof(struct koi_mem_list), ++ GFP_ATOMIC); ++ new_mem_node->addr = addr + size; ++ new_mem_node->size = mem_node->size; ++ list_replace_rcu(&mem_node->list, ++ &new_mem_node->list); ++ } ++ call_rcu(&mem_node->rcu, koi_mem_node_free); ++ } + } -+} -+ -+static inline void iee_set_pmd_pre_init(pmd_t *pmdp, pmd_t pmd) -+{ -+#ifdef __PAGETABLE_PMD_FOLDED -+ if (in_swapper_pgdir(pmdp)) { -+ iee_set_swapper_pgd_pre_init((pgd_t *)pmdp, __pgd(pmd_val(pmd))); -+ return; ++ spin_unlock_irqrestore(&target->spin_lock, flags); ++ if (!addr) { ++ addr = (unsigned long)kmalloc(THREAD_SIZE, GFP_KERNEL); ++ if ((void *)addr == NULL) { ++ return 0; ++ } ++ koi_copy_pagetable(target->ko_mm, target->pgdp, addr, ++ addr + THREAD_SIZE, (0)); ++ mem_node = kmalloc(sizeof(struct koi_mem_list), GFP_KERNEL); ++ if (!mem_node) { ++ printk(KERN_ERR "NULL mem_node\n"); ++ } ++ if (size > THREAD_SIZE) { ++ return 0; ++ } ++ mem_node->addr = addr + size; ++ mem_node->size = THREAD_SIZE - size; ++ spin_lock_irqsave(&target->spin_lock, flags); ++ list_add_tail_rcu(&mem_node->list, &target->mem_list_head); ++ spin_unlock_irqrestore(&target->spin_lock, flags); + } -+#endif /* __PAGETABLE_PMD_FOLDED */ -+#ifdef CONFIG_KOI -+ pmdval_t val = pmd_val(pmd); -+ if (pmd_valid(pmd) && !(val & PMD_TABLE_BIT)) { -+ pmd = __pmd(val | PMD_SECT_NG); -+ } -+#endif -+ WRITE_ONCE(*pmdp, pmd); + -+ if (pmd_valid(pmd)) { -+ dsb(ishst); -+ isb(); -+ } ++ new_addr_node = kzalloc(sizeof(struct koi_addr_map), GFP_KERNEL); ++ new_addr_node->buffer_addr = addr; ++ new_addr_node->orig_addr = orig_addr; ++ spin_lock_irqsave(&target->addr_htbl_spin_lock, flags); ++ hash_add_rcu(target->addr_htbl, &new_addr_node->node, ++ new_addr_node->buffer_addr); ++ spin_unlock_irqrestore(&target->addr_htbl_spin_lock, flags); ++ return addr; +} -+ -+ -+void __iee_p4d_populate_pre_init(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot) ++EXPORT_SYMBOL(koi_mem_alloc); ++// find the parameter pointer corresponding to the copy ++noinline void *koi_mem_lookup(struct module *mod, unsigned long addr) +{ -+ iee_set_p4d_pre_init(p4dp, __p4d(__phys_to_p4d_val(pudp) | prot)); -+} ++ struct koi_mem_hash_node *target = NULL; ++ struct koi_addr_map *addr_map_node; ++ unsigned long orig_addr = addr; ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) { ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ if (target == NULL) { ++ printk(KERN_ERR "mem node for module: %s not found\n", ++ mod->name); ++ return NULL; ++ } + -+void __iee_pud_populate_pre_init(pud_t *pudp, phys_addr_t pmdp, pudval_t prot) -+{ -+ iee_set_pud_pre_init(pudp, __pud(__phys_to_pud_val(pmdp) | prot)); ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (target->addr_htbl, addr_map_node, node, ++ orig_addr) { ++ if (addr_map_node->buffer_addr == addr) { ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ if (addr_map_node) { ++ return (void *)(addr_map_node->orig_addr); ++ } else { ++ return NULL; ++ } +} -+ -+void __iee_pmd_populate_pre_init(pmd_t *pmdp, phys_addr_t ptep, -+ pmdval_t prot) ++EXPORT_SYMBOL(koi_mem_lookup); ++/** ++* kio_mem_free - recycle a copy of the copied parameters and synchronize the parameters ++* @mod: driver module ++* @addr: the starting addr of parameter ++* @size: the size of the parameter ++* @is_const: const pointers or not ++* @count: contry the number of parameters ++*/ ++noinline void koi_mem_free(struct module *mod, unsigned long addr, ++ unsigned long size, bool is_const, int count, ...) +{ -+ iee_set_pmd_pre_init(pmdp, __pmd(__phys_to_pmd_val(ptep) | prot)); -+} ++ struct koi_mem_hash_node *target = NULL; ++ struct koi_mem_list *mem_node; ++ struct list_head *pos = NULL; ++ struct koi_addr_map *addr_map_node; ++ unsigned long orig_size = size; ++ unsigned long orig_addr = addr; ++ va_list valist; ++ int i; ++ unsigned int offset; ++ unsigned long flags; ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) { ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ if (target == NULL) { ++ printk(KERN_ERR "mem node for module: %s not found\n", ++ mod->name); ++ return; ++ } + -+/* Funcs to set fixmap before iee initialized. */ -+bool pgattr_change_is_safe(u64 old, u64 new); -+static int iee_pud_set_huge_fixmap(pud_t *pudp, phys_addr_t phys, pgprot_t prot) -+{ -+ pud_t new_pud = pfn_pud(__phys_to_pfn(phys), mk_pud_sect_prot(prot)); ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (target->addr_htbl, addr_map_node, node, ++ orig_addr) { ++ if (addr_map_node->buffer_addr == orig_addr) { ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ va_start(valist, count); ++ for (i = 0; i < count; i++) { ++ offset = va_arg(valist, int); ++ *(unsigned long *)(addr_map_node->buffer_addr + offset) = ++ *(unsigned long *)(addr_map_node->orig_addr + offset); ++ } ++ va_end(valist); ++ memcpy((void *)addr_map_node->orig_addr, ++ (void *)addr_map_node->buffer_addr, orig_size); + -+ /* Only allow permission changes for now */ -+ if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pudp)), -+ pud_val(new_pud))) -+ return 0; ++ spin_lock_irqsave(&target->addr_htbl_spin_lock, flags); ++ hlist_del_init_rcu(&addr_map_node->node); ++ call_rcu(&addr_map_node->rcu, koi_addr_map_node_free); ++ spin_unlock_irqrestore(&target->addr_htbl_spin_lock, flags); + -+ VM_BUG_ON(phys & ~PUD_MASK); -+ iee_set_fixmap_pud_pre_init(pudp, new_pud); -+ return 1; ++ spin_lock_irqsave(&target->spin_lock, flags); ++ list_for_each_entry_rcu (mem_node, &target->mem_list_head, list) { ++ if (mem_node->addr + mem_node->size == addr) { ++ pos = mem_node->list.prev; ++ addr = mem_node->addr; ++ size += mem_node->size; ++ list_del_rcu(&mem_node->list); ++ call_rcu(&mem_node->rcu, koi_mem_node_free); ++ } else if (addr + size == mem_node->addr) { ++ if (!pos) ++ pos = mem_node->list.prev; ++ size += mem_node->size; ++ list_del_rcu(&mem_node->list); ++ call_rcu(&mem_node->rcu, koi_mem_node_free); ++ } else if (addr + size < mem_node->addr) { ++ if (!pos) ++ pos = mem_node->list.prev; ++ break; ++ } ++ } ++ mem_node = kzalloc(sizeof(struct koi_mem_list), GFP_ATOMIC); ++ mem_node->addr = addr; ++ mem_node->size = size; ++ if (pos) ++ list_add_rcu(&mem_node->list, pos); ++ else ++ list_add_tail_rcu(&mem_node->list, &target->mem_list_head); ++ spin_unlock_irqrestore(&target->spin_lock, flags); +} -+ -+static int iee_pmd_set_huge_fixmap(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) ++EXPORT_SYMBOL(koi_mem_free); ++/** ++* koi_mem_free_callback - used to recycle the copy of parameter. ++*@addr: the address of the parameter ++*@(*func)(void*): callback func, used to release the copy of the parameter pointer ++*/ ++noinline void koi_mem_free_callback(struct module *mod, unsigned long addr, ++ unsigned long size, void (*func)(void *)) +{ -+ pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), mk_pmd_sect_prot(prot)); ++ struct koi_mem_hash_node *target = NULL; ++ struct koi_mem_list *mem_node; ++ struct list_head *pos = NULL; ++ struct koi_addr_map *addr_map_node; ++ unsigned long flags; ++ unsigned long orig_size = size; ++ unsigned long orig_addr = addr; ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) { ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ if (target == NULL) { ++ // printk("mem node for module: %s not found\n", mod->name); ++ return; ++ } + -+ /* Only allow permission changes for now */ -+ if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)), -+ pmd_val(new_pmd))) -+ return 0; ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (target->addr_htbl, addr_map_node, node, ++ orig_addr) { ++ if (addr_map_node->buffer_addr == orig_addr) { ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ if (addr_map_node != NULL) { ++ memcpy((void *)addr_map_node->orig_addr, ++ (void *)addr_map_node->buffer_addr, orig_size); ++ func((void *)addr_map_node->orig_addr); ++ } else { ++ printk("Cannot find addr_map_node in addr_htbl, maybe addr is in kernel space!!\n"); ++ func((void *)orig_addr); ++ } + -+ VM_BUG_ON(phys & ~PMD_MASK); -+ iee_set_fixmap_pmd_pre_init(pmdp, new_pmd); -+ return 1; ++ spin_lock_irqsave(&target->addr_htbl_spin_lock, flags); ++ if (addr_map_node != NULL) { ++ hlist_del_init_rcu(&addr_map_node->node); ++ call_rcu(&addr_map_node->rcu, koi_addr_map_node_free); ++ } ++ spin_unlock_irqrestore(&target->addr_htbl_spin_lock, flags); ++ spin_lock_irqsave(&target->spin_lock, flags); ++ list_for_each_entry_rcu (mem_node, &target->mem_list_head, list) { ++ if (mem_node->addr + mem_node->size == addr) { ++ pos = mem_node->list.prev; ++ addr = mem_node->addr; ++ size += mem_node->size; ++ list_del_rcu(&mem_node->list); ++ call_rcu(&mem_node->rcu, koi_mem_node_free); ++ } else if (addr + size == mem_node->addr) { ++ if (!pos) ++ pos = mem_node->list.prev; ++ size += mem_node->size; ++ list_del_rcu(&mem_node->list); ++ call_rcu(&mem_node->rcu, koi_mem_node_free); ++ } else if (addr + size < mem_node->addr) { ++ if (!pos) ++ pos = mem_node->list.prev; ++ break; ++ } ++ } ++ mem_node = kzalloc(sizeof(struct koi_mem_list), GFP_ATOMIC); ++ mem_node->addr = addr; ++ mem_node->size = size; ++ if (pos) ++ list_add_rcu(&mem_node->list, pos); ++ else ++ list_add_tail_rcu(&mem_node->list, &target->mem_list_head); ++ spin_unlock_irqrestore(&target->spin_lock, flags); +} ++EXPORT_SYMBOL(koi_mem_free_callback); + -+static inline void __iee_pmd_populate_fixmap(pmd_t *pmdp, phys_addr_t ptep, -+ pmdval_t prot) ++void koi_map_mem(struct module *mod, unsigned long addr, unsigned long size) +{ -+ iee_set_fixmap_pmd_pre_init(pmdp, __pmd(__phys_to_pmd_val(ptep) | prot)); -+} ++ struct koi_mem_hash_node *target = NULL; ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) ++ break; ++ } ++ rcu_read_unlock(); + -+static inline void __iee_pud_populate_fixmap(pud_t *pudp, phys_addr_t pmdp, pudval_t prot) -+{ -+ iee_set_fixmap_pud_pre_init(pudp, __pud(__phys_to_pud_val(pmdp) | prot)); ++ if (target == NULL) { ++ printk(KERN_ERR "mem node for module: %s not found\n", ++ mod->name); ++ return; ++ } ++ koi_copy_pagetable(target->ko_mm, target->pgdp, addr & PAGE_MASK, ++ (addr + size + PAGE_SIZE) & PAGE_MASK, (0)); ++ flush_tlb_kernel_range(addr & PAGE_MASK, ++ (addr + size + PAGE_SIZE) & PAGE_MASK); +} -+#endif /* END CONFIG_PTP*/ ++EXPORT_SYMBOL(koi_map_mem); + -+void iee_set_pte_pre_init(pte_t *ptep, pte_t pte) ++void koi_unmap_mem(struct module *mod, unsigned long addr, unsigned long size) +{ -+#ifdef CONFIG_KOI -+ if (!pte_none(pte)) { -+ pte = __pte(pte_val(pte) | PTE_NG); ++ struct koi_mem_hash_node *target = NULL; ++ if (!addr || ! size) { ++ return; + } -+#endif -+ WRITE_ONCE(*ptep, pte); ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) ++ break; ++ } ++ rcu_read_unlock(); + -+ /* -+ * Only if the new pte is valid and kernel, otherwise TLB maintenance -+ * or update_mmu_cache() have the necessary barriers. -+ */ -+ if (pte_valid_not_user(pte)) { -+ dsb(ishst); -+ isb(); ++ if (target == NULL) { ++ printk(KERN_ERR "[KOI UNMAP] mem node for module: %s not found\n", ++ mod->name); ++ return; + } ++ koi_unmap_pagetable(target->ko_mm, target->pgdp, addr & PAGE_MASK, ++ (addr + size + PAGE_SIZE) & PAGE_MASK); ++ flush_tlb_kernel_range(addr & PAGE_MASK, ++ (addr + size + PAGE_SIZE) & PAGE_MASK); +} -+ -+static void __init iee_set_token_page_valid_pre_init(void *token, void *new) ++EXPORT_SYMBOL(koi_unmap_mem); ++/** ++* koi_mem_free_to_user - function 'copy_to_user' in driver space ++*/ ++void koi_mem_free_to_user(struct module *mod, unsigned long addr, ++ unsigned long size) +{ -+ pgd_t *pgdir = swapper_pg_dir; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, (unsigned long)token); -+ -+ p4d_t *p4dp = p4d_offset(pgdp, (unsigned long)token); -+ -+ pud_t *pudp = pud_offset(p4dp, (unsigned long)token); ++ struct koi_mem_hash_node *target = NULL; ++ struct koi_mem_list *mem_node; ++ struct list_head *pos = NULL; ++ struct koi_addr_map *addr_map_node; ++ unsigned long flags; ++ unsigned long orig_size = size; ++ unsigned long orig_addr = addr; ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) { ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ if (target == NULL) { ++ printk(KERN_ERR "mem node for module: %s not found\n", ++ mod->name); ++ return; ++ } + -+ pmd_t *pmdp = pmd_offset(pudp, (unsigned long)token); ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (target->addr_htbl, addr_map_node, node, ++ orig_addr) { ++ if (addr_map_node->buffer_addr == orig_addr) { ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ if (copy_to_user((void *)addr_map_node->orig_addr, ++ (void *)addr_map_node->buffer_addr, orig_size)) { ++ return; ++ } + -+ pte_t *ptep = pte_offset_kernel(pmdp, (unsigned long)token); -+ pte_t pte = READ_ONCE(*ptep); -+ pte = __pte(((pte_val(pte) | 0x1) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(new))); -+ iee_set_pte_pre_init(ptep, pte); -+ flush_tlb_kernel_range((unsigned long)token, (unsigned long)(token+PAGE_SIZE)); -+ isb(); ++ spin_lock_irqsave(&target->addr_htbl_spin_lock, flags); ++ hlist_del_init_rcu(&addr_map_node->node); ++ call_rcu(&addr_map_node->rcu, koi_addr_map_node_free); ++ spin_unlock_irqrestore(&target->addr_htbl_spin_lock, flags); ++ spin_lock_irqsave(&target->spin_lock, flags); ++ list_for_each_entry_rcu (mem_node, &target->mem_list_head, list) { ++ if (mem_node->addr + mem_node->size == addr) { ++ pos = mem_node->list.prev; ++ addr = mem_node->addr; ++ size += mem_node->size; ++ list_del_rcu(&mem_node->list); ++ call_rcu(&mem_node->rcu, koi_mem_node_free); ++ } else if (addr + size == mem_node->addr) { ++ if (!pos) ++ pos = mem_node->list.prev; ++ size += mem_node->size; ++ list_del_rcu(&mem_node->list); ++ call_rcu(&mem_node->rcu, koi_mem_node_free); ++ } else if (addr + size < mem_node->addr) { ++ if (!pos) ++ pos = mem_node->list.prev; ++ break; ++ } ++ } ++ mem_node = kzalloc(sizeof(struct koi_mem_list), GFP_ATOMIC); ++ mem_node->addr = addr; ++ mem_node->size = size; ++ if (pos) ++ list_add_rcu(&mem_node->list, pos); ++ else ++ list_add_tail_rcu(&mem_node->list, &target->mem_list_head); ++ spin_unlock_irqrestore(&target->spin_lock, flags); +} -+#endif /* END CONFIG_IEE*/ -+ -+#if defined(CONFIG_KOI) && !defined(CONFIG_IEE) -+int koi_add_page_mapping(unsigned long dst, unsigned long src) ++EXPORT_SYMBOL(koi_mem_free_to_user); ++// map the driver stack to kernel ++void koi_map_kostack(struct module *mod) +{ -+ pgd_t *src_pgdp, *dst_pgdp; -+ p4d_t *src_p4dp, *dst_p4dp; -+ pud_t *src_pudp, *dst_pudp; -+ pmd_t *src_pmdp, *dst_pmdp; -+ pte_t *src_ptep, *dst_ptep; -+ -+ src_pgdp = pgd_offset_pgd(swapper_pg_dir, src); -+ dst_pgdp = pgd_offset_pgd(swapper_pg_dir, dst); -+ -+ src_p4dp = p4d_offset(src_pgdp, src); -+ dst_p4dp = p4d_alloc(&init_mm, dst_pgdp, dst); -+ if (!dst_p4dp) { -+ return -ENOMEM; -+ } -+ src_pudp = pud_offset(src_p4dp, src); -+ dst_pudp = pud_alloc(&init_mm, dst_p4dp, dst); -+ if (!dst_pudp) { -+ return -ENOMEM; -+ } -+ if (pud_val(*src_pudp) & PMD_TABLE_BIT) { -+ src_pmdp = pmd_offset(src_pudp, src); -+ dst_pmdp = pmd_alloc(&init_mm, dst_pudp, dst); -+ if (!dst_pmdp) { -+ return -ENOMEM; -+ } -+ if (pmd_val(*src_pmdp) & PMD_TABLE_BIT) { -+ src_ptep = pte_offset_kernel(src_pmdp, src); -+ dst_ptep = pte_alloc_map(&init_mm, dst_pmdp, dst); -+ set_pte(dst_ptep, *src_ptep); -+ } else { -+ set_pte((pte_t *)dst_pmdp, pmd_pte(*src_pmdp)); -+ } -+ } else { -+ set_pte((pte_t *)dst_pudp, pud_pte(*src_pudp)); -+ } -+ -+ -+ flush_tlb_kernel_range(dst, dst+PAGE_SIZE); -+ isb(); -+ return 0; +} ++EXPORT_SYMBOL(koi_map_kostack); + -+void koi_remove_page_mapping(unsigned long addr) { -+ pgd_t *src_pgdp; -+ p4d_t *src_p4dp; -+ pud_t *src_pudp; -+ pmd_t *src_pmdp; -+ pte_t *src_ptep; ++#ifndef CONFIG_IEE ++void koi_init_token(struct task_struct *tsk) ++{ ++ struct task_token *token_addr = ++ (struct task_token *)(__phys_to_virt(__pa(tsk)) + KOI_OFFSET); + -+ src_pgdp = pgd_offset_pgd(swapper_pg_dir, addr); -+ if (pgd_none(*src_pgdp) || pgd_bad(*src_pgdp)) -+ return; -+ src_p4dp = p4d_offset(src_pgdp, addr); -+ if (p4d_none(*src_p4dp) || p4d_bad(*src_p4dp)) -+ return; -+ src_pudp = pud_offset(src_p4dp, addr); -+ if (pud_none(*src_pudp)) -+ return; -+ if (pud_val(*src_pudp) & PMD_TABLE_BIT) { -+ src_pmdp = pmd_offset(src_pudp, addr); -+ if (pmd_none(*src_pmdp)) -+ return; -+ if (pmd_val(*src_pmdp) & PMD_TABLE_BIT) { -+ src_ptep = pte_offset_kernel(src_pmdp, addr); -+ if(!pte_none(*src_ptep)) -+ pte_clear(&init_mm, addr, src_ptep); -+ } else { -+ pmd_clear(src_pmdp); -+ } -+ } else { -+ pud_clear(src_pudp); -+ } -+ -+ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); -+ isb(); ++ token_addr->koi_kernel_stack = NULL; ++ // token_addr->koi_stack = NULL; ++ // token_addr->koi_stack_base = NULL; ++ token_addr->current_ttbr1 = 0; +} -+#endif + - void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd) ++#endif +\ No newline at end of file +diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c +index cea96ee75d22..cbddc8e464e4 100644 +--- a/arch/arm64/kernel/mte.c ++++ b/arch/arm64/kernel/mte.c +@@ -79,8 +79,13 @@ int memcmp_pages(struct page *page1, struct page *page2) + static inline void __mte_enable_kernel(const char *mode, unsigned long tcf) { -+ #ifdef CONFIG_PTP -+ spin_lock(&swapper_pgdir_lock); -+ iee_rw_gate(IEE_OP_SET_SWAPPER_PGD, pgdp, pgd); -+ spin_unlock(&swapper_pgdir_lock); -+ #else - pgd_t *fixmap_pgdp; + /* Enable MTE Sync Mode for EL1. */ ++#ifdef CONFIG_IEE ++ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_EL1_TCF_MASK, ++ SYS_FIELD_PREP(SCTLR_EL1, TCF, tcf)); ++#else + sysreg_clear_set(sctlr_el1, SCTLR_EL1_TCF_MASK, + SYS_FIELD_PREP(SCTLR_EL1, TCF, tcf)); ++#endif + isb(); - spin_lock(&swapper_pgdir_lock); -@@ -90,6 +370,7 @@ void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd) - */ - pgd_clear_fixmap(); - spin_unlock(&swapper_pgdir_lock); -+ #endif - } + pr_info_once("MTE: enabled in %s mode at EL1\n", mode); +diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c +index 068e5bb2661b..e545a2df805f 100644 +--- a/arch/arm64/kernel/process.c ++++ b/arch/arm64/kernel/process.c +@@ -471,7 +471,14 @@ DEFINE_PER_CPU(struct task_struct *, __entry_task); - pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, -@@ -118,7 +399,11 @@ static phys_addr_t __init early_pgtable_alloc(int shift) - * slot will be free, so we can (ab)use the FIX_PTE slot to initialise - * any level of table. - */ -+ #ifdef CONFIG_PTP -+ ptr = pte_set_fixmap_init(phys); -+ #else - ptr = pte_set_fixmap(phys); + static void entry_task_switch(struct task_struct *next) + { ++ #if defined(CONFIG_IEE) || defined (CONFIG_KOI) ++ if(next == &init_task) ++ __this_cpu_write(__entry_task, (struct task_struct *)__va(__pa_symbol(next))); ++ else ++ __this_cpu_write(__entry_task, next); ++ #else + __this_cpu_write(__entry_task, next); + #endif + } - memset(ptr, 0, PAGE_SIZE); - -@@ -126,11 +411,16 @@ static phys_addr_t __init early_pgtable_alloc(int shift) - * Implicit barriers also ensure the zeroed page is visible to the page - * table walker + /* +@@ -506,11 +513,15 @@ static void erratum_1418040_new_exec(void) + */ + void update_sctlr_el1(u64 sctlr) + { +- /* ++ /* + * EnIA must not be cleared while in the kernel as this is necessary for + * in-kernel PAC. It will be cleared on kernel exit if needed. */ -+ #ifdef CONFIG_PTP -+ pte_clear_fixmap_init(); ++ #ifdef CONFIG_IEE ++ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_USER_MASK & ~SCTLR_ELx_ENIA, sctlr); + #else - pte_clear_fixmap(); + sysreg_clear_set(sctlr_el1, SCTLR_USER_MASK & ~SCTLR_ELx_ENIA, sctlr); + #endif - return phys; - } + /* ISB required for the kernel uaccess routines when setting TCF0. */ + isb(); +diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c +index 58a97861bfc5..c7839247327d 100644 +--- a/arch/arm64/kernel/proton-pack.c ++++ b/arch/arm64/kernel/proton-pack.c +@@ -551,7 +551,11 @@ static enum mitigation_state spectre_v4_enable_hw_mitigation(void) + return state; -+ - bool pgattr_change_is_safe(u64 old, u64 new) - { - /* -@@ -178,7 +468,11 @@ static void init_pte(pmd_t *pmdp, unsigned long addr, unsigned long end, - do { - pte_t old_pte = __ptep_get(ptep); + if (spectre_v4_mitigations_off()) { ++#ifdef CONFIG_IEE ++ sysreg_clear_set_iee_si(sctlr_el1, 0, SCTLR_ELx_DSSBS); ++#else + sysreg_clear_set(sctlr_el1, 0, SCTLR_ELx_DSSBS); ++#endif + set_pstate_ssbs(1); + return SPECTRE_VULNERABLE; + } +@@ -975,7 +979,11 @@ static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot) + if (arm64_kernel_unmapped_at_el0()) + return; -+ #ifdef CONFIG_PTP -+ iee_set_fixmap_pte_pre_init(ptep, pfn_pte(__phys_to_pfn(phys), prot)); -+ #else - __set_pte(ptep, pfn_pte(__phys_to_pfn(phys), prot)); -+ #endif ++#ifdef CONFIG_IEE ++ iee_rwx_gate_entry(IEE_WRITE_vbar_el1, v); ++#else + write_sysreg(v, vbar_el1); ++#endif + isb(); + } - /* - * After the PTE entry has been populated once, we -@@ -211,7 +505,11 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr, - pmdval |= PMD_TABLE_PXN; - BUG_ON(!pgtable_alloc); - pte_phys = pgtable_alloc(PAGE_SHIFT); -+ #ifdef CONFIG_PTP -+ __iee_pmd_populate_fixmap(pmdp, pte_phys, pmdval); -+ #else - __pmd_populate(pmdp, pte_phys, pmdval); -+ #endif - pmd = READ_ONCE(*pmdp); - } - BUG_ON(pmd_bad(pmd)); -@@ -248,7 +546,11 @@ static void init_pmd(pud_t *pudp, unsigned long addr, unsigned long end, - /* try section mapping first */ - if (((addr | next | phys) & ~PMD_MASK) == 0 && - (flags & NO_BLOCK_MAPPINGS) == 0) { -+ #ifdef CONFIG_PTP -+ iee_pmd_set_huge_fixmap(pmdp, phys, prot); -+ #else - pmd_set_huge(pmdp, phys, prot); -+ #endif +diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c +index d82fd6902ea8..84f4fce0b8bc 100644 +--- a/arch/arm64/kernel/setup.c ++++ b/arch/arm64/kernel/setup.c +@@ -33,6 +33,11 @@ + #include + #include - /* - * After the PMD entry has been populated once, we -@@ -289,7 +591,11 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr, - pudval |= PUD_TABLE_PXN; - BUG_ON(!pgtable_alloc); - pmd_phys = pgtable_alloc(PMD_SHIFT); -- __pud_populate(pudp, pmd_phys, pudval); -+ #ifdef CONFIG_PTP -+ __iee_pud_populate_fixmap(pudp, pmd_phys, PUD_TYPE_TABLE); -+ #else -+ __pud_populate(pudp, pmd_phys, PUD_TYPE_TABLE); -+ #endif - pud = READ_ONCE(*pudp); - } - BUG_ON(pud_bad(pud)); -@@ -345,7 +651,11 @@ static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end, - if (pud_sect_supported() && - ((addr | next | phys) & ~PUD_MASK) == 0 && - (flags & NO_BLOCK_MAPPINGS) == 0) { -+ #ifdef CONFIG_PTP -+ iee_pud_set_huge_fixmap(pudp, phys, prot); -+ #else - pud_set_huge(pudp, phys, prot); -+ #endif ++#ifdef CONFIG_IEE ++#include ++#include ++#endif ++ + #include + #include + #include +@@ -336,10 +341,31 @@ u64 cpu_logical_map(unsigned int cpu) + return __cpu_logical_map[cpu]; + } - /* - * After the PUD entry has been populated once, we -@@ -374,6 +684,10 @@ static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys, ++#ifdef CONFIG_IEE ++/* used for secure modification of vbar*/ ++extern char __bp_harden_el1_vectors[]; ++/* prepare iee rwx gate for senario of ttbr1=init_pg_dir */ ++static void __init iee_si_init_early(void) ++{ ++ /* prepare data used for iee rwx gate. */ ++ iee_base_swapper_pg_dir = phys_to_ttbr(__pa_symbol(swapper_pg_dir)); ++ iee_base_idmap_pg_dir = phys_to_ttbr(__pa_symbol(idmap_pg_dir)); ++ iee_base_reserved_pg_dir = phys_to_ttbr(__pa_symbol(reserved_pg_dir)) ++ | FIELD_PREP(TTBR_ASID_MASK, 1); ++ iee_base__bp_harden_el1_vectors = (unsigned long)__bp_harden_el1_vectors; ++ iee_si_tcr = 0; ++} ++#endif ++ + void __init __no_sanitize_address setup_arch(char **cmdline_p) { - unsigned long addr, end, next; - pgd_t *pgdp = pgd_offset_pgd(pgdir, virt); + setup_initial_init_mm(_stext, _etext, _edata, _end); + + #ifdef CONFIG_IEE -+ p4d_t *p4dp; -+ p4d_t p4d; ++ init_new_context(&init_task, &init_mm); ++ atomic64_set(&init_mm.context.id, (1UL << get_cpu_asid_bits()) | INIT_ASID); + #endif ++ + *cmdline_p = boot_command_line; + + kaslr_init(); +@@ -375,6 +401,14 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p) + */ + local_daif_restore(DAIF_PROCCTX_NOIRQ); ++#ifdef CONFIG_IEE ++ /* ++ * Map iee si codes to init_pg_dir to run the following ++ * cpu_uninstall_idmap() which writes ttbr0. ++ */ ++ iee_si_init_early(); ++#endif ++ /* - * If the virtual and physical address don't have the same offset -@@ -390,10 +704,14 @@ static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys, - next = pgd_addr_end(addr, end); - alloc_init_pud(pgdp, addr, next, phys, prot, pgtable_alloc, - flags); -+ #ifdef CONFIG_IEE -+ p4dp = p4d_offset(pgdp, addr); -+ p4d = READ_ONCE(*p4dp); -+ __p4d_populate(p4dp, __p4d_to_phys(p4d), (PGD_APT | PUD_TYPE_TABLE)); -+ #endif - phys += next - addr; - } while (pgdp++, addr = next, addr != end); + * TTBR0 is only used for the identity mapping at this stage. Make it + * point to zero page to avoid speculatively fetching new entries. +diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c +index b7b7afb4a8c7..168a9390d6e9 100644 +--- a/arch/arm64/kernel/traps.c ++++ b/arch/arm64/kernel/traps.c +@@ -902,6 +902,32 @@ const char *esr_get_class_string(unsigned long esr) + return esr_class_str[ESR_ELx_EC(esr)]; } -- - static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys, - unsigned long virt, phys_addr_t size, - pgprot_t prot, -@@ -413,162 +731,844 @@ void create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt, - phys_addr_t (*pgtable_alloc)(int), int flags); - #endif - --static phys_addr_t __pgd_pgtable_alloc(int shift) -+#ifdef CONFIG_PTP -+static int __init iee_pud_set_huge_pre_init(pud_t *pudp, phys_addr_t phys, pgprot_t prot) - { -- void *ptr = (void *)__get_free_page(GFP_PGTABLE_KERNEL); -- BUG_ON(!ptr); -+ pud_t new_pud = pfn_pud(__phys_to_pfn(phys), mk_pud_sect_prot(prot)); -- /* Ensure the zeroed page is visible to the page table walker */ -- dsb(ishst); -- return __pa(ptr); -+ /* Only allow permission changes for now */ -+ if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pudp)), -+ pud_val(new_pud))) -+ return 0; ++#ifdef CONFIG_IEE ++extern void arm64_enter_nmi(struct pt_regs *regs); ++static const char *handler[]= { ++ "SP_EL0", ++ "ELR_EL1", ++ "TCR_EL1", ++ "TTBR0 ASID" ++ "IEE_SI" ++}; + -+ VM_BUG_ON(phys & ~PUD_MASK); -+ iee_set_pud_pre_init(pudp, new_pud); -+ return 1; - } ++asmlinkage void notrace iee_bad_mode(struct pt_regs *regs, int reason, unsigned int esr) ++{ ++ arm64_enter_nmi(regs); ++ ++ console_verbose(); ++ ++ pr_crit("IEE : Bad mode in %s check detected on CPU%d, code 0x%08x -- %s\n", ++ handler[reason], smp_processor_id(), esr, ++ esr_get_class_string(esr)); ++ ++ __show_regs(regs); ++ local_daif_mask(); ++ panic("bad mode"); ++} ++#endif ++ + /* + * bad_el0_sync handles unexpected, but potentially recoverable synchronous + * exceptions taken from EL0. +diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S +index 3cd7e76cc562..8f074828f706 100644 +--- a/arch/arm64/kernel/vmlinux.lds.S ++++ b/arch/arm64/kernel/vmlinux.lds.S +@@ -134,6 +134,51 @@ jiffies = jiffies_64; + #define UNWIND_DATA_SECTIONS + #endif --static phys_addr_t pgd_pgtable_alloc(int shift) -+static int __init iee_pmd_set_huge_pre_init(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) - { -- phys_addr_t pa = __pgd_pgtable_alloc(shift); -- struct ptdesc *ptdesc = page_ptdesc(phys_to_page(pa)); -- -- /* -- * Call proper page table ctor in case later we need to -- * call core mm functions like apply_to_page_range() on -- * this pre-allocated page table. -- * -- * We don't select ARCH_ENABLE_SPLIT_PMD_PTLOCK if pmd is -- * folded, and if so pagetable_pte_ctor() becomes nop. -- */ -- if (shift == PAGE_SHIFT) -- BUG_ON(!pagetable_pte_ctor(ptdesc)); -- else if (shift == PMD_SHIFT) -- BUG_ON(!pagetable_pmd_ctor(ptdesc)); -+ pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), mk_pmd_sect_prot(prot)); - -- return pa; --} -+ /* Only allow permission changes for now */ -+ if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)), -+ pmd_val(new_pmd))) -+ return 0; - --/* -- * This function can only be used to modify existing table entries, -- * without allocating new levels of table. Note that this permits the -- * creation of new section or page entries. -- */ --void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt, -- phys_addr_t size, pgprot_t prot) --{ -- if (virt < PAGE_OFFSET) { -- pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n", -- &phys, virt); -- return; -- } -- __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, -- NO_CONT_MAPPINGS); -+ VM_BUG_ON(phys & ~PMD_MASK); -+ iee_set_pmd_pre_init(pmdp, new_pmd); -+ return 1; - } - --void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, -- unsigned long virt, phys_addr_t size, -- pgprot_t prot, bool page_mappings_only) -+static __init void iee_init_pte_pre_init(pmd_t *pmdp, unsigned long addr, unsigned long end, -+ phys_addr_t phys, pgprot_t prot) - { -- int flags = 0; -- -- BUG_ON(mm == &init_mm); -+ pte_t *ptep; - -- if (page_mappings_only) -- flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; -+ ptep = pte_set_fixmap_offset_init(pmdp, addr); -+ do { -+ pte_t old_pte = READ_ONCE(*ptep); ++#ifdef CONFIG_IEE ++#define IEE_TEXT \ ++ . = ALIGN(PAGE_SIZE); \ ++ __iee_code_start = .; \ ++ *(.iee.text.header) \ ++ *(.iee.text) \ ++ . = ALIGN(PAGE_SIZE); \ ++ __iee_code_end = .; ++#else ++#define IEE_TEXT ++#endif ++ ++#ifdef CONFIG_IEE ++#define IEE_SI_TEXT \ ++ . = ALIGN(PAGE_SIZE); \ ++ __iee_si_data_start = .; \ ++ *(.iee.si_data) \ ++ . = ALIGN(PAGE_SIZE); \ ++ __iee_exec_entry_start = .; \ ++ __iee_si_no_irq = . + (16); \ ++ *(.iee.exec_entry) \ ++ . = ALIGN(PAGE_SIZE); \ ++ __iee_si_text_start = .; \ ++ *(.iee.si_text) \ ++ . = ALIGN(PAGE_SIZE); \ ++ . += PAGE_SIZE - (24); \ ++ __iee_si_text_end = . + (24); \ ++ *(.iee.exec_exit) \ ++ . = ALIGN(PAGE_SIZE); ++ ++#else ++#define IEE_SI_TEXT ++#endif ++ ++#ifdef CONFIG_KOI ++#define KOI_TEXT \ ++ . = ALIGN(PAGE_SIZE); \ ++ __koi_code_start = .; \ ++ *(.koi.text) \ ++ . = ALIGN(PAGE_SIZE); \ ++ __koi_code_end = .; ++#else ++#define KOI_TEXT ++#endif ++ + /* + * The size of the PE/COFF section that covers the kernel image, which + * runs from _stext to _edata, must be a round multiple of the PE/COFF +@@ -176,10 +221,13 @@ SECTIONS + SOFTIRQENTRY_TEXT + ENTRY_TEXT + TEXT_TEXT ++ IEE_TEXT + SCHED_TEXT + LOCK_TEXT + KPROBES_TEXT + HYPERVISOR_TEXT ++ IEE_SI_TEXT ++ KOI_TEXT + *(.gnu.warning) + } -- __create_pgd_mapping(mm->pgd, phys, virt, size, prot, -- pgd_pgtable_alloc, flags); --} -+ iee_set_pte_pre_init(ptep, pfn_pte(__phys_to_pfn(phys), prot)); +@@ -318,6 +366,18 @@ SECTIONS + . += INIT_DIR_SIZE; + init_pg_end = .; --static void update_mapping_prot(phys_addr_t phys, unsigned long virt, -- phys_addr_t size, pgprot_t prot) --{ -- if (virt < PAGE_OFFSET) { -- pr_warn("BUG: not updating mapping for %pa at 0x%016lx - outside kernel range\n", -- &phys, virt); -- return; -- } -+ /* -+ * After the PTE entry has been populated once, we -+ * only allow updates to the permission attributes. -+ */ -+ BUG_ON(!pgattr_change_is_safe(pte_val(old_pte), -+ READ_ONCE(pte_val(*ptep)))); ++ #ifdef CONFIG_IEE ++ . = ALIGN(PAGE_SIZE*8); ++ init_iee_stack_begin = .; ++ . += PAGE_SIZE*4; ++ init_iee_stack_end = .; ++ ++ . = ALIGN(PAGE_SIZE); ++ init_iee_si_stack_begin = .; ++ . += PAGE_SIZE*4; ++ init_iee_si_stack_end = .; ++ #endif ++ + . = ALIGN(SEGMENT_ALIGN); + __pecoff_data_size = ABSOLUTE(. - __initdata_begin); + _end = .; +diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c +index 188197590fc9..b6d8a7d0aeca 100644 +--- a/arch/arm64/mm/context.c ++++ b/arch/arm64/mm/context.c +@@ -17,6 +17,10 @@ + #include + #include -- __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, -- NO_CONT_MAPPINGS); -+ phys += PAGE_SIZE; -+ } while (ptep++, addr += PAGE_SIZE, addr != end); ++#ifdef CONFIG_IEE ++#include ++#endif ++ + static u32 asid_bits; + static DEFINE_RAW_SPINLOCK(cpu_asid_lock); -- /* flush the TLBs after updating live kernel mappings */ -- flush_tlb_kernel_range(virt, virt + size); -+ pte_clear_fixmap_init(); - } +@@ -39,7 +43,11 @@ static unsigned long *pinned_asid_map; + #define asid2ctxid(asid, genid) ((asid) | (genid)) --static void __init __map_memblock(pgd_t *pgdp, phys_addr_t start, -- phys_addr_t end, pgprot_t prot, int flags) -+static __init void iee_alloc_init_cont_pte_pre_init(pmd_t *pmdp, unsigned long addr, -+ unsigned long end, phys_addr_t phys, -+ pgprot_t prot, -+ phys_addr_t (*pgtable_alloc)(int), -+ int flags) + /* Get the ASIDBits supported by the current CPU */ ++#ifdef CONFIG_IEE ++u32 get_cpu_asid_bits(void) ++#else + static u32 get_cpu_asid_bits(void) ++#endif { -- __create_pgd_mapping(pgdp, start, __phys_to_virt(start), end - start, -- prot, early_pgtable_alloc, flags); --} -+ unsigned long next; -+ pmd_t pmd = READ_ONCE(*pmdp); + u32 asid; + int fld = cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64MMFR0_EL1), +@@ -96,6 +104,16 @@ static void set_reserved_asid_bits(void) + set_kpti_asid_bits(asid_map); + else + bitmap_clear(asid_map, 0, NUM_USER_ASIDS); ++ #ifdef CONFIG_IEE ++ unsigned int len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long); ++ memset(asid_map, 0xaa, len); ++ __set_bit(INIT_ASID, asid_map); ++ #else ++ #ifdef CONFIG_KOI ++ unsigned int len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long); ++ memset(asid_map, 0xaa, len); ++ #endif ++ #endif + } --void __init mark_linear_text_alias_ro(void) --{ -- /* -- * Remove the write permissions from the linear alias of .text/.rodata -- */ -- update_mapping_prot(__pa_symbol(_stext), (unsigned long)lm_alias(_stext), -- (unsigned long)__init_begin - (unsigned long)_stext, -- PAGE_KERNEL_RO); --} -+ BUG_ON(pmd_sect(pmd)); -+ if (pmd_none(pmd)) { -+ pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN; -+ phys_addr_t pte_phys; + #define asid_gen_match(asid) \ +@@ -212,6 +230,38 @@ static u64 new_context(struct mm_struct *mm) + return asid2ctxid(asid, generation); + } --#ifdef CONFIG_KFENCE -+ if (flags & NO_EXEC_MAPPINGS) -+ pmdval |= PMD_TABLE_PXN; -+ BUG_ON(!pgtable_alloc); -+ pte_phys = pgtable_alloc(PAGE_SHIFT); -+ __iee_pmd_populate_pre_init(pmdp, pte_phys, pmdval); -+ pmd = READ_ONCE(*pmdp); ++#ifdef CONFIG_KOI ++/* ++ * This function is used to check and allocate ASID for ko's pgd ++ * The mm MUST point to the isolated kos' mm_struct, other behaviours are undefined. ++ */ ++void koi_check_and_switch_context(struct mm_struct *mm) { ++ u64 asid = atomic64_read(&mm->context.id); ++ u64 old_active_asid; ++ unsigned long flags; ++ unsigned int cpu; ++ ++ old_active_asid = atomic64_read(this_cpu_ptr(&active_asids)); ++ if (old_active_asid && asid_gen_match(asid) && atomic64_cmpxchg_relaxed(this_cpu_ptr(&active_asids), old_active_asid, asid)) { ++ return; + } -+ BUG_ON(pmd_bad(pmd)); ++ ++ raw_spin_lock_irqsave(&cpu_asid_lock, flags); ++ asid = atomic64_read(&mm->context.id); ++ if (!asid_gen_match(asid)) { ++ asid = new_context(mm); ++ atomic64_set(&mm->context.id, asid); ++ } ++ ++ cpu = smp_processor_id(); ++ if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) ++ local_flush_tlb_all(); ++ ++ atomic64_set(this_cpu_ptr(&active_asids), asid); ++ raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); ++} ++#endif ++ + void check_and_switch_context(struct mm_struct *mm) + { + unsigned long flags; +@@ -348,7 +398,9 @@ asmlinkage void post_ttbr_update_workaround(void) --bool __ro_after_init kfence_early_init = !!CONFIG_KFENCE_SAMPLE_INTERVAL; -+ do { -+ pgprot_t __prot = prot; + void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm) + { ++ #ifndef CONFIG_IEE + unsigned long ttbr1 = read_sysreg(ttbr1_el1); ++ #endif + unsigned long asid = ASID(mm); + unsigned long ttbr0 = phys_to_ttbr(pgd_phys); --/* early_param() will be parsed before map_mem() below. */ --static int __init parse_kfence_early_init(char *arg) --{ -- int val; -+ next = pte_cont_addr_end(addr, end); +@@ -360,14 +412,28 @@ void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm) + if (IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN)) + ttbr0 |= FIELD_PREP(TTBR_ASID_MASK, asid); -- if (get_option(&arg, &val)) -- kfence_early_init = !!val; -+ /* use a contiguous mapping if the range is suitably aligned */ -+ if ((((addr | next | phys) & ~CONT_PTE_MASK) == 0) && -+ (flags & NO_CONT_MAPPINGS) == 0) -+ __prot = __pgprot(pgprot_val(prot) | PTE_CONT); - --#if IS_ENABLED(CONFIG_KFENCE_MUST_EARLY_INIT) -- kfence_must_early_init = (val == -1) ? true : false; --#endif -+ iee_init_pte_pre_init(pmdp, addr, next, phys, __prot); - -- return 0; -+ phys += next - addr; -+ } while (addr = next, addr != end); +- /* Set ASID in TTBR1 since TCR.A1 is set */ ++ #ifdef CONFIG_IEE ++ ttbr0 |= FIELD_PREP(TTBR_ASID_MASK, asid+1); ++ iee_rwx_gate_entry(IEE_CONTEXT_SWITCH, ttbr0); ++ // TODO : if defined CONFIG_IEE and defined CONFIG_KOI ++ #else ++ /* Set ASID in TTBR0 since TCR.A1 is set 0*/ ++ ++ #ifdef CONFIG_KOI ++ ttbr0 |= FIELD_PREP(TTBR_ASID_MASK, asid+1); ++ ttbr1 &= ~TTBR_ASID_MASK; ++ ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); ++ #else + ttbr1 &= ~TTBR_ASID_MASK; + ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); +- ++ ++ #endif + cpu_set_reserved_ttbr0_nosync(); + write_sysreg(ttbr1, ttbr1_el1); + write_sysreg(ttbr0, ttbr0_el1); + isb(); ++ #endif ++ + post_ttbr_update_workaround(); } --early_param("kfence.sample_interval", parse_kfence_early_init); --static phys_addr_t __init arm64_kfence_alloc_pool(void) -+static __init void iee_init_pmd_pre_init(pud_t *pudp, unsigned long addr, unsigned long end, -+ phys_addr_t phys, pgprot_t prot, -+ phys_addr_t (*pgtable_alloc)(int), int flags) +@@ -375,11 +441,28 @@ static int asids_update_limit(void) { -- phys_addr_t kfence_pool; -+ unsigned long next; -+ pmd_t *pmdp; - -- if (!kfence_early_init) -- return 0; -+ pmdp = pmd_set_fixmap_offset_init(pudp, addr); -+ do { -+ pmd_t old_pmd = READ_ONCE(*pmdp); + unsigned long num_available_asids = NUM_USER_ASIDS; -- kfence_pool = memblock_phys_alloc(KFENCE_POOL_SIZE, PAGE_SIZE); -- if (!kfence_pool) { -- pr_err("failed to allocate kfence pool\n"); -- kfence_early_init = false; -- return 0; -- } -+ next = pmd_addr_end(addr, end); +- if (arm64_kernel_unmapped_at_el0()) { +- num_available_asids /= 2; +- if (pinned_asid_map) +- set_kpti_asid_bits(pinned_asid_map); ++ if (arm64_kernel_unmapped_at_el0()) { ++ num_available_asids /= 2; ++ if (pinned_asid_map) ++ set_kpti_asid_bits(pinned_asid_map); + } ++ #if defined(CONFIG_IEE) ++ num_available_asids /= 2; ++ if (pinned_asid_map) { ++ unsigned int len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long); ++ memset(pinned_asid_map, 0xaa, len); ++ __set_bit(INIT_ASID, pinned_asid_map); ++ } ++ #else ++ #ifdef CONFIG_KOI ++ num_available_asids /= 2; ++ if (pinned_asid_map) { ++ unsigned int len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long); ++ memset(pinned_asid_map, 0xaa, len); ++ } ++ #endif ++ #endif ++ + /* + * Expect allocation after rollover to fail if we don't have at least + * one more ASID than CPUs. ASID #0 is reserved for init_mm. +@@ -400,6 +483,10 @@ arch_initcall(asids_update_limit); -- /* Temporarily mark as NOMAP. */ -- memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE); -+ /* try section mapping first */ -+ if (((addr | next | phys) & ~PMD_MASK) == 0 && -+ (flags & NO_BLOCK_MAPPINGS) == 0) { -+ iee_pmd_set_huge_pre_init(pmdp, phys, prot); + static int asids_init(void) + { ++ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++ unsigned int len; ++ #endif + -+ /* -+ * After the PMD entry has been populated once, we -+ * only allow updates to the permission attributes. -+ */ -+ BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd), -+ READ_ONCE(pmd_val(*pmdp)))); -+ } else { -+ iee_alloc_init_cont_pte_pre_init(pmdp, addr, next, phys, prot, -+ pgtable_alloc, flags); + asid_bits = get_cpu_asid_bits(); + atomic64_set(&asid_generation, ASID_FIRST_VERSION); + asid_map = bitmap_zalloc(NUM_USER_ASIDS, GFP_KERNEL); +@@ -410,13 +497,25 @@ static int asids_init(void) + pinned_asid_map = bitmap_zalloc(NUM_USER_ASIDS, GFP_KERNEL); + nr_pinned_asids = 0; + +- /* +- * We cannot call set_reserved_asid_bits() here because CPU +- * caps are not finalized yet, so it is safer to assume KPTI +- * and reserve kernel ASID's from beginning. +- */ +- if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) +- set_kpti_asid_bits(asid_map); ++ #ifdef CONFIG_IEE ++ len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long); ++ memset(asid_map, 0xaa, len); ++ __set_bit(INIT_ASID, asid_map); ++ #else ++ #ifdef CONFIG_KOI ++ len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long); ++ memset(asid_map, 0xaa, len); ++ #else ++ /* ++ * We cannot call set_reserved_asid_bits() here because CPU ++ * caps are not finalized yet, so it is safer to assume KPTI ++ * and reserve kernel ASID's from beginning. ++ */ ++ if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) ++ set_kpti_asid_bits(asid_map); ++ #endif ++ #endif + -+ BUG_ON(pmd_val(old_pmd) != 0 && -+ pmd_val(old_pmd) != READ_ONCE(pmd_val(*pmdp))); -+ } -+ phys += next - addr; -+ } while (pmdp++, addr = next, addr != end); + return 0; + } + early_initcall(asids_init); +diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c +index 4ea07caba71c..909c75bf9e41 100644 +--- a/arch/arm64/mm/fault.c ++++ b/arch/arm64/mm/fault.c +@@ -261,7 +261,15 @@ int __ptep_set_access_flags(struct vm_area_struct *vma, + pteval ^= PTE_RDONLY; + pteval |= pte_val(entry); + pteval ^= PTE_RDONLY; ++ #ifdef CONFIG_KOI ++ if (pteval & PTE_VALID) ++ pteval |= PTE_NG; ++ #endif ++ #ifdef CONFIG_PTP ++ pteval = iee_set_cmpxchg_relaxed(ptep, old_pteval, pteval); ++ #else + pteval = cmpxchg_relaxed(&pte_val(*ptep), old_pteval, pteval); ++ #endif + } while (pteval != old_pteval); + + /* Invalidate a stale read-only entry */ +@@ -376,8 +384,13 @@ static void do_tag_recovery(unsigned long addr, unsigned long esr, + * It will be done lazily on the other CPUs when they will hit a + * tag fault. + */ ++ #ifdef CONFIG_IEE ++ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_EL1_TCF_MASK, ++ SYS_FIELD_PREP_ENUM(SCTLR_EL1, TCF, NONE)); ++ #else + sysreg_clear_set(sctlr_el1, SCTLR_EL1_TCF_MASK, + SYS_FIELD_PREP_ENUM(SCTLR_EL1, TCF, NONE)); ++ #endif + isb(); + } + +diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c +index bfc02568805a..580ecb596d2d 100644 +--- a/arch/arm64/mm/fixmap.c ++++ b/arch/arm64/mm/fixmap.c +@@ -32,6 +32,22 @@ static pte_t bm_pte[NR_BM_PTE_TABLES][PTRS_PER_PTE] __page_aligned_bss; + static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused; + static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused; + ++#ifdef CONFIG_IEE ++void *bm_pte_addr = (void *)bm_pte; ++void *bm_pmd_addr = (void *)bm_pmd; ++void *bm_pud_addr = (void *)bm_pud; ++#endif + -+ pmd_clear_fixmap_init(); -+} ++#ifdef CONFIG_PTP ++extern void __iee_p4d_populate_pre_init(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot); ++extern void __iee_pud_populate_pre_init(pud_t *pudp, phys_addr_t pmdp, pudval_t prot); ++extern void __iee_pmd_populate_pre_init(pmd_t *pmdp, phys_addr_t ptep, ++ pmdval_t prot); + -+static __init void iee_alloc_init_cont_pmd_pre_init(pud_t *pudp, unsigned long addr, -+ unsigned long end, phys_addr_t phys, -+ pgprot_t prot, -+ phys_addr_t (*pgtable_alloc)(int), int flags) -+{ -+ unsigned long next; -+ pud_t pud = READ_ONCE(*pudp); ++extern void iee_set_p4d_pre_init(p4d_t *p4dp, p4d_t p4d); ++#define set_pgd_init(pgdptr, pgdval) iee_set_p4d_pre_init((p4d_t *)(pgdptr), (p4d_t) { pgdval }) ++#endif + -+ /* -+ * Check for initial section mappings in the pgd/pud. -+ */ -+ BUG_ON(pud_sect(pud)); + static inline pte_t *fixmap_pte(unsigned long addr) + { + return &bm_pte[BM_PTE_TABLE_IDX(addr)][pte_index(addr)]; +@@ -44,7 +60,11 @@ static void __init early_fixmap_init_pte(pmd_t *pmdp, unsigned long addr) + + if (pmd_none(pmd)) { + ptep = bm_pte[BM_PTE_TABLE_IDX(addr)]; ++ #ifdef CONFIG_PTP ++ __iee_pmd_populate_pre_init(pmdp, __pa_symbol(ptep), PMD_TYPE_TABLE); ++ #else + __pmd_populate(pmdp, __pa_symbol(ptep), PMD_TYPE_TABLE); ++ #endif + } + } + +@@ -55,8 +75,13 @@ static void __init early_fixmap_init_pmd(pud_t *pudp, unsigned long addr, + pud_t pud = READ_ONCE(*pudp); + pmd_t *pmdp; + +- if (pud_none(pud)) + if (pud_none(pud)) { -+ pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN; -+ phys_addr_t pmd_phys; -+ -+ if (flags & NO_EXEC_MAPPINGS) -+ pudval |= PUD_TABLE_PXN; -+ BUG_ON(!pgtable_alloc); -+ pmd_phys = pgtable_alloc(PMD_SHIFT); -+ __iee_pud_populate_pre_init(pudp, pmd_phys, pudval); -+ pud = READ_ONCE(*pudp); ++ #ifdef CONFIG_PTP ++ __iee_pud_populate_pre_init(pudp, __pa_symbol(bm_pmd), PUD_TYPE_TABLE); ++ #else + __pud_populate(pudp, __pa_symbol(bm_pmd), PUD_TYPE_TABLE); ++ #endif + } -+ BUG_ON(pud_bad(pud)); -+ -+ do { -+ pgprot_t __prot = prot; -+ -+ next = pmd_cont_addr_end(addr, end); + + pmdp = pmd_offset_kimg(pudp, addr); + do { +@@ -82,8 +107,13 @@ static void __init early_fixmap_init_pud(p4d_t *p4dp, unsigned long addr, + BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES)); + } + +- if (p4d_none(p4d)) ++ if (p4d_none(p4d)) { ++ #ifdef CONFIG_PTP ++ __iee_p4d_populate_pre_init(p4dp, __pa_symbol(bm_pud), P4D_TYPE_TABLE); ++ #else + __p4d_populate(p4dp, __pa_symbol(bm_pud), P4D_TYPE_TABLE); ++ #endif ++ } + + pudp = pud_offset_kimg(p4dp, addr); + early_fixmap_init_pmd(pudp, addr, end); +@@ -106,6 +136,27 @@ void __init early_fixmap_init(void) + early_fixmap_init_pud(p4dp, addr, end); + } + ++#ifdef CONFIG_PTP ++extern void iee_set_pte_pre_init(pte_t *ptep, pte_t pte); ++void __iee_set_fixmap_pre_init(enum fixed_addresses idx, ++ phys_addr_t phys, pgprot_t flags) ++{ ++ unsigned long addr = __fix_to_virt(idx); ++ pte_t *ptep; + -+ /* use a contiguous mapping if the range is suitably aligned */ -+ if ((((addr | next | phys) & ~CONT_PMD_MASK) == 0) && -+ (flags & NO_CONT_MAPPINGS) == 0) -+ __prot = __pgprot(pgprot_val(prot) | PTE_CONT); ++ BUG_ON(idx <= FIX_HOLE || idx >= __end_of_fixed_addresses); + -+ iee_init_pmd_pre_init(pudp, addr, next, phys, __prot, pgtable_alloc, flags); ++ ptep = fixmap_pte(addr); + -+ phys += next - addr; -+ } while (addr = next, addr != end); ++ if (pgprot_val(flags)) { ++ iee_set_pte_pre_init(ptep, pfn_pte(phys >> PAGE_SHIFT, flags)); ++ } else { ++ iee_set_pte_pre_init(ptep, __pte(0)); ++ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); ++ } +} ++#endif + -+static __init void iee_alloc_init_pud_pre_init(pgd_t *pgdp, unsigned long addr, unsigned long end, -+ phys_addr_t phys, pgprot_t prot, -+ phys_addr_t (*pgtable_alloc)(int), -+ int flags) -+{ -+ unsigned long next; -+ pud_t *pudp; -+ p4d_t *p4dp = p4d_offset(pgdp, addr); -+ p4d_t p4d = READ_ONCE(*p4dp); -+ -+ if (p4d_none(p4d)) { -+ p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN; -+ phys_addr_t pud_phys; -+ -+ if (flags & NO_EXEC_MAPPINGS) -+ p4dval |= P4D_TABLE_PXN; -+ BUG_ON(!pgtable_alloc); -+ pud_phys = pgtable_alloc(PUD_SHIFT); -+ __iee_p4d_populate_pre_init(p4dp, pud_phys, p4dval); -+ p4d = READ_ONCE(*p4dp); -+ } -+ BUG_ON(p4d_bad(p4d)); -+ -+ pudp = pud_set_fixmap_offset_init(p4dp, addr); -+ do { -+ pud_t old_pud = READ_ONCE(*pudp); + /* + * Unusually, this is also called in IRQ context (ghes_iounmap_irq) so if we + * ever need to use IPIs for TLB broadcasting, then we're in trouble here. +@@ -121,9 +172,17 @@ void __set_fixmap(enum fixed_addresses idx, + ptep = fixmap_pte(addr); + + if (pgprot_val(flags)) { ++ #ifdef CONFIG_PTP ++ iee_set_bm_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, flags)); ++ #else + __set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, flags)); ++ #endif + } else { ++ #ifdef CONFIG_PTP ++ iee_set_bm_pte(ptep, __pte(0)); ++ #else + __pte_clear(&init_mm, addr, ptep); ++ #endif + flush_tlb_kernel_range(addr, addr+PAGE_SIZE); + } + } +@@ -179,8 +238,13 @@ void __init fixmap_copy(pgd_t *pgdir) + * live in the carveout for the swapper_pg_dir. We can simply + * re-use the existing dir for the fixmap. + */ ++ #ifdef CONFIG_PTP ++ set_pgd_init(pgd_offset_pgd(pgdir, FIXADDR_TOT_START), ++ READ_ONCE(*pgd_offset_k(FIXADDR_TOT_START))); ++ #else + set_pgd(pgd_offset_pgd(pgdir, FIXADDR_TOT_START), + READ_ONCE(*pgd_offset_k(FIXADDR_TOT_START))); ++ #endif + } else if (CONFIG_PGTABLE_LEVELS > 3) { + pgd_t *bm_pgdp; + p4d_t *bm_p4dp; +@@ -194,9 +258,15 @@ void __init fixmap_copy(pgd_t *pgdir) + BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES)); + bm_pgdp = pgd_offset_pgd(pgdir, FIXADDR_TOT_START); + bm_p4dp = p4d_offset(bm_pgdp, FIXADDR_TOT_START); ++ #ifdef CONFIG_PTP ++ bm_pudp = pud_set_fixmap_offset_init(bm_p4dp, FIXADDR_TOT_START); ++ __iee_pud_populate_pre_init(bm_pudp, __pa(lm_alias(bm_pmd)), PMD_TYPE_TABLE); ++ pud_clear_fixmap_init(); ++ #else + bm_pudp = pud_set_fixmap_offset(bm_p4dp, FIXADDR_TOT_START); + pud_populate(&init_mm, bm_pudp, lm_alias(bm_pmd)); + pud_clear_fixmap(); ++ #endif + } else { + BUG(); + } +diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c +index 66a7fff9f373..fa3726fb793d 100644 +--- a/arch/arm64/mm/init.c ++++ b/arch/arm64/mm/init.c +@@ -56,8 +56,20 @@ + * that cannot be mistaken for a real physical address. + */ + s64 memstart_addr __ro_after_init = -1; ++#if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++s64 memstart_addr_init __ro_after_init = -1; ++#endif ++#ifdef CONFIG_KOI ++s64 koi_offset __ro_after_init = -1; ++EXPORT_SYMBOL(koi_offset); ++#endif ++#ifdef CONFIG_IEE ++s64 iee_offset __ro_after_init = -1; ++extern s64 iee_si_offset; ++#endif + EXPORT_SYMBOL(memstart_addr); + + -+ next = pud_addr_end(addr, end); + /* + * If the corresponding config options are enabled, we create both ZONE_DMA + * and ZONE_DMA32. By default ZONE_DMA covers the 32-bit addressable memory +@@ -422,7 +434,11 @@ early_param("memmap", parse_memmap_opt); + + void __init arm64_memblock_init(void) + { ++ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++ s64 linear_region_size = BIT(vabits_actual - 2); ++ #else + s64 linear_region_size = PAGE_END - _PAGE_OFFSET(vabits_actual); ++ #endif + + /* + * Corner case: 52-bit VA capable systems running KVM in nVHE mode may +@@ -439,13 +455,24 @@ void __init arm64_memblock_init(void) + } + + /* Remove memory above our supported physical address size */ ++ #ifdef CONFIG_IEE ++ // If config iee, phys size can not be above 0x400000000000 ++ if(__pa_symbol(_end) > BIT_ULL(vabits_actual - 2)) ++ panic("Image on too high phys mem.\n"); ++ else ++ memblock_remove(BIT_ULL(vabits_actual - 2), ULLONG_MAX); ++ #else + memblock_remove(1ULL << PHYS_MASK_SHIFT, ULLONG_MAX); ++ #endif + + /* + * Select a suitable value for the base of physical memory. + */ + memstart_addr = round_down(memblock_start_of_DRAM(), + ARM64_MEMSTART_ALIGN); ++ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++ memstart_addr_init = memstart_addr; ++ #endif + + if ((memblock_end_of_DRAM() - memstart_addr) > linear_region_size) + pr_warn("Memory doesn't fit in the linear mapping, VA_BITS too small\n"); +@@ -532,6 +559,15 @@ void __init arm64_memblock_init(void) + ((range * memstart_offset_seed) >> 16); + } + } ++ ++ #ifdef CONFIG_KOI ++ koi_offset = memstart_addr - memstart_addr_init + ((unsigned long)BIT(vabits_actual - 2)); ++ #endif ++ #ifdef CONFIG_IEE ++ iee_offset = memstart_addr - memstart_addr_init + ((unsigned long)BIT(vabits_actual - 2)); ++ iee_si_offset = iee_offset; ++ #endif ++ //printk(KERN_ERR "koi_offset: 0x%16llx\n", koi_offset); + + /* + * Register the kernel text, kernel data, initrd, and initial +diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c +index 31f04f19b635..753fa8d887f3 100644 +--- a/arch/arm64/mm/mmu.c ++++ b/arch/arm64/mm/mmu.c +@@ -6,6 +6,7 @@ + * Copyright (C) 2012 ARM Ltd. + */ + ++#include "asm/pgtable.h" + #include + #include + #include +@@ -41,6 +42,14 @@ + #include + #include + #include ++#ifdef CONFIG_IEE ++#include ++#include ++#include ++#endif ++#ifdef CONFIG_PTP ++#include ++#endif + + #define NO_BLOCK_MAPPINGS BIT(0) + #define NO_CONT_MAPPINGS BIT(1) +@@ -77,8 +86,249 @@ EXPORT_SYMBOL(empty_zero_page); + static DEFINE_SPINLOCK(swapper_pgdir_lock); + static DEFINE_MUTEX(fixmap_lock); + ++#ifdef CONFIG_IEE ++extern struct cred init_cred; + -+ /* -+ * For 4K granule only, attempt to put down a 1GB block -+ */ -+ if (pud_sect_supported() && -+ ((addr | next | phys) & ~PUD_MASK) == 0 && -+ (flags & NO_BLOCK_MAPPINGS) == 0) { -+ iee_pud_set_huge_pre_init(pudp, phys, prot); ++extern unsigned long __iee_si_data_start[]; ++extern unsigned long __iee_exec_entry_start[]; ++extern unsigned long __iee_si_text_start[]; ++extern unsigned long __iee_si_text_end[]; + -+ /* -+ * After the PUD entry has been populated once, we -+ * only allow updates to the permission attributes. -+ */ -+ BUG_ON(!pgattr_change_is_safe(pud_val(old_pud), -+ READ_ONCE(pud_val(*pudp)))); -+ } else { -+ iee_alloc_init_cont_pmd_pre_init(pudp, addr, next, phys, prot, -+ pgtable_alloc, flags); ++extern void *bm_pte_addr; ++extern void *bm_pmd_addr; ++extern void *bm_pud_addr; + -+ BUG_ON(pud_val(old_pud) != 0 && -+ pud_val(old_pud) != READ_ONCE(pud_val(*pudp))); -+ } -+ phys += next - addr; -+ } while (pudp++, addr = next, addr != end); ++void *init_token_page_vaddr; + -+ pud_clear_fixmap_init(); -+} ++#ifdef CONFIG_PTP + -+static __init void __iee_create_pgd_mapping_locked_pre_init(pgd_t *pgdir, phys_addr_t phys, -+ unsigned long virt, phys_addr_t size, -+ pgprot_t prot, -+ phys_addr_t (*pgtable_alloc)(int), -+ int flags) ++/* Funcs to set pgtable before iee initialized. */ ++static void iee_set_swapper_pgd_pre_init(pgd_t *pgdp, pgd_t pgd) +{ -+ unsigned long addr, end, next; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, virt); -+ p4d_t *p4dp; -+ p4d_t p4d; ++ pgd_t *fixmap_pgdp; + ++ spin_lock(&swapper_pgdir_lock); ++ fixmap_pgdp = pgd_set_fixmap_init(__pa_symbol(pgdp)); ++ WRITE_ONCE(*fixmap_pgdp, pgd); + /* -+ * If the virtual and physical address don't have the same offset -+ * within a page, we cannot map the region as the caller expects. ++ * We need dsb(ishst) here to ensure the page-table-walker sees ++ * our new entry before set_p?d() returns. The fixmap's ++ * flush_tlb_kernel_range() via clear_fixmap() does this for us. + */ -+ if (WARN_ON((phys ^ virt) & ~PAGE_MASK)) -+ return; -+ -+ phys &= PAGE_MASK; -+ addr = virt & PAGE_MASK; -+ end = PAGE_ALIGN(virt + size); -+ -+ do { -+ next = pgd_addr_end(addr, end); -+ iee_alloc_init_pud_pre_init(pgdp, addr, next, phys, prot, pgtable_alloc, -+ flags); -+ p4dp = p4d_offset(pgdp, addr); -+ p4d = READ_ONCE(*p4dp); -+ __iee_p4d_populate_pre_init(p4dp, __p4d_to_phys(p4d), (PGD_APT | PUD_TYPE_TABLE)); -+ phys += next - addr; -+ } while (pgdp++, addr = next, addr != end); ++ pgd_clear_fixmap_init(); ++ spin_unlock(&swapper_pgdir_lock); +} + -+static __init void __iee_create_pgd_mapping_pre_init(pgd_t *pgdir, phys_addr_t phys, -+ unsigned long virt, phys_addr_t size, -+ pgprot_t prot, -+ phys_addr_t (*pgtable_alloc)(int), -+ int flags) ++void iee_set_p4d_pre_init(p4d_t *p4dp, p4d_t p4d) +{ -+ mutex_lock(&fixmap_lock); -+ __iee_create_pgd_mapping_locked_pre_init(pgdir, phys, virt, size, prot, -+ pgtable_alloc, flags); -+ mutex_unlock(&fixmap_lock); ++ if (in_swapper_pgdir(p4dp)) { ++ iee_set_swapper_pgd_pre_init((pgd_t *)p4dp, __pgd(p4d_val(p4d))); ++ return; ++ } ++ ++ WRITE_ONCE(*p4dp, p4d); ++ dsb(ishst); ++ isb(); +} -+#endif + -+static phys_addr_t __pgd_pgtable_alloc(int shift) ++static inline void iee_set_pud_pre_init(pud_t *pudp, pud_t pud) +{ -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; -+ #endif -+ void *ptr = (void *)__get_free_page(GFP_PGTABLE_KERNEL); -+ BUG_ON(!ptr); -+ -+ #ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(ptr)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)ptr); -+ #endif ++#ifdef __PAGETABLE_PUD_FOLDED ++ if (in_swapper_pgdir(pudp)) { ++ iee_set_swapper_pgd_pre_init((pgd_t *)pudp, __pgd(pud_val(pud))); ++ return; ++ } ++#endif /* __PAGETABLE_PUD_FOLDED */ ++#ifdef CONFIG_KOI ++ pudval_t val = pud_val(pud); ++ if (pud_valid(pud) && !(val & PUD_TABLE_BIT)) { ++ // There is no PUD_SEC_NG, so we use PMD_SECT_NG instead. ++ pud = __pud(val | PMD_SECT_NG); ++ } ++#endif ++ WRITE_ONCE(*pudp, pud); + -+ /* Ensure the zeroed page is visible to the page table walker */ -+ dsb(ishst); -+ return __pa(ptr); ++ if (pud_valid(pud)) { ++ dsb(ishst); ++ isb(); ++ } +} + -+static phys_addr_t pgd_pgtable_alloc(int shift) ++static inline void iee_set_pmd_pre_init(pmd_t *pmdp, pmd_t pmd) +{ -+ phys_addr_t pa = __pgd_pgtable_alloc(shift); -+ struct ptdesc *ptdesc = page_ptdesc(phys_to_page(pa)); -+ -+ /* -+ * Call proper page table ctor in case later we need to -+ * call core mm functions like apply_to_page_range() on -+ * this pre-allocated page table. -+ * -+ * We don't select ARCH_ENABLE_SPLIT_PMD_PTLOCK if pmd is -+ * folded, and if so pagetable_pte_ctor() becomes nop. -+ */ -+ if (shift == PAGE_SHIFT) -+ BUG_ON(!pagetable_pte_ctor(ptdesc)); -+ else if (shift == PMD_SHIFT) -+ BUG_ON(!pagetable_pmd_ctor(ptdesc)); ++#ifdef __PAGETABLE_PMD_FOLDED ++ if (in_swapper_pgdir(pmdp)) { ++ iee_set_swapper_pgd_pre_init((pgd_t *)pmdp, __pgd(pmd_val(pmd))); ++ return; ++ } ++#endif /* __PAGETABLE_PMD_FOLDED */ ++#ifdef CONFIG_KOI ++ pmdval_t val = pmd_val(pmd); ++ if (pmd_valid(pmd) && !(val & PMD_TABLE_BIT)) { ++ pmd = __pmd(val | PMD_SECT_NG); ++ } ++#endif ++ WRITE_ONCE(*pmdp, pmd); + -+ return pa; ++ if (pmd_valid(pmd)) { ++ dsb(ishst); ++ isb(); ++ } +} + -+/* -+ * This function can only be used to modify existing table entries, -+ * without allocating new levels of table. Note that this permits the -+ * creation of new section or page entries. -+ */ -+void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt, -+ phys_addr_t size, pgprot_t prot) ++ ++void __iee_p4d_populate_pre_init(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot) +{ -+ if (virt < PAGE_OFFSET) { -+ pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n", -+ &phys, virt); -+ return; -+ } ++ iee_set_p4d_pre_init(p4dp, __p4d(__phys_to_p4d_val(pudp) | prot)); ++} + -+ #ifdef CONFIG_PTP -+ __iee_create_pgd_mapping_pre_init(init_mm.pgd, phys, virt, size, prot, NULL, -+ NO_CONT_MAPPINGS); -+ #else -+ __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, -+ NO_CONT_MAPPINGS); -+ #endif ++void __iee_pud_populate_pre_init(pud_t *pudp, phys_addr_t pmdp, pudval_t prot) ++{ ++ iee_set_pud_pre_init(pudp, __pud(__phys_to_pud_val(pmdp) | prot)); +} + -+void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, -+ unsigned long virt, phys_addr_t size, -+ pgprot_t prot, bool page_mappings_only) ++void __iee_pmd_populate_pre_init(pmd_t *pmdp, phys_addr_t ptep, ++ pmdval_t prot) +{ -+ int flags = 0; ++ iee_set_pmd_pre_init(pmdp, __pmd(__phys_to_pmd_val(ptep) | prot)); ++} + -+ BUG_ON(mm == &init_mm); ++/* Funcs to set fixmap before iee initialized. */ ++bool pgattr_change_is_safe(u64 old, u64 new); ++static int iee_pud_set_huge_fixmap(pud_t *pudp, phys_addr_t phys, pgprot_t prot) ++{ ++ pud_t new_pud = pfn_pud(__phys_to_pfn(phys), mk_pud_sect_prot(prot)); + -+ if (page_mappings_only) -+ flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; ++ /* Only allow permission changes for now */ ++ if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pudp)), ++ pud_val(new_pud))) ++ return 0; + -+ __create_pgd_mapping(mm->pgd, phys, virt, size, prot, -+ pgd_pgtable_alloc, flags); ++ VM_BUG_ON(phys & ~PUD_MASK); ++ iee_set_fixmap_pud_pre_init(pudp, new_pud); ++ return 1; +} + -+static void update_mapping_prot(phys_addr_t phys, unsigned long virt, -+ phys_addr_t size, pgprot_t prot) ++static int iee_pmd_set_huge_fixmap(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) +{ -+ if (virt < PAGE_OFFSET) { -+ pr_warn("BUG: not updating mapping for %pa at 0x%016lx - outside kernel range\n", -+ &phys, virt); -+ return; -+ } ++ pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), mk_pmd_sect_prot(prot)); + -+ __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, -+ NO_CONT_MAPPINGS); ++ /* Only allow permission changes for now */ ++ if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)), ++ pmd_val(new_pmd))) ++ return 0; + -+ /* flush the TLBs after updating live kernel mappings */ -+ flush_tlb_kernel_range(virt, virt + size); ++ VM_BUG_ON(phys & ~PMD_MASK); ++ iee_set_fixmap_pmd_pre_init(pmdp, new_pmd); ++ return 1; +} + -+static void __init __map_memblock(pgd_t *pgdp, phys_addr_t start, -+ phys_addr_t end, pgprot_t prot, int flags) ++static inline void __iee_pmd_populate_fixmap(pmd_t *pmdp, phys_addr_t ptep, ++ pmdval_t prot) +{ -+ #ifdef CONFIG_PTP -+ __iee_create_pgd_mapping_pre_init(pgdp, start, __phys_to_virt(start), end - start, -+ prot, early_pgtable_alloc, flags); -+ #else -+ __create_pgd_mapping(pgdp, start, __phys_to_virt(start), end - start, -+ prot, early_pgtable_alloc, flags); -+ #endif ++ iee_set_fixmap_pmd_pre_init(pmdp, __pmd(__phys_to_pmd_val(ptep) | prot)); +} + -+void __init mark_linear_text_alias_ro(void) ++static inline void __iee_pud_populate_fixmap(pud_t *pudp, phys_addr_t pmdp, pudval_t prot) +{ -+ /* -+ * Remove the write permissions from the linear alias of .text/.rodata -+ */ -+ update_mapping_prot(__pa_symbol(_stext), (unsigned long)lm_alias(_stext), -+ (unsigned long)__init_begin - (unsigned long)_stext, -+ PAGE_KERNEL_RO); ++ iee_set_fixmap_pud_pre_init(pudp, __pud(__phys_to_pud_val(pmdp) | prot)); +} ++#endif /* END CONFIG_PTP*/ + -+#ifdef CONFIG_KFENCE ++void iee_set_pte_pre_init(pte_t *ptep, pte_t pte) ++{ ++#ifdef CONFIG_KOI ++ if (pte_valid(pte)) { ++ pte = __pte(pte_val(pte) | PTE_NG); ++ } ++#endif ++ WRITE_ONCE(*ptep, pte); + -+bool __ro_after_init kfence_early_init = !!CONFIG_KFENCE_SAMPLE_INTERVAL; ++ /* ++ * Only if the new pte is valid and kernel, otherwise TLB maintenance ++ * or update_mmu_cache() have the necessary barriers. ++ */ ++ if (pte_valid_not_user(pte)) { ++ dsb(ishst); ++ isb(); ++ } ++} + -+/* early_param() will be parsed before map_mem() below. */ -+static int __init parse_kfence_early_init(char *arg) ++static void __init iee_set_token_page_valid_pre_init(void *token, void *new) +{ -+ int val; ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, (unsigned long)token); + -+ if (get_option(&arg, &val)) -+ kfence_early_init = !!val; ++ p4d_t *p4dp = p4d_offset(pgdp, (unsigned long)token); + -+#if IS_ENABLED(CONFIG_KFENCE_MUST_EARLY_INIT) -+ kfence_must_early_init = (val == -1) ? true : false; -+#endif ++ pud_t *pudp = pud_offset(p4dp, (unsigned long)token); + -+ return 0; ++ pmd_t *pmdp = pmd_offset(pudp, (unsigned long)token); ++ ++ pte_t *ptep = pte_offset_kernel(pmdp, (unsigned long)token); ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) | 0x1) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(new))); ++ #ifdef CONFIG_PTP ++ iee_set_pte_pre_init(ptep, pte); ++ #else ++ set_pte(ptep, pte); ++ #endif ++ flush_tlb_kernel_range((unsigned long)token, (unsigned long)(token+PAGE_SIZE)); ++ isb(); +} -+early_param("kfence.sample_interval", parse_kfence_early_init); ++#endif /* END CONFIG_IEE*/ ++ ++#if defined(CONFIG_KOI) && !defined(CONFIG_IEE) + -+static phys_addr_t __init arm64_kfence_alloc_pool(void) ++void koi_add_page_mapping(void *token, void *new) +{ -+ phys_addr_t kfence_pool; ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, (unsigned long)token); + -+ if (!kfence_early_init) -+ return 0; ++ p4d_t *p4dp = p4d_offset(pgdp, (unsigned long)token); + -+ kfence_pool = memblock_phys_alloc(KFENCE_POOL_SIZE, PAGE_SIZE); -+ if (!kfence_pool) { -+ pr_err("failed to allocate kfence pool\n"); -+ kfence_early_init = false; -+ return 0; -+ } ++ pud_t *pudp = pud_offset(p4dp, (unsigned long)token); + -+ /* Temporarily mark as NOMAP. */ -+ memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE); ++ pmd_t *pmdp = pmd_offset(pudp, (unsigned long)token); + -+ return kfence_pool; ++ pte_t *ptep = pte_offset_kernel(pmdp, (unsigned long)token); ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) | 0x1) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(new))); ++ set_pte(ptep, pte); ++ dsb(ishst); ++ isb(); ++ ++ flush_tlb_kernel_range((unsigned long)new, (unsigned long)new+PAGE_SIZE); ++ flush_tlb_kernel_range((unsigned long)token, (unsigned long)token+PAGE_SIZE); ++ isb(); +} + -+static void __init arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) -+{ -+ if (!kfence_pool) -+ return; ++void koi_remove_page_mapping(unsigned long token) { ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, token); + -+ /* KFENCE pool needs page-level mapping. */ -+ __map_memblock(pgdp, kfence_pool, kfence_pool + KFENCE_POOL_SIZE, -+ pgprot_tagged(PAGE_KERNEL), -+ NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS); -+ memblock_clear_nomap(kfence_pool, KFENCE_POOL_SIZE); -+ __kfence_pool = phys_to_virt(kfence_pool); -+} -+#else /* CONFIG_KFENCE */ ++ p4d_t *p4dp = p4d_offset(pgdp, token); + -+static inline phys_addr_t arm64_kfence_alloc_pool(void) { return 0; } -+static inline void arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) { } ++ pud_t *pudp = pud_offset(p4dp, token); + -+#endif /* CONFIG_KFENCE */ ++ pmd_t *pmdp = pmd_offset(pudp, token); ++ ++ pte_t *ptep = pte_offset_kernel(pmdp, token); ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(((pte_val(pte) & ~((unsigned long)0x1)) & ~PTE_ADDR_MASK) | __phys_to_pte_val(__pa(token - KOI_OFFSET))); ++ set_pte(ptep, pte); ++ flush_tlb_kernel_range(token, token+PAGE_SIZE); ++ isb(); ++} ++#endif + -+static void __init map_mem(pgd_t *pgdp) + void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd) + { ++ #ifdef CONFIG_PTP ++ spin_lock(&swapper_pgdir_lock); ++ iee_rw_gate(IEE_OP_SET_SWAPPER_PGD, pgdp, pgd); ++ spin_unlock(&swapper_pgdir_lock); ++ #else + pgd_t *fixmap_pgdp; + + spin_lock(&swapper_pgdir_lock); +@@ -91,6 +341,7 @@ void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd) + */ + pgd_clear_fixmap(); + spin_unlock(&swapper_pgdir_lock); ++ #endif + } + + pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, +@@ -104,6 +355,34 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + } + EXPORT_SYMBOL(phys_mem_access_prot); + ++#ifdef CONFIG_PTP ++phys_addr_t __init early_pgtable_alloc(int shift) +{ -+ static const u64 direct_map_end = _PAGE_END(VA_BITS_MIN); -+ phys_addr_t kernel_start = __pa_symbol(_stext); -+ phys_addr_t kernel_end = __pa_symbol(__init_begin); -+ phys_addr_t start, end; -+ phys_addr_t early_kfence_pool; -+ int flags = NO_EXEC_MAPPINGS; -+ u64 i; ++ phys_addr_t phys; ++ void *ptr; ++ ++ phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE); ++ if (!phys) ++ panic("Failed to allocate page table page\n"); + + /* -+ * Setting hierarchical PXNTable attributes on table entries covering -+ * the linear region is only possible if it is guaranteed that no table -+ * entries at any level are being shared between the linear region and -+ * the vmalloc region. Check whether this is true for the PGD level, in -+ * which case it is guaranteed to be true for all other levels as well. ++ * The FIX_{PGD,PUD,PMD} slots may be in active use, but the FIX_PTE ++ * slot will be free, so we can (ab)use the FIX_PTE slot to initialise ++ * any level of table. + */ -+ BUILD_BUG_ON(pgd_index(direct_map_end - 1) == pgd_index(direct_map_end)); -+ -+ early_kfence_pool = arm64_kfence_alloc_pool(); ++ ptr = pte_set_fixmap_init(phys); + -+ if (can_set_direct_map()) -+ flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; ++ memset(ptr, 0, PAGE_SIZE); + -+ #ifdef CONFIG_IEE -+ flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; -+ #endif + /* -+ * Take care not to create a writable alias for the -+ * read-only text and rodata sections of the kernel image. -+ * So temporarily mark them as NOMAP to skip mappings in -+ * the following for-loop ++ * Implicit barriers also ensure the zeroed page is visible to the page ++ * table walker + */ -+ memblock_mark_nomap(kernel_start, kernel_end - kernel_start); ++ pte_clear_fixmap_init(); + -+ /* map all the memory banks */ -+ for_each_mem_range(i, &start, &end) { -+ if (start >= end) -+ break; ++ return phys; ++} ++#else + static phys_addr_t __init early_pgtable_alloc(int shift) + { + phys_addr_t phys; +@@ -119,7 +398,11 @@ static phys_addr_t __init early_pgtable_alloc(int shift) + * slot will be free, so we can (ab)use the FIX_PTE slot to initialise + * any level of table. + */ ++ #ifdef CONFIG_PTP ++ ptr = pte_set_fixmap_init(phys); ++ #else + ptr = pte_set_fixmap(phys); ++ #endif + + memset(ptr, 0, PAGE_SIZE); + +@@ -127,10 +410,15 @@ static phys_addr_t __init early_pgtable_alloc(int shift) + * Implicit barriers also ensure the zeroed page is visible to the page + * table walker + */ ++ #ifdef CONFIG_PTP ++ pte_clear_fixmap_init(); ++ #else + pte_clear_fixmap(); ++ #endif + + return phys; + } ++#endif + + bool pgattr_change_is_safe(u64 old, u64 new) + { +@@ -179,7 +467,11 @@ static void init_pte(pmd_t *pmdp, unsigned long addr, unsigned long end, + do { + pte_t old_pte = __ptep_get(ptep); + ++ #ifdef CONFIG_PTP ++ iee_set_fixmap_pte_pre_init(ptep, pfn_pte(__phys_to_pfn(phys), prot)); ++ #else + __set_pte(ptep, pfn_pte(__phys_to_pfn(phys), prot)); ++ #endif + + /* + * After the PTE entry has been populated once, we +@@ -212,7 +504,11 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr, + pmdval |= PMD_TABLE_PXN; + BUG_ON(!pgtable_alloc); + pte_phys = pgtable_alloc(PAGE_SHIFT); ++ #ifdef CONFIG_PTP ++ __iee_pmd_populate_fixmap(pmdp, pte_phys, pmdval); ++ #else + __pmd_populate(pmdp, pte_phys, pmdval); ++ #endif + pmd = READ_ONCE(*pmdp); + } + BUG_ON(pmd_bad(pmd)); +@@ -247,9 +543,17 @@ static void init_pmd(pud_t *pudp, unsigned long addr, unsigned long end, + next = pmd_addr_end(addr, end); + + /* try section mapping first */ ++ #ifdef CONFIG_IEE ++ if (!((pmd_val(old_pmd) & PTE_VALID) && (pmd_val(old_pmd) & PTE_TABLE_BIT)) && (((addr | next | phys) & ~PMD_MASK) == 0 && (flags & NO_BLOCK_MAPPINGS) == 0)) { ++ #else + if (((addr | next | phys) & ~PMD_MASK) == 0 && + (flags & NO_BLOCK_MAPPINGS) == 0) { ++ #endif ++ #ifdef CONFIG_PTP ++ iee_pmd_set_huge_fixmap(pmdp, phys, prot); ++ #else + pmd_set_huge(pmdp, phys, prot); ++ #endif + + /* + * After the PMD entry has been populated once, we +@@ -290,7 +594,11 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr, + pudval |= PUD_TABLE_PXN; + BUG_ON(!pgtable_alloc); + pmd_phys = pgtable_alloc(PMD_SHIFT); +- __pud_populate(pudp, pmd_phys, pudval); ++ #ifdef CONFIG_PTP ++ __iee_pud_populate_fixmap(pudp, pmd_phys, PUD_TYPE_TABLE); ++ #else ++ __pud_populate(pudp, pmd_phys, PUD_TYPE_TABLE); ++ #endif + pud = READ_ONCE(*pudp); + } + BUG_ON(pud_bad(pud)); +@@ -343,10 +651,21 @@ static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end, + /* + * For 4K granule only, attempt to put down a 1GB block + */ ++ #ifdef CONFIG_IEE ++ alloc_init_cont_pmd(pudp, addr, next, phys, prot, ++ pgtable_alloc, flags); ++ ++ BUG_ON(pud_val(old_pud) != 0 && ++ pud_val(old_pud) != READ_ONCE(pud_val(*pudp))); ++ #else + if (pud_sect_supported() && + ((addr | next | phys) & ~PUD_MASK) == 0 && + (flags & NO_BLOCK_MAPPINGS) == 0) { ++ #ifdef CONFIG_PTP ++ iee_pud_set_huge_fixmap(pudp, phys, prot); ++ #else + pud_set_huge(pudp, phys, prot); ++ #endif + + /* + * After the PUD entry has been populated once, we +@@ -361,6 +680,7 @@ static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end, + BUG_ON(pud_val(old_pud) != 0 && + pud_val(old_pud) != READ_ONCE(pud_val(*pudp))); + } ++ #endif + phys += next - addr; + } while (pudp++, addr = next, addr != end); + +@@ -375,6 +695,10 @@ static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys, + { + unsigned long addr, end, next; + pgd_t *pgdp = pgd_offset_pgd(pgdir, virt); ++ #ifdef CONFIG_IEE ++ p4d_t *p4dp; ++ p4d_t p4d; ++ #endif + + /* + * If the virtual and physical address don't have the same offset +@@ -391,10 +715,14 @@ static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys, + next = pgd_addr_end(addr, end); + alloc_init_pud(pgdp, addr, next, phys, prot, pgtable_alloc, + flags); ++ #ifdef CONFIG_IEE ++ p4dp = p4d_offset(pgdp, addr); ++ p4d = READ_ONCE(*p4dp); ++ __p4d_populate(p4dp, __p4d_to_phys(p4d), (PGD_APT | PUD_TYPE_TABLE)); ++ #endif + phys += next - addr; + } while (pgdp++, addr = next, addr != end); + } +- + static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys, + unsigned long virt, phys_addr_t size, + pgprot_t prot, +@@ -414,90 +742,364 @@ void create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt, + phys_addr_t (*pgtable_alloc)(int), int flags); + #endif + +-static phys_addr_t __pgd_pgtable_alloc(int shift) ++#ifdef CONFIG_PTP ++static int __init iee_pud_set_huge_pre_init(pud_t *pudp, phys_addr_t phys, pgprot_t prot) + { +- void *ptr = (void *)__get_free_page(GFP_PGTABLE_KERNEL); +- BUG_ON(!ptr); ++ pud_t new_pud = pfn_pud(__phys_to_pfn(phys), mk_pud_sect_prot(prot)); + +- /* Ensure the zeroed page is visible to the page table walker */ +- dsb(ishst); +- return __pa(ptr); ++ /* Only allow permission changes for now */ ++ if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pudp)), ++ pud_val(new_pud))) ++ return 0; ++ ++ VM_BUG_ON(phys & ~PUD_MASK); ++ iee_set_pud_pre_init(pudp, new_pud); ++ return 1; + } + +-static phys_addr_t pgd_pgtable_alloc(int shift) ++static int __init iee_pmd_set_huge_pre_init(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) + { +- phys_addr_t pa = __pgd_pgtable_alloc(shift); +- struct ptdesc *ptdesc = page_ptdesc(phys_to_page(pa)); ++ pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), mk_pmd_sect_prot(prot)); + +- /* +- * Call proper page table ctor in case later we need to +- * call core mm functions like apply_to_page_range() on +- * this pre-allocated page table. +- * +- * We don't select ARCH_ENABLE_SPLIT_PMD_PTLOCK if pmd is +- * folded, and if so pagetable_pte_ctor() becomes nop. +- */ +- if (shift == PAGE_SHIFT) +- BUG_ON(!pagetable_pte_ctor(ptdesc)); +- else if (shift == PMD_SHIFT) +- BUG_ON(!pagetable_pmd_ctor(ptdesc)); ++ /* Only allow permission changes for now */ ++ if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)), ++ pmd_val(new_pmd))) ++ return 0; + +- return pa; ++ VM_BUG_ON(phys & ~PMD_MASK); ++ iee_set_pmd_pre_init(pmdp, new_pmd); ++ return 1; + } + +-/* +- * This function can only be used to modify existing table entries, +- * without allocating new levels of table. Note that this permits the +- * creation of new section or page entries. +- */ +-void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt, +- phys_addr_t size, pgprot_t prot) ++static __init void iee_init_pte_pre_init(pmd_t *pmdp, unsigned long addr, unsigned long end, ++ phys_addr_t phys, pgprot_t prot) + { +- if (virt < PAGE_OFFSET) { +- pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n", +- &phys, virt); +- return; +- } +- __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, +- NO_CONT_MAPPINGS); +-} ++ pte_t *ptep; + +-void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, +- unsigned long virt, phys_addr_t size, +- pgprot_t prot, bool page_mappings_only) +-{ +- int flags = 0; ++ ptep = pte_set_fixmap_offset_init(pmdp, addr); ++ do { ++ pte_t old_pte = READ_ONCE(*ptep); + +- BUG_ON(mm == &init_mm); ++ iee_set_pte_pre_init(ptep, pfn_pte(__phys_to_pfn(phys), prot)); + +- if (page_mappings_only) +- flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; + /* -+ * The linear map must allow allocation tags reading/writing -+ * if MTE is present. Otherwise, it has the same attributes as -+ * PAGE_KERNEL. ++ * After the PTE entry has been populated once, we ++ * only allow updates to the permission attributes. + */ -+ __map_memblock(pgdp, start, end, pgprot_tagged(PAGE_KERNEL), -+ flags); -+ } ++ BUG_ON(!pgattr_change_is_safe(pte_val(old_pte), ++ READ_ONCE(pte_val(*ptep)))); -- return kfence_pool; -+ /* -+ * Map the linear alias of the [_stext, __init_begin) interval -+ * as non-executable now, and remove the write permission in -+ * mark_linear_text_alias_ro() below (which will be called after -+ * alternative patching has completed). This makes the contents -+ * of the region accessible to subsystems such as hibernate, -+ * but protects it from inadvertent modification or execution. -+ * Note that contiguous mappings cannot be remapped in this way, -+ * so we should avoid them here. -+ */ -+ #ifdef CONFIG_IEE -+ __map_memblock(pgdp, kernel_start, kernel_end, -+ PAGE_KERNEL, flags); +- __create_pgd_mapping(mm->pgd, phys, virt, size, prot, +- pgd_pgtable_alloc, flags); ++ phys += PAGE_SIZE; ++ } while (ptep++, addr += PAGE_SIZE, addr != end); ++ ++ pte_clear_fixmap_init(); + } + +-static void update_mapping_prot(phys_addr_t phys, unsigned long virt, +- phys_addr_t size, pgprot_t prot) ++static __init void iee_alloc_init_cont_pte_pre_init(pmd_t *pmdp, unsigned long addr, ++ unsigned long end, phys_addr_t phys, ++ pgprot_t prot, ++ phys_addr_t (*pgtable_alloc)(int), ++ int flags) + { +- if (virt < PAGE_OFFSET) { +- pr_warn("BUG: not updating mapping for %pa at 0x%016lx - outside kernel range\n", +- &phys, virt); +- return; ++ unsigned long next; ++ pmd_t pmd = READ_ONCE(*pmdp); ++ ++ BUG_ON(pmd_sect(pmd)); ++ if (pmd_none(pmd)) { ++ pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN; ++ phys_addr_t pte_phys; ++ ++ if (flags & NO_EXEC_MAPPINGS) ++ pmdval |= PMD_TABLE_PXN; ++ BUG_ON(!pgtable_alloc); ++ pte_phys = pgtable_alloc(PAGE_SHIFT); ++ __iee_pmd_populate_pre_init(pmdp, pte_phys, pmdval); ++ pmd = READ_ONCE(*pmdp); + } ++ BUG_ON(pmd_bad(pmd)); + +- __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, +- NO_CONT_MAPPINGS); ++ do { ++ pgprot_t __prot = prot; + +- /* flush the TLBs after updating live kernel mappings */ +- flush_tlb_kernel_range(virt, virt + size); ++ next = pte_cont_addr_end(addr, end); ++ ++ /* use a contiguous mapping if the range is suitably aligned */ ++ if ((((addr | next | phys) & ~CONT_PTE_MASK) == 0) && ++ (flags & NO_CONT_MAPPINGS) == 0) ++ __prot = __pgprot(pgprot_val(prot) | PTE_CONT); ++ ++ iee_init_pte_pre_init(pmdp, addr, next, phys, __prot); ++ ++ phys += next - addr; ++ } while (addr = next, addr != end); ++} ++ ++static __init void iee_init_pmd_pre_init(pud_t *pudp, unsigned long addr, unsigned long end, ++ phys_addr_t phys, pgprot_t prot, ++ phys_addr_t (*pgtable_alloc)(int), int flags) ++{ ++ unsigned long next; ++ pmd_t *pmdp; ++ ++ pmdp = pmd_set_fixmap_offset_init(pudp, addr); ++ do { ++ pmd_t old_pmd = READ_ONCE(*pmdp); ++ ++ next = pmd_addr_end(addr, end); ++ ++ /* try section mapping first */ ++ if (((addr | next | phys) & ~PMD_MASK) == 0 && ++ (flags & NO_BLOCK_MAPPINGS) == 0) { ++ iee_pmd_set_huge_pre_init(pmdp, phys, prot); ++ ++ /* ++ * After the PMD entry has been populated once, we ++ * only allow updates to the permission attributes. ++ */ ++ BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd), ++ READ_ONCE(pmd_val(*pmdp)))); ++ } else { ++ iee_alloc_init_cont_pte_pre_init(pmdp, addr, next, phys, prot, ++ pgtable_alloc, flags); ++ ++ BUG_ON(pmd_val(old_pmd) != 0 && ++ pmd_val(old_pmd) != READ_ONCE(pmd_val(*pmdp))); ++ } ++ phys += next - addr; ++ } while (pmdp++, addr = next, addr != end); ++ ++ pmd_clear_fixmap_init(); ++} ++ ++static __init void iee_alloc_init_cont_pmd_pre_init(pud_t *pudp, unsigned long addr, ++ unsigned long end, phys_addr_t phys, ++ pgprot_t prot, ++ phys_addr_t (*pgtable_alloc)(int), int flags) ++{ ++ unsigned long next; ++ pud_t pud = READ_ONCE(*pudp); ++ ++ /* ++ * Check for initial section mappings in the pgd/pud. ++ */ ++ BUG_ON(pud_sect(pud)); ++ if (pud_none(pud)) { ++ pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN; ++ phys_addr_t pmd_phys; ++ ++ if (flags & NO_EXEC_MAPPINGS) ++ pudval |= PUD_TABLE_PXN; ++ BUG_ON(!pgtable_alloc); ++ pmd_phys = pgtable_alloc(PMD_SHIFT); ++ __iee_pud_populate_pre_init(pudp, pmd_phys, pudval); ++ pud = READ_ONCE(*pudp); ++ } ++ BUG_ON(pud_bad(pud)); ++ ++ do { ++ pgprot_t __prot = prot; ++ ++ next = pmd_cont_addr_end(addr, end); ++ ++ /* use a contiguous mapping if the range is suitably aligned */ ++ if ((((addr | next | phys) & ~CONT_PMD_MASK) == 0) && ++ (flags & NO_CONT_MAPPINGS) == 0) ++ __prot = __pgprot(pgprot_val(prot) | PTE_CONT); ++ ++ iee_init_pmd_pre_init(pudp, addr, next, phys, __prot, pgtable_alloc, flags); ++ ++ phys += next - addr; ++ } while (addr = next, addr != end); ++} ++ ++static __init void iee_alloc_init_pud_pre_init(pgd_t *pgdp, unsigned long addr, unsigned long end, ++ phys_addr_t phys, pgprot_t prot, ++ phys_addr_t (*pgtable_alloc)(int), ++ int flags) ++{ ++ unsigned long next; ++ pud_t *pudp; ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ p4d_t p4d = READ_ONCE(*p4dp); ++ ++ if (p4d_none(p4d)) { ++ p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN; ++ phys_addr_t pud_phys; ++ ++ if (flags & NO_EXEC_MAPPINGS) ++ p4dval |= P4D_TABLE_PXN; ++ BUG_ON(!pgtable_alloc); ++ pud_phys = pgtable_alloc(PUD_SHIFT); ++ __iee_p4d_populate_pre_init(p4dp, pud_phys, p4dval); ++ p4d = READ_ONCE(*p4dp); ++ } ++ BUG_ON(p4d_bad(p4d)); ++ ++ pudp = pud_set_fixmap_offset_init(p4dp, addr); ++ do { ++ pud_t old_pud = READ_ONCE(*pudp); ++ ++ next = pud_addr_end(addr, end); ++ ++ /* ++ * For 4K granule only, attempt to put down a 1GB block ++ */ ++ iee_alloc_init_cont_pmd_pre_init(pudp, addr, next, phys, prot, ++ pgtable_alloc, flags); ++ ++ BUG_ON(pud_val(old_pud) != 0 && ++ pud_val(old_pud) != READ_ONCE(pud_val(*pudp))); ++ phys += next - addr; ++ } while (pudp++, addr = next, addr != end); ++ ++ pud_clear_fixmap_init(); ++} ++ ++static __init void __iee_create_pgd_mapping_locked_pre_init(pgd_t *pgdir, phys_addr_t phys, ++ unsigned long virt, phys_addr_t size, ++ pgprot_t prot, ++ phys_addr_t (*pgtable_alloc)(int), ++ int flags) ++{ ++ unsigned long addr, end, next; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, virt); ++ p4d_t *p4dp; ++ p4d_t p4d; ++ ++ /* ++ * If the virtual and physical address don't have the same offset ++ * within a page, we cannot map the region as the caller expects. ++ */ ++ if (WARN_ON((phys ^ virt) & ~PAGE_MASK)) ++ return; ++ ++ phys &= PAGE_MASK; ++ addr = virt & PAGE_MASK; ++ end = PAGE_ALIGN(virt + size); ++ ++ do { ++ next = pgd_addr_end(addr, end); ++ iee_alloc_init_pud_pre_init(pgdp, addr, next, phys, prot, pgtable_alloc, ++ flags); ++ p4dp = p4d_offset(pgdp, addr); ++ p4d = READ_ONCE(*p4dp); ++ __iee_p4d_populate_pre_init(p4dp, __p4d_to_phys(p4d), (PGD_APT | PUD_TYPE_TABLE)); ++ phys += next - addr; ++ } while (pgdp++, addr = next, addr != end); ++} ++ ++static __init void __iee_create_pgd_mapping_pre_init(pgd_t *pgdir, phys_addr_t phys, ++ unsigned long virt, phys_addr_t size, ++ pgprot_t prot, ++ phys_addr_t (*pgtable_alloc)(int), ++ int flags) ++{ ++ mutex_lock(&fixmap_lock); ++ __iee_create_pgd_mapping_locked_pre_init(pgdir, phys, virt, size, prot, ++ pgtable_alloc, flags); ++ mutex_unlock(&fixmap_lock); ++} ++#endif ++ ++static phys_addr_t __pgd_pgtable_alloc(int shift) ++{ ++ #ifdef CONFIG_PTP ++ void *ptr = get_iee_pgtable_page(GFP_PGTABLE_KERNEL); ++ #else ++ void *ptr = (void *)__get_free_page(GFP_PGTABLE_KERNEL); ++ #endif ++ BUG_ON(!ptr); ++ ++ /* Ensure the zeroed page is visible to the page table walker */ ++ dsb(ishst); ++ return __pa(ptr); ++} ++ ++static phys_addr_t pgd_pgtable_alloc(int shift) ++{ ++ phys_addr_t pa = __pgd_pgtable_alloc(shift); ++ struct ptdesc *ptdesc = page_ptdesc(phys_to_page(pa)); ++ ++ /* ++ * Call proper page table ctor in case later we need to ++ * call core mm functions like apply_to_page_range() on ++ * this pre-allocated page table. ++ * ++ * We don't select ARCH_ENABLE_SPLIT_PMD_PTLOCK if pmd is ++ * folded, and if so pagetable_pte_ctor() becomes nop. ++ */ ++ if (shift == PAGE_SHIFT) ++ BUG_ON(!pagetable_pte_ctor(ptdesc)); ++ else if (shift == PMD_SHIFT) ++ BUG_ON(!pagetable_pmd_ctor(ptdesc)); ++ ++ return pa; ++} ++ ++/* ++ * This function can only be used to modify existing table entries, ++ * without allocating new levels of table. Note that this permits the ++ * creation of new section or page entries. ++ */ ++void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt, ++ phys_addr_t size, pgprot_t prot) ++{ ++ if (virt < PAGE_OFFSET) { ++ pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n", ++ &phys, virt); ++ return; ++ } ++ ++ #ifdef CONFIG_PTP ++ __iee_create_pgd_mapping_pre_init(init_mm.pgd, phys, virt, size, prot, NULL, ++ NO_CONT_MAPPINGS); ++ #else ++ __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, ++ NO_CONT_MAPPINGS); ++ #endif ++} ++ ++void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, ++ unsigned long virt, phys_addr_t size, ++ pgprot_t prot, bool page_mappings_only) ++{ ++ int flags = 0; ++ ++ BUG_ON(mm == &init_mm); ++ ++ if (page_mappings_only) ++ flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; ++ ++ __create_pgd_mapping(mm->pgd, phys, virt, size, prot, ++ pgd_pgtable_alloc, flags); ++} ++ ++static void update_mapping_prot(phys_addr_t phys, unsigned long virt, ++ phys_addr_t size, pgprot_t prot) ++{ ++ if (virt < PAGE_OFFSET) { ++ pr_warn("BUG: not updating mapping for %pa at 0x%016lx - outside kernel range\n", ++ &phys, virt); ++ return; ++ } ++ ++ __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, ++ NO_CONT_MAPPINGS); ++ ++ /* flush the TLBs after updating live kernel mappings */ ++ flush_tlb_kernel_range(virt, virt + size); + } + + static void __init __map_memblock(pgd_t *pgdp, phys_addr_t start, + phys_addr_t end, pgprot_t prot, int flags) + { ++ #ifdef CONFIG_PTP ++ __iee_create_pgd_mapping_pre_init(pgdp, start, __phys_to_virt(start), end - start, ++ prot, early_pgtable_alloc, flags); ++ #else + __create_pgd_mapping(pgdp, start, __phys_to_virt(start), end - start, + prot, early_pgtable_alloc, flags); ++ #endif + } + + void __init mark_linear_text_alias_ro(void) +@@ -645,157 +1247,815 @@ void mark_rodata_ro(void) + debug_checkwx(); + } + +-static void __init map_kernel_segment(pgd_t *pgdp, void *va_start, void *va_end, +- pgprot_t prot, struct vm_struct *vma, +- int flags, unsigned long vm_flags) ++static void __init map_kernel_segment(pgd_t *pgdp, void *va_start, void *va_end, ++ pgprot_t prot, struct vm_struct *vma, ++ int flags, unsigned long vm_flags) ++{ ++ phys_addr_t pa_start = __pa_symbol(va_start); ++ unsigned long size = va_end - va_start; ++ ++ BUG_ON(!PAGE_ALIGNED(pa_start)); ++ BUG_ON(!PAGE_ALIGNED(size)); ++ ++ #ifdef CONFIG_PTP ++ __iee_create_pgd_mapping_pre_init(pgdp, pa_start, (unsigned long)va_start, size, prot, ++ early_pgtable_alloc, flags); ++ #else ++ __create_pgd_mapping(pgdp, pa_start, (unsigned long)va_start, size, prot, ++ early_pgtable_alloc, flags); ++ #endif ++ ++ if (!(vm_flags & VM_NO_GUARD)) ++ size += PAGE_SIZE; ++ ++ vma->addr = va_start; ++ vma->phys_addr = pa_start; ++ vma->size = size; ++ vma->flags = VM_MAP | vm_flags; ++ vma->caller = __builtin_return_address(0); ++ ++ vm_area_add_early(vma); ++} ++ ++static pgprot_t kernel_exec_prot(void) ++{ ++ return rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC; ++} ++ ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++static int __init map_entry_trampoline(void) ++{ ++ int i; ++ ++ pgprot_t prot = kernel_exec_prot(); ++ phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start); ++ ++ /* The trampoline is always mapped and can therefore be global */ ++ pgprot_val(prot) &= ~PTE_NG; ++ ++ /* Map only the text into the trampoline page table */ ++ memset(tramp_pg_dir, 0, PGD_SIZE); ++ #ifdef CONFIG_PTP ++ iee_set_logical_mem_ro((unsigned long)tramp_pg_dir); ++ #endif ++ __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, ++ entry_tramp_text_size(), prot, ++ __pgd_pgtable_alloc, NO_BLOCK_MAPPINGS); ++ ++ /* Map both the text and data into the kernel page table */ ++ for (i = 0; i < DIV_ROUND_UP(entry_tramp_text_size(), PAGE_SIZE); i++) ++ __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i, ++ pa_start + i * PAGE_SIZE, prot); ++ ++ if (IS_ENABLED(CONFIG_RELOCATABLE)) ++ __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i, ++ pa_start + i * PAGE_SIZE, PAGE_KERNEL_RO); ++ ++ return 0; ++} ++core_initcall(map_entry_trampoline); ++#endif ++ ++/* ++ * Open coded check for BTI, only for use to determine configuration ++ * for early mappings for before the cpufeature code has run. ++ */ ++static bool arm64_early_this_cpu_has_bti(void) ++{ ++ u64 pfr1; ++ ++ if (!IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)) ++ return false; ++ ++ pfr1 = __read_sysreg_by_encoding(SYS_ID_AA64PFR1_EL1); ++ return cpuid_feature_extract_unsigned_field(pfr1, ++ ID_AA64PFR1_EL1_BT_SHIFT); ++} ++ ++#ifdef CONFIG_IEE ++/* Set PMD APTable of iee si codes as (1,1) to revert it to ROX P pages when HPD1=0. */ ++static void __init iee_si_set_pmd_APtable(unsigned long addr, pgd_t *pgdir) ++{ ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ ++ #ifdef CONFIG_PTP ++ pud_t *pudp = pud_set_fixmap_offset_init(p4dp, addr); ++ ++ pmd_t *pmdp = pmd_set_fixmap_offset_init(pudp, addr); ++ ++ pmd_t pmd = READ_ONCE(*pmdp); ++ ++ __iee_pmd_populate_pre_init(pmdp, __pmd_to_phys(pmd), PGD_APT_RO | PGD_APT | PMD_TYPE_TABLE); ++ ++ pud_clear_fixmap_init(); ++ pmd_clear_fixmap_init(); ++ #else ++ pud_t *pudp = pud_set_fixmap_offset(p4dp, addr); ++ ++ pmd_t *pmdp = pmd_set_fixmap_offset(pudp, addr); ++ ++ pmd_t pmd = READ_ONCE(*pmdp); ++ ++ __pmd_populate(pmdp, __pmd_to_phys(pmd), PGD_APT_RO | PGD_APT | PMD_TYPE_TABLE); ++ ++ pud_clear_fixmap(); ++ pmd_clear_fixmap(); ++ #endif ++} ++/* Set PMD APTable of iee si codes as (1,1) to revert it to ROX P pages when HPD1=0. */ ++static void __init mark_iee_si_pmd_APtable(pgd_t *pgdir) ++{ ++ unsigned long addr = (unsigned long)__iee_si_text_start; ++ iee_si_set_pmd_APtable(addr, pgdir); ++ // iee rwx gate exit may be mapped by another pmd. ++ iee_si_set_pmd_APtable(addr + PAGE_SIZE, pgdir); ++} ++#endif ++ ++/* ++ * Create fine-grained mappings for the kernel. ++ */ ++static void __init map_kernel(pgd_t *pgdp) ++{ ++ static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_inittext, ++ vmlinux_initdata, vmlinux_data; ++ ++ #ifdef CONFIG_IEE ++ static struct vm_struct vmlinux_iee_code, vmlinux_iee_data, vmlinux_iee_gate, vmlinux_text_end; ++ #endif ++ ++ /* ++ * External debuggers may need to write directly to the text ++ * mapping to install SW breakpoints. Allow this (only) when ++ * explicitly requested with rodata=off. ++ */ ++ pgprot_t text_prot = kernel_exec_prot(); ++ ++ /* ++ * If we have a CPU that supports BTI and a kernel built for ++ * BTI then mark the kernel executable text as guarded pages ++ * now so we don't have to rewrite the page tables later. ++ */ ++ if (arm64_early_this_cpu_has_bti()) ++ text_prot = __pgprot_modify(text_prot, PTE_GP, PTE_GP); ++ ++ /* ++ * Only rodata will be remapped with different permissions later on, ++ * all other segments are allowed to use contiguous mappings. ++ */ ++ #ifdef CONFIG_IEE ++ map_kernel_segment(pgdp, _stext, __iee_si_data_start, text_prot, &vmlinux_text, ++ 0, VM_NO_GUARD); ++ /* Set iee si data RW. */ ++ map_kernel_segment(pgdp, __iee_si_data_start, __iee_exec_entry_start, SET_NG(PAGE_KERNEL), ++ &vmlinux_iee_data, NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); ++ /* Set iee entry codes NG. */ ++ map_kernel_segment(pgdp, __iee_exec_entry_start, __iee_si_text_start, SET_NG(text_prot), &vmlinux_iee_gate, ++ NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); ++ /* Map __iee_si_text_start - __iee_si_text_end as U RWX pages and set PMD APTABLE = (1,1). */ ++ map_kernel_segment(pgdp, __iee_si_text_start, __iee_si_text_end, SET_NG((PAGE_KERNEL_EXEC)), ++ &vmlinux_iee_code, NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); ++ mark_iee_si_pmd_APtable(pgdp); ++ ++ map_kernel_segment(pgdp, __iee_si_text_end, _etext, text_prot, &vmlinux_text_end, 0, ++ VM_NO_GUARD); ++ ++ map_kernel_segment(pgdp, __start_rodata, __inittext_begin, PAGE_KERNEL, ++ &vmlinux_rodata, NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); ++ map_kernel_segment(pgdp, __inittext_begin, __inittext_end, text_prot, ++ &vmlinux_inittext, 0, VM_NO_GUARD); ++ map_kernel_segment(pgdp, __initdata_begin, __initdata_end, PAGE_KERNEL, ++ &vmlinux_initdata, 0, VM_NO_GUARD); ++ map_kernel_segment(pgdp, _data, _end, PAGE_KERNEL, &vmlinux_data, NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, 0); ++ #else ++ map_kernel_segment(pgdp, _stext, _etext, text_prot, &vmlinux_text, 0, ++ VM_NO_GUARD); ++ map_kernel_segment(pgdp, __start_rodata, __inittext_begin, PAGE_KERNEL, ++ &vmlinux_rodata, NO_CONT_MAPPINGS, VM_NO_GUARD); ++ map_kernel_segment(pgdp, __inittext_begin, __inittext_end, text_prot, ++ &vmlinux_inittext, 0, VM_NO_GUARD); ++ map_kernel_segment(pgdp, __initdata_begin, __initdata_end, PAGE_KERNEL, ++ &vmlinux_initdata, 0, VM_NO_GUARD); ++ map_kernel_segment(pgdp, _data, _end, PAGE_KERNEL, &vmlinux_data, 0, 0); ++ #endif ++ ++ ++ fixmap_copy(pgdp); ++ kasan_copy_shadow(pgdp); ++} ++ ++static void __init create_idmap(void) ++{ ++ u64 start = __pa_symbol(__idmap_text_start); ++ u64 size = __pa_symbol(__idmap_text_end) - start; ++ pgd_t *pgd = idmap_pg_dir; ++ u64 pgd_phys; ++ ++ /* check if we need an additional level of translation */ ++ if (VA_BITS < 48 && idmap_t0sz < (64 - VA_BITS_MIN)) { ++ pgd_phys = early_pgtable_alloc(PAGE_SHIFT); ++ set_pgd(&idmap_pg_dir[start >> VA_BITS], ++ __pgd(pgd_phys | P4D_TYPE_TABLE)); ++ pgd = __va(pgd_phys); ++ } ++ #ifdef CONFIG_PTP ++ __iee_create_pgd_mapping_pre_init(pgd, start, start, size, PAGE_KERNEL_ROX, ++ early_pgtable_alloc, 0); ++ #else ++ __create_pgd_mapping(pgd, start, start, size, PAGE_KERNEL_ROX, ++ early_pgtable_alloc, 0); ++ #endif ++ ++ if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) { ++ extern u32 __idmap_kpti_flag; ++ u64 pa = __pa_symbol(&__idmap_kpti_flag); ++ ++ /* ++ * The KPTI G-to-nG conversion code needs a read-write mapping ++ * of its synchronization flag in the ID map. ++ */ ++ #ifdef CONFIG_PTP ++ __iee_create_pgd_mapping_pre_init(pgd, pa, pa, sizeof(u32), PAGE_KERNEL, ++ early_pgtable_alloc, 0); ++ #else ++ __create_pgd_mapping(pgd, pa, pa, sizeof(u32), PAGE_KERNEL, ++ early_pgtable_alloc, 0); ++ #endif ++ } ++} ++ ++#ifdef CONFIG_IEE ++static void set_init_iee_stack_page(unsigned long addr) ++{ ++ unsigned long iee_addr = __phys_to_iee(__pa_symbol(addr)); ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ p4d_t p4d = READ_ONCE(*p4dp); ++ ++ pud_t *pudp = pud_offset(p4dp, addr); ++ ++ pmd_t *pmdp = pmd_offset(pudp, addr); ++ ++ pte_t *ptep = pte_offset_kernel(pmdp, addr); ++ ++ int i; ++ for(i = 0; i < 4; i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ set_pte(ptep, pte); ++ ptep++; ++ } ++ ++ pgdp = pgd_offset_pgd(pgdir, iee_addr); ++ ++ p4dp = p4d_offset(pgdp, iee_addr); ++ p4d = READ_ONCE(*p4dp); ++ ++ pudp = pud_offset(p4dp, iee_addr); ++ ++ pmdp = pmd_offset(pudp, iee_addr); ++ ++ ptep = pte_offset_kernel(pmdp, iee_addr); ++ ++ for(i = 0; i < 4; i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ set_pte(ptep, pte); ++ ptep++; ++ } ++ flush_tlb_kernel_range(addr, addr+4*PAGE_SIZE); ++ isb(); ++} ++ ++static void __create_pgd_mapping_for_iee_locked(pgd_t *pgdir, phys_addr_t phys, ++ unsigned long virt, phys_addr_t size, ++ pgprot_t prot, ++ phys_addr_t (*pgtable_alloc)(int), ++ int flags) ++{ ++ unsigned long addr, end, next; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, virt); ++ p4d_t *p4dp; ++ p4d_t p4d; ++ ++ /* ++ * If the virtual and physical address don't have the same offset ++ * within a page, we cannot map the region as the caller expects. ++ */ ++ if (WARN_ON((phys ^ virt) & ~PAGE_MASK)) ++ return; ++ ++ phys &= PAGE_MASK; ++ addr = virt & PAGE_MASK; ++ end = PAGE_ALIGN(virt + size); ++ ++ do { ++ next = pgd_addr_end(addr, end); ++ #ifdef CONFIG_PTP ++ iee_alloc_init_pud_pre_init(pgdp, addr, next, phys, prot, pgtable_alloc, ++ flags); ++ #else ++ alloc_init_pud(pgdp, addr, next, phys, prot, pgtable_alloc, ++ flags); ++ #endif ++ p4dp = p4d_offset(pgdp, addr); ++ p4d = READ_ONCE(*p4dp); ++ #ifdef CONFIG_PTP ++ __iee_p4d_populate_pre_init(p4dp, __p4d_to_phys(p4d), (PGD_APT | PGD_PXN | PGD_UXN | PUD_TYPE_TABLE)); ++ #else ++ __p4d_populate(p4dp, __p4d_to_phys(p4d), (PGD_APT | PGD_PXN | PGD_UXN | PUD_TYPE_TABLE)); ++ #endif ++ phys += next - addr; ++ } while (pgdp++, addr = next, addr != end); ++} ++ ++static void __create_pgd_mapping_for_iee(pgd_t *pgdir, phys_addr_t phys, ++ unsigned long virt, phys_addr_t size, ++ pgprot_t prot, ++ phys_addr_t (*pgtable_alloc)(int), ++ int flags) ++{ ++ mutex_lock(&fixmap_lock); ++ __create_pgd_mapping_for_iee_locked(pgdir, phys, virt, size, prot, ++ pgtable_alloc, flags); ++ mutex_unlock(&fixmap_lock); ++} ++ ++static void __init __map_memblock_for_iee(pgd_t *pgdp, phys_addr_t start, ++ phys_addr_t end, pgprot_t prot, int flags) ++{ ++ #ifdef CONFIG_PTP ++ __create_pgd_mapping_for_iee(pgdp, start, __phys_to_iee(start), end - start, ++ prot, early_pgtable_alloc, flags); ++ #else ++ __create_pgd_mapping_for_iee(pgdp, start, __phys_to_iee(start), end - start, ++ prot, early_pgtable_alloc, flags); ++ #endif ++} ++ ++static void __init map_iee(pgd_t *pgdp) ++{ ++ static const u64 direct_map_end = _PAGE_END(VA_BITS_MIN); ++ phys_addr_t kernel_start = __pa_symbol(_stext); ++ phys_addr_t kernel_end = __pa_symbol(__init_begin); ++ phys_addr_t start, end; ++ phys_addr_t early_kfence_pool; ++ int flags = NO_EXEC_MAPPINGS; ++ u64 i; ++ ++ flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; ++ ++ /* ++ * Setting hierarchical PXNTable attributes on table entries covering ++ * the linear region is only possible if it is guaranteed that no table ++ * entries at any level are being shared between the linear region and ++ * the vmalloc region. Check whether this is true for the PGD level, in ++ * which case it is guaranteed to be true for all other levels as well. ++ */ ++ BUILD_BUG_ON(pgd_index(direct_map_end - 1) == pgd_index(direct_map_end)); ++ ++ early_kfence_pool = arm64_kfence_alloc_pool(); ++ ++ /* ++ * Take care not to create a writable alias for the ++ * read-only text and rodata sections of the kernel image. ++ * So temporarily mark them as NOMAP to skip mappings in ++ * the following for-loop ++ */ ++ memblock_mark_nomap(kernel_start, kernel_end - kernel_start); ++ ++ /* map all the memory banks */ ++ for_each_mem_range(i, &start, &end) { ++ if (start >= end) ++ break; ++ /* ++ * The linear map must allow allocation tags reading/writing ++ * if MTE is present. Otherwise, it has the same attributes as ++ * PAGE_KERNEL. ++ */ ++ __map_memblock_for_iee(pgdp, start, end, SET_NG(SET_INVALID(SET_UPAGE(PAGE_KERNEL))), flags); ++ } ++ ++ /* ++ * Map the linear alias of the [_text, __init_begin) interval ++ * as non-executable now, and remove the write permission in ++ * mark_linear_text_alias_ro() below (which will be called after ++ * alternative patching has completed). This makes the contents ++ * of the region accessible to subsystems such as hibernate, ++ * but protects it from inadvertent modification or execution. ++ * Note that contiguous mappings cannot be remapped in this way, ++ * so we should avoid them here. ++ */ ++ __map_memblock_for_iee(pgdp, kernel_start, kernel_end, ++ SET_NG(SET_INVALID(SET_UPAGE(PAGE_KERNEL))), flags); ++ memblock_clear_nomap(kernel_start, kernel_end - kernel_start); ++ arm64_kfence_map_pool(early_kfence_pool, pgdp); ++} ++ ++/* ++ * Change page access permission, whereas not handling huge pages. ++ * Only used on IEE init functions. ++ */ ++static void __init iee_si_set_page_attr(unsigned long addr, pteval_t attr) ++{ ++ unsigned long flag; ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ ++ pud_t *pudp = pud_offset(p4dp, addr); ++ ++ pmd_t *pmdp = pmd_offset(pudp, addr); ++ ++ pte_t *ptep = pte_offset_kernel(pmdp, addr); ++ pte_t pte = READ_ONCE(*ptep); ++ ++ if(attr & PTE_RDONLY) ++ pte = __pte((pte_val(pte) | PTE_RDONLY) & ~PTE_DBM); ++ pte = __pte(pte_val(pte) | attr); ++ #ifdef CONFIG_PTP ++ // Write pgtable in IEE directly. ++ flag = local_daif_save(); ++ asm volatile ("msr pan, #0"); ++ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa(ptep)))), pte); ++ asm volatile ("msr pan, #1"); ++ local_daif_restore(flag); ++ #else ++ WRITE_ONCE(*ptep, pte); ++ #endif ++} ++ ++/* Prepare data used for iee rwx gates. These data are setted only once. */ ++void __init iee_si_prepare_data(void) ++{ ++ unsigned long va; ++ // Record current TCR val after system init. ++ iee_si_tcr = read_sysreg(tcr_el1) & ~(SYS_TCR_IEE_SI); ++ // CNP maybe enable. ++ if (system_supports_cnp()) { ++ iee_base_swapper_pg_dir |= TTBR_CNP_BIT; ++ } ++ // Mark iee data as RO and move it to iee after setting up. ++ va = (unsigned long)__iee_si_data_start; ++ iee_si_set_page_attr(va, PTE_RDONLY); ++ // iee_si_set_page_attr(lm_alias(va)+iee_offset, 0x1 | PTE_RDONLY); ++ // Set iee sensitive inst code page U RWX here to hide it from kernel. ++ va = (unsigned long)__iee_si_text_start; ++ iee_si_set_page_attr(va, PTE_USER); ++ va = (unsigned long)__iee_si_text_start + PAGE_SIZE; ++ iee_si_set_page_attr(va, PTE_USER); ++ flush_tlb_all(); ++} ++ ++#endif ++ ++#ifdef CONFIG_PTP ++// Attention : Using set_xxx without adding offset. ++static void __init set_iee_valid_pre_init(unsigned long addr) ++{ ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ ++ pud_t *pudp = pud_offset(p4dp, addr); ++ ++ pmd_t *pmdp = pmd_offset(pudp, addr); ++ ++ pte_t *ptep = pte_offset_kernel(pmdp, addr); ++ pte_t pte = READ_ONCE(*ptep); ++ ++ if((addr < (PAGE_OFFSET + IEE_OFFSET)) | (addr > (PAGE_OFFSET + BIT(vabits_actual - 1)))) ++ return; ++ ++ pte = __pte(pte_val(pte) | 0x1); ++ iee_set_pte_pre_init(ptep, pte); ++ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); ++ isb(); ++} ++ ++static void __init move_pte_table_into_iee(pmd_t *pmdp, unsigned long addr, unsigned long end) ++{ ++ pmd_t pmd = READ_ONCE(*pmdp); ++ unsigned long iee_addr = __phys_to_iee(__pmd_to_phys(pmd)); ++ set_iee_valid_pre_init(iee_addr); ++} ++ ++static void __init move_pmd_table_into_iee(pud_t *pudp, unsigned long addr, unsigned long end) ++{ ++ unsigned long next; ++ pud_t pud = READ_ONCE(*pudp); ++ pmd_t *pmdp; ++ pmd_t pmd; ++ unsigned long iee_addr = __phys_to_iee(__pud_to_phys(pud)); ++ set_iee_valid_pre_init(iee_addr); ++ ++ pmdp = pmd_offset(pudp, addr); ++ do { ++ next = pmd_addr_end(addr, end); ++ pmd = READ_ONCE(*pmdp); ++ if((pmd_val(pmd) & PMD_TABLE_BIT) == 0) ++ { ++ continue; ++ } ++ else ++ { ++ move_pte_table_into_iee(pmdp, addr, next); ++ } ++ } while (pmdp++, addr = next, addr != end); ++} ++ ++static void __init move_pud_table_into_iee(pgd_t *pgdp, unsigned long addr, unsigned long end) ++{ ++ unsigned long next; ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ p4d_t p4d = READ_ONCE(*p4dp); ++ pud_t *pudp; ++ pud_t pud; ++ unsigned long iee_addr = __phys_to_iee(__p4d_to_phys(p4d)); ++ set_iee_valid_pre_init(iee_addr); ++ ++ pudp = pud_offset(p4dp, addr); ++ do { ++ next = pud_addr_end(addr, end); ++ pud = READ_ONCE(*pudp); ++ if ((pud_val(pud) & PUD_TABLE_BIT) == 0) ++ { ++ continue; ++ } ++ else ++ { ++ move_pmd_table_into_iee(pudp, addr, next); ++ } ++ } while (pudp++, addr = next, addr != end); ++} ++ ++static void __init init_iee_for_one_region(pgd_t *pgdir, unsigned long va_start, unsigned long va_end) + { +- phys_addr_t pa_start = __pa_symbol(va_start); +- unsigned long size = va_end - va_start; +- +- BUG_ON(!PAGE_ALIGNED(pa_start)); +- BUG_ON(!PAGE_ALIGNED(size)); +- +- __create_pgd_mapping(pgdp, pa_start, (unsigned long)va_start, size, prot, +- early_pgtable_alloc, flags); +- +- if (!(vm_flags & VM_NO_GUARD)) +- size += PAGE_SIZE; ++ unsigned long addr, end, next; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, va_start); + +- vma->addr = va_start; +- vma->phys_addr = pa_start; +- vma->size = size; +- vma->flags = VM_MAP | vm_flags; +- vma->caller = __builtin_return_address(0); ++ addr = va_start & PAGE_MASK; ++ end = PAGE_ALIGN(va_end); + +- vm_area_add_early(vma); ++ do { ++ next = pgd_addr_end(addr, end); ++ move_pud_table_into_iee(pgdp, addr, next); ++ } while (pgdp++, addr = next, addr != end); + } + +-static pgprot_t kernel_exec_prot(void) ++static void __init init_iee(void) + { +- return rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC; ++ unsigned long iee_addr; ++ phys_addr_t start, end; ++ u64 i; ++ pgd_t *pgdp; ++ ++ #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++ // handling 1-level tramp page table tramp_pg_dir ++ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(tramp_pg_dir)); ++ set_iee_valid_pre_init(iee_addr); ++ #endif ++ // handling 1-level page table swapper_pg_dir ++ pgdp = swapper_pg_dir; ++ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(swapper_pg_dir)); ++ set_iee_valid_pre_init(iee_addr); ++ // handling 2/3/4-level page table for kernel ++ init_iee_for_one_region(pgdp, (unsigned long)_text, (unsigned long)_etext); ++ init_iee_for_one_region(pgdp, (unsigned long)__start_rodata, (unsigned long)__inittext_begin); ++ init_iee_for_one_region(pgdp, (unsigned long)__inittext_begin, (unsigned long)__inittext_end); ++ init_iee_for_one_region(pgdp, (unsigned long)__initdata_begin, (unsigned long)__initdata_end); ++ init_iee_for_one_region(pgdp, (unsigned long)_data, (unsigned long)_end); ++ // handling 2/3/4-level page table for fixmap i.e. remap bm_xxx ++ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(bm_pte_addr)); ++ set_iee_valid_pre_init(iee_addr); ++ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(bm_pmd_addr)); ++ set_iee_valid_pre_init(iee_addr); ++ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(bm_pud_addr)); ++ set_iee_valid_pre_init(iee_addr); ++ // handling 2/3/4-level page table for logical mem and iee ++ for_each_mem_range(i, &start, &end) { ++ if (start >= end) ++ break; ++ /* ++ * The linear map must allow allocation tags reading/writing ++ * if MTE is present. Otherwise, it has the same attributes as ++ * PAGE_KERNEL. ++ */ ++ init_iee_for_one_region(pgdp, (unsigned long)__va(start), (unsigned long)__va(end)); ++ init_iee_for_one_region(pgdp, (unsigned long)__phys_to_iee(start), (unsigned long)__phys_to_iee(end)); ++ } + } + +-#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +-static int __init map_entry_trampoline(void) ++static void set_init_iee_stack_page_pre_init(unsigned long addr) + { +- int i; ++ unsigned long iee_addr = __phys_to_iee(__pa_symbol(addr)); ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); + +- pgprot_t prot = kernel_exec_prot(); +- phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start); ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ p4d_t p4d = READ_ONCE(*p4dp); + +- /* The trampoline is always mapped and can therefore be global */ +- pgprot_val(prot) &= ~PTE_NG; ++ pud_t *pudp = pud_offset(p4dp, addr); + +- /* Map only the text into the trampoline page table */ +- memset(tramp_pg_dir, 0, PGD_SIZE); +- __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, +- entry_tramp_text_size(), prot, +- __pgd_pgtable_alloc, NO_BLOCK_MAPPINGS); ++ pmd_t *pmdp = pmd_offset(pudp, addr); + +- /* Map both the text and data into the kernel page table */ +- for (i = 0; i < DIV_ROUND_UP(entry_tramp_text_size(), PAGE_SIZE); i++) +- __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i, +- pa_start + i * PAGE_SIZE, prot); ++ pte_t *ptep = pte_offset_kernel(pmdp, addr); + +- if (IS_ENABLED(CONFIG_RELOCATABLE)) +- __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i, +- pa_start + i * PAGE_SIZE, PAGE_KERNEL_RO); ++ int i; ++ for(i = 0; i < 4; i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(pte_val(pte) & ~PTE_VALID); ++ iee_set_pte_pre_init(ptep, pte); ++ ptep++; ++ } + +- return 0; +-} +-core_initcall(map_entry_trampoline); +-#endif ++ pgdp = pgd_offset_pgd(pgdir, iee_addr); + +-/* +- * Open coded check for BTI, only for use to determine configuration +- * for early mappings for before the cpufeature code has run. +- */ +-static bool arm64_early_this_cpu_has_bti(void) +-{ +- u64 pfr1; ++ p4dp = p4d_offset(pgdp, iee_addr); ++ p4d = READ_ONCE(*p4dp); + +- if (!IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)) +- return false; ++ pudp = pud_offset(p4dp, iee_addr); + +- pfr1 = __read_sysreg_by_encoding(SYS_ID_AA64PFR1_EL1); +- return cpuid_feature_extract_unsigned_field(pfr1, +- ID_AA64PFR1_EL1_BT_SHIFT); ++ pmdp = pmd_offset(pudp, iee_addr); ++ ++ ptep = pte_offset_kernel(pmdp, iee_addr); ++ ++ for(i = 0; i < 4; i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(pte_val(pte) | PTE_VALID); ++ iee_set_pte_pre_init(ptep, pte); ++ ptep++; ++ } ++ flush_tlb_kernel_range(addr, addr+4*PAGE_SIZE); ++ isb(); + } + +-/* +- * Create fine-grained mappings for the kernel. +- */ +-static void __init map_kernel(pgd_t *pgdp) ++static void __init iee_set_pte_table_ro(pmd_t *pmdp, unsigned long addr, unsigned long end) + { +- static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_inittext, +- vmlinux_initdata, vmlinux_data; ++ pmd_t pmd = READ_ONCE(*pmdp); ++ unsigned long logical_addr = (unsigned long)__va(__pmd_to_phys(pmd)); ++ iee_set_logical_mem_ro(logical_addr); ++} + +- /* +- * External debuggers may need to write directly to the text +- * mapping to install SW breakpoints. Allow this (only) when +- * explicitly requested with rodata=off. +- */ +- pgprot_t text_prot = kernel_exec_prot(); ++static void __init iee_set_pmd_table_ro(pud_t *pudp, unsigned long addr, unsigned long end) ++{ ++ unsigned long next; ++ pud_t pud = READ_ONCE(*pudp); ++ pmd_t *pmdp; ++ pmd_t pmd; ++ unsigned long logical_addr = (unsigned long)__va(__pud_to_phys(pud)); ++ iee_set_logical_mem_ro(logical_addr); + +- /* +- * If we have a CPU that supports BTI and a kernel built for +- * BTI then mark the kernel executable text as guarded pages +- * now so we don't have to rewrite the page tables later. +- */ +- if (arm64_early_this_cpu_has_bti()) +- text_prot = __pgprot_modify(text_prot, PTE_GP, PTE_GP); ++ pmdp = pmd_offset(pudp, addr); ++ do { ++ next = pmd_addr_end(addr, end); ++ pmd = READ_ONCE(*pmdp); ++ if((pmd_val(pmd) & PMD_TABLE_BIT) == 0) ++ { ++ continue; ++ } ++ else ++ { ++ iee_set_pte_table_ro(pmdp, addr, next); ++ } ++ } while (pmdp++, addr = next, addr != end); ++} + +- /* +- * Only rodata will be remapped with different permissions later on, +- * all other segments are allowed to use contiguous mappings. +- */ +- map_kernel_segment(pgdp, _stext, _etext, text_prot, &vmlinux_text, 0, +- VM_NO_GUARD); +- map_kernel_segment(pgdp, __start_rodata, __inittext_begin, PAGE_KERNEL, +- &vmlinux_rodata, NO_CONT_MAPPINGS, VM_NO_GUARD); +- map_kernel_segment(pgdp, __inittext_begin, __inittext_end, text_prot, +- &vmlinux_inittext, 0, VM_NO_GUARD); +- map_kernel_segment(pgdp, __initdata_begin, __initdata_end, PAGE_KERNEL, +- &vmlinux_initdata, 0, VM_NO_GUARD); +- map_kernel_segment(pgdp, _data, _end, PAGE_KERNEL, &vmlinux_data, 0, 0); ++static void __init iee_set_pud_table_ro(pgd_t *pgdp, unsigned long addr, unsigned long end) ++{ ++ unsigned long next; ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ p4d_t p4d = READ_ONCE(*p4dp); ++ pud_t *pudp; ++ pud_t pud; ++ unsigned long logical_addr = (unsigned long)__va(__p4d_to_phys(p4d)); ++ iee_set_logical_mem_ro(logical_addr); + +- fixmap_copy(pgdp); +- kasan_copy_shadow(pgdp); ++ pudp = pud_offset(p4dp, addr); ++ do { ++ next = pud_addr_end(addr, end); ++ pud = READ_ONCE(*pudp); ++ if ((pud_val(pud) & PUD_TABLE_BIT) == 0) ++ { ++ continue; ++ } ++ else ++ { ++ iee_set_pmd_table_ro(pudp, addr, next); ++ } ++ } while (pudp++, addr = next, addr != end); + } + +-static void __init create_idmap(void) ++static void __init iee_mark_pgtable_for_one_region_ro(pgd_t *pgdir, unsigned long va_start, unsigned long va_end) + { +- u64 start = __pa_symbol(__idmap_text_start); +- u64 size = __pa_symbol(__idmap_text_end) - start; +- pgd_t *pgd = idmap_pg_dir; +- u64 pgd_phys; ++ unsigned long addr, end, next; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, va_start); + +- /* check if we need an additional level of translation */ +- if (VA_BITS < 48 && idmap_t0sz < (64 - VA_BITS_MIN)) { +- pgd_phys = early_pgtable_alloc(PAGE_SHIFT); +- set_pgd(&idmap_pg_dir[start >> VA_BITS], +- __pgd(pgd_phys | P4D_TYPE_TABLE)); +- pgd = __va(pgd_phys); +- } +- __create_pgd_mapping(pgd, start, start, size, PAGE_KERNEL_ROX, +- early_pgtable_alloc, 0); ++ addr = va_start & PAGE_MASK; ++ end = PAGE_ALIGN(va_end); + +- if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) { +- extern u32 __idmap_kpti_flag; +- u64 pa = __pa_symbol(&__idmap_kpti_flag); ++ do { ++ next = pgd_addr_end(addr, end); ++ iee_set_pud_table_ro(pgdp, addr, next); ++ } while (pgdp++, addr = next, addr != end); ++} + ++// Mark pgtable outside as RO. ++void __init iee_mark_all_lm_pgtable_ro(void) ++{ ++ unsigned long logical_addr; ++ phys_addr_t start, end; ++ u64 i; ++ pgd_t *pgdp; ++ ++ // handling static allocated page table ++ #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++ // handling 1-level tramp page table tramp_pg_dir ++ logical_addr = (unsigned long)__va(__pa_symbol(tramp_pg_dir)); ++ iee_set_logical_mem_ro(logical_addr); ++ #endif ++ // handling 1-level page table swapper_pg_dir ++ pgdp = swapper_pg_dir; ++ iee_set_logical_mem_ro((unsigned long)swapper_pg_dir); ++ logical_addr = (unsigned long)__va(__pa_symbol(swapper_pg_dir)); ++ iee_set_logical_mem_ro(logical_addr); ++ ++ // handling 2/3/4-level page table for kernel ++ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)_text, (unsigned long)_etext); ++ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)__start_rodata, (unsigned long)__inittext_begin); ++ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)__inittext_begin, (unsigned long)__inittext_end); ++ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)__initdata_begin, (unsigned long)__initdata_end); ++ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)_data, (unsigned long)_end); ++ ++ // handling 2/3/4-level page table for fixmap i.e. remap bm_xxx ++ logical_addr = (unsigned long)__va(__pa_symbol(bm_pte_addr)); ++ iee_set_logical_mem_ro(logical_addr); ++ ++ iee_set_logical_mem_ro((unsigned long)bm_pmd_addr); ++ logical_addr = (unsigned long)__va(__pa_symbol(bm_pmd_addr)); ++ iee_set_logical_mem_ro(logical_addr); ++ ++ iee_set_logical_mem_ro((unsigned long)bm_pud_addr); ++ logical_addr = (unsigned long)__va(__pa_symbol(bm_pud_addr)); ++ iee_set_logical_mem_ro(logical_addr); ++ ++ // handling 2/3/4-level page table for logical mem and iee ++ for_each_mem_range(i, &start, &end) { ++ if (start >= end) ++ break; + /* +- * The KPTI G-to-nG conversion code needs a read-write mapping +- * of its synchronization flag in the ID map. ++ * The linear map must allow allocation tags reading/writing ++ * if MTE is present. Otherwise, it has the same attributes as ++ * PAGE_KERNEL. + */ +- __create_pgd_mapping(pgd, pa, pa, sizeof(u32), PAGE_KERNEL, +- early_pgtable_alloc, 0); ++ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)__va(start), (unsigned long)__va(end)); ++ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)__phys_to_iee(start), (unsigned long)__phys_to_iee(end)); + } + } ++#endif ++ ++#ifdef CONFIG_KOI ++static void map_koi(pgd_t *pgdp); ++extern s64 koi_offset; ++#endif + + void __init paging_init(void) + { ++ #ifdef CONFIG_IEE ++ unsigned long SP_EL0; ++ void *new; ++ void *init_token; ++ struct task_token *token; ++ unsigned long tcr; ++ ++ // Check if cpu has PAN and HPDS. ++ if(!cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64MMFR1_EL1), ++ ID_AA64MMFR1_EL1_PAN_SHIFT)) ++ panic("Architecture doesn't support PAN, please disable CONFIG_IEE.\n"); ++ ++ if(!cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64MMFR1_EL1), ++ ID_AA64MMFR1_EL1_HPDS_SHIFT)) ++ panic("Architecture doesn't support HPDS, please disable CONFIG_IEE.\n"); ++ #endif ++ ++ // Avoid using iee code to modify pgtable before iee initialized. ++ #ifdef CONFIG_PTP ++ pgd_t *pgdp = pgd_set_fixmap_init(__pa_symbol(swapper_pg_dir)); ++ #else + pgd_t *pgdp = pgd_set_fixmap(__pa_symbol(swapper_pg_dir)); ++ #endif ++ ++ + extern pgd_t init_idmap_pg_dir[]; + + idmap_t0sz = 63UL - __fls(__pa_symbol(_end) | GENMASK(VA_BITS_MIN - 1, 0)); +@@ -803,7 +2063,21 @@ void __init paging_init(void) + map_kernel(pgdp); + map_mem(pgdp); + ++ // Map the whole physical mem into IEE, but set invalid. ++#ifdef CONFIG_IEE ++ map_iee(pgdp); ++#else ++#ifdef CONFIG_KOI ++ map_koi(pgdp); ++#endif ++#endif ++ ++ // Avoid using iee code to modify pgtable before iee initialized. ++ #ifdef CONFIG_PTP ++ pgd_clear_fixmap_init(); ++ #else + pgd_clear_fixmap(); ++ #endif + + cpu_replace_ttbr1(lm_alias(swapper_pg_dir), init_idmap_pg_dir); + init_mm.pgd = swapper_pg_dir; +@@ -814,6 +2088,83 @@ void __init paging_init(void) + memblock_allow_resize(); + + create_idmap(); ++ ++ #ifdef CONFIG_IEE ++ // test iee_exec_entry ++ iee_rwx_gate_entry(IEE_SI_TEST); ++ // Initialize init iee stack. ++ #ifdef CONFIG_PTP ++ set_init_iee_stack_page_pre_init((unsigned long)init_iee_stack_begin); ++ #else ++ set_init_iee_stack_page((unsigned long)init_iee_stack_begin); ++ #endif ++ #endif ++ ++ // Init token for init_task. ++ #ifdef CONFIG_IEE ++ // Change SP_EL0 from Image VA to Logical VA. ++ SP_EL0 = (unsigned long)__va(__pa_symbol(&init_task)); ++ write_sysreg(SP_EL0, sp_el0); ++ init_task.cpus_ptr = &(((struct task_struct *)(__va(__pa_symbol(&init_task))))->cpus_mask); ++ init_task.children.prev = (__va(__pa_symbol(init_task.children.prev))); ++ init_task.children.next = (__va(__pa_symbol(init_task.children.next))); ++ // Alloc a page for init_token. ++ new = __va(early_pgtable_alloc(0)); ++ init_token_page_vaddr = new; ++ init_token = (void *)__phys_to_iee(__pa_symbol(&init_task)); ++ // Use lm to write token before IEE initialized. ++ token = (struct task_token *)((unsigned long)new + (((unsigned long)&init_task) & ~PAGE_MASK)); ++ token->pgd = NULL; ++ token->iee_stack = __phys_to_iee(__pa_symbol((void *)init_iee_stack_end)); ++ token->valid = true; ++ iee_set_token_page_valid_pre_init(init_token, new); ++ #endif ++ ++ #ifdef CONFIG_PTP ++ // Map the existing pgtable into IEE, set valid. ++ init_iee(); ++ #endif ++ ++ #ifdef CONFIG_IEE ++ sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_SPAN); ++ #endif ++ ++ // IEE ready. ++ // Pgtable writing before uses logical memory and after uses IEE memory. ++ ++ #ifdef CONFIG_IEE ++ // Set HPD1 as 1. ++ tcr = read_sysreg(tcr_el1); ++ tcr |= ((unsigned long)0x1 << 42); ++ write_sysreg(tcr, tcr_el1); ++ isb(); ++ ++ // Flush tlb to enable IEE. ++ flush_tlb_all(); ++ ++ // mark that iee is prepared. ++ iee_init_done = true; ++#else ++#ifdef CONFIG_KOI ++ unsigned long SP_EL0 = __va(__pa_symbol(&init_task)); ++ write_sysreg(SP_EL0, sp_el0); ++ init_task.cpus_ptr = &(((struct task_struct *)(__va(__pa_symbol(&init_task))))->cpus_mask); ++ init_task.children.prev = (__va(__pa_symbol(init_task.children.prev))); ++ init_task.children.next = (__va(__pa_symbol(init_task.children.next))); ++ // create a new page for token ++ void *alloc_token = __va(early_pgtable_alloc(0)); ++ // get the address of token ++ void *token_addr = __phys_to_virt(__pa_symbol(&init_task)) + KOI_OFFSET; ++ // add memory mapping for token ++ koi_add_page_mapping(token_addr, (void *)alloc_token); ++ // printk(KERN_ERR "token_addr=0x%16llx, alloc_token=0x%16llx, init_task=0x%16llx, virt=0x%16llx\n", token_addr, alloc_token, &init_task, __phys_to_virt(__pa_symbol(&init_task))); ++ struct task_token *token = (struct task_token *)((unsigned long)alloc_token + (((unsigned long)&init_task) & ~PAGE_MASK)); ++ token->koi_kernel_stack = NULL; ++ token->koi_stack = NULL; ++ token->koi_stack_base = NULL; ++ token->current_ttbr1 = 0; ++#endif ++#endif + } + + #ifdef CONFIG_MEMORY_HOTPLUG +@@ -1261,6 +2612,9 @@ int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr) + table = pte_offset_kernel(pmdp, addr); + pmd_clear(pmdp); + __flush_tlb_kernel_pgtable(addr); ++ #ifdef CONFIG_PTP ++ iee_memset(table, 0, PAGE_SIZE); ++ #endif + pte_free_kernel(NULL, table); + return 1; + } +@@ -1521,3 +2875,93 @@ void ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte + { + set_pte_at(vma->vm_mm, addr, ptep, pte); + } ++ ++#if !defined(CONFIG_IEE) && defined (CONFIG_KOI) ++static void __create_pgd_mapping_for_koi(pgd_t *pgdir, phys_addr_t phys, ++ unsigned long virt, phys_addr_t size, ++ pgprot_t prot, ++ phys_addr_t (*pgtable_alloc)(int), ++ int flags) ++{ ++ unsigned long addr, end, next; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, virt); ++ ++ /* ++ * If the virtual and physical address don't have the same offset ++ * within a page, we cannot map the region as the caller expects. ++ */ ++ if (WARN_ON((phys ^ virt) & ~PAGE_MASK)) ++ return; ++ ++ phys &= PAGE_MASK; ++ addr = virt & PAGE_MASK; ++ end = PAGE_ALIGN(virt + size); ++ ++ do { ++ next = pgd_addr_end(addr, end); ++ alloc_init_pud(pgdp, addr, next, phys, prot, pgtable_alloc, ++ flags); ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ p4d_t p4d = READ_ONCE(*p4dp); ++ __p4d_populate(p4dp, __p4d_to_phys(p4d), PUD_TYPE_TABLE); ++ phys += next - addr; ++ } while (pgdp++, addr = next, addr != end); ++} ++ ++static void __init __map_memblock_for_koi(pgd_t *pgdp, phys_addr_t start, ++ phys_addr_t end, pgprot_t prot, int flags) ++{ ++ __create_pgd_mapping_for_koi(pgdp, start, __phys_to_virt(start) + KOI_OFFSET, end - start, ++ prot, early_pgtable_alloc, flags); ++} ++ ++static void __init map_koi(pgd_t *pgdp) ++{ ++ phys_addr_t kernel_start = __pa_symbol(_text); ++ phys_addr_t kernel_end = __pa_symbol(__init_begin); ++ phys_addr_t start, end; ++ int flags = 0; ++ u64 i; ++ ++ flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; ++ ++ /* ++ * Take care not to create a writable alias for the ++ * read-only text and rodata sections of the kernel image. ++ * So temporarily mark them as NOMAP to skip mappings in ++ * the following for-loop ++ */ ++ memblock_mark_nomap(kernel_start, kernel_end - kernel_start); ++#ifdef CONFIG_KEXEC_CORE ++ if (crashk_res.end) ++ memblock_mark_nomap(crashk_res.start, ++ resource_size(&crashk_res)); ++#endif ++ ++ /* map all the memory banks */ ++ for_each_mem_range(i, &start, &end) { ++ if (start >= end) ++ break; ++ /* ++ * The linear map must allow allocation tags reading/writing ++ * if MTE is present. Otherwise, it has the same attributes as ++ * PAGE_KERNEL. ++ */ ++ __map_memblock_for_koi(pgdp, start, end, SET_NG(SET_INVALID(PAGE_KERNEL)), flags); ++ } ++#ifdef CONFIG_KEXEC_CORE ++ /* ++ * Use page-level mappings here so that we can shrink the region ++ * in page granularity and put back unused memory to buddy system ++ * through /sys/kernel/kexec_crash_size interface. ++ */ ++ if (crashk_res.end) { ++ __map_memblock_for_koi(pgdp, crashk_res.start, crashk_res.end + 1, ++ SET_NG(SET_INVALID(PAGE_KERNEL)), ++ NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS); ++ memblock_clear_nomap(crashk_res.start, ++ resource_size(&crashk_res)); ++ } ++#endif ++} ++#endif +\ No newline at end of file +diff --git a/arch/arm64/mm/pgd.c b/arch/arm64/mm/pgd.c +index 4a64089e5771..b99b35a5190f 100644 +--- a/arch/arm64/mm/pgd.c ++++ b/arch/arm64/mm/pgd.c +@@ -15,14 +15,38 @@ + #include + #include + ++#ifdef CONFIG_PTP ++#include ++#endif ++ + static struct kmem_cache *pgd_cache __ro_after_init; + ++#ifdef CONFIG_KOI ++pgd_t *koi_pgd_alloc(void) ++{ ++ pgd_t *pgd; ++#ifdef CONFIG_PTP ++ pgd = (pgd_t *)get_iee_pgtable_page(GFP_PGTABLE_KERNEL); ++#else ++ pgd = (pgd_t *)__get_free_page(GFP_PGTABLE_KERNEL); ++#endif ++ return pgd; ++} ++#endif ++ + pgd_t *pgd_alloc(struct mm_struct *mm) + { + gfp_t gfp = GFP_PGTABLE_USER; + + if (PGD_SIZE == PAGE_SIZE) ++#ifdef CONFIG_PTP ++ { ++ pgd_t* new = (pgd_t *)get_iee_pgtable_page(gfp); ++ return new; ++ } ++#else + return (pgd_t *)__get_free_page(gfp); ++#endif + else + return kmem_cache_alloc(pgd_cache, gfp); + } +@@ -30,7 +54,13 @@ pgd_t *pgd_alloc(struct mm_struct *mm) + void pgd_free(struct mm_struct *mm, pgd_t *pgd) + { + if (PGD_SIZE == PAGE_SIZE) ++#ifdef CONFIG_PTP ++ { ++ free_iee_pgtable_page((void *)pgd); ++ } ++#else + free_page((unsigned long)pgd); ++#endif + else + kmem_cache_free(pgd_cache, pgd); + } +diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S +index 14fdf645edc8..4fad195becff 100644 +--- a/arch/arm64/mm/proc.S ++++ b/arch/arm64/mm/proc.S +@@ -22,6 +22,8 @@ + #include + #include + ++ ++ + #ifdef CONFIG_ARM64_64K_PAGES + #define TCR_TG_FLAGS TCR_TG0_64K | TCR_TG1_64K + #elif defined(CONFIG_ARM64_16K_PAGES) +@@ -190,6 +192,7 @@ SYM_TYPED_FUNC_START(idmap_cpu_replace_ttbr1) + __idmap_cpu_set_reserved_ttbr1 x1, x3 + + offset_ttbr1 x0, x3 ++ + msr ttbr1_el1, x0 + isb + +@@ -452,6 +455,11 @@ SYM_FUNC_START(__cpu_setup) + orr tcr, tcr, #TCR_HA // hardware Access flag update + 1: + #endif /* CONFIG_ARM64_HW_AFDBM */ ++ ++#ifdef CONFIG_IEE ++ orr tcr, tcr, #TCR_HPD1 // Hierarchical permission disables ++#endif ++ + msr mair_el1, mair + msr tcr_el1, tcr + +diff --git a/arch/arm64/mm/trans_pgd.c b/arch/arm64/mm/trans_pgd.c +index 5139a28130c0..729b6f5a9314 100644 +--- a/arch/arm64/mm/trans_pgd.c ++++ b/arch/arm64/mm/trans_pgd.c +@@ -25,6 +25,9 @@ + #include + #include + #include ++#ifdef CONFIG_PTP ++#include ++#endif + + static void *trans_alloc(struct trans_pgd_info *info) + { +@@ -65,10 +68,16 @@ static int copy_pte(struct trans_pgd_info *info, pmd_t *dst_pmdp, + pte_t *src_ptep; + pte_t *dst_ptep; + unsigned long addr = start; ++ #ifdef CONFIG_PTP ++ unsigned long iee_addr; ++ #endif + + dst_ptep = trans_alloc(info); + if (!dst_ptep) + return -ENOMEM; ++ #ifdef CONFIG_PTP ++ set_iee_page((unsigned long)dst_ptep,0); ++ #endif + pmd_populate_kernel(NULL, dst_pmdp, dst_ptep); + dst_ptep = pte_offset_kernel(dst_pmdp, start); + +@@ -87,11 +96,17 @@ static int copy_pmd(struct trans_pgd_info *info, pud_t *dst_pudp, + pmd_t *dst_pmdp; + unsigned long next; + unsigned long addr = start; ++ #ifdef CONFIG_PTP ++ unsigned long iee_addr; ++ #endif + + if (pud_none(READ_ONCE(*dst_pudp))) { + dst_pmdp = trans_alloc(info); + if (!dst_pmdp) + return -ENOMEM; ++ #ifdef CONFIG_PTP ++ set_iee_page((unsigned long)dst_pmdp,0); ++ #endif + pud_populate(NULL, dst_pudp, dst_pmdp); + } + dst_pmdp = pmd_offset(dst_pudp, start); +@@ -123,11 +138,17 @@ static int copy_pud(struct trans_pgd_info *info, p4d_t *dst_p4dp, + pud_t *src_pudp; + unsigned long next; + unsigned long addr = start; ++ #ifdef CONFIG_PTP ++ unsigned long iee_addr; ++ #endif + + if (p4d_none(READ_ONCE(*dst_p4dp))) { + dst_pudp = trans_alloc(info); + if (!dst_pudp) + return -ENOMEM; ++ #ifdef CONFIG_PTP ++ set_iee_page((unsigned long)dst_pudp,0); ++ #endif + p4d_populate(NULL, dst_p4dp, dst_pudp); + } + dst_pudp = pud_offset(dst_p4dp, start); +@@ -212,6 +233,10 @@ int trans_pgd_create_copy(struct trans_pgd_info *info, pgd_t **dst_pgdp, + return -ENOMEM; + } + ++ #ifdef CONFIG_PTP ++ set_iee_page((unsigned long)trans_pgd,0); ++ #endif ++ + rc = copy_page_tables(info, trans_pgd, start, end); + if (!rc) + *dst_pgdp = trans_pgd; +@@ -238,6 +263,9 @@ int trans_pgd_idmap_page(struct trans_pgd_info *info, phys_addr_t *trans_ttbr0, + int bits_mapped = PAGE_SHIFT - 4; + unsigned long level_mask, prev_level_entry, *levels[4]; + int this_level, index, level_lsb, level_msb; ++ #ifdef CONFIG_PTP ++ unsigned long iee_addr; ++ #endif + + dst_addr &= PAGE_MASK; + prev_level_entry = pte_val(pfn_pte(pfn, PAGE_KERNEL_ROX)); +@@ -247,12 +275,20 @@ int trans_pgd_idmap_page(struct trans_pgd_info *info, phys_addr_t *trans_ttbr0, + if (!levels[this_level]) + return -ENOMEM; + ++ #ifdef CONFIG_PTP ++ set_iee_page((unsigned long)levels[this_level],0); ++ #endif ++ + level_lsb = ARM64_HW_PGTABLE_LEVEL_SHIFT(this_level); + level_msb = min(level_lsb + bits_mapped, max_msb); + level_mask = GENMASK_ULL(level_msb, level_lsb); + + index = (dst_addr & level_mask) >> level_lsb; ++ #ifdef CONFIG_PTP ++ set_pte((pte_t *)(levels[this_level] + index), __pte(prev_level_entry)); ++ #else + *(levels[this_level] + index) = prev_level_entry; ++ #endif + + pfn = virt_to_pfn(levels[this_level]); + prev_level_entry = pte_val(pfn_pte(pfn, +diff --git a/block/sed-opal.c b/block/sed-opal.c +index 1a1cb35bf4b7..7149485a808c 100644 +--- a/block/sed-opal.c ++++ b/block/sed-opal.c +@@ -316,7 +316,11 @@ static int read_sed_opal_key(const char *key_name, u_char *buffer, int buflen) + return PTR_ERR(kref); + + key = key_ref_to_ptr(kref); ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(key)); ++ #else + down_read(&key->sem); ++ #endif + ret = key_validate(key); + if (ret == 0) { + if (buflen > key->datalen) +@@ -324,7 +328,11 @@ static int read_sed_opal_key(const char *key_name, u_char *buffer, int buflen) + + ret = key->type->read(key, (char *)buffer, buflen); + } ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + + key_ref_put(kref); + +diff --git a/certs/blacklist.c b/certs/blacklist.c +index 675dd7a8f07a..4db9c6cb7732 100644 +--- a/certs/blacklist.c ++++ b/certs/blacklist.c +@@ -19,6 +19,10 @@ + #include + #include "blacklist.h" + ++#ifdef CONFIG_KEYP ++#include ++#endif ++ + /* + * According to crypto/asymmetric_keys/x509_cert_parser.c:x509_note_pkey_algo(), + * the size of the currently longest supported hash algorithm is 512 bits, +@@ -91,7 +95,11 @@ static int blacklist_key_instantiate(struct key *key, + #endif + + /* Sets safe default permissions for keys loaded by user space. */ ++ #ifdef CONFIG_KEYP ++ iee_set_key_perm(key, BLACKLIST_KEY_PERM); ++ #else + key->perm = BLACKLIST_KEY_PERM; ++ #endif + + /* + * Skips the authentication step for builtin hashes, they are not +diff --git a/certs/system_keyring.c b/certs/system_keyring.c +index a803524044bd..eab10ce55564 100644 +--- a/certs/system_keyring.c ++++ b/certs/system_keyring.c +@@ -96,9 +96,15 @@ int restrict_link_by_builtin_and_secondary_trusted( + /* If we have a secondary trusted keyring, then that contains a link + * through to the builtin keyring and the search will follow that link. + */ ++ #ifdef CONFIG_KEYP ++ if (type == &key_type_keyring && ++ dest_keyring == secondary_trusted_keys && ++ payload == (union key_payload *)(builtin_trusted_keys->name_link.next)) ++ #else + if (type == &key_type_keyring && + dest_keyring == secondary_trusted_keys && + payload == &builtin_trusted_keys->payload) ++ #endif + /* Allow the builtin keyring to be added to the secondary */ + return 0; + +@@ -125,9 +131,15 @@ int restrict_link_by_digsig_builtin_and_secondary(struct key *dest_keyring, + /* If we have a secondary trusted keyring, then that contains a link + * through to the builtin keyring and the search will follow that link. + */ ++ #ifdef CONFIG_KEYP ++ if (type == &key_type_keyring && ++ dest_keyring == secondary_trusted_keys && ++ payload == (union key_payload *)(builtin_trusted_keys->name_link.next)) ++ #else + if (type == &key_type_keyring && + dest_keyring == secondary_trusted_keys && + payload == &builtin_trusted_keys->payload) ++ #endif + /* Allow the builtin keyring to be added to the secondary */ + return 0; + +@@ -212,9 +224,15 @@ int restrict_link_by_builtin_secondary_and_machine( + const union key_payload *payload, + struct key *restrict_key) + { ++ #ifdef CONFIG_KEYP ++ if (machine_trusted_keys && type == &key_type_keyring && ++ dest_keyring == secondary_trusted_keys && ++ payload == (union key_payload *)(machine_trusted_keys->name_link.next)) ++ #else + if (machine_trusted_keys && type == &key_type_keyring && + dest_keyring == secondary_trusted_keys && + payload == &machine_trusted_keys->payload) ++ #endif + /* Allow the machine keyring to be added to the secondary */ + return 0; + +diff --git a/crypto/af_alg.c b/crypto/af_alg.c +index 68cc9290cabe..6d4415de9ee4 100644 +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -304,7 +304,11 @@ static int alg_setkey_by_key_serial(struct alg_sock *ask, sockptr_t optval, + if (IS_ERR(key)) + return PTR_ERR(key); + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(key)); ++ #else + down_read(&key->sem); ++ #endif + + ret = ERR_PTR(-ENOPROTOOPT); + if (!strcmp(key->type->name, "user") || +@@ -319,21 +323,33 @@ static int alg_setkey_by_key_serial(struct alg_sock *ask, sockptr_t optval, + } + + if (IS_ERR(ret)) { ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + return PTR_ERR(ret); + } + + key_data = sock_kmalloc(&ask->sk, key_datalen, GFP_KERNEL); + if (!key_data) { ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + return -ENOMEM; + } + + memcpy(key_data, ret, key_datalen); + ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + + err = type->setkey(ask->private, key_data, key_datalen); +diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c +index 43af5fa510c0..40dd58a69617 100644 +--- a/crypto/asymmetric_keys/asymmetric_type.c ++++ b/crypto/asymmetric_keys/asymmetric_type.c +@@ -16,6 +16,9 @@ + #include + #include + #include "asymmetric_keys.h" ++#ifdef CONFIG_KEYP ++#include ++#endif + + + const char *const key_being_used_for[NR__KEY_BEING_USED_FOR] = { +@@ -467,6 +470,18 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) + static void asymmetric_key_destroy(struct key *key) + { + struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); ++ #ifdef CONFIG_KEYP ++ struct asymmetric_key_ids *kids = ((union key_payload *)(key->name_link.next))->data[asym_key_ids]; ++ void *data = ((union key_payload *)(key->name_link.next))->data[asym_crypto]; ++ void *auth = ((union key_payload *)(key->name_link.next))->data[asym_auth]; ++ ++ union key_payload key_payload = *((union key_payload *)(key->name_link.next)); ++ key_payload.data[asym_crypto] = NULL; ++ key_payload.data[asym_subtype] = NULL; ++ key_payload.data[asym_key_ids] = NULL; ++ key_payload.data[asym_auth] = NULL; ++ iee_write_key_payload(key, key_payload); ++ #else + struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids]; + void *data = key->payload.data[asym_crypto]; + void *auth = key->payload.data[asym_auth]; +@@ -475,6 +490,7 @@ static void asymmetric_key_destroy(struct key *key) + key->payload.data[asym_subtype] = NULL; + key->payload.data[asym_key_ids] = NULL; + key->payload.data[asym_auth] = NULL; ++ #endif + + if (subtype) { + subtype->destroy(data, auth); +@@ -580,8 +596,13 @@ int asymmetric_key_eds_op(struct kernel_pkey_params *params, + if (key->type != &key_type_asymmetric) + return -EINVAL; + subtype = asymmetric_key_subtype(key); ++ #ifdef CONFIG_KEYP ++ if (!subtype || ++ !((union key_payload *)(key->name_link.next))->data[0]) ++ #else + if (!subtype || + !key->payload.data[0]) ++ #endif + return -EINVAL; + if (!subtype->eds_op) + return -ENOTSUPP; +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +index 1dcab27986a6..490ba98995c1 100644 +--- a/crypto/asymmetric_keys/public_key.c ++++ b/crypto/asymmetric_keys/public_key.c +@@ -30,7 +30,11 @@ MODULE_LICENSE("GPL"); + static void public_key_describe(const struct key *asymmetric_key, + struct seq_file *m) + { ++ #ifdef CONFIG_KEYP ++ struct public_key *key = ((union key_payload *)(asymmetric_key->name_link.next))->data[asym_crypto]; ++ #else + struct public_key *key = asymmetric_key->payload.data[asym_crypto]; ++ #endif + + if (key) + seq_printf(m, "%s.%s", key->id_type, key->pkey_algo); +@@ -158,7 +162,11 @@ static int software_key_query(const struct kernel_pkey_params *params, + struct kernel_pkey_query *info) + { + struct crypto_akcipher *tfm; ++ #ifdef CONFIG_KEYP ++ struct public_key *pkey = ((union key_payload *)(params->key->name_link.next))->data[asym_crypto]; ++ #else + struct public_key *pkey = params->key->payload.data[asym_crypto]; ++ #endif + char alg_name[CRYPTO_MAX_ALG_NAME]; + struct crypto_sig *sig; + u8 *key, *ptr; +@@ -273,7 +281,11 @@ static int software_key_query(const struct kernel_pkey_params *params, + static int software_key_eds_op(struct kernel_pkey_params *params, + const void *in, void *out) + { ++ #ifdef CONFIG_KEYP ++ const struct public_key *pkey = ((union key_payload *)(params->key->name_link.next))->data[asym_crypto]; ++ #else + const struct public_key *pkey = params->key->payload.data[asym_crypto]; ++ #endif + char alg_name[CRYPTO_MAX_ALG_NAME]; + struct crypto_akcipher *tfm; + struct crypto_sig *sig; +@@ -453,7 +465,11 @@ EXPORT_SYMBOL_GPL(public_key_verify_signature); + static int public_key_verify_signature_2(const struct key *key, + const struct public_key_signature *sig) + { ++ #ifdef CONFIG_KEYP ++ const struct public_key *pk = ((union key_payload *)(key->name_link.next))->data[asym_crypto]; ++ #else + const struct public_key *pk = key->payload.data[asym_crypto]; ++ #endif + return public_key_verify_signature(pk, sig); + } + +diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c +index 2deff81f8af5..696fa2c4e708 100644 +--- a/crypto/asymmetric_keys/signature.c ++++ b/crypto/asymmetric_keys/signature.c +@@ -51,8 +51,13 @@ int query_asymmetric_key(const struct kernel_pkey_params *params, + if (key->type != &key_type_asymmetric) + return -EINVAL; + subtype = asymmetric_key_subtype(key); ++ #ifdef CONFIG_KEYP ++ if (!subtype || ++ !((union key_payload *)(key->name_link.next))->data[0]) ++ #else + if (!subtype || + !key->payload.data[0]) ++ #endif + return -EINVAL; + if (!subtype->query) + return -ENOTSUPP; +@@ -145,8 +150,13 @@ int verify_signature(const struct key *key, + if (key->type != &key_type_asymmetric) + return -EINVAL; + subtype = asymmetric_key_subtype(key); ++ #ifdef CONFIG_KEYP ++ if (!subtype || ++ !((union key_payload *)(key->name_link.next))->data[0]) ++ #else + if (!subtype || + !key->payload.data[0]) ++ #endif + return -EINVAL; + if (!subtype->verify_signature) + return -ENOTSUPP; +diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c +index 83092d93f36a..fb12e7d0660a 100644 +--- a/drivers/firmware/efi/arm-runtime.c ++++ b/drivers/firmware/efi/arm-runtime.c +@@ -94,7 +94,11 @@ static int __init arm_enable_runtime_services(void) + return 0; + } + ++ #ifdef CONFIG_PTP ++ efi_memmap_unmap_after_init(); + #else -+ __map_memblock(pgdp, kernel_start, kernel_end, -+ PAGE_KERNEL, NO_CONT_MAPPINGS); + efi_memmap_unmap(); + #endif -+ memblock_clear_nomap(kernel_start, kernel_end - kernel_start); -+ arm64_kfence_map_pool(early_kfence_pool, pgdp); -+} -+ -+void mark_rodata_ro(void) + + mapsize = efi.memmap.desc_size * efi.memmap.nr_map; + +diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c +index 77dd20f9df31..ea8ebecaa153 100644 +--- a/drivers/firmware/efi/memmap.c ++++ b/drivers/firmware/efi/memmap.c +@@ -96,6 +96,26 @@ void __init efi_memmap_unmap(void) + clear_bit(EFI_MEMMAP, &efi.flags); + } + ++#ifdef CONFIG_PTP ++void __init efi_memmap_unmap_after_init(void) +{ -+ unsigned long section_size; ++ if (!efi_enabled(EFI_MEMMAP)) ++ return; + -+ /* -+ * mark .rodata as read only. Use __init_begin rather than __end_rodata -+ * to cover NOTES and EXCEPTION_TABLE. -+ */ -+ section_size = (unsigned long)__init_begin - (unsigned long)__start_rodata; -+ update_mapping_prot(__pa_symbol(__start_rodata), (unsigned long)__start_rodata, -+ section_size, PAGE_KERNEL_RO); ++ if (!(efi.memmap.flags & EFI_MEMMAP_LATE)) { ++ unsigned long size; ++ ++ size = efi.memmap.desc_size * efi.memmap.nr_map; ++ early_iounmap_after_init((__force void __iomem *)efi.memmap.map, size); ++ } else { ++ memunmap(efi.memmap.map); ++ } + -+ debug_checkwx(); ++ efi.memmap.map = NULL; ++ clear_bit(EFI_MEMMAP, &efi.flags); +} ++#endif + -+static void __init map_kernel_segment(pgd_t *pgdp, void *va_start, void *va_end, -+ pgprot_t prot, struct vm_struct *vma, -+ int flags, unsigned long vm_flags) -+{ -+ phys_addr_t pa_start = __pa_symbol(va_start); -+ unsigned long size = va_end - va_start; + /** + * efi_memmap_init_late - Map efi.memmap with memremap() + * @phys_addr: Physical address of the new EFI memory map +diff --git a/drivers/md/Makefile b/drivers/md/Makefile +index 84291e38dca8..b3af9d419b6e 100644 +--- a/drivers/md/Makefile ++++ b/drivers/md/Makefile +@@ -71,6 +71,7 @@ obj-$(CONFIG_DM_PERSISTENT_DATA) += persistent-data/ + obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o + obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o + obj-$(CONFIG_DM_ZERO) += dm-zero.o ++obj-$(CONFIG_DM_ZERO_KOI) += dm-zero_koi.o + obj-$(CONFIG_DM_RAID) += dm-raid.o + obj-$(CONFIG_DM_THIN_PROVISIONING) += dm-thin-pool.o + obj-$(CONFIG_DM_VERITY) += dm-verity.o +diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c +index aa6bb5b4704b..ecf777e5d176 100644 +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -2512,7 +2512,11 @@ static int set_key_encrypted(struct crypt_config *cc, struct key *key) + { + const struct encrypted_key_payload *ekp; + ++ #ifdef CONFIG_KEYP ++ ekp = ((union key_payload *)(key->name_link.next))->data[0]; ++ #else + ekp = key->payload.data[0]; ++ #endif + if (!ekp) + return -EKEYREVOKED; + +@@ -2528,7 +2532,11 @@ static int set_key_trusted(struct crypt_config *cc, struct key *key) + { + const struct trusted_key_payload *tkp; + ++ #ifdef CONFIG_KEYP ++ tkp = ((union key_payload *)(key->name_link.next))->data[0]; ++ #else + tkp = key->payload.data[0]; ++ #endif + if (!tkp) + return -EKEYREVOKED; + +@@ -2590,17 +2598,29 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string + return PTR_ERR(key); + } + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(key)); ++ #else + down_read(&key->sem); ++ #endif + + ret = set_key(cc, key); + if (ret < 0) { ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + kfree_sensitive(new_key_string); + return ret; + } + ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + + /* clear the flag since following operations may invalidate previously valid key */ +diff --git a/drivers/md/dm-verity-verify-sig.c b/drivers/md/dm-verity-verify-sig.c +index 4836508ea50c..d52d5bccc190 100644 +--- a/drivers/md/dm-verity-verify-sig.c ++++ b/drivers/md/dm-verity-verify-sig.c +@@ -40,7 +40,11 @@ static int verity_verify_get_sig_from_key(const char *key_desc, + if (IS_ERR(key)) + return PTR_ERR(key); + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(key)); ++ #else + down_read(&key->sem); ++ #endif + + ukp = user_key_payload_locked(key); + if (!ukp) { +@@ -58,7 +62,11 @@ static int verity_verify_get_sig_from_key(const char *key_desc, + memcpy(sig_opts->sig, ukp->data, sig_opts->sig_size); + + end: ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + + return ret; +diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c +index a03e3c45f297..71bccea085e9 100644 +--- a/drivers/nvdimm/security.c ++++ b/drivers/nvdimm/security.c +@@ -28,7 +28,11 @@ static void *key_data(struct key *key) + { + struct encrypted_key_payload *epayload = dereference_key_locked(key); + ++ #ifdef CONFIG_KEYP ++ lockdep_assert_held_read(&KEY_SEM(key)); ++ #else + lockdep_assert_held_read(&key->sem); ++ #endif + + return epayload->decrypted_data; + } +@@ -38,7 +42,11 @@ static void nvdimm_put_key(struct key *key) + if (!key) + return; + ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + } + +@@ -65,10 +73,18 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm) + } else { + struct encrypted_key_payload *epayload; + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(key)); ++ #else + down_read(&key->sem); ++ #endif + epayload = dereference_key_locked(key); + if (epayload->decrypted_datalen != NVDIMM_PASSPHRASE_LEN) { ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + key = NULL; + } +@@ -107,10 +123,18 @@ static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, + + dev_dbg(dev, "%s: key found: %#x\n", __func__, key_serial(key)); + ++ #ifdef CONFIG_KEYP ++ down_read_nested(&KEY_SEM(key), subclass); ++ #else + down_read_nested(&key->sem, subclass); ++ #endif + epayload = dereference_key_locked(key); + if (epayload->decrypted_datalen != NVDIMM_PASSPHRASE_LEN) { ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + key = NULL; + } +diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c +index 7e0d8fb26465..950ee6396659 100644 +--- a/drivers/rtc/rtc-test.c ++++ b/drivers/rtc/rtc-test.c +@@ -198,4 +198,4 @@ MODULE_DESCRIPTION("RTC test driver/device"); + MODULE_LICENSE("GPL v2"); + + module_init(test_init); +-module_exit(test_exit); ++module_exit(test_exit); +\ No newline at end of file +diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c +index a5fbb6ed38ae..81428783b9da 100644 +--- a/drivers/tty/serial/earlycon.c ++++ b/drivers/tty/serial/earlycon.c +@@ -40,7 +40,11 @@ static void __iomem * __init earlycon_map(resource_size_t paddr, size_t size) + { + void __iomem *base; + #ifdef CONFIG_FIX_EARLYCON_MEM ++ #ifdef CONFIG_PTP ++ __iee_set_fixmap_pre_init(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK, FIXMAP_PAGE_IO); ++ #else + set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK); ++ #endif + base = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); + base += paddr & ~PAGE_MASK; + #else +diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c +index 45b42d8f6453..b71072d6957e 100644 +--- a/drivers/usb/early/ehci-dbgp.c ++++ b/drivers/usb/early/ehci-dbgp.c +@@ -879,7 +879,11 @@ int __init early_dbgp_init(char *s) + * FIXME I don't have the bar size so just guess PAGE_SIZE is more + * than enough. 1K is the biggest I have seen. + */ ++ #ifdef CONFIG_PTP ++ __iee_set_fixmap_pre_init(FIX_DBGP_BASE, bar_val & PAGE_MASK, FIXMAP_PAGE_NOCACHE); ++ #else + set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK); ++ #endif + ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE); + ehci_bar += bar_val & ~PAGE_MASK; + dbgp_printk("ehci_bar: %p\n", ehci_bar); +diff --git a/fs/coredump.c b/fs/coredump.c +index 9d235fa14ab9..72be355903ca 100644 +--- a/fs/coredump.c ++++ b/fs/coredump.c +@@ -53,6 +53,10 @@ + + #include + ++#ifdef CONFIG_CREDP ++#include ++#endif + -+ BUG_ON(!PAGE_ALIGNED(pa_start)); -+ BUG_ON(!PAGE_ALIGNED(size)); + static bool dump_vma_snapshot(struct coredump_params *cprm); + static void free_vma_snapshot(struct coredump_params *cprm); + +@@ -564,7 +568,11 @@ void do_coredump(const kernel_siginfo_t *siginfo) + */ + if (__get_dumpable(cprm.mm_flags) == SUID_DUMP_ROOT) { + /* Setuid core dump mode */ ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(cred,GLOBAL_ROOT_UID); ++ #else + cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */ ++ #endif + need_suid_safe = true; + } + +diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c +index 7cbb1fd872ac..a8425a83aabf 100644 +--- a/fs/crypto/keyring.c ++++ b/fs/crypto/keyring.c +@@ -590,8 +590,13 @@ static void fscrypt_provisioning_key_describe(const struct key *key, + { + seq_puts(m, key->description); + if (key_is_positive(key)) { ++ #ifdef CONFIG_KEYP ++ const struct fscrypt_provisioning_key_payload *payload = ++ ((union key_payload *)(key->name_link.next))->data[0]; ++ #else + const struct fscrypt_provisioning_key_payload *payload = + key->payload.data[0]; ++ #endif + + seq_printf(m, ": %u [%u]", key->datalen, payload->type); + } +@@ -599,7 +604,11 @@ static void fscrypt_provisioning_key_describe(const struct key *key, + + static void fscrypt_provisioning_key_destroy(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ kfree_sensitive(((union key_payload *)(key->name_link.next))->data[0]); ++ #else + kfree_sensitive(key->payload.data[0]); ++ #endif + } + + static struct key_type key_type_fscrypt_provisioning = { +@@ -641,7 +650,11 @@ static int get_keyring_key(u32 key_id, u32 type, + + if (key->type != &key_type_fscrypt_provisioning) + goto bad_key; ++ #ifdef CONFIG_KEYP ++ payload = ((union key_payload *)(key->name_link.next))->data[0]; ++ #else + payload = key->payload.data[0]; ++ #endif + + /* Don't allow fscrypt v1 keys to be used as v2 keys and vice versa. */ + if (payload->type != type) +diff --git a/fs/crypto/keysetup_v1.c b/fs/crypto/keysetup_v1.c +index 75dabd9b27f9..9d0cc6ef8e48 100644 +--- a/fs/crypto/keysetup_v1.c ++++ b/fs/crypto/keysetup_v1.c +@@ -109,7 +109,11 @@ find_and_lock_process_key(const char *prefix, + if (IS_ERR(key)) + return key; + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(key)); ++ #else + down_read(&key->sem); ++ #endif + ukp = user_key_payload_locked(key); + + if (!ukp) /* was the key revoked before we acquired its semaphore? */ +@@ -136,7 +140,11 @@ find_and_lock_process_key(const char *prefix, + return key; + + invalid: ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + return ERR_PTR(-ENOKEY); + } +@@ -315,7 +323,11 @@ int fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_info *ci) + return PTR_ERR(key); + + err = fscrypt_setup_v1_file_key(ci, payload->raw); ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + return err; + } +diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h +index f2ed0c0266cb..1a24f8dcff5c 100644 +--- a/fs/ecryptfs/ecryptfs_kernel.h ++++ b/fs/ecryptfs/ecryptfs_kernel.h +@@ -82,7 +82,11 @@ ecryptfs_get_encrypted_key_payload_data(struct key *key) + if (key->type != &key_type_encrypted) + return NULL; + ++ #ifdef CONFIG_KEYP ++ payload = ((union key_payload *)(key->name_link.next))->data[0]; ++ #else + payload = key->payload.data[0]; ++ #endif + if (!payload) + return ERR_PTR(-EKEYREVOKED); + +diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c +index 7f9f68c00ef6..a4859a7d3b5d 100644 +--- a/fs/ecryptfs/keystore.c ++++ b/fs/ecryptfs/keystore.c +@@ -512,7 +512,11 @@ ecryptfs_find_global_auth_tok_for_sig( + goto out_invalid_auth_tok; + } + ++ #ifdef CONFIG_KEYP ++ down_write(&(KEY_SEM(walker->global_auth_tok_key))); ++ #else + down_write(&(walker->global_auth_tok_key->sem)); ++ #endif + rc = ecryptfs_verify_auth_tok_from_key( + walker->global_auth_tok_key, auth_tok); + if (rc) +@@ -525,7 +529,11 @@ ecryptfs_find_global_auth_tok_for_sig( + rc = -ENOENT; + goto out; + out_invalid_auth_tok_unlock: ++ #ifdef CONFIG_KEYP ++ up_write(&(KEY_SEM(walker->global_auth_tok_key))); ++ #else + up_write(&(walker->global_auth_tok_key->sem)); ++ #endif + out_invalid_auth_tok: + printk(KERN_WARNING "Invalidating auth tok with sig = [%s]\n", sig); + walker->flags |= ECRYPTFS_AUTH_TOK_INVALID; +@@ -846,7 +854,11 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, + mutex_unlock(s->tfm_mutex); + out: + if (auth_tok_key) { ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(auth_tok_key)); ++ #else + up_write(&(auth_tok_key->sem)); ++ #endif + key_put(auth_tok_key); + } + skcipher_request_free(s->skcipher_req); +@@ -1088,7 +1100,11 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, + (*filename) = NULL; + } + if (auth_tok_key) { ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(auth_tok_key)); ++ #else + up_write(&(auth_tok_key->sem)); ++ #endif + key_put(auth_tok_key); + } + skcipher_request_free(s->skcipher_req); +@@ -1625,10 +1641,18 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, + goto out; + } + } ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM((*auth_tok_key))); ++ #else + down_write(&(*auth_tok_key)->sem); ++ #endif + rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok); + if (rc) { ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM((*auth_tok_key))); ++ #else + up_write(&(*auth_tok_key)->sem); ++ #endif + key_put(*auth_tok_key); + (*auth_tok_key) = NULL; + goto out; +@@ -1901,7 +1925,11 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, + memcpy(&(candidate_auth_tok->token.private_key), + &(matching_auth_tok->token.private_key), + sizeof(struct ecryptfs_private_key)); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(auth_tok_key)); ++ #else + up_write(&(auth_tok_key->sem)); ++ #endif + key_put(auth_tok_key); + rc = decrypt_pki_encrypted_session_key(candidate_auth_tok, + crypt_stat); +@@ -1909,12 +1937,20 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, + memcpy(&(candidate_auth_tok->token.password), + &(matching_auth_tok->token.password), + sizeof(struct ecryptfs_password)); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(auth_tok_key)); ++ #else + up_write(&(auth_tok_key->sem)); ++ #endif + key_put(auth_tok_key); + rc = decrypt_passphrase_encrypted_session_key( + candidate_auth_tok, crypt_stat); + } else { ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(auth_tok_key)); ++ #else + up_write(&(auth_tok_key->sem)); ++ #endif + key_put(auth_tok_key); + rc = -EINVAL; + } +@@ -1976,7 +2012,11 @@ pki_encrypt_session_key(struct key *auth_tok_key, + crypt_stat->cipher, + crypt_stat->key_size), + crypt_stat, &payload, &payload_len); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(auth_tok_key)); ++ #else + up_write(&(auth_tok_key->sem)); ++ #endif + key_put(auth_tok_key); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n"); +@@ -2040,7 +2080,11 @@ write_tag_1_packet(char *dest, size_t *remaining_bytes, + memcpy(key_rec->enc_key, + auth_tok->session_key.encrypted_key, + auth_tok->session_key.encrypted_key_size); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(auth_tok_key)); ++ #else + up_write(&(auth_tok_key->sem)); ++ #endif + key_put(auth_tok_key); + goto encrypted_session_key_set; + } +@@ -2438,7 +2482,11 @@ ecryptfs_generate_key_packet_set(char *dest_base, + &max, auth_tok, + crypt_stat, key_rec, + &written); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(auth_tok_key)); ++ #else + up_write(&(auth_tok_key->sem)); ++ #endif + key_put(auth_tok_key); + if (rc) { + ecryptfs_printk(KERN_WARNING, "Error " +@@ -2467,7 +2515,11 @@ ecryptfs_generate_key_packet_set(char *dest_base, + } + (*len) += written; + } else { ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(auth_tok_key)); ++ #else + up_write(&(auth_tok_key->sem)); ++ #endif + key_put(auth_tok_key); + ecryptfs_printk(KERN_WARNING, "Unsupported " + "authentication token type\n"); +diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c +index 2dc927ba067f..39c6f1d1438c 100644 +--- a/fs/ecryptfs/main.c ++++ b/fs/ecryptfs/main.c +@@ -202,7 +202,11 @@ static int ecryptfs_init_global_auth_toks( + goto out; + } else { + global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID; ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(global_auth_tok->global_auth_tok_key)); ++ #else + up_write(&(global_auth_tok->global_auth_tok_key)->sem); ++ #endif + } + } + out: +diff --git a/fs/exec.c b/fs/exec.c +index a4725461a443..7691f803c9fa 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -76,6 +76,14 @@ + + #include + ++#ifdef CONFIG_CREDP ++#include ++#endif ++ ++#ifdef CONFIG_IEE ++#include ++#endif + + static int bprm_creds_from_file(struct linux_binprm *bprm); + + int suid_dumpable = 0; +@@ -725,7 +733,11 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) + free_pgd_range(&tlb, old_start, old_end, new_end, + next ? next->vm_start : USER_PGTABLES_CEILING); + } + #ifdef CONFIG_PTP -+ __iee_create_pgd_mapping_pre_init(pgdp, pa_start, (unsigned long)va_start, size, prot, -+ early_pgtable_alloc, flags); ++ iee_tlb_finish_mmu(&tlb); + #else -+ __create_pgd_mapping(pgdp, pa_start, (unsigned long)va_start, size, prot, -+ early_pgtable_alloc, flags); + tlb_finish_mmu(&tlb); + #endif + + vma_prev(&vmi); + /* Shrink the vma to just the new range */ +@@ -1005,6 +1017,9 @@ static int exec_mmap(struct mm_struct *mm) + if (!IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM)) + local_irq_enable(); + activate_mm(active_mm, mm); ++ #ifdef CONFIG_IEE ++ iee_set_token_pgd(tsk, mm->pgd); ++ #endif + if (IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM)) + local_irq_enable(); + lru_gen_add_mm(mm); +@@ -1624,12 +1639,20 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) + + if (mode & S_ISUID) { + bprm->per_clear |= PER_CLEAR_ON_SETID; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_euid(bprm->cred, vfsuid_into_kuid(vfsuid)); ++ #else + bprm->cred->euid = vfsuid_into_kuid(vfsuid); ++ #endif + } + + if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { + bprm->per_clear |= PER_CLEAR_ON_SETID; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_egid(bprm->cred, vfsgid_into_kgid(vfsgid)); ++ #else + bprm->cred->egid = vfsgid_into_kgid(vfsgid); ++ #endif + } + } + +diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c +index 3e724cb7ef01..e32e136e4271 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -15,6 +15,10 @@ + + #include + ++#ifdef CONFIG_CREDP ++#include ++#endif + -+ if (!(vm_flags & VM_NO_GUARD)) -+ size += PAGE_SIZE; -+ -+ vma->addr = va_start; -+ vma->phys_addr = pa_start; -+ vma->size = size; -+ vma->flags = VM_MAP | vm_flags; -+ vma->caller = __builtin_return_address(0); -+ -+ vm_area_add_early(vma); -+} -+ -+static pgprot_t kernel_exec_prot(void) -+{ -+ return rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC; -+} -+ -+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 -+static int __init map_entry_trampoline(void) -+{ -+ int i; -+ -+ pgprot_t prot = kernel_exec_prot(); -+ phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start); + #include "flexfilelayout.h" + #include "../nfs4session.h" + #include "../nfs4idmap.h" +@@ -502,8 +506,13 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, + rc = -ENOMEM; + if (!kcred) + goto out_err_free; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(kcred,uid); ++ iee_set_cred_fsgid(kcred,gid); ++ #else + kcred->fsuid = uid; + kcred->fsgid = gid; ++ #endif + cred = RCU_INITIALIZER(kcred); + + if (lgr->range.iomode == IOMODE_READ) +diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c +index 25a7c771cfd8..c11c2e78e782 100644 +--- a/fs/nfs/nfs4idmap.c ++++ b/fs/nfs/nfs4idmap.c +@@ -48,6 +48,13 @@ + #include + #include + ++#ifdef CONFIG_CREDP ++#include ++#endif ++#ifdef CONFIG_KEYP ++#include ++#endif + -+ /* The trampoline is always mapped and can therefore be global */ -+ pgprot_val(prot) &= ~PTE_NG; + #include "internal.h" + #include "netns.h" + #include "nfs4idmap.h" +@@ -225,9 +232,18 @@ int nfs_idmap_init(void) + if (ret < 0) + goto failed_reg_legacy; + ++ #ifdef CONFIG_KEYP ++ iee_set_key_flag_bit(keyring, KEY_FLAG_ROOT_CAN_CLEAR, SET_BIT_OP); ++ #else + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); ++ #endif ++ #ifdef CONFIG_CREDP ++ iee_set_cred_thread_keyring(cred,keyring); ++ iee_set_cred_jit_keyring(cred,KEY_REQKEY_DEFL_THREAD_KEYRING); ++ #else + cred->thread_keyring = keyring; + cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; ++ #endif + id_resolver_cache = cred; + return 0; + +@@ -296,7 +312,11 @@ static struct key *nfs_idmap_request_key(const char *name, size_t namelen, + mutex_unlock(&idmap->idmap_mutex); + } + if (!IS_ERR(rkey)) ++ #ifdef CONFIG_KEYP ++ iee_set_key_flag_bit(rkey, KEY_FLAG_ROOT_CAN_INVAL, SET_BIT_OP); ++ #else + set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags); ++ #endif + + kfree(desc); + return rkey; +@@ -321,7 +341,11 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, + } + + rcu_read_lock(); ++ #ifdef CONFIG_KEYP ++ iee_set_key_perm(rkey, rkey->perm | KEY_USR_VIEW); ++ #else + rkey->perm |= KEY_USR_VIEW; ++ #endif + + ret = key_validate(rkey); + if (ret < 0) +diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c +index e6beaaf4f170..e89385fd81f1 100644 +--- a/fs/nfsd/auth.c ++++ b/fs/nfsd/auth.c +@@ -2,6 +2,9 @@ + /* Copyright (C) 1995, 1996 Olaf Kirch */ + + #include ++#ifdef CONFIG_CREDP ++#include ++#endif + #include "nfsd.h" + #include "auth.h" + +@@ -32,22 +35,40 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) + if (!new) + return -ENOMEM; + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(new,rqstp->rq_cred.cr_uid); ++ iee_set_cred_fsgid(new,rqstp->rq_cred.cr_gid); ++ #else + new->fsuid = rqstp->rq_cred.cr_uid; + new->fsgid = rqstp->rq_cred.cr_gid; ++ #endif + + rqgi = rqstp->rq_cred.cr_group_info; + + if (flags & NFSEXP_ALLSQUASH) { ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(new,exp->ex_anon_uid); ++ iee_set_cred_fsgid(new,exp->ex_anon_gid); ++ #else + new->fsuid = exp->ex_anon_uid; + new->fsgid = exp->ex_anon_gid; ++ #endif + gi = groups_alloc(0); + if (!gi) + goto oom; + } else if (flags & NFSEXP_ROOTSQUASH) { + if (uid_eq(new->fsuid, GLOBAL_ROOT_UID)) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(new,exp->ex_anon_uid); ++ #else + new->fsuid = exp->ex_anon_uid; ++ #endif + if (gid_eq(new->fsgid, GLOBAL_ROOT_GID)) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsgid(new,exp->ex_anon_gid); ++ #else + new->fsgid = exp->ex_anon_gid; ++ #endif + + gi = groups_alloc(rqgi->ngroups); + if (!gi) +@@ -67,18 +88,35 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) + } + + if (uid_eq(new->fsuid, INVALID_UID)) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(new,exp->ex_anon_uid); ++ #else + new->fsuid = exp->ex_anon_uid; ++ #endif + if (gid_eq(new->fsgid, INVALID_GID)) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsgid(new,exp->ex_anon_gid); ++ #else + new->fsgid = exp->ex_anon_gid; ++ #endif + + set_groups(new, gi); + put_group_info(gi); + + if (!uid_eq(new->fsuid, GLOBAL_ROOT_UID)) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_cap_effective(new,cap_drop_nfsd_set(new->cap_effective)); ++ #else + new->cap_effective = cap_drop_nfsd_set(new->cap_effective); ++ #endif + else ++ #ifdef CONFIG_CREDP ++ iee_set_cred_cap_effective(new,cap_raise_nfsd_set(new->cap_effective, ++ new->cap_permitted)); ++ #else + new->cap_effective = cap_raise_nfsd_set(new->cap_effective, + new->cap_permitted); ++ #endif + put_cred(override_creds(new)); + put_cred(new); + return 0; +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index 49a88dde9631..4fde340b8471 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -41,6 +41,9 @@ + #include "trace.h" + #include "xdr4cb.h" + #include "xdr4.h" ++#ifdef CONFIG_CREDP ++#include ++#endif + + #define NFSDDBG_FACILITY NFSDDBG_PROC + +@@ -946,8 +949,13 @@ static const struct cred *get_backchannel_cred(struct nfs4_client *clp, struct r + if (!kcred) + return NULL; + +- kcred->fsuid = ses->se_cb_sec.uid; +- kcred->fsgid = ses->se_cb_sec.gid; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_uid(kcred,ses->se_cb_sec.uid); ++ iee_set_cred_gid(kcred,ses->se_cb_sec.gid); ++ #else ++ kcred->uid = ses->se_cb_sec.uid; ++ kcred->gid = ses->se_cb_sec.gid; ++ #endif + return kcred; + } + } +diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c +index 4395577825a7..8c34cfe01075 100644 +--- a/fs/nfsd/nfs4recover.c ++++ b/fs/nfsd/nfs4recover.c +@@ -44,6 +44,10 @@ + #include + #include + ++#ifdef CONFIG_CREDP ++#include ++#endif + -+ /* Map only the text into the trampoline page table */ -+ memset(tramp_pg_dir, 0, PGD_SIZE); -+ #ifdef CONFIG_PTP -+ iee_set_logical_mem_ro((unsigned long)tramp_pg_dir); + #include "nfsd.h" + #include "state.h" + #include "vfs.h" +@@ -78,8 +82,13 @@ nfs4_save_creds(const struct cred **original_creds) + if (!new) + return -ENOMEM; + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(new,GLOBAL_ROOT_UID); ++ iee_set_cred_fsgid(new,GLOBAL_ROOT_GID); ++ #else + new->fsuid = GLOBAL_ROOT_UID; + new->fsgid = GLOBAL_ROOT_GID; + #endif -+ __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, -+ entry_tramp_text_size(), prot, -+ __pgd_pgtable_alloc, NO_BLOCK_MAPPINGS); -+ -+ /* Map both the text and data into the kernel page table */ -+ for (i = 0; i < DIV_ROUND_UP(entry_tramp_text_size(), PAGE_SIZE); i++) -+ __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i, -+ pa_start + i * PAGE_SIZE, prot); -+ -+ if (IS_ENABLED(CONFIG_RELOCATABLE)) -+ __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i, -+ pa_start + i * PAGE_SIZE, PAGE_KERNEL_RO); -+ -+ return 0; -+} -+core_initcall(map_entry_trampoline); + *original_creds = override_creds(new); + put_cred(new); + return 0; +diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c +index c2495d98c189..779471a0aa66 100644 +--- a/fs/nfsd/nfsfh.c ++++ b/fs/nfsd/nfsfh.c +@@ -16,6 +16,10 @@ + #include "auth.h" + #include "trace.h" + ++#ifdef CONFIG_CREDP ++#include +#endif + -+/* -+ * Open coded check for BTI, only for use to determine configuration -+ * for early mappings for before the cpufeature code has run. -+ */ -+static bool arm64_early_this_cpu_has_bti(void) -+{ -+ u64 pfr1; -+ -+ if (!IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)) -+ return false; -+ -+ pfr1 = __read_sysreg_by_encoding(SYS_ID_AA64PFR1_EL1); -+ return cpuid_feature_extract_unsigned_field(pfr1, -+ ID_AA64PFR1_EL1_BT_SHIFT); -+} -+ -+#ifdef CONFIG_IEE -+/* Set PMD APTable of iee si codes as (1,1) to revert it to ROX P pages when HPD1=0. */ -+static void __init iee_si_set_pmd_APtable(unsigned long addr, pgd_t *pgdir) -+{ -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); -+ -+ p4d_t *p4dp = p4d_offset(pgdp, addr); -+ -+ #ifdef CONFIG_PTP -+ pud_t *pudp = pud_set_fixmap_offset_init(p4dp, addr); -+ -+ pmd_t *pmdp = pmd_set_fixmap_offset_init(pudp, addr); -+ -+ pmd_t pmd = READ_ONCE(*pmdp); -+ -+ __iee_pmd_populate_pre_init(pmdp, __pmd_to_phys(pmd), PGD_APT_RO | PGD_APT | PMD_TYPE_TABLE); -+ -+ pud_clear_fixmap_init(); -+ pmd_clear_fixmap_init(); -+ #else -+ pud_t *pudp = pud_set_fixmap_offset(p4dp, addr); -+ -+ pmd_t *pmdp = pmd_set_fixmap_offset(pudp, addr); -+ -+ pmd_t pmd = READ_ONCE(*pmdp); -+ -+ __pmd_populate(pmdp, __pmd_to_phys(pmd), PGD_APT_RO | PGD_APT | PMD_TYPE_TABLE); -+ -+ pud_clear_fixmap(); -+ pmd_clear_fixmap(); -+ #endif -+} -+/* Set PMD APTable of iee si codes as (1,1) to revert it to ROX P pages when HPD1=0. */ -+static void __init mark_iee_si_pmd_APtable(pgd_t *pgdir) -+{ -+ unsigned long addr = (unsigned long)__iee_si_start; -+ iee_si_set_pmd_APtable(addr, pgdir); -+ // iee rwx gate exit may be mapped by another pmd. -+ iee_si_set_pmd_APtable(addr + PAGE_SIZE, pgdir); -+} + #define NFSDDBG_FACILITY NFSDDBG_FH + + +@@ -223,9 +227,14 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) + error = nfserrno(-ENOMEM); + goto out; + } ++ #ifdef CONFIG_CREDP ++ iee_set_cred_cap_effective(new,cap_raise_nfsd_set(new->cap_effective, ++ new->cap_permitted)); ++ #else + new->cap_effective = + cap_raise_nfsd_set(new->cap_effective, + new->cap_permitted); ++ #endif + put_cred(override_creds(new)); + put_cred(new); + } else { +diff --git a/fs/open.c b/fs/open.c +index 59db720693f9..dbbca8701fd1 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -35,6 +35,11 @@ + #include + #include + ++#ifdef CONFIG_CREDP ++#include +#endif + -+/* -+ * Create fine-grained mappings for the kernel. -+ */ -+static void __init map_kernel(pgd_t *pgdp) -+{ -+ static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_inittext, -+ vmlinux_initdata, vmlinux_data; -+ -+ #ifdef CONFIG_IEE -+ static struct vm_struct vmlinux_iee_code, vmlinux_iee_data, vmlinux_iee_gate, vmlinux_text_end; -+ #endif -+ -+ /* -+ * External debuggers may need to write directly to the text -+ * mapping to install SW breakpoints. Allow this (only) when -+ * explicitly requested with rodata=off. -+ */ -+ pgprot_t text_prot = kernel_exec_prot(); -+ -+ /* -+ * If we have a CPU that supports BTI and a kernel built for -+ * BTI then mark the kernel executable text as guarded pages -+ * now so we don't have to rewrite the page tables later. -+ */ -+ if (arm64_early_this_cpu_has_bti()) -+ text_prot = __pgprot_modify(text_prot, PTE_GP, PTE_GP); + -+ /* -+ * Only rodata will be remapped with different permissions later on, -+ * all other segments are allowed to use contiguous mappings. -+ */ -+ #ifdef CONFIG_IEE -+ map_kernel_segment(pgdp, _stext, __iee_si_data_start, text_prot, &vmlinux_text, -+ 0, VM_NO_GUARD); -+ /* Set iee si data RW. */ -+ map_kernel_segment(pgdp, __iee_si_data_start, __iee_exec_entry_start, SET_NG(PAGE_KERNEL), -+ &vmlinux_iee_data, NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); -+ /* Set iee entry codes NG. */ -+ map_kernel_segment(pgdp, __iee_exec_entry_start, __iee_si_start, SET_NG(text_prot), &vmlinux_iee_gate, -+ NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); -+ /* Map __iee_si_start - __iee_si_end as U RWX pages and set PMD APTABLE = (1,1). */ -+ map_kernel_segment(pgdp, __iee_si_start, __iee_si_end, SET_NG((PAGE_KERNEL_EXEC)), -+ &vmlinux_iee_code, NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); -+ mark_iee_si_pmd_APtable(pgdp); -+ -+ map_kernel_segment(pgdp, __iee_si_end, _etext, text_prot, &vmlinux_text_end, 0, -+ VM_NO_GUARD); -+ -+ map_kernel_segment(pgdp, __start_rodata, __inittext_begin, PAGE_KERNEL, -+ &vmlinux_rodata, NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); -+ map_kernel_segment(pgdp, __inittext_begin, __inittext_end, text_prot, -+ &vmlinux_inittext, 0, VM_NO_GUARD); -+ map_kernel_segment(pgdp, __initdata_begin, __initdata_end, PAGE_KERNEL, -+ &vmlinux_initdata, 0, VM_NO_GUARD); -+ map_kernel_segment(pgdp, _data, _end, PAGE_KERNEL, &vmlinux_data, NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, 0); + #include "internal.h" + + int do_truncate(struct mnt_idmap *idmap, struct dentry *dentry, +@@ -414,17 +419,34 @@ static const struct cred *access_override_creds(void) + * routine. + */ + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(override_cred,override_cred->uid); ++ iee_set_cred_fsgid(override_cred,override_cred->gid); + #else -+ map_kernel_segment(pgdp, _stext, _etext, text_prot, &vmlinux_text, 0, -+ VM_NO_GUARD); -+ map_kernel_segment(pgdp, __start_rodata, __inittext_begin, PAGE_KERNEL, -+ &vmlinux_rodata, NO_CONT_MAPPINGS, VM_NO_GUARD); -+ map_kernel_segment(pgdp, __inittext_begin, __inittext_end, text_prot, -+ &vmlinux_inittext, 0, VM_NO_GUARD); -+ map_kernel_segment(pgdp, __initdata_begin, __initdata_end, PAGE_KERNEL, -+ &vmlinux_initdata, 0, VM_NO_GUARD); -+ map_kernel_segment(pgdp, _data, _end, PAGE_KERNEL, &vmlinux_data, 0, 0); + override_cred->fsuid = override_cred->uid; + override_cred->fsgid = override_cred->gid; + #endif + + if (!issecure(SECURE_NO_SETUID_FIXUP)) { + /* Clear the capabilities if we switch to a non-root user */ + kuid_t root_uid = make_kuid(override_cred->user_ns, 0); + if (!uid_eq(override_cred->uid, root_uid)) ++ #ifdef CONFIG_CREDP ++ do { ++ kernel_cap_t tmp_cap = override_cred->cap_effective; ++ tmp_cap.val = 0; ++ iee_set_cred_cap_effective(override_cred, tmp_cap); ++ } while (0); ++ #else + cap_clear(override_cred->cap_effective); ++ #endif + else ++ #ifdef CONFIG_CREDP ++ iee_set_cred_cap_effective(override_cred,override_cred->cap_permitted); ++ #else + override_cred->cap_effective = + override_cred->cap_permitted; ++ #endif + } + + /* +@@ -444,7 +466,11 @@ static const struct cred *access_override_creds(void) + * expecting RCU freeing. But normal thread-synchronous + * cred accesses will keep things non-RCY. + */ ++ #ifdef CONFIG_CREDP ++ iee_set_cred_non_rcu(override_cred,1); ++ #else + override_cred->non_rcu = 1; ++ #endif + + old_cred = override_creds(override_cred); + +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +index 54602f0bed8b..58534612dc64 100644 +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -16,6 +16,10 @@ + #include + #include "overlayfs.h" + ++#ifdef CONFIG_CREDP ++#include ++#endif + -+ -+ fixmap_copy(pgdp); -+ kasan_copy_shadow(pgdp); -+} -+ -+static void __init create_idmap(void) -+{ -+ u64 start = __pa_symbol(__idmap_text_start); -+ u64 size = __pa_symbol(__idmap_text_end) - start; -+ pgd_t *pgd = idmap_pg_dir; -+ u64 pgd_phys; -+ -+ /* check if we need an additional level of translation */ -+ if (VA_BITS < 48 && idmap_t0sz < (64 - VA_BITS_MIN)) { -+ pgd_phys = early_pgtable_alloc(PAGE_SHIFT); -+ set_pgd(&idmap_pg_dir[start >> VA_BITS], -+ __pgd(pgd_phys | P4D_TYPE_TABLE)); -+ pgd = __va(pgd_phys); + static unsigned short ovl_redirect_max = 256; + module_param_named(redirect_max, ovl_redirect_max, ushort, 0644); + MODULE_PARM_DESC(redirect_max, +@@ -590,8 +594,13 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, + * create a new inode, so just use the ovl mounter's + * fs{u,g}id. + */ ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(override_cred,inode->i_uid); ++ iee_set_cred_fsgid(override_cred,inode->i_gid); ++ #else + override_cred->fsuid = inode->i_uid; + override_cred->fsgid = inode->i_gid; ++ #endif + err = security_dentry_create_files_as(dentry, + attr->mode, &dentry->d_name, old_cred, + override_cred); +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index 2c056d737c27..9ede99ddb04b 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -21,6 +21,10 @@ + #include "overlayfs.h" + #include "params.h" + ++#ifdef CONFIG_CREDP ++#include ++#endif ++ + MODULE_AUTHOR("Miklos Szeredi "); + MODULE_DESCRIPTION("Overlay filesystem"); + MODULE_LICENSE("GPL"); +@@ -1485,7 +1489,15 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc) + sb->s_export_op = &ovl_export_fid_operations; + + /* Never override disk quota limits or use reserved space */ ++ #ifdef CONFIG_CREDP ++ { ++ kernel_cap_t tmp = cred->cap_effective; ++ cap_lower(tmp, CAP_SYS_RESOURCE); ++ iee_set_cred_cap_effective(cred, tmp); + } -+ #ifdef CONFIG_PTP -+ __iee_create_pgd_mapping_pre_init(pgd, start, start, size, PAGE_KERNEL_ROX, -+ early_pgtable_alloc, 0); + #else -+ __create_pgd_mapping(pgd, start, start, size, PAGE_KERNEL_ROX, -+ early_pgtable_alloc, 0); + cap_lower(cred->cap_effective, CAP_SYS_RESOURCE); + #endif + + sb->s_magic = OVERLAYFS_SUPER_MAGIC; + sb->s_xattr = ofs->config.userxattr ? ovl_user_xattr_handlers : +diff --git a/fs/smb/client/cifs_spnego.c b/fs/smb/client/cifs_spnego.c +index af7849e5974f..d913a255265f 100644 +--- a/fs/smb/client/cifs_spnego.c ++++ b/fs/smb/client/cifs_spnego.c +@@ -18,6 +18,13 @@ + #include "cifs_spnego.h" + #include "cifs_debug.h" + #include "cifsproto.h" ++#ifdef CONFIG_CREDP ++#include ++#endif ++#ifdef CONFIG_KEYP ++#include ++#endif + -+ if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) { -+ extern u32 __idmap_kpti_flag; -+ u64 pa = __pa_symbol(&__idmap_kpti_flag); -+ -+ /* -+ * The KPTI G-to-nG conversion code needs a read-write mapping -+ * of its synchronization flag in the ID map. -+ */ -+ #ifdef CONFIG_PTP -+ __iee_create_pgd_mapping_pre_init(pgd, pa, pa, sizeof(u32), PAGE_KERNEL, -+ early_pgtable_alloc, 0); + static const struct cred *spnego_cred; + + /* create a new cifs key */ +@@ -33,7 +40,13 @@ cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + goto error; + + /* attach the data */ ++ #ifdef CONFIG_KEYP ++ union key_payload key_payload = *((union key_payload *)(key->name_link.next)); ++ key_payload.data[0] = payload; ++ iee_write_key_payload(key, key_payload); ++ #else + key->payload.data[0] = payload; ++ #endif + ret = 0; + + error: +@@ -43,7 +56,11 @@ cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + static void + cifs_spnego_key_destroy(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ kfree(((union key_payload *)(key->name_link.next))->data[0]); ++ #else + kfree(key->payload.data[0]); ++ #endif + } + + +@@ -163,7 +180,11 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo, + + #ifdef CONFIG_CIFS_DEBUG2 + if (cifsFYI && !IS_ERR(spnego_key)) { ++ #ifdef CONFIG_KEYP ++ struct cifs_spnego_msg *msg = ((union key_payload *)(spnego_key->name_link.next))->data[0]; + #else -+ __create_pgd_mapping(pgd, pa, pa, sizeof(u32), PAGE_KERNEL, -+ early_pgtable_alloc, 0); + struct cifs_spnego_msg *msg = spnego_key->payload.data[0]; + #endif -+ } -+} -+ -+#ifdef CONFIG_IEE -+static void __create_pgd_mapping_for_iee_locked(pgd_t *pgdir, phys_addr_t phys, -+ unsigned long virt, phys_addr_t size, -+ pgprot_t prot, -+ phys_addr_t (*pgtable_alloc)(int), -+ int flags) -+{ -+ unsigned long addr, end, next; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, virt); -+ p4d_t *p4dp; -+ p4d_t p4d; -+ -+ /* -+ * If the virtual and physical address don't have the same offset -+ * within a page, we cannot map the region as the caller expects. -+ */ -+ if (WARN_ON((phys ^ virt) & ~PAGE_MASK)) -+ return; -+ -+ phys &= PAGE_MASK; -+ addr = virt & PAGE_MASK; -+ end = PAGE_ALIGN(virt + size); + cifs_dump_mem("SPNEGO reply blob:", msg->data, min(1024U, + msg->secblob_len + msg->sesskey_len)); + } +@@ -211,9 +232,18 @@ init_cifs_spnego(void) + * instruct request_key() to use this special keyring as a cache for + * the results it looks up + */ ++ #ifdef CONFIG_KEYP ++ iee_set_key_flag_bit(keyring, KEY_FLAG_ROOT_CAN_CLEAR, SET_BIT_OP); ++ #else + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); ++ #endif ++ #ifdef CONFIG_CREDP ++ iee_set_cred_thread_keyring(cred,keyring); ++ iee_set_cred_jit_keyring(cred,KEY_REQKEY_DEFL_THREAD_KEYRING); ++ #else + cred->thread_keyring = keyring; + cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; ++ #endif + spnego_cred = cred; + + cifs_dbg(FYI, "cifs spnego keyring: %d\n", key_serial(keyring)); +diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c +index f5b6df82e857..7684cf4639e1 100644 +--- a/fs/smb/client/cifsacl.c ++++ b/fs/smb/client/cifsacl.c +@@ -26,6 +26,14 @@ + #include "cifs_fs_sb.h" + #include "cifs_unicode.h" + ++#ifdef CONFIG_CREDP ++#include ++#endif ++#ifdef CONFIG_KEYP ++#include ++#include ++#endif + -+ do { -+ next = pgd_addr_end(addr, end); -+ #ifdef CONFIG_PTP -+ iee_alloc_init_pud_pre_init(pgdp, addr, next, phys, prot, pgtable_alloc, -+ flags); + /* security id for everyone/world system group */ + static const struct cifs_sid sid_everyone = { + 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; +@@ -78,16 +86,33 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + * dereference payload.data! + */ + if (prep->datalen <= sizeof(key->payload)) { ++ #ifdef CONFIG_KEYP ++ union key_payload key_payload = *((union key_payload *)(key->name_link.next)); ++ key_payload.data[0] = NULL; ++ iee_write_key_payload(key, key_payload); ++ iee_memcpy(((union key_payload *)(key->name_link.next)), prep->data, prep->datalen); + #else -+ alloc_init_pud(pgdp, addr, next, phys, prot, pgtable_alloc, -+ flags); + key->payload.data[0] = NULL; + memcpy(&key->payload, prep->data, prep->datalen); + #endif -+ p4dp = p4d_offset(pgdp, addr); -+ p4d = READ_ONCE(*p4dp); -+ #ifdef CONFIG_PTP -+ __iee_p4d_populate_pre_init(p4dp, __p4d_to_phys(p4d), (PGD_APT | PGD_PXN | PGD_UXN | PUD_TYPE_TABLE)); + } else { + payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL); + if (!payload) + return -ENOMEM; ++ #ifdef CONFIG_KEYP ++ union key_payload key_payload = *((union key_payload *)(key->name_link.next)); ++ key_payload.data[0] = payload; ++ iee_write_key_payload(key, key_payload); + #else -+ __p4d_populate(p4dp, __p4d_to_phys(p4d), (PGD_APT | PGD_PXN | PGD_UXN | PUD_TYPE_TABLE)); + key->payload.data[0] = payload; + #endif -+ phys += next - addr; -+ } while (pgdp++, addr = next, addr != end); -+} -+ -+static void __create_pgd_mapping_for_iee(pgd_t *pgdir, phys_addr_t phys, -+ unsigned long virt, phys_addr_t size, -+ pgprot_t prot, -+ phys_addr_t (*pgtable_alloc)(int), -+ int flags) -+{ -+ mutex_lock(&fixmap_lock); -+ __create_pgd_mapping_for_iee_locked(pgdir, phys, virt, size, prot, -+ pgtable_alloc, flags); -+ mutex_unlock(&fixmap_lock); - } + } --static void __init arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) -+static void __init __map_memblock_for_iee(pgd_t *pgdp, phys_addr_t start, -+ phys_addr_t end, pgprot_t prot, int flags) - { -- if (!kfence_pool) -- return; -- -- /* KFENCE pool needs page-level mapping. */ -- __map_memblock(pgdp, kfence_pool, kfence_pool + KFENCE_POOL_SIZE, -- pgprot_tagged(PAGE_KERNEL), -- NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS); -- memblock_clear_nomap(kfence_pool, KFENCE_POOL_SIZE); -- __kfence_pool = phys_to_virt(kfence_pool); -+ #ifdef CONFIG_PTP -+ __create_pgd_mapping_for_iee(pgdp, start, __phys_to_iee(start), end - start, -+ prot, early_pgtable_alloc, flags); ++ #ifdef CONFIG_KEYP ++ iee_set_key_datalen(key, prep->datalen); + #else -+ __create_pgd_mapping_for_iee(pgdp, start, __phys_to_iee(start), end - start, -+ prot, early_pgtable_alloc, flags); + key->datalen = prep->datalen; + #endif + return 0; } --#else /* CONFIG_KFENCE */ --static inline phys_addr_t arm64_kfence_alloc_pool(void) { return 0; } --static inline void arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) { } -- --#endif /* CONFIG_KFENCE */ -- --static void __init map_mem(pgd_t *pgdp) -+static void __init map_iee(pgd_t *pgdp) +@@ -95,7 +120,11 @@ static inline void + cifs_idmap_key_destroy(struct key *key) { - static const u64 direct_map_end = _PAGE_END(VA_BITS_MIN); - phys_addr_t kernel_start = __pa_symbol(_stext); -@@ -578,6 +1578,8 @@ static void __init map_mem(pgd_t *pgdp) - int flags = NO_EXEC_MAPPINGS; - u64 i; + if (key->datalen > sizeof(key->payload)) ++ #ifdef CONFIG_KEYP ++ kfree(((union key_payload *)(key->name_link.next))->data[0]); ++ #else + kfree(key->payload.data[0]); ++ #endif + } -+ flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; -+ - /* - * Setting hierarchical PXNTable attributes on table entries covering - * the linear region is only possible if it is guaranteed that no table -@@ -589,9 +1591,6 @@ static void __init map_mem(pgd_t *pgdp) + static struct key_type cifs_idmap_key_type = { +@@ -311,9 +340,15 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid) + * there are no subauthorities and the host has 8-byte pointers, then + * it could be. + */ ++ #ifdef CONFIG_KEYP ++ ksid = sidkey->datalen <= sizeof(sidkey->payload) ? ++ (struct cifs_sid *)(sidkey->name_link.next) : ++ (struct cifs_sid *)((union key_payload *)(sidkey->name_link.next))->data[0]; ++ #else + ksid = sidkey->datalen <= sizeof(sidkey->payload) ? + (struct cifs_sid *)&sidkey->payload : + (struct cifs_sid *)sidkey->payload.data[0]; ++ #endif - early_kfence_pool = arm64_kfence_alloc_pool(); + ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32)); + if (ksid_size > sidkey->datalen) { +@@ -422,14 +457,22 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, + if (sidtype == SIDOWNER) { + kuid_t uid; + uid_t id; ++ #ifdef CONFIG_KEYP ++ memcpy(&id, &((union key_payload *)(sidkey->name_link.next))->data[0], sizeof(uid_t)); ++ #else + memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t)); ++ #endif + uid = make_kuid(&init_user_ns, id); + if (uid_valid(uid)) + fuid = uid; + } else { + kgid_t gid; + gid_t id; ++ #ifdef CONFIG_KEYP ++ memcpy(&id, &((union key_payload *)(sidkey->name_link.next))->data[0], sizeof(gid_t)); ++ #else + memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t)); ++ #endif + gid = make_kgid(&init_user_ns, id); + if (gid_valid(gid)) + fgid = gid; +@@ -490,9 +533,18 @@ init_cifs_idmap(void) -- if (can_set_direct_map()) -- flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; -- + /* instruct request_key() to use this special keyring as a cache for + * the results it looks up */ ++ #ifdef CONFIG_KEYP ++ iee_set_key_flag_bit(keyring, KEY_FLAG_ROOT_CAN_CLEAR, SET_BIT_OP); ++ #else + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); ++ #endif ++ #ifdef CONFIG_CREDP ++ iee_set_cred_thread_keyring(cred,keyring); ++ iee_set_cred_jit_keyring(cred,KEY_REQKEY_DEFL_THREAD_KEYRING); ++ #else + cred->thread_keyring = keyring; + cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; ++ #endif + root_cred = cred; + + cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring)); +diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c +index e325e06357ff..e43723e8cd0f 100644 +--- a/fs/smb/client/connect.c ++++ b/fs/smb/client/connect.c +@@ -2150,7 +2150,11 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses) + is_domain = 1; + } + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(key)); ++ #else + down_read(&key->sem); ++ #endif + upayload = user_key_payload_locked(key); + if (IS_ERR_OR_NULL(upayload)) { + rc = upayload ? PTR_ERR(upayload) : -EINVAL; +@@ -2228,7 +2232,11 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses) + strscpy(ctx->workstation_name, ses->workstation_name, sizeof(ctx->workstation_name)); + + out_key_put: ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + key_put(key); + out_err: + kfree(desc); +diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c +index 3216f786908f..3160e70b820f 100644 +--- a/fs/smb/client/sess.c ++++ b/fs/smb/client/sess.c +@@ -1591,7 +1591,11 @@ sess_auth_kerberos(struct sess_data *sess_data) + goto out; + } + ++ #ifdef CONFIG_KEYP ++ msg = ((union key_payload *)(spnego_key->name_link.next))->data[0]; ++ #else + msg = spnego_key->payload.data[0]; ++ #endif /* - * Take care not to create a writable alias for the - * read-only text and rodata sections of the kernel image. -@@ -609,12 +1608,11 @@ static void __init map_mem(pgd_t *pgdp) - * if MTE is present. Otherwise, it has the same attributes as - * PAGE_KERNEL. - */ -- __map_memblock(pgdp, start, end, pgprot_tagged(PAGE_KERNEL), -- flags); -+ __map_memblock_for_iee(pgdp, start, end, SET_NG(SET_INVALID(SET_UPAGE(PAGE_KERNEL))), flags); + * check version field to make sure that cifs.upcall is + * sending us a response in an expected form +diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c +index bf45b8652e58..a1ebf2f1fa81 100644 +--- a/fs/smb/client/smb2pdu.c ++++ b/fs/smb/client/smb2pdu.c +@@ -1623,7 +1623,11 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) + goto out; + } + ++ #ifdef CONFIG_KEYP ++ msg = ((union key_payload *)(spnego_key->name_link.next))->data[0]; ++ #else + msg = spnego_key->payload.data[0]; ++ #endif + /* + * check version field to make sure that cifs.upcall is + * sending us a response in an expected form +diff --git a/fs/ubifs/auth.c b/fs/ubifs/auth.c +index e564d5ff8781..2d3ca5951fa2 100644 +--- a/fs/ubifs/auth.c ++++ b/fs/ubifs/auth.c +@@ -284,7 +284,11 @@ int ubifs_init_authentication(struct ubifs_info *c) + return PTR_ERR(keyring_key); + } + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(keyring_key)); ++ #else + down_read(&keyring_key->sem); ++ #endif + + if (keyring_key->type != &key_type_logon) { + ubifs_err(c, "key type must be logon"); +@@ -351,7 +355,11 @@ int ubifs_init_authentication(struct ubifs_info *c) + if (err) + crypto_free_shash(c->hash_tfm); + out: ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(keyring_key)); ++ #else + up_read(&keyring_key->sem); ++ #endif + key_put(keyring_key); + + return err; +diff --git a/fs/verity/signature.c b/fs/verity/signature.c +index 90c07573dd77..e076cb6fbc84 100644 +--- a/fs/verity/signature.c ++++ b/fs/verity/signature.c +@@ -62,7 +62,11 @@ int fsverity_verify_signature(const struct fsverity_info *vi, + return 0; } - /* -- * Map the linear alias of the [_stext, __init_begin) interval -+ * Map the linear alias of the [_text, __init_begin) interval - * as non-executable now, and remove the write permission in - * mark_linear_text_alias_ro() below (which will be called after - * alternative patching has completed). This makes the contents -@@ -623,178 +1621,384 @@ static void __init map_mem(pgd_t *pgdp) - * Note that contiguous mappings cannot be remapped in this way, - * so we should avoid them here. - */ -- __map_memblock(pgdp, kernel_start, kernel_end, -- PAGE_KERNEL, NO_CONT_MAPPINGS); -+ __map_memblock_for_iee(pgdp, kernel_start, kernel_end, -+ SET_NG(SET_INVALID(SET_UPAGE(PAGE_KERNEL))), flags); - memblock_clear_nomap(kernel_start, kernel_end - kernel_start); - arm64_kfence_map_pool(early_kfence_pool, pgdp); - } - --void mark_rodata_ro(void) -+/* -+ * Change page access permission, whereas not handling huge pages. -+ * Only used on IEE init functions. -+ */ -+static void __init iee_si_set_page_attr(unsigned long addr, pteval_t attr) - { -- unsigned long section_size; -+ unsigned long flag; -+ pgd_t *pgdir = swapper_pg_dir; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); ++ #ifdef CONFIG_KEYP ++ if (((struct key_struct *)(fsverity_keyring->name_link.prev))->keys.nr_leaves_on_tree == 0) { ++ #else + if (fsverity_keyring->keys.nr_leaves_on_tree == 0) { ++ #endif + /* + * The ".fs-verity" keyring is empty, due to builtin signatures + * being supported by the kernel but not actually being used. +diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h +index 9d0479f50f97..f501e0f965f8 100644 +--- a/include/asm-generic/early_ioremap.h ++++ b/include/asm-generic/early_ioremap.h +@@ -17,6 +17,9 @@ extern void *early_memremap_ro(resource_size_t phys_addr, + extern void *early_memremap_prot(resource_size_t phys_addr, + unsigned long size, unsigned long prot_val); + extern void early_iounmap(void __iomem *addr, unsigned long size); ++#ifdef CONFIG_PTP ++extern void early_iounmap_after_init(void __iomem *addr, unsigned long size); ++#endif + extern void early_memunmap(void *addr, unsigned long size); -- /* -- * mark .rodata as read only. Use __init_begin rather than __end_rodata -- * to cover NOTES and EXCEPTION_TABLE. -- */ -- section_size = (unsigned long)__init_begin - (unsigned long)__start_rodata; -- update_mapping_prot(__pa_symbol(__start_rodata), (unsigned long)__start_rodata, -- section_size, PAGE_KERNEL_RO); -+ p4d_t *p4dp = p4d_offset(pgdp, addr); + #if defined(CONFIG_GENERIC_EARLY_IOREMAP) && defined(CONFIG_MMU) +diff --git a/include/asm-generic/fixmap.h b/include/asm-generic/fixmap.h +index 8cc7b09c1bc7..83158589a545 100644 +--- a/include/asm-generic/fixmap.h ++++ b/include/asm-generic/fixmap.h +@@ -70,6 +70,24 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr) + __set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR) + #endif -- debug_checkwx(); -+ pud_t *pudp = pud_offset(p4dp, addr); -+ -+ pmd_t *pmdp = pmd_offset(pudp, addr); ++#ifdef CONFIG_PTP ++#ifndef clear_fixmap_init ++#define clear_fixmap_init(idx) \ ++ __iee_set_fixmap_pre_init(idx, 0, FIXMAP_PAGE_CLEAR) ++#endif + -+ pte_t *ptep = pte_offset_kernel(pmdp, addr); -+ pte_t pte = READ_ONCE(*ptep); ++#define __iee_set_fixmap_offset_pre_init(idx, phys, flags) \ ++({ \ ++ unsigned long ________addr; \ ++ __iee_set_fixmap_pre_init(idx, phys, flags); \ ++ ________addr = fix_to_virt(idx) + ((phys) & (PAGE_SIZE - 1)); \ ++ ________addr; \ ++}) + -+ if(attr & PTE_RDONLY) -+ pte = __pte((pte_val(pte) | PTE_RDONLY) & ~PTE_DBM); -+ pte = __pte(pte_val(pte) | attr); -+ #ifdef CONFIG_PTP -+ // Write pgtable in IEE directly. -+ flag = local_daif_save(); -+ asm volatile ("msr pan, #0"); -+ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa(ptep)))), pte); -+ asm volatile ("msr pan, #1"); -+ local_daif_restore(flag); -+ #else -+ WRITE_ONCE(*ptep, pte); -+ #endif -+} ++#define iee_set_fixmap_offset_pre_init(idx, phys) \ ++ __iee_set_fixmap_offset_pre_init(idx, phys, FIXMAP_PAGE_NORMAL) ++#endif + -+/* Prepare data used for iee rwx gates. These data are setted only once. */ -+void __init iee_si_prepare_data(void) -+{ -+ unsigned long va; -+ // Record current TCR val after system init. -+ iee_si_tcr = read_sysreg(tcr_el1) & ~(SYS_TCR_IEE_SI); -+ // Mark iee data as RO and move it to iee after setting up. -+ va = (unsigned long)__iee_si_data_start; -+ iee_si_set_page_attr(va, PTE_RDONLY); -+ iee_si_set_page_attr(lm_alias(va)+iee_offset, 0x1 | PTE_RDONLY); -+ // Set iee sensitive inst code page U RWX here to hide it from kernel. -+ va = (unsigned long)__iee_si_start; -+ iee_si_set_page_attr(va, PTE_USER); -+ va = (unsigned long)__iee_si_start + PAGE_SIZE; -+ iee_si_set_page_attr(va, PTE_USER); -+ flush_tlb_all(); - } + /* Return a pointer with offset calculated */ + #define __set_fixmap_offset(idx, phys, flags) \ + ({ \ +diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h +index c75d4a753849..1d86942b242c 100644 +--- a/include/asm-generic/pgalloc.h ++++ b/include/asm-generic/pgalloc.h +@@ -7,6 +7,10 @@ + #define GFP_PGTABLE_KERNEL (GFP_KERNEL | __GFP_ZERO) + #define GFP_PGTABLE_USER (GFP_PGTABLE_KERNEL | __GFP_ACCOUNT) --static void __init map_kernel_segment(pgd_t *pgdp, void *va_start, void *va_end, -- pgprot_t prot, struct vm_struct *vma, -- int flags, unsigned long vm_flags) ++#ifdef CONFIG_PTP ++#include +#endif + -+#ifdef CONFIG_PTP -+// Attention : Using set_xxx without adding offset. -+static void __init set_iee_valid_pre_init(unsigned long addr) - { -- phys_addr_t pa_start = __pa_symbol(va_start); -- unsigned long size = va_end - va_start; -+ pgd_t *pgdir = swapper_pg_dir; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); + /** + * __pte_alloc_one_kernel - allocate memory for a PTE-level kernel page table + * @mm: the mm_struct of the current context +@@ -23,6 +27,7 @@ static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm) -- BUG_ON(!PAGE_ALIGNED(pa_start)); -- BUG_ON(!PAGE_ALIGNED(size)); -+ p4d_t *p4dp = p4d_offset(pgdp, addr); + if (!ptdesc) + return NULL; ++ + return ptdesc_address(ptdesc); + } -- __create_pgd_mapping(pgdp, pa_start, (unsigned long)va_start, size, prot, -- early_pgtable_alloc, flags); -+ pud_t *pudp = pud_offset(p4dp, addr); +@@ -106,6 +111,7 @@ static inline void pte_free(struct mm_struct *mm, struct page *pte_page) + struct ptdesc *ptdesc = page_ptdesc(pte_page); -- if (!(vm_flags & VM_NO_GUARD)) -- size += PAGE_SIZE; -+ pmd_t *pmdp = pmd_offset(pudp, addr); + pagetable_pte_dtor(ptdesc); ++ + pagetable_free(ptdesc); + } -- vma->addr = va_start; -- vma->phys_addr = pa_start; -- vma->size = size; -- vma->flags = VM_MAP | vm_flags; -- vma->caller = __builtin_return_address(0); -+ pte_t *ptep = pte_offset_kernel(pmdp, addr); -+ pte_t pte = READ_ONCE(*ptep); +@@ -149,6 +155,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) -- vm_area_add_early(vma); -+ if((addr < (PAGE_OFFSET + IEE_OFFSET)) | (addr > (PAGE_OFFSET + BIT(vabits_actual - 1)))) -+ return; + BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); + pagetable_pmd_dtor(ptdesc); + -+ pte = __pte(pte_val(pte) | 0x1); -+ iee_set_pte_pre_init(ptep, pte); -+ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); -+ isb(); + pagetable_free(ptdesc); } + #endif +diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h +index 22384baee10e..9a6de5467a1c 100644 +--- a/include/asm-generic/tlb.h ++++ b/include/asm-generic/tlb.h +@@ -209,6 +209,9 @@ struct mmu_table_batch { + ((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *)) + + extern void tlb_remove_table(struct mmu_gather *tlb, void *table); ++#ifdef CONFIG_PTP ++extern void iee_tlb_remove_table(struct mmu_gather *tlb, void *table); ++#endif --static pgprot_t kernel_exec_prot(void) -+static void __init move_pte_table_into_iee(pmd_t *pmdp, unsigned long addr, unsigned long end) - { -- return rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC; -+ pmd_t pmd = READ_ONCE(*pmdp); -+ unsigned long iee_addr = __phys_to_iee(__pmd_to_phys(pmd)); -+ set_iee_valid_pre_init(iee_addr); - } + #else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */ --#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 --static int __init map_entry_trampoline(void) -+static void __init move_pmd_table_into_iee(pud_t *pudp, unsigned long addr, unsigned long end) - { -- int i; -+ unsigned long next; -+ pud_t pud = READ_ONCE(*pudp); -+ pmd_t *pmdp; -+ pmd_t pmd; -+ unsigned long iee_addr = __phys_to_iee(__pud_to_phys(pud)); -+ set_iee_valid_pre_init(iee_addr); +@@ -493,7 +496,11 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) -- pgprot_t prot = kernel_exec_prot(); -- phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start); -+ pmdp = pmd_offset(pudp, addr); -+ do { -+ next = pmd_addr_end(addr, end); -+ pmd = READ_ONCE(*pmdp); -+ if((pmd_val(pmd) & PMD_TABLE_BIT) == 0) -+ { -+ continue; -+ } -+ else -+ { -+ move_pte_table_into_iee(pmdp, addr, next); -+ } -+ } while (pmdp++, addr = next, addr != end); -+} + static inline void tlb_remove_ptdesc(struct mmu_gather *tlb, void *pt) + { ++ #ifdef CONFIG_PTP ++ iee_tlb_remove_table(tlb, pt); ++ #else + tlb_remove_table(tlb, pt); ++ #endif + } -- /* The trampoline is always mapped and can therefore be global */ -- pgprot_val(prot) &= ~PTE_NG; -+static void __init move_pud_table_into_iee(pgd_t *pgdp, unsigned long addr, unsigned long end) -+{ -+ unsigned long next; -+ p4d_t *p4dp = p4d_offset(pgdp, addr); -+ p4d_t p4d = READ_ONCE(*p4dp); -+ pud_t *pudp; -+ pud_t pud; -+ unsigned long iee_addr = __phys_to_iee(__p4d_to_phys(p4d)); -+ set_iee_valid_pre_init(iee_addr); + /* Like tlb_remove_ptdesc, but for page-like page directories. */ +diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h +index 174d865ce46e..0d945cdd78e0 100644 +--- a/include/asm-generic/vmlinux.lds.h ++++ b/include/asm-generic/vmlinux.lds.h +@@ -379,6 +379,17 @@ + KEEP(*(.dtb.init.rodata)) \ + __dtb_end = .; -- /* Map only the text into the trampoline page table */ -- memset(tramp_pg_dir, 0, PGD_SIZE); -- __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, -- entry_tramp_text_size(), prot, -- __pgd_pgtable_alloc, NO_BLOCK_MAPPINGS); -+ pudp = pud_offset(p4dp, addr); -+ do { -+ next = pud_addr_end(addr, end); -+ pud = READ_ONCE(*pudp); -+ if ((pud_val(pud) & PUD_TABLE_BIT) == 0) -+ { -+ continue; -+ } -+ else -+ { -+ move_pmd_table_into_iee(pudp, addr, next); -+ } -+ } while (pudp++, addr = next, addr != end); -+} ++#ifdef CONFIG_KOI ++#define KOI_DATA() \ ++ . = ALIGN(PAGE_SIZE); \ ++ __koi_data_start = .; \ ++ *(.data..koi) \ ++ . = ALIGN(PAGE_SIZE); \ ++ __koi_data_end = .; ++#else ++#define KOI_DATA() ++#endif ++ + /* + * .data section + */ +@@ -403,8 +414,8 @@ + BRANCH_PROFILE() \ + TRACE_PRINTKS() \ + BPF_RAW_TP() \ +- TRACEPOINT_STR() +- ++ TRACEPOINT_STR() \ ++ KOI_DATA() + /* + * Data section helpers + */ +@@ -1126,6 +1137,23 @@ + * They will fit only a subset of the architectures + */ -- /* Map both the text and data into the kernel page table */ -- for (i = 0; i < DIV_ROUND_UP(entry_tramp_text_size(), PAGE_SIZE); i++) -- __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i, -- pa_start + i * PAGE_SIZE, prot); -+static void __init init_iee_for_one_region(pgd_t *pgdir, unsigned long va_start, unsigned long va_end) -+{ -+ unsigned long addr, end, next; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, va_start); ++#ifdef CONFIG_CREDP ++ #define CRED_DATA \ ++ . = ALIGN(PAGE_SIZE); \ ++ *(.iee.cred) \ ++ . = ALIGN(PAGE_SIZE); ++#else ++ #define CRED_DATA ++#endif ++ ++#ifdef CONFIG_IEE_SELINUX_P ++ #define IEE_SELINUX_DATA \ ++ . = ALIGN(PAGE_SIZE); \ ++ *(.iee.selinux) \ ++ . = ALIGN(PAGE_SIZE); ++#else ++ #define IEE_SELINUX_DATA ++#endif -- if (IS_ENABLED(CONFIG_RELOCATABLE)) -- __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i, -- pa_start + i * PAGE_SIZE, PAGE_KERNEL_RO); -+ addr = va_start & PAGE_MASK; -+ end = PAGE_ALIGN(va_end); + /* + * Writeable data. +@@ -1143,6 +1171,8 @@ + . = ALIGN(PAGE_SIZE); \ + .data : AT(ADDR(.data) - LOAD_OFFSET) { \ + INIT_TASK_DATA(inittask) \ ++ CRED_DATA \ ++ IEE_SELINUX_DATA \ + NOSAVE_DATA \ + PAGE_ALIGNED_DATA(pagealigned) \ + CACHELINE_ALIGNED_DATA(cacheline) \ +diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h +index d55171f640a0..1293c5a1c624 100644 +--- a/include/keys/asymmetric-subtype.h ++++ b/include/keys/asymmetric-subtype.h +@@ -54,7 +54,11 @@ struct asymmetric_key_subtype { + static inline + struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key) + { ++ #ifdef CONFIG_KEYP ++ return ((union key_payload *)(key->name_link.next))->data[asym_subtype]; ++ #else + return key->payload.data[asym_subtype]; ++ #endif + } -- return 0; -+ do { -+ next = pgd_addr_end(addr, end); -+ move_pud_table_into_iee(pgdp, addr, next); -+ } while (pgdp++, addr = next, addr != end); + #endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */ +diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h +index 69a13e1e5b2e..6cd556bfb216 100644 +--- a/include/keys/asymmetric-type.h ++++ b/include/keys/asymmetric-type.h +@@ -69,13 +69,21 @@ extern struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1, + static inline + const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key) + { ++ #ifdef CONFIG_KEYP ++ return ((union key_payload *)(key->name_link.next))->data[asym_key_ids]; ++ #else + return key->payload.data[asym_key_ids]; ++ #endif } --core_initcall(map_entry_trampoline); --#endif --/* -- * Open coded check for BTI, only for use to determine configuration -- * for early mappings for before the cpufeature code has run. -- */ --static bool arm64_early_this_cpu_has_bti(void) -+static void __init init_iee(void) + static inline + const struct public_key *asymmetric_key_public_key(const struct key *key) { -- u64 pfr1; -+ unsigned long iee_addr; -+ phys_addr_t start, end; -+ u64 i; -+ pgd_t *pgdp; -+ -+ #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 -+ // handling 1-level tramp page table tramp_pg_dir -+ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(tramp_pg_dir)); -+ set_iee_valid_pre_init(iee_addr); ++ #ifdef CONFIG_KEYP ++ return ((union key_payload *)(key->name_link.next))->data[asym_crypto]; ++ #else + return key->payload.data[asym_crypto]; + #endif -+ // handling 1-level page table swapper_pg_dir -+ pgdp = swapper_pg_dir; -+ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(swapper_pg_dir)); -+ set_iee_valid_pre_init(iee_addr); -+ // handling 2/3/4-level page table for kernel -+ init_iee_for_one_region(pgdp, (unsigned long)_text, (unsigned long)_etext); -+ init_iee_for_one_region(pgdp, (unsigned long)__start_rodata, (unsigned long)__inittext_begin); -+ init_iee_for_one_region(pgdp, (unsigned long)__inittext_begin, (unsigned long)__inittext_end); -+ init_iee_for_one_region(pgdp, (unsigned long)__initdata_begin, (unsigned long)__initdata_end); -+ init_iee_for_one_region(pgdp, (unsigned long)_data, (unsigned long)_end); -+ // handling 2/3/4-level page table for fixmap i.e. remap bm_xxx -+ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(bm_pte_addr)); -+ set_iee_valid_pre_init(iee_addr); -+ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(bm_pmd_addr)); -+ set_iee_valid_pre_init(iee_addr); -+ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(bm_pud_addr)); -+ set_iee_valid_pre_init(iee_addr); -+ // handling 2/3/4-level page table for logical mem and iee -+ for_each_mem_range(i, &start, &end) { -+ if (start >= end) -+ break; -+ /* -+ * The linear map must allow allocation tags reading/writing -+ * if MTE is present. Otherwise, it has the same attributes as -+ * PAGE_KERNEL. -+ */ -+ init_iee_for_one_region(pgdp, (unsigned long)__va(start), (unsigned long)__va(end)); -+ init_iee_for_one_region(pgdp, (unsigned long)__phys_to_iee(start), (unsigned long)__phys_to_iee(end)); -+ } -+} + } -- if (!IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)) -- return false; -+static void iee_set_kernel_upage_pre_init(unsigned long addr) -+{ -+ pgd_t *pgdir = swapper_pg_dir; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); + extern struct key *find_asymmetric_key(struct key *keyring, +diff --git a/include/keys/request_key_auth-type.h b/include/keys/request_key_auth-type.h +index 36b89a933310..63d5d9f66cb4 100644 +--- a/include/keys/request_key_auth-type.h ++++ b/include/keys/request_key_auth-type.h +@@ -26,7 +26,11 @@ struct request_key_auth { -- pfr1 = __read_sysreg_by_encoding(SYS_ID_AA64PFR1_EL1); -- return cpuid_feature_extract_unsigned_field(pfr1, -- ID_AA64PFR1_EL1_BT_SHIFT); -+ p4d_t *p4dp = p4d_offset(pgdp, addr); -+ p4d_t p4d = READ_ONCE(*p4dp); -+ -+ pud_t *pudp = pud_offset(p4dp, addr); -+ -+ pmd_t *pmdp = pmd_offset(pudp, addr); -+ -+ pte_t *ptep = pte_offset_kernel(pmdp, addr); -+ -+ int i; -+ for(i = 0; i < 4; i++) -+ { -+ pte_t pte = READ_ONCE(*ptep); -+ pte = __pte(pte_val(pte) | PTE_USER | PTE_NG); -+ iee_set_pte_pre_init(ptep, pte); -+ ptep++; -+ } -+ flush_tlb_kernel_range(addr, addr+4*PAGE_SIZE); -+ isb(); + static inline struct request_key_auth *get_request_key_auth(const struct key *key) + { ++ #ifdef CONFIG_KEYP ++ return ((union key_payload *)(key->name_link.next))->data[0]; ++ #else + return key->payload.data[0]; ++ #endif } --/* -- * Create fine-grained mappings for the kernel. -- */ --static void __init map_kernel(pgd_t *pgdp) -+static void __init iee_set_pte_table_ro(pmd_t *pmdp, unsigned long addr, unsigned long end) - { -- static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_inittext, -- vmlinux_initdata, vmlinux_data; -+ pmd_t pmd = READ_ONCE(*pmdp); -+ unsigned long logical_addr = (unsigned long)__va(__pmd_to_phys(pmd)); -+ iee_set_logical_mem_ro(logical_addr); -+} -- /* -- * External debuggers may need to write directly to the text -- * mapping to install SW breakpoints. Allow this (only) when -- * explicitly requested with rodata=off. -- */ -- pgprot_t text_prot = kernel_exec_prot(); -+static void __init iee_set_pmd_table_ro(pud_t *pudp, unsigned long addr, unsigned long end) -+{ -+ unsigned long next; -+ pud_t pud = READ_ONCE(*pudp); -+ pmd_t *pmdp; -+ pmd_t pmd; -+ unsigned long logical_addr = (unsigned long)__va(__pud_to_phys(pud)); -+ iee_set_logical_mem_ro(logical_addr); +diff --git a/include/linux/cred.h b/include/linux/cred.h +index e01c6d094a30..c7b3fe009f66 100644 +--- a/include/linux/cred.h ++++ b/include/linux/cred.h +@@ -18,6 +18,11 @@ + #include + #include -- /* -- * If we have a CPU that supports BTI and a kernel built for -- * BTI then mark the kernel executable text as guarded pages -- * now so we don't have to rewrite the page tables later. -- */ -- if (arm64_early_this_cpu_has_bti()) -- text_prot = __pgprot_modify(text_prot, PTE_GP, PTE_GP); -+ pmdp = pmd_offset(pudp, addr); -+ do { -+ next = pmd_addr_end(addr, end); -+ pmd = READ_ONCE(*pmdp); -+ if((pmd_val(pmd) & PMD_TABLE_BIT) == 0) -+ { -+ continue; -+ } -+ else -+ { -+ iee_set_pte_table_ro(pmdp, addr, next); -+ } -+ } while (pmdp++, addr = next, addr != end); -+} ++#ifdef CONFIG_CREDP ++#include ++#include ++#endif ++ + struct cred; + struct inode; -- /* -- * Only rodata will be remapped with different permissions later on, -- * all other segments are allowed to use contiguous mappings. -- */ -- map_kernel_segment(pgdp, _stext, _etext, text_prot, &vmlinux_text, 0, -- VM_NO_GUARD); -- map_kernel_segment(pgdp, __start_rodata, __inittext_begin, PAGE_KERNEL, -- &vmlinux_rodata, NO_CONT_MAPPINGS, VM_NO_GUARD); -- map_kernel_segment(pgdp, __inittext_begin, __inittext_end, text_prot, -- &vmlinux_inittext, 0, VM_NO_GUARD); -- map_kernel_segment(pgdp, __initdata_begin, __initdata_end, PAGE_KERNEL, -- &vmlinux_initdata, 0, VM_NO_GUARD); -- map_kernel_segment(pgdp, _data, _end, PAGE_KERNEL, &vmlinux_data, 0, 0); -+static void __init iee_set_pud_table_ro(pgd_t *pgdp, unsigned long addr, unsigned long end) +@@ -153,6 +158,22 @@ struct cred { + KABI_RESERVE(4) + } __randomize_layout; + ++#ifdef CONFIG_CREDP ++extern unsigned long long iee_rw_gate(int flag, ...); ++static void iee_set_cred_non_rcu(struct cred *cred, int non_rcu) +{ -+ unsigned long next; -+ p4d_t *p4dp = p4d_offset(pgdp, addr); -+ p4d_t p4d = READ_ONCE(*p4dp); -+ pud_t *pudp; -+ pud_t pud; -+ unsigned long logical_addr = (unsigned long)__va(__p4d_to_phys(p4d)); -+ iee_set_logical_mem_ro(logical_addr); ++ iee_rw_gate(IEE_OP_SET_CRED_NON_RCU,cred,non_rcu); ++ *(int *)(&(((struct rcu_head *)(cred->rcu.func))->next)) = non_rcu; ++} ++ ++static bool iee_set_cred_atomic_op_usage(struct cred *cred, int flag, int nr) ++{ ++ bool ret; ++ ret = iee_rw_gate(IEE_OP_SET_CRED_ATOP_USAGE,cred,flag,nr); ++ return ret; ++} ++#endif ++ + extern void __put_cred(struct cred *); + extern void exit_creds(struct task_struct *); + extern int copy_creds(struct task_struct *, unsigned long); +@@ -189,7 +210,11 @@ static inline bool cap_ambient_invariant_ok(const struct cred *cred) + */ + static inline struct cred *get_new_cred_many(struct cred *cred, int nr) + { ++ #ifdef CONFIG_CREDP ++ iee_set_cred_atomic_op_usage(cred, AT_ADD, nr); ++ #else + atomic_long_add(nr, &cred->usage); ++ #endif + return cred; + } -- fixmap_copy(pgdp); -- kasan_copy_shadow(pgdp); -+ pudp = pud_offset(p4dp, addr); -+ do { -+ next = pud_addr_end(addr, end); -+ pud = READ_ONCE(*pudp); -+ if ((pud_val(pud) & PUD_TABLE_BIT) == 0) -+ { -+ continue; -+ } -+ else -+ { -+ iee_set_pmd_table_ro(pudp, addr, next); -+ } -+ } while (pudp++, addr = next, addr != end); +@@ -202,7 +227,7 @@ static inline struct cred *get_new_cred_many(struct cred *cred, int nr) + */ + static inline struct cred *get_new_cred(struct cred *cred) + { +- return get_new_cred_many(cred, 1); ++ return get_new_cred_many(cred, 1); // XXXzgc atomic_inc -> get_new_cred_many + } + + /** +@@ -224,7 +249,11 @@ static inline const struct cred *get_cred_many(const struct cred *cred, int nr) + struct cred *nonconst_cred = (struct cred *) cred; + if (!cred) + return cred; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_non_rcu(nonconst_cred,0); ++ #else + nonconst_cred->non_rcu = 0; ++ #endif + return get_new_cred_many(nonconst_cred, nr); } --static void __init create_idmap(void) -+static void __init iee_mark_pgtable_for_one_region_ro(pgd_t *pgdir, unsigned long va_start, unsigned long va_end) - { -- u64 start = __pa_symbol(__idmap_text_start); -- u64 size = __pa_symbol(__idmap_text_end) - start; -- pgd_t *pgd = idmap_pg_dir; -- u64 pgd_phys; -+ unsigned long addr, end, next; -+ pgd_t *pgdp = pgd_offset_pgd(pgdir, va_start); +@@ -247,9 +276,19 @@ static inline const struct cred *get_cred_rcu(const struct cred *cred) + struct cred *nonconst_cred = (struct cred *) cred; + if (!cred) + return NULL; ++ #ifdef CONFIG_CREDP ++ if (!iee_set_cred_atomic_op_usage(nonconst_cred,AT_INC_NOT_ZERO,0)) ++ return NULL; ++ #else + if (!atomic_long_inc_not_zero(&nonconst_cred->usage)) + return NULL; ++ #endif ++ ++ #ifdef CONFIG_CREDP ++ iee_set_cred_non_rcu(nonconst_cred,0); ++ #else + nonconst_cred->non_rcu = 0; ++ #endif + return cred; + } -- /* check if we need an additional level of translation */ -- if (VA_BITS < 48 && idmap_t0sz < (64 - VA_BITS_MIN)) { -- pgd_phys = early_pgtable_alloc(PAGE_SHIFT); -- set_pgd(&idmap_pg_dir[start >> VA_BITS], -- __pgd(pgd_phys | P4D_TYPE_TABLE)); -- pgd = __va(pgd_phys); -- } -- __create_pgd_mapping(pgd, start, start, size, PAGE_KERNEL_ROX, -- early_pgtable_alloc, 0); -+ addr = va_start & PAGE_MASK; -+ end = PAGE_ALIGN(va_end); +@@ -270,8 +309,13 @@ static inline void put_cred_many(const struct cred *_cred, int nr) + struct cred *cred = (struct cred *) _cred; -- if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) { -- extern u32 __idmap_kpti_flag; -- u64 pa = __pa_symbol(&__idmap_kpti_flag); -+ do { -+ next = pgd_addr_end(addr, end); -+ iee_set_pud_table_ro(pgdp, addr, next); -+ } while (pgdp++, addr = next, addr != end); -+} + if (cred) { ++ #ifdef CONFIG_CREDP ++ if (iee_set_cred_atomic_op_usage(cred,AT_SUB_AND_TEST,nr)) ++ __put_cred(cred); ++ #else + if (atomic_long_sub_and_test(nr, &cred->usage)) + __put_cred(cred); ++ #endif + } + } -+static void __init iee_mark_all_lm_pgtable_ro(void) -+{ -+ unsigned long logical_addr; -+ phys_addr_t start, end; -+ u64 i; -+ pgd_t *pgdp; +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 9ed79128458c..970cc4f7068b 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -740,6 +740,15 @@ extern int __init __efi_memmap_init(struct efi_memory_map_data *data); + extern int __init efi_memmap_init_early(struct efi_memory_map_data *data); + extern int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size); + extern void __init efi_memmap_unmap(void); ++#ifdef CONFIG_PTP ++extern void __init efi_memmap_unmap_after_init(void); ++#endif ++extern int __init efi_memmap_install(struct efi_memory_map_data *data); ++extern int __init efi_memmap_split_count(efi_memory_desc_t *md, ++ struct range *range); ++extern void __init efi_memmap_insert(struct efi_memory_map *old_memmap, ++ void *buf, struct efi_mem_range *mem); ++extern void __init efi_print_memmap(void); + + #ifdef CONFIG_EFI_ESRT + extern void __init efi_esrt_init(void); +diff --git a/include/linux/iee-flag.h b/include/linux/iee-flag.h +new file mode 100644 +index 000000000000..a6d70ef1d446 +--- /dev/null ++++ b/include/linux/iee-flag.h +@@ -0,0 +1,116 @@ ++#ifndef _LINUX_IEE_FLAG_H ++#define _LINUX_IEE_FLAG_H + -+ // handling static allocated page table -+ #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 -+ // handling 1-level tramp page table tramp_pg_dir -+ logical_addr = (unsigned long)__va(__pa_symbol(tramp_pg_dir)); -+ iee_set_logical_mem_ro(logical_addr); -+ #endif -+ // handling 1-level page table swapper_pg_dir -+ pgdp = swapper_pg_dir; -+ iee_set_logical_mem_ro((unsigned long)swapper_pg_dir); -+ logical_addr = (unsigned long)__va(__pa_symbol(swapper_pg_dir)); -+ iee_set_logical_mem_ro(logical_addr); ++// Function Identifiers with Parameters Description ++enum { ++ IEE_WRITE_IN_BYTE=0, // Parameters: void *ptr, __u64 data, int length ++ IEE_OP_SET_PTE, // Parameters: pte_t *ptep, pte_t pte ++ IEE_OP_SET_PMD, // Parameters: pmd_t *pmdp, pmd_t pmd ++ IEE_OP_SET_PUD, // Parameters: pud_t *pudp, pud_t pud ++ IEE_OP_SET_P4D, // Parameters: p4d_t *p4dp, p4d_t p4d ++ IEE_OP_SET_BM_PTE, // Parameters: pte_t *ptep, pte_t pte ++ IEE_OP_SET_SWAPPER_PGD, // Parameters: pgd_t *pgdp, pgd_t pgd ++ IEE_OP_SET_TRAMP_PGD, // Parameters: pgd_t *pgdp, pgd_t pgd ++ IEE_MEMSET, // Parameters: void *ptr, int data, size_t n ++ IEE_OP_SET_TRACK, // Parameters: struct track *ptr, struct track *data ++ IEE_OP_SET_FREEPTR, // Parameters: void **pptr, void *ptr ++ IEE_OP_SET_PTE_U, // Parameters: pte_t *ptep ++ IEE_OP_SET_PTE_P, // Parameters: pte_t *ptep ++ IEE_SET_TOKEN_PGD, // Parameters: struct task_token *token, pgd_t *pgd ++ IEE_INIT_TOKEN, // Parameters: struct task_struct *tsk, void *kernel_stack, void *iee_stack ++ IEE_INVALIDATE_TOKEN, // Parameters: struct task_struct *tsk ++ IEE_SET_SENSITIVE_PTE, // Parameters: pte_t *lm_ptep, pte_t *iee_ptep ++ IEE_UNSET_SENSITIVE_PTE, // Parameters: pte_t *lm_ptep, pte_t *iee_ptep ++ IEE_SET_TOKEN, // Parameters: pte_t *ptep, void *new, unsigned long order ++ IEE_UNSET_TOKEN, // Parameters: pte_t *ptep, void *token_addr, void *token_page, unsigned long order ++ IEE_COPY_PTE_RANGE, // Parameters: pte_t *new_dst, pte_t *old_dst, pte_t *src_pte, struct vm_area_struct *src_vma, ++ // unsigned long dst_vm_flags, pte_t *end_pte ++ IEE_SPLIT_HUGE_PMD, ++ IEE_VALIDATE_TOKEN, ++ IEE_MEMCPY, ++#ifdef CONFIG_KOI ++ _IEE_READ_KOI_STACK, // Parameters: struct task_struct *tsk ++ _IEE_WRITE_KOI_STACK, // Parameters: struct task_struct *tsk, unsigned long koi_stack ++ _IEE_READ_TOKEN_TTBR1, // Parameters: struct task_struct *tsk ++ _IEE_WRITE_TOKEN_TTBR1, // Parameters: struct task_struct *tsk, unsigned long current_ttbr1 ++ _IEE_READ_KOI_KERNEL_STACK, // Parameters: struct task_struct *tsk ++ _IEE_WRITE_KOI_KERNEL_STACK, // Parameters: struct task_struct *tsk, unsigned long kernel_stack ++ _IEE_READ_KOI_STACK_BASE, // Parameters: struct task_struct *tsk ++ _IEE_WRITE_KOI_STACK_BASE, // Parameters: struct task_struct *tsk, unsigned long koi_stack_base ++ _IEE_SET_KOI_PGD, // Parameters: unsigned long koi_pgd_addr ++#endif ++#ifdef CONFIG_CREDP ++ IEE_OP_COPY_CRED, // Parameters: struct cred *old, struct cred *new ++ IEE_OP_SET_CRED_UID, // Parameters: struct cred *cred, kuid_t uid ++ IEE_OP_SET_CRED_GID, // Parameters: struct cred *cred, kgid_t gid ++ IEE_OP_SET_CRED_SUID, // Parameters: struct cred *cred, kuid_t suid ++ IEE_OP_SET_CRED_SGID, // Parameters: struct cred *cred, kgid_t sgid ++ IEE_OP_SET_CRED_EUID, // Parameters: struct cred *cred, kuid_t euid ++ IEE_OP_SET_CRED_EGID, // Parameters: struct cred *cred, kgid_t egid ++ IEE_OP_SET_CRED_FSUID, // Parameters: struct cred *cred, kuid_t fsuid ++ IEE_OP_SET_CRED_FSGID, // Parameters: struct cred *cred, kgid_t fsgid ++ IEE_OP_SET_CRED_USER, // Parameters: struct cred *cred, struct user_struct *user ++ IEE_OP_SET_CRED_USER_NS, // Parameters: struct cred *cred, struct user_namespace *user_ns ++ IEE_OP_SET_CRED_GROUP_INFO, // Parameters: struct cred *cred, struct group_info *group_info ++ IEE_OP_SET_CRED_SECUREBITS, // Parameters: struct cred *cred, unsigned securebits ++ IEE_OP_SET_CRED_CAP_INHER, // Parameters: struct cred *cred, kernel_cap_t cap_inheritable ++ IEE_OP_SET_CRED_CAP_PERM, // Parameters: struct cred *cred, kernel_cap_t cap_permitted ++ IEE_OP_SET_CRED_CAP_EFFECT, // Parameters: struct cred *cred, kernel_cap_t cap_effective ++ IEE_OP_SET_CRED_CAP_BSET, // Parameters: struct cred *cred, kernel_cap_t cap_bset ++ IEE_OP_SET_CRED_CAP_AMBIENT, // Parameters: struct cred *cred, kernel_cap_t cap_ambient ++ IEE_OP_SET_CRED_JIT_KEYRING, // Parameters: struct cred *cred, unsigned char jit_keyring ++ IEE_OP_SET_CRED_SESS_KEYRING, // Parameters: struct cred *cred, struct key *session_keyring ++ IEE_OP_SET_CRED_PROC_KEYRING, // Parameters: struct cred *cred, struct key *process_keyring ++ IEE_OP_SET_CRED_THREAD_KEYRING, // Parameters: struct cred *cred, struct key *thread_keyring ++ IEE_OP_SET_CRED_REQ_KEYRING, // Parameters: struct cred *cred, struct key *request_key_auth ++ IEE_OP_SET_CRED_NON_RCU, // Parameters: struct cred *cred, int non_rcu ++ IEE_OP_SET_CRED_ATSET_USAGE, // Parameters: struct cred *cred, int i ++ IEE_OP_SET_CRED_ATOP_USAGE, // Parameters: struct cred *cred, int flag ++ IEE_OP_SET_CRED_SECURITY, // Parameters: struct cred *cred, void *security ++ IEE_OP_SET_CRED_RCU, // Parameters: struct cred *cred, struct rcu_head *rcu ++ IEE_OP_SET_CRED_UCOUNTS, // Parameters: struct cred *cred, struct ucounts *ucounts ++// IEE_OP_COMMIT_CRED, // Parameters: struct cred *cred ++// IEE_OP_COPY_CRED_KERNEL, // Parameters: struct cred *old, struct cred *new ++#endif ++#ifdef CONFIG_KEYP ++ IEE_OP_SET_KEY_UNION, ++ IEE_OP_SET_KEY_STRUCT, ++ IEE_OP_SET_KEY_PAYLOAD, ++ IEE_OP_WRITE_KEY_PAYLOAD, ++ IEE_OP_WRITE_KEY_PAYLOAD_RCU_DATA0, ++ IEE_OP_SET_KEY_USAGE, ++ IEE_OP_SET_KEY_SERIAL, ++ IEE_OP_SET_KEY_WATCHERS, ++ IEE_OP_SET_KEY_USERS, ++ IEE_OP_SET_KEY_SECURITY, ++ IEE_OP_SET_KEY_EXPIRY, ++ IEE_OP_SET_KEY_REVOKED_AT, ++ IEE_OP_SET_KEY_LAST_USED_AT, ++ IEE_OP_SET_KEY_UID, ++ IEE_OP_SET_KEY_GID, ++ IEE_OP_SET_KEY_PERM, ++ IEE_OP_SET_KEY_QUOTALEN, ++ IEE_OP_SET_KEY_DATALEN, ++ IEE_OP_SET_KEY_STATE, ++ IEE_OP_SET_KEY_MAGIC, ++ IEE_OP_SET_KEY_FLAGS, ++ IEE_OP_SET_KEY_INDEX_KEY, ++ IEE_OP_SET_KEY_HASH, ++ IEE_OP_SET_KEY_LEN_DESC, ++ IEE_OP_SET_KEY_TYPE, ++ IEE_OP_SET_KEY_TAG, ++ IEE_OP_SET_KEY_DESCRIPTION, ++ IEE_OP_SET_KEY_RESTRICT_LINK, ++ IEE_OP_SET_KEY_FLAG_BIT, ++#endif ++#ifdef CONFIG_IEE_SELINUX_P ++ IEE_SEL_SET_STATUS_PG, // Parameters: struct page* new_page ++ IEE_SEL_SET_ENFORCING, // Parameters: bool value ++ IEE_SEL_SET_INITIALIZED, ++ IEE_SEL_SET_POLICY_CAP, // Parameters: unsigned int idx, int cap ++ IEE_SEL_RCU_ASSIGN_POLICY, // Parameters: struct selinux_policy* new_policy, struct selinux_policy* iee_new_policy ++#endif ++ IEE_FLAG_END ++}; + -+ // handling 2/3/4-level page table for kernel -+ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)_text, (unsigned long)_etext); -+ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)__start_rodata, (unsigned long)__inittext_begin); -+ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)__inittext_begin, (unsigned long)__inittext_end); -+ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)__initdata_begin, (unsigned long)__initdata_end); -+ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)_data, (unsigned long)_end); ++#endif +\ No newline at end of file +diff --git a/include/linux/iee-func.h b/include/linux/iee-func.h +new file mode 100644 +index 000000000000..a3e4909a650f +--- /dev/null ++++ b/include/linux/iee-func.h +@@ -0,0 +1,35 @@ ++#ifndef _LINUX_IEE_FUNC_H ++#define _LINUX_IEE_FUNC_H + -+ // handling 2/3/4-level page table for fixmap i.e. remap bm_xxx -+ logical_addr = (unsigned long)__va(__pa_symbol(bm_pte_addr)); -+ iee_set_logical_mem_ro(logical_addr); ++#ifdef CONFIG_IEE ++#define HUGE_PMD_ORDER 9 ++#define TASK_ORDER 4 ++extern unsigned long init_iee_stack_begin[]; ++extern unsigned long init_iee_stack_end[]; ++extern void *init_token_page_vaddr; + -+ iee_set_logical_mem_ro((unsigned long)bm_pmd_addr); -+ logical_addr = (unsigned long)__va(__pa_symbol(bm_pmd_addr)); -+ iee_set_logical_mem_ro(logical_addr); ++extern unsigned long long iee_rw_gate(int flag, ...); ++extern u32 get_cpu_asid_bits(void); ++extern unsigned long arm64_mm_context_get(struct mm_struct *mm); ++extern void set_iee_page(unsigned long addr, int order); ++extern void unset_iee_page(unsigned long addr, int order); ++extern void set_iee_page_valid(unsigned long addr); ++extern void iee_set_logical_mem_ro(unsigned long addr); ++extern void __init iee_mark_all_lm_pgtable_ro(void); ++extern void iee_set_token_pgd(struct task_struct *tsk, pgd_t *pgd); ++extern void iee_init_token(struct task_struct *tsk, void *iee_stack, void *tmp_page); ++extern void iee_invalidate_token(struct task_struct *tsk); ++extern void iee_validate_token(struct task_struct *tsk); ++extern unsigned long iee_read_token_stack(struct task_struct *tsk); ++extern void iee_set_token_page_valid(void *token, void *new, unsigned int order); ++extern void iee_set_token_page_invalid(void *token_addr, void *token_page, unsigned long order); ++extern void unset_iee_stack_page(unsigned long addr, int order); ++extern void set_iee_stack_page(unsigned long addr, int order); ++extern void iee_write_in_byte(void *ptr, u64 data, int length); ++extern void *iee_read_tmp_page(struct task_struct *tsk); ++extern void *iee_read_freeptr(void *ptr); ++extern void iee_set_stack_freeptr(unsigned long addr, void *free_ptr); ++extern void iee_memset(void *ptr, int data, size_t n); ++#endif + -+ iee_set_logical_mem_ro((unsigned long)bm_pud_addr); -+ logical_addr = (unsigned long)__va(__pa_symbol(bm_pud_addr)); -+ iee_set_logical_mem_ro(logical_addr); ++#endif +\ No newline at end of file +diff --git a/include/linux/key.h b/include/linux/key.h +index 938d7ecfb495..7cde506953cd 100644 +--- a/include/linux/key.h ++++ b/include/linux/key.h +@@ -280,6 +280,39 @@ struct key { + struct key_restriction *restrict_link; + }; + ++#ifdef CONFIG_IEE ++struct key_union { ++ union { ++ struct list_head graveyard_link; ++ struct rb_node serial_node; ++ }; ++ struct rw_semaphore sem; ++ struct key *key; ++}; + -+ // handling 2/3/4-level page table for logical mem and iee -+ for_each_mem_range(i, &start, &end) { -+ if (start >= end) -+ break; - /* -- * The KPTI G-to-nG conversion code needs a read-write mapping -- * of its synchronization flag in the ID map. -+ * The linear map must allow allocation tags reading/writing -+ * if MTE is present. Otherwise, it has the same attributes as -+ * PAGE_KERNEL. - */ -- __create_pgd_mapping(pgd, pa, pa, sizeof(u32), PAGE_KERNEL, -- early_pgtable_alloc, 0); -+ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)__va(start), (unsigned long)__va(end)); -+ iee_mark_pgtable_for_one_region_ro(pgdp, (unsigned long)__phys_to_iee(start), (unsigned long)__phys_to_iee(end)); - } - } ++struct key_struct { ++ struct { ++ /* Keyring bits */ ++ struct list_head name_link; ++ struct assoc_array keys; ++ }; ++ struct key *key; ++}; +#endif + -+#ifdef CONFIG_KOI -+extern s64 koi_offset; ++#ifdef CONFIG_KEYP ++#define KEY_SEM(KEY) (((struct key_union *)(KEY->graveyard_link.next))->sem) ++#include ++#include ++extern unsigned long long iee_rw_gate(int flag, ...); ++static bool iee_set_key_usage(struct key *key, int n, int flag) ++{ ++ bool ret; ++ ret = iee_rw_gate(IEE_OP_SET_KEY_USAGE, key, n, flag); ++ return ret; ++} +#endif ++ + extern struct key *key_alloc(struct key_type *type, + const char *desc, + kuid_t uid, kgid_t gid, +@@ -305,7 +338,11 @@ extern void key_remove_domain(struct key_tag *domain_tag); - void __init paging_init(void) + static inline struct key *__key_get(struct key *key) { -+ #ifdef CONFIG_IEE -+ unsigned long SP_EL0; -+ void *new; -+ void *init_token; -+ struct task_token *token; -+ unsigned long tcr; -+ -+ // Check if cpu has PAN and HPDS. -+ if(!cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64MMFR1_EL1), -+ ID_AA64MMFR1_EL1_PAN_SHIFT)) -+ panic("Architecture doesn't support PAN, please disable CONFIG_IEE.\n"); -+ -+ if(!cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64MMFR1_EL1), -+ ID_AA64MMFR1_EL1_HPDS_SHIFT)) -+ panic("Architecture doesn't support HPDS, please disable CONFIG_IEE.\n"); -+ #endif -+ -+ // Avoid using iee code to modify pgtable before iee initialized. -+ #ifdef CONFIG_PTP -+ pgd_t *pgdp = pgd_set_fixmap_init(__pa_symbol(swapper_pg_dir)); ++ #ifdef CONFIG_KEYP ++ iee_set_key_usage(key, 0, REFCOUNT_INC); + #else - pgd_t *pgdp = pgd_set_fixmap(__pa_symbol(swapper_pg_dir)); + refcount_inc(&key->usage); + #endif + return key; + } + +@@ -478,17 +515,63 @@ static inline bool key_is_negative(const struct key *key) + return key_read_state(key) < 0; + } + ++#ifdef CONFIG_KEYP ++extern void iee_write_key_payload_rcu_data0(struct key *key, void *rcu_data0); + -+ - extern pgd_t init_idmap_pg_dir[]; ++#define dereference_key_rcu(KEY) \ ++ (rcu_dereference(((union key_payload *)(KEY->name_link.next))->rcu_data0)) ++ ++#ifdef CONFIG_KEYP ++#define dereference_key_locked(KEY) \ ++ (rcu_dereference_protected(((union key_payload *)(KEY->name_link.next))->rcu_data0, \ ++ rwsem_is_locked(&KEY_SEM(((struct key *)(KEY)))))) ++#else ++#define dereference_key_locked(KEY) \ ++ (rcu_dereference_protected(((union key_payload *)(KEY->name_link.next))->rcu_data0, \ ++ rwsem_is_locked(&((struct key *)(KEY))->sem))) ++#endif ++ ++#define iee_smp_store_release(p, v, KEY) \ ++do { \ ++ compiletime_assert_atomic_type(*p); \ ++ barrier(); \ ++ iee_write_key_payload_rcu_data0(KEY, v); \ ++} while (0) ++ ++#define iee_rcu_assign_pointer(p, v, KEY) \ ++do { \ ++ uintptr_t _r_a_p__v = (uintptr_t)(v); \ ++ rcu_check_sparse(p, __rcu); \ ++ \ ++ if (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL) \ ++ iee_write_key_payload_rcu_data0(KEY, (typeof(p))(_r_a_p__v)); \ ++ else \ ++ iee_smp_store_release(&p, RCU_INITIALIZER((typeof(p))_r_a_p__v), KEY); \ ++} while (0) ++ ++#define rcu_assign_keypointer(KEY, PAYLOAD) \ ++do { \ ++ iee_rcu_assign_pointer(((union key_payload *)(KEY->name_link.next))->rcu_data0, (PAYLOAD), KEY); \ ++} while (0) ++#else + #define dereference_key_rcu(KEY) \ + (rcu_dereference((KEY)->payload.rcu_data0)) - idmap_t0sz = 63UL - __fls(__pa_symbol(_end) | GENMASK(VA_BITS_MIN - 1, 0)); -@@ -802,7 +2006,17 @@ void __init paging_init(void) - map_kernel(pgdp); - map_mem(pgdp); ++#ifdef CONFIG_KEYP ++#define dereference_key_locked(KEY) \ ++ (rcu_dereference_protected((KEY)->payload.rcu_data0, \ ++ rwsem_is_locked(&KEY_SEM(((struct key *)(KEY)))))) ++#else + #define dereference_key_locked(KEY) \ + (rcu_dereference_protected((KEY)->payload.rcu_data0, \ + rwsem_is_locked(&((struct key *)(KEY))->sem))) ++#endif -+ // Map the whole physical mem into IEE, but set invalid. -+ #ifdef CONFIG_IEE -+ map_iee(pgdp); + #define rcu_assign_keypointer(KEY, PAYLOAD) \ + do { \ + rcu_assign_pointer((KEY)->payload.rcu_data0, (PAYLOAD)); \ + } while (0) ++#endif + + /* + * the userspace interface +diff --git a/include/linux/mm.h b/include/linux/mm.h +index ffdd46c1108a..e938f50f2d7f 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -32,6 +32,77 @@ + #include + #include + ++#ifdef CONFIG_PTP ++#include ++struct slab_t { ++ unsigned long __page_flags; ++ ++#if defined(CONFIG_SLAB) ++ ++ void *slab_cache; ++ union { ++ struct { ++ struct list_head slab_list; ++ void *freelist; /* array of free object indexes */ ++ void *s_mem; /* first object */ ++ }; ++ struct rcu_head rcu_head; ++ }; ++ unsigned int active; ++ ++#elif defined(CONFIG_SLUB) ++ ++ void *slab_cache; ++ union { ++ struct { ++ union { ++ struct list_head slab_list; ++#ifdef CONFIG_SLUB_CPU_PARTIAL ++ struct { ++ struct slab_t *next; ++ int slabs; /* Nr of slabs left */ ++ }; ++#endif ++ }; ++ /* Double-word boundary */ ++ union { ++ struct { ++ void *freelist; /* first free object */ ++ union { ++ unsigned long counters; ++ struct { ++ unsigned inuse:16; ++ unsigned objects:15; ++ unsigned frozen:1; ++ }; ++ }; ++ }; ++#ifdef system_has_freelist_aba ++ union { ++ struct { ++ void *freelist; ++ unsigned long counter; ++ }; ++ u64 full; ++ }; ++#endif ++ }; ++ }; ++ struct rcu_head rcu_head; ++ }; ++ unsigned int __unused; ++ ++#else ++#error "Unexpected slab allocator configured" ++#endif ++ ++ atomic_t __page_refcount; ++#ifdef CONFIG_MEMCG ++ unsigned long memcg_data; ++#endif ++}; ++#endif ++ + struct mempolicy; + struct anon_vma; + struct anon_vma_chain; +@@ -2938,7 +3009,11 @@ static inline bool pagetable_is_reserved(struct ptdesc *pt) + */ + static inline struct ptdesc *pagetable_alloc(gfp_t gfp, unsigned int order) + { ++ #ifdef CONFIG_PTP ++ struct page *page = virt_to_page(get_iee_pgtable_page(gfp | __GFP_COMP)); ++ #else + struct page *page = alloc_pages(gfp | __GFP_COMP, order); + #endif -+ -+ // Avoid using iee code to modify pgtable before iee initialized. + + return page_ptdesc(page); + } +@@ -2954,7 +3029,11 @@ static inline void pagetable_free(struct ptdesc *pt) + { + struct page *page = ptdesc_page(pt); + + #ifdef CONFIG_PTP -+ pgd_clear_fixmap_init(); ++ free_iee_pgtable_page((void *)page_address(page)); + #else - pgd_clear_fixmap(); + __free_pages(page, compound_order(page)); + #endif + } - cpu_replace_ttbr1(lm_alias(swapper_pg_dir), init_idmap_pg_dir); - init_mm.pgd = swapper_pg_dir; -@@ -813,6 +2027,80 @@ void __init paging_init(void) - memblock_allow_resize(); + #if USE_SPLIT_PTE_PTLOCKS +@@ -2965,7 +3044,11 @@ void ptlock_free(struct ptdesc *ptdesc); - create_idmap(); -+ -+ #ifdef CONFIG_IEE -+ // test iee_exec_entry -+ iee_rwx_gate_entry(IEE_SI_TEST); -+ // Initialize init iee stack. + static inline spinlock_t *ptlock_ptr(struct ptdesc *ptdesc) + { + #ifdef CONFIG_PTP -+ iee_set_kernel_upage_pre_init((unsigned long)init_iee_stack_begin); -+ iee_set_kernel_upage_pre_init((unsigned long)__va(__pa_symbol(init_iee_stack_begin))); ++ return ((struct ptdesc_t *)(((struct slab_t *)ptdesc)->slab_cache))->ptl; + #else -+ iee_set_kernel_upage((unsigned long)init_iee_stack_begin); -+ iee_set_kernel_upage((unsigned long)__va(__pa_symbol(init_iee_stack_begin))); + return ptdesc->ptl; + #endif + } + #else /* ALLOC_SPLIT_PTLOCKS */ + static inline void ptlock_cache_init(void) +@@ -2983,7 +3066,11 @@ static inline void ptlock_free(struct ptdesc *ptdesc) + + static inline spinlock_t *ptlock_ptr(struct ptdesc *ptdesc) + { ++ #ifdef CONFIG_PTP ++ return &(((struct ptdesc_t *)(((struct slab_t *)ptdesc)->slab_cache))->ptl); ++ #else + return &ptdesc->ptl; + #endif -+ -+ // Init token for init_task. -+ #ifdef CONFIG_IEE -+ // Change SP_EL0 from Image VA to Logical VA. -+ SP_EL0 = (unsigned long)__va(__pa_symbol(&init_task)); -+ write_sysreg(SP_EL0, sp_el0); -+ init_task.cpus_ptr = &(((struct task_struct *)(__va(__pa_symbol(&init_task))))->cpus_mask); -+ init_task.children.prev = (__va(__pa_symbol(init_task.children.prev))); -+ init_task.children.next = (__va(__pa_symbol(init_task.children.next))); -+ // Set init_task into __entry_task before per_cpu init. -+ *(struct task_struct **)__entry_task = __va(__pa_symbol(&init_task)); -+ // Alloc a page for init_token. -+ new = __va(early_pgtable_alloc(0)); -+ init_token = (void *)__phys_to_iee(__pa_symbol(&init_task)); + } + #endif /* ALLOC_SPLIT_PTLOCKS */ + +@@ -3001,7 +3088,11 @@ static inline bool ptlock_init(struct ptdesc *ptdesc) + * It can happen if arch try to use slab for page table allocation: + * slab code uses page->slab_cache, which share storage with page->ptl. + */ + #ifdef CONFIG_PTP -+ iee_set_token_page_valid_pre_init(init_token, new); ++ VM_BUG_ON_PAGE(*(unsigned long *)&(((struct ptdesc_t *)(((struct slab_t *)ptdesc)->slab_cache))->ptl), ptdesc_page(ptdesc)); + #else -+ iee_set_token_page_valid(init_token, new); + VM_BUG_ON_PAGE(*(unsigned long *)&ptdesc->ptl, ptdesc_page(ptdesc)); + #endif -+ // Use lm to write token before IEE initialized. -+ token = (struct task_token *)((unsigned long)new + (((unsigned long)&init_task) & ~PAGE_MASK)); -+ token->mm = &init_mm; -+ token->pgd = NULL; -+ token->iee_stack = (void *)init_iee_stack_end; -+ token->valid = true; + if (!ptlock_alloc(ptdesc)) + return false; + spin_lock_init(ptlock_ptr(ptdesc)); +@@ -3100,7 +3191,11 @@ static inline spinlock_t *pmd_lockptr(struct mm_struct *mm, pmd_t *pmd) + static inline bool pmd_ptlock_init(struct ptdesc *ptdesc) + { + #ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ #ifdef CONFIG_PTP ++ (((struct ptdesc_t *)(((struct slab_t *)ptdesc)->slab_cache))->pmd_huge_pte) = NULL; ++ #else + ptdesc->pmd_huge_pte = NULL; + #endif -+ + #endif + return ptlock_init(ptdesc); + } +@@ -3108,12 +3203,20 @@ static inline bool pmd_ptlock_init(struct ptdesc *ptdesc) + static inline void pmd_ptlock_free(struct ptdesc *ptdesc) + { + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + #ifdef CONFIG_PTP -+ // Map the existing pgtable into IEE, set valid. -+ init_iee(); ++ VM_BUG_ON_PAGE((((struct ptdesc_t *)(((struct slab_t *)ptdesc)->slab_cache))->pmd_huge_pte), ptdesc_page(ptdesc)); ++ #else + VM_BUG_ON_PAGE(ptdesc->pmd_huge_pte, ptdesc_page(ptdesc)); + #endif + #endif + ptlock_free(ptdesc); + } + ++#ifdef CONFIG_PTP ++#define pmd_huge_pte(mm, pmd) (((struct ptdesc_t *)(((struct slab_t *)pmd_ptdesc(pmd))->slab_cache))->pmd_huge_pte) ++#else + #define pmd_huge_pte(mm, pmd) (pmd_ptdesc(pmd)->pmd_huge_pte) ++#endif + + #else + +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 793c16b99237..c54eea1bca0b 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -483,6 +483,42 @@ struct ptdesc { + #endif + }; + ++#ifdef CONFIG_IEE ++struct ptdesc_t { ++ unsigned long __page_flags; ++ ++ union { ++ struct rcu_head pt_rcu_head; ++ struct list_head pt_list; ++ struct { ++ unsigned long _pt_pad_1; ++ pgtable_t pmd_huge_pte; ++ }; ++ }; ++ unsigned long __page_mapping; + -+ #ifdef CONFIG_IEE -+ sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_SPAN); -+ #endif ++ union { ++ struct mm_struct *pt_mm; ++ atomic_t pt_frag_refcount; ++ }; + -+ #ifdef CONFIG_PTP -+ // IEE ready. -+ // Pgtable writing before uses logical memory and after uses IEE memory. ++ union { ++ unsigned long _pt_pad_2; ++#if ALLOC_SPLIT_PTLOCKS ++ spinlock_t *ptl; ++#else ++ spinlock_t ptl; ++#endif ++ }; ++ unsigned int __page_type; ++ atomic_t _refcount; ++#ifdef CONFIG_MEMCG ++ unsigned long pt_memcg_data; ++#endif ++ struct slab_t *slab; ++}; ++#endif ++ + #define TABLE_MATCH(pg, pt) \ + static_assert(offsetof(struct page, pg) == offsetof(struct ptdesc, pt)) + TABLE_MATCH(flags, __page_flags); +@@ -1180,6 +1216,9 @@ struct mmu_gather; + extern void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm); + extern void tlb_gather_mmu_fullmm(struct mmu_gather *tlb, struct mm_struct *mm); + extern void tlb_finish_mmu(struct mmu_gather *tlb); ++#ifdef CONFIG_PTP ++extern void iee_tlb_finish_mmu(struct mmu_gather *tlb); ++#endif + + struct vm_fault; + +diff --git a/include/linux/module.h b/include/linux/module.h +index 4db2878d9e42..ef8d51994017 100644 +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -606,6 +606,7 @@ struct module { + KABI_RESERVE(2) + KABI_RESERVE(3) + KABI_RESERVE(4) ++ + } ____cacheline_aligned __randomize_layout; + #ifndef MODULE_ARCH_INIT + #define MODULE_ARCH_INIT {} +diff --git a/include/linux/sched.h b/include/linux/sched.h +index f40411aa7b70..9859d956f2b4 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -773,6 +773,24 @@ struct task_struct_resvd { + struct task_struct *task; + }; + ++#if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++struct task_token { ++#ifdef CONFIG_IEE ++ pgd_t *pgd; /* Logical VA */ ++ void *iee_stack; /* VA */ ++ void *tmp_page; ++ bool valid; ++ void *kernel_stack; /* VA */ ++#endif ++#ifdef CONFIG_KOI ++ void *koi_kernel_stack; /* VA */ ++ void *koi_stack; /* VA */ ++ void *koi_stack_base; /* VA */ ++ unsigned long current_ttbr1; ++#endif ++}; ++#endif ++ + struct task_struct { + #ifdef CONFIG_THREAD_INFO_IN_TASK + /* +@@ -795,6 +813,7 @@ struct task_struct { + randomized_struct_fields_start + + void *stack; ++ + refcount_t usage; + /* Per task flags (PF_*), defined further below: */ + unsigned int flags; +diff --git a/init/main.c b/init/main.c +index 8fdfa69dba0f..9c6aeae0ea66 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -102,6 +102,14 @@ + #include + #include + ++#ifdef CONFIG_IEE ++#include ++#include ++#include ++#include ++#include ++#endif ++ + #include + #include + #include +@@ -112,6 +120,10 @@ + + #include + ++#ifdef CONFIG_PTP ++extern void *bm_pte_addr; ++#endif + + static int kernel_init(void *); + + /* +@@ -933,6 +945,10 @@ void start_kernel(void) + sort_main_extable(); + trap_init(); + mm_core_init(); ++ #ifdef CONFIG_IEE ++ iee_stack_init(); ++ iee_pgtable_init(); ++ #endif + poking_init(); + ftrace_init(); + +@@ -1073,6 +1089,16 @@ void start_kernel(void) + arch_post_acpi_subsys_init(); + kcsan_init(); + ++ // Later IEE settings. ++ #ifdef CONFIG_IEE ++ set_iee_stack_page((unsigned long)__va(__pa_symbol(init_iee_stack_begin)), 2); ++ set_iee_page((unsigned long)init_token_page_vaddr, 0); + // Set the logical va of existing pgtable readonly. ++ #ifdef CONFIG_PTP + iee_mark_all_lm_pgtable_ro(); + #endif ++ #endif + -+ // Set the init token readonly. -+ #ifdef CONFIG_IEE -+ set_iee_page_valid(__phys_to_iee(__pa(new))); -+ iee_set_logical_mem_ro((unsigned long)new); -+ -+ // Set HPD1 as 1. -+ tcr = read_sysreg(tcr_el1); -+ tcr |= ((unsigned long)0x1 << 42); -+ write_sysreg(tcr, tcr_el1); -+ isb(); + /* Do the rest non-__init'ed, we're now alive */ + arch_call_rest_init(); + +@@ -1444,6 +1470,9 @@ static int __ref kernel_init(void *unused) + wait_for_completion(&kthreadd_done); + + kernel_init_freeable(); ++ #ifdef CONFIG_PTP ++ iee_set_logical_mem_ro((unsigned long)bm_pte_addr); ++ #endif + /* need to finish all async __init code before freeing the memory */ + async_synchronize_full(); + +@@ -1460,7 +1489,7 @@ static int __ref kernel_init(void *unused) + * to finalize PTI. + */ + pti_finalize(); +- ++ + system_state = SYSTEM_RUNNING; + numa_default_policy(); + +diff --git a/kernel/cred.c b/kernel/cred.c +index c033a201c808..ba57e19a26b8 100644 +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -20,6 +20,11 @@ + #include + #include + ++#ifdef CONFIG_CREDP ++#include ++#include ++#endif + -+ // Flush tlb to enable IEE. -+ flush_tlb_all(); + #if 0 + #define kdebug(FMT, ...) \ + printk("[%-5.5s%5u] " FMT "\n", \ +@@ -33,7 +38,14 @@ do { \ + } while (0) + #endif + ++#ifdef CONFIG_IEE ++struct kmem_cache *cred_jar; ++#ifdef CONFIG_CREDP ++static struct kmem_cache *rcu_jar; ++#endif ++#else + static struct kmem_cache *cred_jar; ++#endif + + /* init to 2 - one for init_task, one to ensure it is never freed */ + static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) }; +@@ -41,6 +53,32 @@ static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) }; + /* + * The initial credentials for the initial task + */ ++#ifdef CONFIG_CREDP ++struct cred init_cred __section(".iee.cred") = { ++ .usage = ATOMIC_INIT(4), ++#ifdef CONFIG_DEBUG_CREDENTIALS ++ .subscribers = ATOMIC_INIT(2), ++ .magic = CRED_MAGIC, ++#endif ++ .uid = GLOBAL_ROOT_UID, ++ .gid = GLOBAL_ROOT_GID, ++ .suid = GLOBAL_ROOT_UID, ++ .sgid = GLOBAL_ROOT_GID, ++ .euid = GLOBAL_ROOT_UID, ++ .egid = GLOBAL_ROOT_GID, ++ .fsuid = GLOBAL_ROOT_UID, ++ .fsgid = GLOBAL_ROOT_GID, ++ .securebits = SECUREBITS_DEFAULT, ++ .cap_inheritable = CAP_EMPTY_SET, ++ .cap_permitted = CAP_FULL_SET, ++ .cap_effective = CAP_FULL_SET, ++ .cap_bset = CAP_FULL_SET, ++ .user = INIT_USER, ++ .user_ns = &init_user_ns, ++ .group_info = &init_groups, ++ .ucounts = &init_ucounts, ++}; ++#else + struct cred init_cred = { + .usage = ATOMIC_INIT(4), + .uid = GLOBAL_ROOT_UID, +@@ -61,13 +99,43 @@ struct cred init_cred = { + .group_info = &init_groups, + .ucounts = &init_ucounts, + }; ++#endif + -+ // mark that iee is prepared. -+ iee_init_done = true; -+ #endif - } - - #ifdef CONFIG_MEMORY_HOTPLUG -diff --git a/arch/arm64/mm/pgd.c b/arch/arm64/mm/pgd.c -index 4a64089e5771..894bda11c389 100644 ---- a/arch/arm64/mm/pgd.c -+++ b/arch/arm64/mm/pgd.c -@@ -15,14 +15,44 @@ - #include - #include - -+#ifdef CONFIG_PTP -+#include ++static inline void set_cred_subscribers(struct cred *cred, int n) ++{ ++#ifdef CONFIG_DEBUG_CREDENTIALS ++ atomic_set(&cred->subscribers, n); +#endif ++} + - static struct kmem_cache *pgd_cache __ro_after_init; - -+#ifdef CONFIG_KOI -+pgd_t *koi_pgd_alloc(void) ++static inline int read_cred_subscribers(const struct cred *cred) +{ -+ pgd_t *pgd; -+#ifdef CONFIG_PTP -+ pgd = (pgd_t *)__get_free_page(GFP_PGTABLE_KERNEL); -+ unsigned long iee_addr = __phys_to_iee(__pa(pgd)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)pgd); ++#ifdef CONFIG_DEBUG_CREDENTIALS ++ return atomic_read(&cred->subscribers); +#else -+ pgd = (pgd_t *)__get_free_page(GFP_PGTABLE_KERNEL); ++ return 0; +#endif -+ return pgd; +} -+#endif + - pgd_t *pgd_alloc(struct mm_struct *mm) ++static inline void alter_cred_subscribers(const struct cred *_cred, int n) ++{ ++#ifdef CONFIG_DEBUG_CREDENTIALS ++ struct cred *cred = (struct cred *) _cred; ++ ++ atomic_add(n, &cred->subscribers); ++#endif ++} + + /* + * The RCU callback to actually dispose of a set of credentials + */ + static void put_cred_rcu(struct rcu_head *rcu) { - gfp_t gfp = GFP_PGTABLE_USER; ++ #ifdef CONFIG_CREDP ++ struct cred *cred = *(struct cred **)(rcu + 1); ++ #else + struct cred *cred = container_of(rcu, struct cred, rcu); ++ #endif - if (PGD_SIZE == PAGE_SIZE) -+#ifdef CONFIG_PTP -+ { -+ pgd_t* new = (pgd_t *)__get_free_page(gfp); -+ unsigned long iee_addr = __phys_to_iee(__pa(new)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)new); -+ return new; -+ } -+#else - return (pgd_t *)__get_free_page(gfp); -+#endif - else - return kmem_cache_alloc(pgd_cache, gfp); + kdebug("put_cred_rcu(%p)", cred); + +@@ -86,6 +154,9 @@ static void put_cred_rcu(struct rcu_head *rcu) + if (cred->ucounts) + put_ucounts(cred->ucounts); + put_user_ns(cred->user_ns); ++ #ifdef CONFIG_CREDP ++ kmem_cache_free(rcu_jar, (struct rcu_head *)(cred->rcu.func)); ++ #endif + kmem_cache_free(cred_jar, cred); } -@@ -30,7 +60,16 @@ pgd_t *pgd_alloc(struct mm_struct *mm) - void pgd_free(struct mm_struct *mm, pgd_t *pgd) - { - if (PGD_SIZE == PAGE_SIZE) -+#ifdef CONFIG_PTP -+ { -+ unsigned long iee_addr = __phys_to_iee(__pa(pgd)); -+ set_iee_page_invalid(iee_addr); -+ iee_set_logical_mem_rw((unsigned long)pgd); -+ free_page((unsigned long)pgd); -+ } -+#else - free_page((unsigned long)pgd); -+#endif + +@@ -104,10 +175,22 @@ void __put_cred(struct cred *cred) + BUG_ON(cred == current->cred); + BUG_ON(cred == current->real_cred); + ++ #ifdef CONFIG_CREDP ++ if (*(int *)(&(((struct rcu_head *)(cred->rcu.func))->next))) ++ #else + if (cred->non_rcu) ++ #endif ++ #ifdef CONFIG_CREDP ++ put_cred_rcu((struct rcu_head *)(cred->rcu.func)); ++ #else + put_cred_rcu(&cred->rcu); ++ #endif else - kmem_cache_free(pgd_cache, pgd); ++ #ifdef CONFIG_CREDP ++ call_rcu((struct rcu_head *)(cred->rcu.func), put_cred_rcu); ++ #else + call_rcu(&cred->rcu, put_cred_rcu); ++ #endif } -diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S -index 14fdf645edc8..230b2b883a51 100644 ---- a/arch/arm64/mm/proc.S -+++ b/arch/arm64/mm/proc.S -@@ -22,6 +22,8 @@ - #include - #include + EXPORT_SYMBOL(__put_cred); -+ -+ - #ifdef CONFIG_ARM64_64K_PAGES - #define TCR_TG_FLAGS TCR_TG0_64K | TCR_TG1_64K - #elif defined(CONFIG_ARM64_16K_PAGES) -@@ -105,6 +107,19 @@ SYM_FUNC_START(cpu_do_suspend) - ret - SYM_FUNC_END(cpu_do_suspend) +@@ -178,7 +261,18 @@ struct cred *cred_alloc_blank(void) + if (!new) + return NULL; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_rcu(new,kmem_cache_zalloc(rcu_jar, GFP_KERNEL)); ++ *(struct cred **)(((struct rcu_head *)(new->rcu.func)) + 1) = new; ++ iee_set_cred_atomic_set_usage(new,1); ++ #else + atomic_long_set(&new->usage, 1); ++ #endif + -+#ifdef CONFIG_IEE -+// SP_EL0 check failed. -+SYM_FUNC_START_LOCAL(sp_el0_check_failed) -+1: -+ nop -+ nop -+ nop -+ nop -+ b 1f -+SYM_FUNC_END(sp_el0_check_failed) -+#endif ++ #ifdef CONFIG_DEBUG_CREDENTIALS ++ new->magic = CRED_MAGIC; ++ #endif + - /** - * cpu_do_resume - restore CPU register context - * -@@ -148,6 +163,13 @@ SYM_FUNC_START(cpu_do_resume) - msr sctlr_el1, x12 - set_this_cpu_offset x13 - msr sp_el0, x14 -+#ifdef CONFIG_IEE -+ // tsk check. -+ ldr_this_cpu x2, __entry_task, x3 -+ mrs x3, sp_el0 -+ cmp x2, x3 -+ b.ne sp_el0_check_failed -+#endif - /* - * Restore oslsr_el1 by writing oslar_el1 - */ -@@ -190,6 +212,7 @@ SYM_TYPED_FUNC_START(idmap_cpu_replace_ttbr1) - __idmap_cpu_set_reserved_ttbr1 x1, x3 + if (security_cred_alloc_blank(new, GFP_KERNEL_ACCOUNT) < 0) + goto error; - offset_ttbr1 x0, x3 -+ - msr ttbr1_el1, x0 - isb +@@ -213,13 +307,25 @@ struct cred *prepare_creds(void) + if (!new) + return NULL; -@@ -452,6 +475,11 @@ SYM_FUNC_START(__cpu_setup) - orr tcr, tcr, #TCR_HA // hardware Access flag update - 1: - #endif /* CONFIG_ARM64_HW_AFDBM */ ++ #ifdef CONFIG_CREDP ++ iee_set_cred_rcu(new,kmem_cache_alloc(rcu_jar, GFP_KERNEL)); ++ *(struct cred **)(((struct rcu_head *)(new->rcu.func)) + 1) = new; ++ #endif + -+#ifdef CONFIG_IEE -+ orr tcr, tcr, #TCR_HPD1 // Hierarchical permission disables -+#endif + kdebug("prepare_creds() alloc %p", new); + + old = task->cred; ++ #ifdef CONFIG_CREDP ++ iee_copy_cred(old,new); + - msr mair_el1, mair - msr tcr_el1, tcr ++ iee_set_cred_non_rcu(new,0); ++ iee_set_cred_atomic_set_usage(new,1); ++ #else + memcpy(new, old, sizeof(struct cred)); -diff --git a/arch/arm64/mm/trans_pgd.c b/arch/arm64/mm/trans_pgd.c -index 5139a28130c0..15d2a3faa048 100644 ---- a/arch/arm64/mm/trans_pgd.c -+++ b/arch/arm64/mm/trans_pgd.c -@@ -25,6 +25,9 @@ - #include - #include - #include -+#ifdef CONFIG_PTP -+#include + new->non_rcu = 0; + atomic_long_set(&new->usage, 1); ++ #endif + get_group_info(new->group_info); + get_uid(new->user); + get_user_ns(new->user_ns); +@@ -232,10 +338,18 @@ struct cred *prepare_creds(void) + #endif + + #ifdef CONFIG_SECURITY ++#ifdef CONFIG_CREDP ++ iee_set_cred_security(new,NULL); ++#else + new->security = NULL; +#endif + #endif - static void *trans_alloc(struct trans_pgd_info *info) - { -@@ -65,10 +68,18 @@ static int copy_pte(struct trans_pgd_info *info, pmd_t *dst_pmdp, - pte_t *src_ptep; - pte_t *dst_ptep; - unsigned long addr = start; -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_ucounts(new, get_ucounts(new->ucounts)); ++ #else + new->ucounts = get_ucounts(new->ucounts); + #endif + if (!new->ucounts) + goto error; - dst_ptep = trans_alloc(info); - if (!dst_ptep) - return -ENOMEM; -+ #ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(dst_ptep)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)dst_ptep); +@@ -265,15 +379,30 @@ struct cred *prepare_exec_creds(void) + #ifdef CONFIG_KEYS + /* newly exec'd tasks don't get a thread keyring */ + key_put(new->thread_keyring); ++ #ifdef CONFIG_CREDP ++ iee_set_cred_thread_keyring(new,NULL); ++ #else + new->thread_keyring = NULL; + #endif - pmd_populate_kernel(NULL, dst_pmdp, dst_ptep); - dst_ptep = pte_offset_kernel(dst_pmdp, start); -@@ -87,11 +98,19 @@ static int copy_pmd(struct trans_pgd_info *info, pud_t *dst_pudp, - pmd_t *dst_pmdp; - unsigned long next; - unsigned long addr = start; -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; + /* inherit the session keyring; new process keyring */ + key_put(new->process_keyring); ++ #ifdef CONFIG_CREDP ++ iee_set_cred_process_keyring(new,NULL); ++ #else + new->process_keyring = NULL; + #endif + #endif - if (pud_none(READ_ONCE(*dst_pudp))) { - dst_pmdp = trans_alloc(info); - if (!dst_pmdp) - return -ENOMEM; -+ #ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(dst_pmdp)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)dst_pmdp); -+ #endif - pud_populate(NULL, dst_pudp, dst_pmdp); - } - dst_pmdp = pmd_offset(dst_pudp, start); -@@ -123,11 +142,19 @@ static int copy_pud(struct trans_pgd_info *info, p4d_t *dst_p4dp, - pud_t *src_pudp; - unsigned long next; - unsigned long addr = start; -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(new,new->euid); ++ iee_set_cred_suid(new,new->euid); ++ iee_set_cred_fsgid(new,new->egid); ++ iee_set_cred_sgid(new,new->egid); ++ #else + new->suid = new->fsuid = new->euid; + new->sgid = new->fsgid = new->egid; + #endif - if (p4d_none(READ_ONCE(*dst_p4dp))) { - dst_pudp = trans_alloc(info); - if (!dst_pudp) - return -ENOMEM; -+ #ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(dst_pudp)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)dst_pudp); + return new; + } +@@ -327,7 +456,11 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) + * had one */ + if (new->thread_keyring) { + key_put(new->thread_keyring); ++ #ifdef CONFIG_CREDP ++ iee_set_cred_thread_keyring(new,NULL); ++ #else + new->thread_keyring = NULL; + #endif - p4d_populate(NULL, dst_p4dp, dst_pudp); + if (clone_flags & CLONE_THREAD) + install_thread_keyring_to_cred(new); } - dst_pudp = pud_offset(dst_p4dp, start); -@@ -212,6 +239,12 @@ int trans_pgd_create_copy(struct trans_pgd_info *info, pgd_t **dst_pgdp, - return -ENOMEM; +@@ -337,7 +470,11 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) + */ + if (!(clone_flags & CLONE_THREAD)) { + key_put(new->process_keyring); ++ #ifdef CONFIG_CREDP ++ iee_set_cred_process_keyring(new,NULL); ++ #else + new->process_keyring = NULL; ++ #endif } + #endif -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr = __phys_to_iee(__pa(trans_pgd)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)trans_pgd); +@@ -594,7 +731,11 @@ int set_cred_ucounts(struct cred *new) + if (!(new_ucounts = alloc_ucounts(new->user_ns, new->uid))) + return -EAGAIN; + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_ucounts(new, new_ucounts); ++ #else + new->ucounts = new_ucounts; + #endif -+ - rc = copy_page_tables(info, trans_pgd, start, end); - if (!rc) - *dst_pgdp = trans_pgd; -@@ -238,6 +271,9 @@ int trans_pgd_idmap_page(struct trans_pgd_info *info, phys_addr_t *trans_ttbr0, - int bits_mapped = PAGE_SHIFT - 4; - unsigned long level_mask, prev_level_entry, *levels[4]; - int this_level, index, level_lsb, level_msb; -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; + put_ucounts(old_ucounts); + + return 0; +@@ -606,8 +747,21 @@ int set_cred_ucounts(struct cred *new) + void __init cred_init(void) + { + /* allocate a slab in which we can store credentials */ ++ #ifdef CONFIG_CREDP + cred_jar = kmem_cache_create("cred_jar", sizeof(struct cred), 0, ++ SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT|SLAB_RED_ZONE, NULL); ++ rcu_jar = kmem_cache_create("rcu_jar", sizeof(struct rcu_head) + sizeof(struct cred *), 0, + SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, NULL); ++ // Map init_cred ++ *((struct rcu_head **)(&(init_cred.rcu.func))) = (struct rcu_head *)kmem_cache_zalloc(rcu_jar, GFP_KERNEL); ++ *(struct cred **)(((struct rcu_head *)(init_cred.rcu.func)) + 1) = &init_cred; ++ set_iee_page_valid(__phys_to_iee(__pa_symbol(&init_cred))); ++ iee_set_logical_mem_ro((unsigned long)&init_cred); ++ iee_set_logical_mem_ro((unsigned long)__va(__pa_symbol(&init_cred))); ++ #else ++ cred_jar = kmem_cache_create("cred_jar", sizeof(struct cred), 0, ++ SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, NULL); + #endif + } - dst_addr &= PAGE_MASK; - prev_level_entry = pte_val(pfn_pte(pfn, PAGE_KERNEL_ROX)); -@@ -247,12 +283,22 @@ int trans_pgd_idmap_page(struct trans_pgd_info *info, phys_addr_t *trans_ttbr0, - if (!levels[this_level]) - return -ENOMEM; + /** +@@ -638,29 +792,56 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) + if (!new) + return NULL; -+ #ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(levels[this_level])); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)levels[this_level]); -+ #endif ++ #ifdef CONFIG_CREDP ++ iee_set_cred_rcu(new,kmem_cache_alloc(rcu_jar, GFP_KERNEL)); ++ *(struct cred **)(((struct rcu_head *)(new->rcu.func)) + 1) = new; ++ #endif + - level_lsb = ARM64_HW_PGTABLE_LEVEL_SHIFT(this_level); - level_msb = min(level_lsb + bits_mapped, max_msb); - level_mask = GENMASK_ULL(level_msb, level_lsb); - - index = (dst_addr & level_mask) >> level_lsb; -+ #ifdef CONFIG_PTP -+ set_pte((pte_t *)(levels[this_level] + index), __pte(prev_level_entry)); -+ #else - *(levels[this_level] + index) = prev_level_entry; -+ #endif + kdebug("prepare_kernel_cred() alloc %p", new); - pfn = virt_to_pfn(levels[this_level]); - prev_level_entry = pte_val(pfn_pte(pfn, -diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c -index 83092d93f36a..fb12e7d0660a 100644 ---- a/drivers/firmware/efi/arm-runtime.c -+++ b/drivers/firmware/efi/arm-runtime.c -@@ -94,7 +94,11 @@ static int __init arm_enable_runtime_services(void) - return 0; - } + old = get_task_cred(daemon); -+ #ifdef CONFIG_PTP -+ efi_memmap_unmap_after_init(); ++ #ifdef CONFIG_CREDP ++ iee_copy_cred(old,new); ++ iee_set_cred_non_rcu(new,0); ++ iee_set_cred_atomic_set_usage(new,1); + #else - efi_memmap_unmap(); + *new = *old; + new->non_rcu = 0; + atomic_long_set(&new->usage, 1); + #endif + get_uid(new->user); + get_user_ns(new->user_ns); + get_group_info(new->group_info); - mapsize = efi.memmap.desc_size * efi.memmap.nr_map; - -diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c -index a1180461a445..4c64b6f15717 100644 ---- a/drivers/firmware/efi/memmap.c -+++ b/drivers/firmware/efi/memmap.c -@@ -105,6 +105,26 @@ void __init efi_memmap_unmap(void) - clear_bit(EFI_MEMMAP, &efi.flags); - } + #ifdef CONFIG_KEYS ++#ifdef CONFIG_CREDP ++ iee_set_cred_session_keyring(new,NULL); ++ iee_set_cred_process_keyring(new,NULL); ++ iee_set_cred_thread_keyring(new,NULL); ++ iee_set_cred_request_key_auth(new,NULL); ++ iee_set_cred_jit_keyring(new,KEY_REQKEY_DEFL_THREAD_KEYRING); ++#else + new->session_keyring = NULL; + new->process_keyring = NULL; + new->thread_keyring = NULL; + new->request_key_auth = NULL; + new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; + #endif ++#endif -+#ifdef CONFIG_PTP -+void __init efi_memmap_unmap_after_init(void) -+{ -+ if (!efi_enabled(EFI_MEMMAP)) -+ return; -+ -+ if (!(efi.memmap.flags & EFI_MEMMAP_LATE)) { -+ unsigned long size; -+ -+ size = efi.memmap.desc_size * efi.memmap.nr_map; -+ early_iounmap_after_init((__force void __iomem *)efi.memmap.map, size); -+ } else { -+ memunmap(efi.memmap.map); -+ } -+ -+ efi.memmap.map = NULL; -+ clear_bit(EFI_MEMMAP, &efi.flags); -+} + #ifdef CONFIG_SECURITY ++#ifdef CONFIG_CREDP ++ iee_set_cred_security(new,NULL); ++#else + new->security = NULL; + #endif +#endif -+ - /** - * efi_memmap_init_late - Map efi.memmap with memremap() - * @phys_addr: Physical address of the new EFI memory map -diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c -index a5fbb6ed38ae..81428783b9da 100644 ---- a/drivers/tty/serial/earlycon.c -+++ b/drivers/tty/serial/earlycon.c -@@ -40,7 +40,11 @@ static void __iomem * __init earlycon_map(resource_size_t paddr, size_t size) - { - void __iomem *base; - #ifdef CONFIG_FIX_EARLYCON_MEM -+ #ifdef CONFIG_PTP -+ __iee_set_fixmap_pre_init(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK, FIXMAP_PAGE_IO); ++ #ifdef CONFIG_CREDP ++ iee_set_cred_ucounts(new, get_ucounts(new->ucounts)); + #else - set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK); + new->ucounts = get_ucounts(new->ucounts); + #endif - base = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); - base += paddr & ~PAGE_MASK; - #else -diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c -index 45b42d8f6453..b71072d6957e 100644 ---- a/drivers/usb/early/ehci-dbgp.c -+++ b/drivers/usb/early/ehci-dbgp.c -@@ -879,7 +879,11 @@ int __init early_dbgp_init(char *s) - * FIXME I don't have the bar size so just guess PAGE_SIZE is more - * than enough. 1K is the biggest I have seen. - */ -+ #ifdef CONFIG_PTP -+ __iee_set_fixmap_pre_init(FIX_DBGP_BASE, bar_val & PAGE_MASK, FIXMAP_PAGE_NOCACHE); + if (!new->ucounts) + goto error; + +@@ -727,8 +908,13 @@ int set_create_files_as(struct cred *new, struct inode *inode) + { + if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid)) + return -EINVAL; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(new,inode->i_uid); ++ iee_set_cred_fsgid(new,inode->i_gid); + #else - set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK); + new->fsuid = inode->i_uid; + new->fsgid = inode->i_gid; + #endif - ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE); - ehci_bar += bar_val & ~PAGE_MASK; - dbgp_printk("ehci_bar: %p\n", ehci_bar); -diff --git a/fs/coredump.c b/fs/coredump.c -index 9d235fa14ab9..72be355903ca 100644 ---- a/fs/coredump.c -+++ b/fs/coredump.c -@@ -53,6 +53,10 @@ + return security_kernel_create_files_as(new, inode); + } + EXPORT_SYMBOL(set_create_files_as); +diff --git a/kernel/exit.c b/kernel/exit.c +index 3540b2c9b1b6..e71d3d9290e9 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -74,6 +74,10 @@ + #include + #include + ++#ifdef CONFIG_IEE ++#include ++#endif ++ + /* + * The default value should be high enough to not crash a system that randomly + * crashes its kernel from time to time, but low enough to at least not permit +@@ -560,6 +564,9 @@ static void exit_mm(void) + smp_mb__after_spinlock(); + local_irq_disable(); + current->mm = NULL; ++ #ifdef CONFIG_IEE ++ iee_set_token_pgd(current, NULL); ++ #endif + membarrier_update_current_mm(NULL); + enter_lazy_tlb(mm, current); + local_irq_enable(); +diff --git a/kernel/fork.c b/kernel/fork.c +index 27d605c64b45..9e01499a25a1 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -115,6 +115,11 @@ + #define CREATE_TRACE_POINTS + #include + ++#ifdef CONFIG_IEE ++#include ++#include ++#endif ++ + /* + * Minimum number of threads to boot the kernel + */ +@@ -128,14 +133,14 @@ + /* + * Protected counters by write_lock_irq(&tasklist_lock) + */ +-unsigned long total_forks; /* Handle normal Linux uptimes. */ +-int nr_threads; /* The idle threads do not count.. */ ++unsigned long total_forks; /* Handle normal Linux uptimes. */ ++int nr_threads; /* The idle threads do not count.. */ + +-static int max_threads; /* tunable limit on nr_threads */ ++static int max_threads; /* tunable limit on nr_threads */ + +-#define NAMED_ARRAY_INDEX(x) [x] = __stringify(x) ++#define NAMED_ARRAY_INDEX(x) [x] = __stringify(x) - #include +-static const char * const resident_page_types[] = { ++static const char *const resident_page_types[] = { + NAMED_ARRAY_INDEX(MM_FILEPAGES), + NAMED_ARRAY_INDEX(MM_ANONPAGES), + NAMED_ARRAY_INDEX(MM_SWAPENTS), +@@ -144,7 +149,7 @@ static const char * const resident_page_types[] = { -+#ifdef CONFIG_CREDP -+#include + DEFINE_PER_CPU(unsigned long, process_counts) = 0; + +-__cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */ ++__cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */ + + #ifdef CONFIG_PROVE_RCU + int lockdep_tasklist_lock_is_held(void) +@@ -159,7 +164,7 @@ int nr_processes(void) + int cpu; + int total = 0; + +- for_each_possible_cpu(cpu) ++ for_each_possible_cpu (cpu) + total += per_cpu(process_counts, cpu); + + return total; +@@ -170,7 +175,11 @@ void __weak arch_release_task_struct(struct task_struct *tsk) + } + + #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR ++#if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++struct kmem_cache *task_struct_cachep; ++#else + static struct kmem_cache *task_struct_cachep; +#endif -+ - static bool dump_vma_snapshot(struct coredump_params *cprm); - static void free_vma_snapshot(struct coredump_params *cprm); -@@ -564,7 +568,11 @@ void do_coredump(const kernel_siginfo_t *siginfo) + static inline struct task_struct *alloc_task_struct_node(int node) + { +@@ -190,7 +199,7 @@ static inline void free_task_struct(struct task_struct *tsk) + * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a + * kmemcache based allocator. + */ +-# if THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK) ++#if THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK) + + # ifdef CONFIG_VMAP_STACK + /* +@@ -311,8 +320,8 @@ static int alloc_thread_stack_node(struct task_struct *tsk, int node) + * so memcg accounting is performed manually on assigning/releasing + * stacks to tasks. Drop __GFP_ACCOUNT. */ - if (__get_dumpable(cprm.mm_flags) == SUID_DUMP_ROOT) { - /* Setuid core dump mode */ -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(cred,GLOBAL_ROOT_UID); -+ #else - cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */ -+ #endif - need_suid_safe = true; - } +- stack = __vmalloc_node_range(THREAD_SIZE, THREAD_ALIGN, +- VMALLOC_START, VMALLOC_END, ++ stack = __vmalloc_node_range(THREAD_SIZE, THREAD_ALIGN, VMALLOC_START, ++ VMALLOC_END, + THREADINFO_GFP & ~__GFP_ACCOUNT, + PAGE_KERNEL, + 0, node, __builtin_return_address(0)); +@@ -410,9 +419,10 @@ static void free_thread_stack(struct task_struct *tsk) -diff --git a/fs/exec.c b/fs/exec.c -index 04fb89656cc3..3689c5f008ba 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -76,6 +76,14 @@ + void thread_stack_cache_init(void) + { +- thread_stack_cache = kmem_cache_create_usercopy("thread_stack", +- THREAD_SIZE, THREAD_SIZE, 0, 0, +- THREAD_SIZE, NULL); ++ thread_stack_cache = ++ kmem_cache_create_usercopy("thread_stack", THREAD_SIZE, ++ THREAD_SIZE, 0, 0, THREAD_SIZE, ++ NULL); + BUG_ON(thread_stack_cache == NULL); + } - #include +@@ -502,7 +512,8 @@ struct vm_area_struct *vm_area_alloc(struct mm_struct *mm) -+#ifdef CONFIG_CREDP -+#include + struct vm_area_struct *vm_area_dup(struct vm_area_struct *orig) + { +- struct vm_area_struct *new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); ++ struct vm_area_struct *new = ++ kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); + + if (!new) + return NULL; +@@ -602,6 +613,10 @@ void put_task_stack(struct task_struct *tsk) + } + #endif + ++#ifdef CONFIG_KOI ++extern s64 koi_offset; +#endif + + void free_task(struct task_struct *tsk) + { + #ifdef CONFIG_SECCOMP +@@ -633,6 +648,21 @@ void free_task(struct task_struct *tsk) + if (dynamic_affinity_enabled()) + sched_prefer_cpus_free(tsk); + #endif +#ifdef CONFIG_IEE -+#include ++ iee_invalidate_token(tsk); ++#ifdef CONFIG_KOI ++ // Free koi stack. ++ unsigned long koi_stack = iee_rw_gate(IEE_READ_KOI_STACK_BASE, tsk); ++ if (koi_stack != 0) ++ free_pages(koi_stack, 2); ++#endif ++#else ++#ifdef CONFIG_KOI ++ struct task_token *token = (struct task_token *)((unsigned long)tsk + koi_offset); ++ memset(token, 0, sizeof(struct task_token)); ++#endif +#endif + - static int bprm_creds_from_file(struct linux_binprm *bprm); - - int suid_dumpable = 0; -@@ -1005,6 +1013,10 @@ static int exec_mmap(struct mm_struct *mm) - if (!IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM)) - local_irq_enable(); - activate_mm(active_mm, mm); -+ #ifdef CONFIG_IEE -+ iee_set_token_mm(tsk, mm); -+ iee_set_token_pgd(tsk, mm->pgd); -+ #endif - if (IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM)) - local_irq_enable(); - lru_gen_add_mm(mm); -@@ -1618,12 +1630,20 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) - - if (mode & S_ISUID) { - bprm->per_clear |= PER_CLEAR_ON_SETID; -+ #ifdef CONFIG_CREDP -+ iee_set_cred_euid(bprm->cred, vfsuid_into_kuid(vfsuid)); -+ #else - bprm->cred->euid = vfsuid_into_kuid(vfsuid); -+ #endif - } + #ifdef CONFIG_QOS_SCHED_SMART_GRID + if (smart_grid_enabled()) + sched_grid_qos_free(tsk); +@@ -657,7 +687,7 @@ static void dup_mm_exe_file(struct mm_struct *mm, struct mm_struct *oldmm) - if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { - bprm->per_clear |= PER_CLEAR_ON_SETID; -+ #ifdef CONFIG_CREDP -+ iee_set_cred_egid(bprm->cred, vfsgid_into_kgid(vfsgid)); -+ #else - bprm->cred->egid = vfsgid_into_kgid(vfsgid); -+ #endif - } + #ifdef CONFIG_MMU + static __latent_entropy int dup_mmap(struct mm_struct *mm, +- struct mm_struct *oldmm) ++ struct mm_struct *oldmm) + { + struct vm_area_struct *mpnt, *tmp; + int retval; +@@ -773,7 +803,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, + flush_dcache_mmap_lock(mapping); + /* insert tmp into the share list, just after mpnt */ + vma_interval_tree_insert_after(tmp, mpnt, +- &mapping->i_mmap); ++ &mapping->i_mmap); + flush_dcache_mmap_unlock(mapping); + i_mmap_unlock_write(mapping); + } +@@ -842,7 +872,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) + mmap_write_unlock(oldmm); + return 0; } +-#define mm_alloc_pgd(mm) (0) ++#define mm_alloc_pgd(mm) (0) + #define mm_free_pgd(mm) + #endif /* CONFIG_MMU */ -diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c -index 3e724cb7ef01..e32e136e4271 100644 ---- a/fs/nfs/flexfilelayout/flexfilelayout.c -+++ b/fs/nfs/flexfilelayout/flexfilelayout.c -@@ -15,6 +15,10 @@ +@@ -850,20 +880,22 @@ static void check_mm(struct mm_struct *mm) + { + int i; - #include +- BUILD_BUG_ON_MSG(ARRAY_SIZE(resident_page_types) != NR_MM_COUNTERS, +- "Please make sure 'struct resident_page_types[]' is updated as well"); ++ BUILD_BUG_ON_MSG( ++ ARRAY_SIZE(resident_page_types) != NR_MM_COUNTERS, ++ "Please make sure 'struct resident_page_types[]' is updated as well"); -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - #include "flexfilelayout.h" - #include "../nfs4session.h" - #include "../nfs4idmap.h" -@@ -502,8 +506,13 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, - rc = -ENOMEM; - if (!kcred) - goto out_err_free; -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(kcred,uid); -+ iee_set_cred_fsgid(kcred,gid); -+ #else - kcred->fsuid = uid; - kcred->fsgid = gid; -+ #endif - cred = RCU_INITIALIZER(kcred); + for (i = 0; i < NR_MM_COUNTERS; i++) { + long x = mm_counter_sum(mm, i); - if (lgr->range.iomode == IOMODE_READ) -diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c -index 25a7c771cfd8..b15ab8e33e0e 100644 ---- a/fs/nfs/nfs4idmap.c -+++ b/fs/nfs/nfs4idmap.c -@@ -48,6 +48,10 @@ - #include - #include + if (unlikely(x)) +- pr_alert("BUG: Bad rss-counter state mm:%p type:%s val:%ld\n", +- mm, resident_page_types[i], x); ++ pr_alert( ++ "BUG: Bad rss-counter state mm:%p type:%s val:%ld\n", ++ mm, resident_page_types[i], x); + } -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - #include "internal.h" - #include "netns.h" - #include "nfs4idmap.h" -@@ -226,8 +230,13 @@ int nfs_idmap_init(void) - goto failed_reg_legacy; + if (mm_pgtables_bytes(mm)) + pr_alert("BUG: non-zero pgtables_bytes on freeing mm: %ld\n", +- mm_pgtables_bytes(mm)); ++ mm_pgtables_bytes(mm)); - set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_thread_keyring(cred,keyring); -+ iee_set_cred_jit_keyring(cred,KEY_REQKEY_DEFL_THREAD_KEYRING); -+ #else - cred->thread_keyring = keyring; - cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; -+ #endif - id_resolver_cache = cred; - return 0; + #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS + VM_BUG_ON_MM(mm->pmd_huge_pte, mm); +@@ -1014,14 +1046,6 @@ void __put_task_struct(struct task_struct *tsk) + } + EXPORT_SYMBOL_GPL(__put_task_struct); -diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c -index e6beaaf4f170..e89385fd81f1 100644 ---- a/fs/nfsd/auth.c -+++ b/fs/nfsd/auth.c -@@ -2,6 +2,9 @@ - /* Copyright (C) 1995, 1996 Olaf Kirch */ +-void __put_task_struct_rcu_cb(struct rcu_head *rhp) +-{ +- struct task_struct *task = container_of(rhp, struct task_struct, rcu); +- +- __put_task_struct(task); +-} +-EXPORT_SYMBOL_GPL(__put_task_struct_rcu_cb); +- + void __init __weak arch_task_cache_init(void) { } - #include -+#ifdef CONFIG_CREDP -+#include -+#endif - #include "nfsd.h" - #include "auth.h" + /* +@@ -1039,8 +1063,8 @@ static void set_max_threads(unsigned int max_threads_suggested) + if (fls64(nr_pages) + fls64(PAGE_SIZE) > 64) + threads = MAX_THREADS; + else +- threads = div64_u64((u64) nr_pages * (u64) PAGE_SIZE, +- (u64) THREAD_SIZE * 8UL); ++ threads = div64_u64((u64)nr_pages * (u64)PAGE_SIZE, ++ (u64)THREAD_SIZE * 8UL); -@@ -32,22 +35,40 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) - if (!new) - return -ENOMEM; + if (threads > max_threads_suggested) + threads = max_threads_suggested; +@@ -1075,17 +1099,24 @@ void __init fork_init(void) + int i; + #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR + #ifndef ARCH_MIN_TASKALIGN +-#define ARCH_MIN_TASKALIGN 0 ++#define ARCH_MIN_TASKALIGN 0 + #endif + int align = max_t(int, L1_CACHE_BYTES, ARCH_MIN_TASKALIGN); + unsigned long useroffset, usersize; -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(new,rqstp->rq_cred.cr_uid); -+ iee_set_cred_fsgid(new,rqstp->rq_cred.cr_gid); + /* create a slab on which task_structs can be allocated */ + task_struct_whitelist(&useroffset, &usersize); ++ #ifdef CONFIG_IEE + task_struct_cachep = kmem_cache_create_usercopy("task_struct", + arch_task_struct_size, align, +- SLAB_PANIC|SLAB_ACCOUNT, ++ SLAB_PANIC|SLAB_ACCOUNT|SLAB_RED_ZONE, + useroffset, usersize, NULL); + #else - new->fsuid = rqstp->rq_cred.cr_uid; - new->fsgid = rqstp->rq_cred.cr_gid; ++ task_struct_cachep = ++ kmem_cache_create_usercopy("task_struct", arch_task_struct_size, ++ align, SLAB_PANIC | SLAB_ACCOUNT, ++ useroffset, usersize, NULL); + #endif + #endif - rqgi = rqstp->rq_cred.cr_group_info; - - if (flags & NFSEXP_ALLSQUASH) { -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(new,exp->ex_anon_uid); -+ iee_set_cred_fsgid(new,exp->ex_anon_gid); -+ #else - new->fsuid = exp->ex_anon_uid; - new->fsgid = exp->ex_anon_gid; -+ #endif - gi = groups_alloc(0); - if (!gi) - goto oom; - } else if (flags & NFSEXP_ROOTSQUASH) { - if (uid_eq(new->fsuid, GLOBAL_ROOT_UID)) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(new,exp->ex_anon_uid); -+ #else - new->fsuid = exp->ex_anon_uid; -+ #endif - if (gid_eq(new->fsgid, GLOBAL_ROOT_GID)) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsgid(new,exp->ex_anon_gid); -+ #else - new->fsgid = exp->ex_anon_gid; -+ #endif - - gi = groups_alloc(rqgi->ngroups); - if (!gi) -@@ -67,18 +88,35 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) - } - - if (uid_eq(new->fsuid, INVALID_UID)) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(new,exp->ex_anon_uid); -+ #else - new->fsuid = exp->ex_anon_uid; -+ #endif - if (gid_eq(new->fsgid, INVALID_GID)) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsgid(new,exp->ex_anon_gid); -+ #else - new->fsgid = exp->ex_anon_gid; -+ #endif + /* do the arch specific task caches init */ +@@ -1093,8 +1124,8 @@ void __init fork_init(void) - set_groups(new, gi); - put_group_info(gi); + set_max_threads(MAX_THREADS); - if (!uid_eq(new->fsuid, GLOBAL_ROOT_UID)) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_effective(new,cap_drop_nfsd_set(new->cap_effective)); -+ #else - new->cap_effective = cap_drop_nfsd_set(new->cap_effective); -+ #endif - else -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_effective(new,cap_raise_nfsd_set(new->cap_effective, -+ new->cap_permitted)); -+ #else - new->cap_effective = cap_raise_nfsd_set(new->cap_effective, - new->cap_permitted); -+ #endif - put_cred(override_creds(new)); - put_cred(new); - return 0; -diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c -index 4039ffcf90ba..6e0dfa01e01e 100644 ---- a/fs/nfsd/nfs4callback.c -+++ b/fs/nfsd/nfs4callback.c -@@ -41,6 +41,9 @@ - #include "trace.h" - #include "xdr4cb.h" - #include "xdr4.h" -+#ifdef CONFIG_CREDP -+#include -+#endif +- init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2; +- init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2; ++ init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads / 2; ++ init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads / 2; + init_task.signal->rlim[RLIMIT_SIGPENDING] = + init_task.signal->rlim[RLIMIT_NPROC]; - #define NFSDDBG_FACILITY NFSDDBG_PROC +@@ -1107,8 +1138,8 @@ void __init fork_init(void) + set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK, RLIM_INFINITY); -@@ -946,8 +949,13 @@ static const struct cred *get_backchannel_cred(struct nfs4_client *clp, struct r - if (!kcred) - return NULL; + #ifdef CONFIG_VMAP_STACK +- cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "fork:vm_stack_cache", +- NULL, free_vm_stack_cache); ++ cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "fork:vm_stack_cache", NULL, ++ free_vm_stack_cache); + #endif -- kcred->fsuid = ses->se_cb_sec.uid; -- kcred->fsgid = ses->se_cb_sec.gid; -+ #ifdef CONFIG_CREDP -+ iee_set_cred_uid(kcred,ses->se_cb_sec.uid); -+ iee_set_cred_gid(kcred,ses->se_cb_sec.gid); -+ #else -+ kcred->uid = ses->se_cb_sec.uid; -+ kcred->gid = ses->se_cb_sec.gid; -+ #endif - return kcred; - } + scs_init(); +@@ -1118,7 +1149,7 @@ void __init fork_init(void) } -diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c -index 3509e73abe1f..798fe0352841 100644 ---- a/fs/nfsd/nfs4recover.c -+++ b/fs/nfsd/nfs4recover.c -@@ -44,6 +44,10 @@ - #include - #include - -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - #include "nfsd.h" - #include "state.h" - #include "vfs.h" -@@ -78,8 +82,13 @@ nfs4_save_creds(const struct cred **original_creds) - if (!new) - return -ENOMEM; -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(new,GLOBAL_ROOT_UID); -+ iee_set_cred_fsgid(new,GLOBAL_ROOT_GID); -+ #else - new->fsuid = GLOBAL_ROOT_UID; - new->fsgid = GLOBAL_ROOT_GID; -+ #endif - *original_creds = override_creds(new); - put_cred(new); + int __weak arch_dup_task_struct(struct task_struct *dst, +- struct task_struct *src) ++ struct task_struct *src) + { + *dst = *src; return 0; -diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c -index 355bf0db3235..6cb276dde4e9 100644 ---- a/fs/nfsd/nfsfh.c -+++ b/fs/nfsd/nfsfh.c -@@ -16,6 +16,10 @@ - #include "auth.h" - #include "trace.h" +@@ -1129,14 +1160,14 @@ void set_task_stack_end_magic(struct task_struct *tsk) + unsigned long *stackend; -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - #define NFSDDBG_FACILITY NFSDDBG_FH + stackend = end_of_stack(tsk); +- *stackend = STACK_END_MAGIC; /* for overflow detection */ ++ *stackend = STACK_END_MAGIC; /* for overflow detection */ + } + static bool dup_resvd_task_struct(struct task_struct *dst, + struct task_struct *orig, int node) + { +- dst->_resvd = kzalloc_node(sizeof(struct task_struct_resvd), +- GFP_KERNEL, node); ++ dst->_resvd = kzalloc_node(sizeof(struct task_struct_resvd), GFP_KERNEL, ++ node); + if (!dst->_resvd) + return false; -@@ -223,9 +227,14 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) - error = nfserrno(-ENOMEM); - goto out; - } -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_effective(new,cap_raise_nfsd_set(new->cap_effective, -+ new->cap_permitted)); -+ #else - new->cap_effective = - cap_raise_nfsd_set(new->cap_effective, - new->cap_permitted); -+ #endif - put_cred(override_creds(new)); - put_cred(new); - } else { -diff --git a/fs/open.c b/fs/open.c -index 54723fceb776..d83901dc50ff 100644 ---- a/fs/open.c -+++ b/fs/open.c -@@ -35,6 +35,11 @@ - #include - #include +@@ -1309,7 +1340,7 @@ static void mm_init_uprobes_state(struct mm_struct *mm) + } -+#ifdef CONFIG_CREDP -+#include -+#endif -+ -+ - #include "internal.h" + static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, +- struct user_namespace *user_ns) ++ struct user_namespace *user_ns) + { + mt_init_flags(&mm->mm_mt, MM_MT_FLAGS); + mt_set_external_lock(&mm->mm_mt, &mm->mmap_lock); +@@ -1426,8 +1457,8 @@ EXPORT_SYMBOL_GPL(mmput); + #ifdef CONFIG_MMU + static void mmput_async_fn(struct work_struct *work) + { +- struct mm_struct *mm = container_of(work, struct mm_struct, +- async_put_work); ++ struct mm_struct *mm = ++ container_of(work, struct mm_struct, async_put_work); - int do_truncate(struct mnt_idmap *idmap, struct dentry *dentry, -@@ -414,17 +419,34 @@ static const struct cred *access_override_creds(void) - * routine. - */ + __mmput(mm); + } +@@ -1603,13 +1634,12 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) + struct mm_struct *mm; + int err; -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(override_cred,override_cred->uid); -+ iee_set_cred_fsgid(override_cred,override_cred->gid); -+ #else - override_cred->fsuid = override_cred->uid; - override_cred->fsgid = override_cred->gid; -+ #endif +- err = down_read_killable(&task->signal->exec_update_lock); ++ err = down_read_killable(&task->signal->exec_update_lock); + if (err) + return ERR_PTR(err); - if (!issecure(SECURE_NO_SETUID_FIXUP)) { - /* Clear the capabilities if we switch to a non-root user */ - kuid_t root_uid = make_kuid(override_cred->user_ns, 0); - if (!uid_eq(override_cred->uid, root_uid)) -+ #ifdef CONFIG_CREDP -+ do { -+ kernel_cap_t tmp_cap = override_cred->cap_effective; -+ tmp_cap.val = 0; -+ iee_set_cred_cap_effective(override_cred, tmp_cap); -+ } while (0); -+ #else - cap_clear(override_cred->cap_effective); -+ #endif - else -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_effective(override_cred,override_cred->cap_permitted); -+ #else - override_cred->cap_effective = - override_cred->cap_permitted; -+ #endif + mm = get_task_mm(task); +- if (mm && mm != current->mm && +- !ptrace_may_access(task, mode)) { ++ if (mm && mm != current->mm && !ptrace_may_access(task, mode)) { + mmput(mm); + mm = ERR_PTR(-EACCES); } +@@ -1632,7 +1662,7 @@ static void complete_vfork_done(struct task_struct *tsk) + } - /* -@@ -444,7 +466,11 @@ static const struct cred *access_override_creds(void) - * expecting RCU freeing. But normal thread-synchronous - * cred accesses will keep things non-RCY. - */ -+ #ifdef CONFIG_CREDP -+ iee_set_cred_non_rcu(override_cred,1); -+ #else - override_cred->non_rcu = 1; -+ #endif + static int wait_for_vfork_done(struct task_struct *child, +- struct completion *vfork) ++ struct completion *vfork) + { + unsigned int state = TASK_UNINTERRUPTIBLE|TASK_KILLABLE|TASK_FREEZABLE; + int killed; +@@ -1683,8 +1713,8 @@ static void mm_release(struct task_struct *tsk, struct mm_struct *mm) + * not set up a proper pointer then tough luck. + */ + put_user(0, tsk->clear_child_tid); +- do_futex(tsk->clear_child_tid, FUTEX_WAKE, +- 1, NULL, NULL, 0, 0); ++ do_futex(tsk->clear_child_tid, FUTEX_WAKE, 1, NULL, ++ NULL, 0, 0); + } + tsk->clear_child_tid = NULL; + } +@@ -1768,6 +1798,9 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) + #endif - old_cred = override_creds(override_cred); + tsk->mm = NULL; ++#ifdef CONFIG_IEE ++ iee_set_token_pgd(tsk, NULL); ++#endif + tsk->active_mm = NULL; -diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c -index 033fc0458a3d..2afa31ead2b5 100644 ---- a/fs/overlayfs/dir.c -+++ b/fs/overlayfs/dir.c -@@ -16,6 +16,10 @@ - #include - #include "overlayfs.h" + /* +@@ -1799,6 +1832,9 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) + } -+#ifdef CONFIG_CREDP -+#include + tsk->mm = mm; ++#ifdef CONFIG_IEE ++ iee_set_token_pgd(tsk, mm->pgd); +#endif -+ - static unsigned short ovl_redirect_max = 256; - module_param_named(redirect_max, ovl_redirect_max, ushort, 0644); - MODULE_PARM_DESC(redirect_max, -@@ -593,8 +597,13 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, - * create a new inode, so just use the ovl mounter's - * fs{u,g}id. - */ -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(override_cred,inode->i_uid); -+ iee_set_cred_fsgid(override_cred,inode->i_gid); -+ #else - override_cred->fsuid = inode->i_uid; - override_cred->fsgid = inode->i_gid; -+ #endif - err = security_dentry_create_files_as(dentry, - attr->mode, &dentry->d_name, old_cred, - override_cred); -diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c -index 2c056d737c27..9ede99ddb04b 100644 ---- a/fs/overlayfs/super.c -+++ b/fs/overlayfs/super.c -@@ -21,6 +21,10 @@ - #include "overlayfs.h" - #include "params.h" + tsk->active_mm = mm; + sched_mm_cid_fork(tsk); + return 0; +@@ -2016,8 +2052,8 @@ static inline void init_task_pid_links(struct task_struct *task) + INIT_HLIST_NODE(&task->pid_links[type]); + } -+#ifdef CONFIG_CREDP -+#include +-static inline void +-init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid) ++static inline void init_task_pid(struct task_struct *task, enum pid_type type, ++ struct pid *pid) + { + if (type == PIDTYPE_PID) + task->thread_pid = pid; +@@ -2278,6 +2314,12 @@ static void copy_oom_score_adj(u64 clone_flags, struct task_struct *tsk) + mutex_unlock(&oom_adj_mutex); + } + ++#if defined(CONFIG_KOI) && !defined(CONFIG_IEE) ++extern s64 koi_offset; ++extern void koi_init_token(struct task_struct *tsk); +#endif + - MODULE_AUTHOR("Miklos Szeredi "); - MODULE_DESCRIPTION("Overlay filesystem"); - MODULE_LICENSE("GPL"); -@@ -1485,7 +1489,15 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc) - sb->s_export_op = &ovl_export_fid_operations; ++ + #ifdef CONFIG_RV + static void rv_task_fork(struct task_struct *p) + { +@@ -2315,10 +2357,12 @@ __latent_entropy struct task_struct *copy_process( + * Don't allow sharing the root directory with processes in a different + * namespace + */ +- if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) ++ if ((clone_flags & (CLONE_NEWNS | CLONE_FS)) == ++ (CLONE_NEWNS | CLONE_FS)) + return ERR_PTR(-EINVAL); - /* Never override disk quota limits or use reserved space */ -+ #ifdef CONFIG_CREDP -+ { -+ kernel_cap_t tmp = cred->cap_effective; -+ cap_lower(tmp, CAP_SYS_RESOURCE); -+ iee_set_cred_cap_effective(cred, tmp); -+ } -+ #else - cap_lower(cred->cap_effective, CAP_SYS_RESOURCE); -+ #endif +- if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS)) ++ if ((clone_flags & (CLONE_NEWUSER | CLONE_FS)) == ++ (CLONE_NEWUSER | CLONE_FS)) + return ERR_PTR(-EINVAL); - sb->s_magic = OVERLAYFS_SUPER_MAGIC; - sb->s_xattr = ofs->config.userxattr ? ovl_user_xattr_handlers : -diff --git a/fs/smb/client/cifs_spnego.c b/fs/smb/client/cifs_spnego.c -index af7849e5974f..4ac2f0e65955 100644 ---- a/fs/smb/client/cifs_spnego.c -+++ b/fs/smb/client/cifs_spnego.c -@@ -18,6 +18,10 @@ - #include "cifs_spnego.h" - #include "cifs_debug.h" - #include "cifsproto.h" -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - static const struct cred *spnego_cred; + /* +@@ -2343,7 +2387,7 @@ __latent_entropy struct task_struct *copy_process( + * from creating siblings. + */ + if ((clone_flags & CLONE_PARENT) && +- current->signal->flags & SIGNAL_UNKILLABLE) ++ current->signal->flags & SIGNAL_UNKILLABLE) + return ERR_PTR(-EINVAL); - /* create a new cifs key */ -@@ -212,8 +216,13 @@ init_cifs_spnego(void) - * the results it looks up + /* +@@ -2388,6 +2432,13 @@ __latent_entropy struct task_struct *copy_process( + p = dup_task_struct(current, node); + if (!p) + goto fork_out; ++#ifdef CONFIG_IEE ++ iee_validate_token(p); ++#else ++#ifdef CONFIG_KOI ++ koi_init_token(p); ++#endif ++#endif + p->flags &= ~PF_KTHREAD; + if (args->kthread) + p->flags |= PF_KTHREAD; +@@ -2409,7 +2460,8 @@ __latent_entropy struct task_struct *copy_process( + /* + * Clear TID on mm_release()? */ - set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_thread_keyring(cred,keyring); -+ iee_set_cred_jit_keyring(cred,KEY_REQKEY_DEFL_THREAD_KEYRING); -+ #else - cred->thread_keyring = keyring; - cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; -+ #endif - spnego_cred = cred; +- p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? args->child_tid : NULL; ++ p->clear_child_tid = ++ (clone_flags & CLONE_CHILD_CLEARTID) ? args->child_tid : NULL; - cifs_dbg(FYI, "cifs spnego keyring: %d\n", key_serial(keyring)); -diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c -index f5b6df82e857..9f0ff045836d 100644 ---- a/fs/smb/client/cifsacl.c -+++ b/fs/smb/client/cifsacl.c -@@ -26,6 +26,10 @@ - #include "cifs_fs_sb.h" - #include "cifs_unicode.h" + ftrace_graph_init_task(p); -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - /* security id for everyone/world system group */ - static const struct cifs_sid sid_everyone = { - 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; -@@ -491,8 +495,13 @@ init_cifs_idmap(void) - /* instruct request_key() to use this special keyring as a cache for - * the results it looks up */ - set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_thread_keyring(cred,keyring); -+ iee_set_cred_jit_keyring(cred,KEY_REQKEY_DEFL_THREAD_KEYRING); -+ #else - cred->thread_keyring = keyring; - cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; -+ #endif - root_cred = cred; +@@ -2520,10 +2572,10 @@ __latent_entropy struct task_struct *copy_process( + #endif + #ifdef CONFIG_TRACE_IRQFLAGS + memset(&p->irqtrace, 0, sizeof(p->irqtrace)); +- p->irqtrace.hardirq_disable_ip = _THIS_IP_; +- p->irqtrace.softirq_enable_ip = _THIS_IP_; +- p->softirqs_enabled = 1; +- p->softirq_context = 0; ++ p->irqtrace.hardirq_disable_ip = _THIS_IP_; ++ p->irqtrace.softirq_enable_ip = _THIS_IP_; ++ p->softirqs_enabled = 1; ++ p->softirq_context = 0; + #endif - cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring)); -diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h -index 9d0479f50f97..f501e0f965f8 100644 ---- a/include/asm-generic/early_ioremap.h -+++ b/include/asm-generic/early_ioremap.h -@@ -17,6 +17,9 @@ extern void *early_memremap_ro(resource_size_t phys_addr, - extern void *early_memremap_prot(resource_size_t phys_addr, - unsigned long size, unsigned long prot_val); - extern void early_iounmap(void __iomem *addr, unsigned long size); -+#ifdef CONFIG_PTP -+extern void early_iounmap_after_init(void __iomem *addr, unsigned long size); -+#endif - extern void early_memunmap(void *addr, unsigned long size); + p->pagefault_disabled = 0; +@@ -2536,8 +2588,8 @@ __latent_entropy struct task_struct *copy_process( + p->blocked_on = NULL; /* not blocked yet */ + #endif + #ifdef CONFIG_BCACHE +- p->sequential_io = 0; +- p->sequential_io_avg = 0; ++ p->sequential_io = 0; ++ p->sequential_io_avg = 0; + #endif + #ifdef CONFIG_BPF_SYSCALL + RCU_INIT_POINTER(p->bpf_storage, NULL); +@@ -2624,7 +2676,7 @@ __latent_entropy struct task_struct *copy_process( + /* + * sigaltstack should be cleared when sharing the same VM + */ +- if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM) ++ if ((clone_flags & (CLONE_VM | CLONE_VFORK)) == CLONE_VM) + sas_ss_reset(p); - #if defined(CONFIG_GENERIC_EARLY_IOREMAP) && defined(CONFIG_MMU) -diff --git a/include/asm-generic/fixmap.h b/include/asm-generic/fixmap.h -index 8cc7b09c1bc7..83158589a545 100644 ---- a/include/asm-generic/fixmap.h -+++ b/include/asm-generic/fixmap.h -@@ -70,6 +70,24 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr) - __set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR) + /* +@@ -2703,7 +2755,7 @@ __latent_entropy struct task_struct *copy_process( + write_lock_irq(&tasklist_lock); + + /* CLONE_PARENT re-uses the old parent */ +- if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) { ++ if (clone_flags & (CLONE_PARENT | CLONE_THREAD)) { + p->real_parent = current->real_parent; + p->parent_exec_id = current->parent_exec_id; + if (clone_flags & CLONE_THREAD) +@@ -2767,8 +2819,9 @@ __latent_entropy struct task_struct *copy_process( + * tasklist_lock with adding child to the process tree + * for propagate_has_child_subreaper optimization. + */ +- p->signal->has_child_subreaper = p->real_parent->signal->has_child_subreaper || +- p->real_parent->signal->is_child_subreaper; ++ p->signal->has_child_subreaper = ++ p->real_parent->signal->has_child_subreaper || ++ p->real_parent->signal->is_child_subreaper; + list_add_tail(&p->sibling, &p->real_parent->children); + list_add_tail_rcu(&p->tasks, &init_task.tasks); + attach_pid(p, PIDTYPE_TGID); +@@ -2919,8 +2972,8 @@ struct task_struct * __init fork_idle(int cpu) + */ + struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node) + { +- unsigned long flags = CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD| +- CLONE_IO; ++ unsigned long flags = CLONE_FS | CLONE_FILES | CLONE_SIGHAND | ++ CLONE_THREAD | CLONE_IO; + struct kernel_clone_args args = { + .flags = ((lower_32_bits(flags) | CLONE_VM | + CLONE_UNTRACED) & ~CSIGNAL), +@@ -3084,8 +3137,8 @@ SYSCALL_DEFINE0(fork) + SYSCALL_DEFINE0(vfork) + { + struct kernel_clone_args args = { +- .flags = CLONE_VFORK | CLONE_VM, +- .exit_signal = SIGCHLD, ++ .flags = CLONE_VFORK | CLONE_VM, ++ .exit_signal = SIGCHLD, + }; + + return kernel_clone(&args); +@@ -3095,35 +3148,30 @@ SYSCALL_DEFINE0(vfork) + #ifdef __ARCH_WANT_SYS_CLONE + #ifdef CONFIG_CLONE_BACKWARDS + SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, +- int __user *, parent_tidptr, +- unsigned long, tls, +- int __user *, child_tidptr) ++ int __user *, parent_tidptr, unsigned long, tls, int __user *, ++ child_tidptr) + #elif defined(CONFIG_CLONE_BACKWARDS2) + SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags, +- int __user *, parent_tidptr, +- int __user *, child_tidptr, +- unsigned long, tls) +-#elif defined(CONFIG_CLONE_BACKWARDS3) +-SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp, +- int, stack_size, +- int __user *, parent_tidptr, +- int __user *, child_tidptr, ++ int __user *, parent_tidptr, int __user *, child_tidptr, + unsigned long, tls) ++#elif defined(CONFIG_CLONE_BACKWARDS3) ++SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp, int, ++ stack_size, int __user *, parent_tidptr, int __user *, ++ child_tidptr, unsigned long, tls) + #else + SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, +- int __user *, parent_tidptr, +- int __user *, child_tidptr, +- unsigned long, tls) ++ int __user *, parent_tidptr, int __user *, child_tidptr, ++ unsigned long, tls) #endif + { + struct kernel_clone_args args = { +- .flags = (lower_32_bits(clone_flags) & ~CSIGNAL), +- .pidfd = parent_tidptr, +- .child_tid = child_tidptr, +- .parent_tid = parent_tidptr, +- .exit_signal = (lower_32_bits(clone_flags) & CSIGNAL), +- .stack = newsp, +- .tls = tls, ++ .flags = (lower_32_bits(clone_flags) & ~CSIGNAL), ++ .pidfd = parent_tidptr, ++ .child_tid = child_tidptr, ++ .parent_tid = parent_tidptr, ++ .exit_signal = (lower_32_bits(clone_flags) & CSIGNAL), ++ .stack = newsp, ++ .tls = tls, + }; -+#ifdef CONFIG_PTP -+#ifndef clear_fixmap_init -+#define clear_fixmap_init(idx) \ -+ __iee_set_fixmap_pre_init(idx, 0, FIXMAP_PAGE_CLEAR) -+#endif -+ -+#define __iee_set_fixmap_offset_pre_init(idx, phys, flags) \ -+({ \ -+ unsigned long ________addr; \ -+ __iee_set_fixmap_pre_init(idx, phys, flags); \ -+ ________addr = fix_to_virt(idx) + ((phys) & (PAGE_SIZE - 1)); \ -+ ________addr; \ -+}) -+ -+#define iee_set_fixmap_offset_pre_init(idx, phys) \ -+ __iee_set_fixmap_offset_pre_init(idx, phys, FIXMAP_PAGE_NORMAL) -+#endif -+ - /* Return a pointer with offset calculated */ - #define __set_fixmap_offset(idx, phys, flags) \ - ({ \ -diff --git a/include/asm-generic/pgalloc.h b/include/asm-generic/pgalloc.h -index c75d4a753849..506ff9662e02 100644 ---- a/include/asm-generic/pgalloc.h -+++ b/include/asm-generic/pgalloc.h -@@ -7,6 +7,10 @@ - #define GFP_PGTABLE_KERNEL (GFP_KERNEL | __GFP_ZERO) - #define GFP_PGTABLE_USER (GFP_PGTABLE_KERNEL | __GFP_ACCOUNT) + return kernel_clone(&args); +@@ -3179,21 +3227,21 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, + return -EINVAL; -+#ifdef CONFIG_PTP -+#include -+#endif -+ - /** - * __pte_alloc_one_kernel - allocate memory for a PTE-level kernel page table - * @mm: the mm_struct of the current context -@@ -23,6 +27,13 @@ static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm) + *kargs = (struct kernel_clone_args){ +- .flags = args.flags, +- .pidfd = u64_to_user_ptr(args.pidfd), +- .child_tid = u64_to_user_ptr(args.child_tid), +- .parent_tid = u64_to_user_ptr(args.parent_tid), +- .exit_signal = args.exit_signal, +- .stack = args.stack, +- .stack_size = args.stack_size, +- .tls = args.tls, +- .set_tid_size = args.set_tid_size, +- .cgroup = args.cgroup, ++ .flags = args.flags, ++ .pidfd = u64_to_user_ptr(args.pidfd), ++ .child_tid = u64_to_user_ptr(args.child_tid), ++ .parent_tid = u64_to_user_ptr(args.parent_tid), ++ .exit_signal = args.exit_signal, ++ .stack = args.stack, ++ .stack_size = args.stack_size, ++ .tls = args.tls, ++ .set_tid_size = args.set_tid_size, ++ .cgroup = args.cgroup, + }; - if (!ptdesc) - return NULL; -+ -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr = __phys_to_iee(__pa(ptdesc_address(ptdesc))); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)ptdesc_address(ptdesc)); -+ #endif -+ - return ptdesc_address(ptdesc); - } + if (args.set_tid && +- copy_from_user(kset_tid, u64_to_user_ptr(args.set_tid), +- (kargs->set_tid_size * sizeof(pid_t)))) ++ copy_from_user(kset_tid, u64_to_user_ptr(args.set_tid), ++ (kargs->set_tid_size * sizeof(pid_t)))) + return -EFAULT; -@@ -46,6 +57,11 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm) - */ - static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) - { -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr = __phys_to_iee(__pa(pte)); -+ set_iee_page_invalid(iee_addr); -+ iee_set_logical_mem_rw((unsigned long)pte); -+ #endif - pagetable_free(virt_to_ptdesc(pte)); + kargs->set_tid = kset_tid; +@@ -3288,7 +3336,8 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size) } + #endif -@@ -73,6 +89,13 @@ static inline pgtable_t __pte_alloc_one(struct mm_struct *mm, gfp_t gfp) - return NULL; +-void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data) ++void walk_process_tree(struct task_struct *top, proc_visitor visitor, ++ void *data) + { + struct task_struct *leader, *parent, *child; + int res; +@@ -3296,8 +3345,8 @@ void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data + read_lock(&tasklist_lock); + leader = top = top->group_leader; + down: +- for_each_thread(leader, parent) { +- list_for_each_entry(child, &parent->children, sibling) { ++ for_each_thread (leader, parent) { ++ list_for_each_entry (child, &parent->children, sibling) { + res = visitor(child, data); + if (res) { + if (res < 0) +@@ -3305,8 +3354,7 @@ void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data + leader = child; + goto down; + } +-up: +- ; ++ up:; + } } -+ #ifdef CONFIG_PTP -+ pte_t *pte = (pte_t *)page_address(ptdesc_page(ptdesc)); -+ unsigned long iee_addr = __phys_to_iee(__pa(pte)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)pte); -+ #endif -+ - return ptdesc_page(ptdesc); +@@ -3383,11 +3431,11 @@ void __init proc_caches_init(void) + */ + static int check_unshare_flags(unsigned long unshare_flags) + { +- if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| +- CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| +- CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET| +- CLONE_NEWUSER|CLONE_NEWPID|CLONE_NEWCGROUP| +- CLONE_NEWTIME)) ++ if (unshare_flags & ++ ~(CLONE_THREAD | CLONE_FS | CLONE_NEWNS | CLONE_SIGHAND | CLONE_VM | ++ CLONE_FILES | CLONE_SYSVSEM | CLONE_NEWUTS | CLONE_NEWIPC | ++ CLONE_NEWNET | CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWCGROUP | ++ CLONE_NEWTIME)) + return -EINVAL; + /* + * Not implemented, but pretend it works if there is nothing +@@ -3498,7 +3546,7 @@ int ksys_unshare(unsigned long unshare_flags) + * to a new ipc namespace, the semaphore arrays from the old + * namespace are unreachable. + */ +- if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM)) ++ if (unshare_flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) + do_sysvsem = 1; + err = unshare_fs(unshare_flags, &new_fs); + if (err) +@@ -3509,8 +3557,8 @@ int ksys_unshare(unsigned long unshare_flags) + err = unshare_userns(unshare_flags, &new_cred); + if (err) + goto bad_unshare_cleanup_fd; +- err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, +- new_cred, new_fs); ++ err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, new_cred, ++ new_fs); + if (err) + goto bad_unshare_cleanup_cred; + +@@ -3607,8 +3655,8 @@ int unshare_files(void) + return 0; } -@@ -103,9 +126,20 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm) - */ - static inline void pte_free(struct mm_struct *mm, struct page *pte_page) +-int sysctl_max_threads(struct ctl_table *table, int write, +- void *buffer, size_t *lenp, loff_t *ppos) ++int sysctl_max_threads(struct ctl_table *table, int write, void *buffer, ++ size_t *lenp, loff_t *ppos) + { + struct ctl_table t; + int ret; +diff --git a/kernel/groups.c b/kernel/groups.c +index 9b43da22647d..8045812e8a3c 100644 +--- a/kernel/groups.c ++++ b/kernel/groups.c +@@ -11,6 +11,9 @@ + #include + #include + #include ++#ifdef CONFIG_CREDP ++#include ++#endif + + struct group_info *groups_alloc(int gidsetsize) { -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; -+ #endif -+ - struct ptdesc *ptdesc = page_ptdesc(pte_page); - - pagetable_pte_dtor(ptdesc); -+ -+ #ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(page_address(pte_page))); -+ set_iee_page_invalid(iee_addr); -+ iee_set_logical_mem_rw((unsigned long)page_address(pte_page)); +@@ -119,7 +122,11 @@ void set_groups(struct cred *new, struct group_info *group_info) + { + put_group_info(new->group_info); + get_group_info(group_info); ++ #ifdef CONFIG_CREDP ++ iee_set_cred_group_info(new,group_info); ++ #else + new->group_info = group_info; + #endif -+ - pagetable_free(ptdesc); } -@@ -145,10 +179,21 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) - #ifndef __HAVE_ARCH_PMD_FREE - static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) - { -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; -+ #endif -+ - struct ptdesc *ptdesc = virt_to_ptdesc(pmd); + EXPORT_SYMBOL(set_groups); +diff --git a/kernel/kthread.c b/kernel/kthread.c +index ac03bc55e17c..07d936afe9e4 100644 +--- a/kernel/kthread.c ++++ b/kernel/kthread.c +@@ -30,6 +30,10 @@ + #include + #include - BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); - pagetable_pmd_dtor(ptdesc); -+ -+ #ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(pmd)); -+ set_iee_page_invalid(iee_addr); -+ iee_set_logical_mem_rw((unsigned long)pmd); -+ #endif ++#ifdef CONFIG_IEE ++#include ++#endif + - pagetable_free(ptdesc); - } - #endif -@@ -190,7 +235,16 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) - static inline void __pud_free(struct mm_struct *mm, pud_t *pud) - { -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; + static DEFINE_SPINLOCK(kthread_create_lock); + static LIST_HEAD(kthread_create_list); +@@ -1455,6 +1459,9 @@ void kthread_use_mm(struct mm_struct *mm) + tsk->active_mm = mm; + tsk->mm = mm; + membarrier_update_current_mm(mm); ++ #ifdef CONFIG_IEE ++ iee_set_token_pgd(tsk, mm->pgd); + #endif -+ - BUG_ON((unsigned long)pud & (PAGE_SIZE-1)); -+ #ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(pud)); -+ set_iee_page_invalid(iee_addr); -+ iee_set_logical_mem_rw((unsigned long)pud); + switch_mm_irqs_off(active_mm, mm, tsk); + local_irq_enable(); + task_unlock(tsk); +@@ -1499,7 +1506,11 @@ void kthread_unuse_mm(struct mm_struct *mm) + local_irq_disable(); + tsk->mm = NULL; + membarrier_update_current_mm(NULL); ++ #ifdef CONFIG_IEE ++ iee_set_token_pgd(tsk, NULL); + #endif - pagetable_free(virt_to_ptdesc(pud)); - } - -diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h -index 200853042fc7..9d733afced53 100644 ---- a/include/asm-generic/vmlinux.lds.h -+++ b/include/asm-generic/vmlinux.lds.h -@@ -346,6 +346,17 @@ - KEEP(*(.dtb.init.rodata)) \ - __dtb_end = .; + mmgrab_lazy_tlb(mm); ++ + /* active_mm is still 'mm' */ + enter_lazy_tlb(mm, tsk); + local_irq_enable(); +diff --git a/kernel/module/main.c b/kernel/module/main.c +index 14a51af2fbea..f810f005d90a 100644 +--- a/kernel/module/main.c ++++ b/kernel/module/main.c +@@ -63,6 +63,10 @@ + #define CREATE_TRACE_POINTS + #include +#ifdef CONFIG_KOI -+#define KOI_DATA() \ -+ . = ALIGN(PAGE_SIZE); \ -+ __koi_data_start = .; \ -+ *(.data..koi) \ -+ . = ALIGN(PAGE_SIZE); \ -+ __koi_data_end = .; -+#else -+#define KOI_DATA() ++#include "asm/koi.h" +#endif + /* - * .data section - */ -@@ -370,8 +381,8 @@ - BRANCH_PROFILE() \ - TRACE_PRINTKS() \ - BPF_RAW_TP() \ -- TRACEPOINT_STR() + * Mutex protects: + * 1) List of modules (also safely readable with preempt_disable), +@@ -769,7 +773,11 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, + /* Store the name and taints of the last unloaded module for diagnostic purposes */ + strscpy(last_unloaded_module.name, mod->name, sizeof(last_unloaded_module.name)); + strscpy(last_unloaded_module.taints, module_flags(mod, buf, false), sizeof(last_unloaded_module.taints)); - -+ TRACEPOINT_STR() \ -+ KOI_DATA() - /* - * Data section helpers - */ -@@ -1093,6 +1104,14 @@ - * They will fit only a subset of the architectures - */ - -+#ifdef CONFIG_CREDP -+ #define CRED_DATA \ -+ . = ALIGN(PAGE_SIZE); \ -+ *(.iee.cred) \ -+ . = ALIGN(PAGE_SIZE); -+#else -+ #define CRED_DATA ++#ifdef CONFIG_KOI ++ koi_destroy_pagetable(mod); ++ ++ printk(KERN_ERR "pagetable destroyed\n"); +#endif - - /* - * Writeable data. -@@ -1110,6 +1129,7 @@ - . = ALIGN(PAGE_SIZE); \ - .data : AT(ADDR(.data) - LOAD_OFFSET) { \ - INIT_TASK_DATA(inittask) \ -+ CRED_DATA \ - NOSAVE_DATA \ - PAGE_ALIGNED_DATA(pagealigned) \ - CACHELINE_ALIGNED_DATA(cacheline) \ -diff --git a/include/linux/cred.h b/include/linux/cred.h -index e01c6d094a30..cceb4842b619 100644 ---- a/include/linux/cred.h -+++ b/include/linux/cred.h -@@ -18,6 +18,10 @@ - #include - #include - -+#ifdef CONFIG_CREDP -+#include + free_module(mod); + /* someone could wait for the module in add_unformed_module() */ + wake_up_all(&module_wq); +@@ -2590,6 +2598,11 @@ static noinline int do_init_module(struct module *mod) + module_enable_ro(mod, true); + mod_tree_remove_init(mod); + module_arch_freeing_init(mod); ++#ifdef CONFIG_KOI ++ for_class_mod_mem_type(type, init) { ++ koi_unmap_mem(mod, (unsigned long)mod->mem[type].base, mod->mem[type].size); ++ } +#endif -+ - struct cred; - struct inode; + for_class_mod_mem_type(type, init) { + mod->mem[type].base = NULL; + mod->mem[type].size = 0; +@@ -2636,6 +2649,11 @@ static noinline int do_init_module(struct module *mod) + MODULE_STATE_GOING, mod); + klp_module_going(mod); + ftrace_release_mod(mod); ++#ifdef CONFIG_KOI ++ koi_destroy_pagetable(mod); ++ ++ printk(KERN_ERR "[KOI] pagetable for module: %s destroyed\n", mod->name); ++#endif + free_module(mod); + wake_up_all(&module_wq); -@@ -153,6 +157,22 @@ struct cred { - KABI_RESERVE(4) - } __randomize_layout; +@@ -2840,6 +2858,32 @@ static int early_mod_check(struct load_info *info, int flags) + return err; + } -+#ifdef CONFIG_CREDP -+extern unsigned long long iee_rw_gate(int flag, ...); -+static void iee_set_cred_non_rcu(struct cred *cred, int non_rcu) ++#ifdef CONFIG_KOI ++void shared_variable_dfs(struct mm_struct *ko_mm, pgd_t *ko_pg_dir, struct shared_variable_descriptor *desc, unsigned int *get_val_id, unsigned int *from_id_get_ad, unsigned int i, unsigned long addr) +{ -+ iee_rw_gate(IEE_OP_SET_CRED_NON_RCU,cred,non_rcu); -+ *(int *)(&(((struct rcu_head *)(cred->rcu.func))->next)) = non_rcu; ++ unsigned int j; ++ unsigned int new_desc_num; ++ unsigned long *ptr; ++ for(j=0; iasync_probe_requested = async_probe; ++#ifdef CONFIG_KOI ++ /* ++ * find the shared_vars_section and get the shared var list ++ */ ++ ndx = find_sec(info, ".shared_vars_section"); ++ if (ndx){ ++ koi_create_pagetable(mod); ++ target = NULL; ++ rcu_read_lock(); ++ hash_for_each_possible_rcu (koi_mem_htbl, target, node, ++ (unsigned long)mod) { ++ if (target->mod == mod) { ++ break; ++ } ++ } ++ rcu_read_unlock(); + ++ if (target == NULL) { ++ printk("[Error] shared_vars_section detected, But mem node for module: %s not found\n", mod->name); ++ koi_destroy_pagetable(mod); ++ goto bug_cleanup; ++ } + - extern void __put_cred(struct cred *); - extern void exit_creds(struct task_struct *); - extern int copy_creds(struct task_struct *, unsigned long); -@@ -189,7 +209,11 @@ static inline bool cap_ambient_invariant_ok(const struct cred *cred) - */ - static inline struct cred *get_new_cred_many(struct cred *cred, int nr) - { -+ #ifdef CONFIG_CREDP -+ iee_set_cred_atomic_op_usage(cred, AT_ADD, nr); -+ #else - atomic_long_add(nr, &cred->usage); -+ #endif - return cred; - } ++ ko_mm = target->ko_mm; ++ ko_pg_dir = target->pgdp; ++ ++ desc = (struct shared_variable_descriptor *)info->sechdrs[ndx].sh_addr; ++ ++ num_desc = info->sechdrs[ndx].sh_size / sizeof(struct shared_variable_descriptor); ++ get_val_id = kmalloc(DRIVER_ISOLATION_MAX_VAL, GFP_KERNEL); ++ from_id_get_ad = kmalloc(DRIVER_ISOLATION_MAX_VAL, GFP_KERNEL); ++ ++ for (j = 0; j < num_desc; j++) { ++ unsigned int desc_id = desc[j].id; ++ get_val_id[j] = desc_id; ++ from_id_get_ad[desc_id] = j; ++ } ++ ++ for (i = 0; i < num_desc; i++) { ++ if (desc[i].type == 0) { ++ addr = kallsyms_lookup_name(desc[i].name); ++ koi_copy_pagetable(ko_mm, ko_pg_dir, addr & PAGE_MASK, (addr + desc[i].size + PAGE_SIZE) & PAGE_MASK, 0); ++ shared_variable_dfs(ko_mm, ko_pg_dir, desc, get_val_id, from_id_get_ad, i, addr); ++ } ++ } ++ kfree(get_val_id); ++ kfree(from_id_get_ad); ++ } ++#endif + /* Module is ready to execute: parsing args may do that. */ + after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, + -32768, 32767, mod, +diff --git a/kernel/sys.c b/kernel/sys.c +index 44b575990333..fbc47f83af50 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -75,6 +75,10 @@ + #include + #include -@@ -202,7 +226,7 @@ static inline struct cred *get_new_cred_many(struct cred *cred, int nr) - */ - static inline struct cred *get_new_cred(struct cred *cred) - { -- return get_new_cred_many(cred, 1); -+ return get_new_cred_many(cred, 1); // XXXzgc atomic_inc -> get_new_cred_many - } ++#ifdef CONFIG_CREDP ++#include ++#endif ++ + #include "uid16.h" - /** -@@ -224,7 +248,11 @@ static inline const struct cred *get_cred_many(const struct cred *cred, int nr) - struct cred *nonconst_cred = (struct cred *) cred; - if (!cred) - return cred; -+ #ifdef CONFIG_CREDP -+ iee_set_cred_non_rcu(nonconst_cred,0); -+ #else - nonconst_cred->non_rcu = 0; -+ #endif - return get_new_cred_many(nonconst_cred, nr); - } + #ifndef SET_UNALIGN_CTL +@@ -395,7 +399,11 @@ long __sys_setregid(gid_t rgid, gid_t egid) + if (gid_eq(old->gid, krgid) || + gid_eq(old->egid, krgid) || + ns_capable_setid(old->user_ns, CAP_SETGID)) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_gid(new,krgid); ++ #else + new->gid = krgid; ++ #endif + else + goto error; + } +@@ -404,15 +412,27 @@ long __sys_setregid(gid_t rgid, gid_t egid) + gid_eq(old->egid, kegid) || + gid_eq(old->sgid, kegid) || + ns_capable_setid(old->user_ns, CAP_SETGID)) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_egid(new,kegid); ++ #else + new->egid = kegid; ++ #endif + else + goto error; + } -@@ -247,9 +275,19 @@ static inline const struct cred *get_cred_rcu(const struct cred *cred) - struct cred *nonconst_cred = (struct cred *) cred; - if (!cred) - return NULL; + if (rgid != (gid_t) -1 || + (egid != (gid_t) -1 && !gid_eq(kegid, old->gid))) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_sgid(new,new->egid); ++ #else + new->sgid = new->egid; ++ #endif + #ifdef CONFIG_CREDP -+ if (!iee_set_cred_atomic_op_usage(nonconst_cred,AT_INC_NOT_ZERO,0)) -+ return NULL; ++ iee_set_cred_fsgid(new,new->egid); + #else - if (!atomic_long_inc_not_zero(&nonconst_cred->usage)) - return NULL; + new->fsgid = new->egid; + #endif -+ + + retval = security_task_fix_setgid(new, old, LSM_SETID_RE); + if (retval < 0) +@@ -454,9 +474,25 @@ long __sys_setgid(gid_t gid) + + retval = -EPERM; + if (ns_capable_setid(old->user_ns, CAP_SETGID)) ++ #ifdef CONFIG_CREDP ++ { ++ iee_set_cred_fsgid(new,kgid); ++ iee_set_cred_sgid(new,kgid); ++ iee_set_cred_egid(new,kgid); ++ iee_set_cred_gid(new,kgid); ++ } ++ #else + new->gid = new->egid = new->sgid = new->fsgid = kgid; ++ #endif + else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid)) ++ #ifdef CONFIG_CREDP ++ { ++ iee_set_cred_fsgid(new,kgid); ++ iee_set_cred_egid(new,kgid); ++ } ++ #else + new->egid = new->fsgid = kgid; ++ #endif + else + goto error; + +@@ -488,7 +524,11 @@ static int set_user(struct cred *new) + return -EAGAIN; + + free_uid(new->user); + #ifdef CONFIG_CREDP -+ iee_set_cred_non_rcu(nonconst_cred,0); ++ iee_set_cred_user(new,new_user); + #else - nonconst_cred->non_rcu = 0; + new->user = new_user; + #endif - return cred; + return 0; } -@@ -270,8 +308,13 @@ static inline void put_cred_many(const struct cred *_cred, int nr) - struct cred *cred = (struct cred *) _cred; +@@ -549,7 +589,11 @@ long __sys_setreuid(uid_t ruid, uid_t euid) - if (cred) { + retval = -EPERM; + if (ruid != (uid_t) -1) { + #ifdef CONFIG_CREDP -+ if (iee_set_cred_atomic_op_usage(cred,AT_SUB_AND_TEST,nr)) -+ __put_cred(cred); ++ iee_set_cred_uid(new,kruid); + #else - if (atomic_long_sub_and_test(nr, &cred->usage)) - __put_cred(cred); + new->uid = kruid; + #endif + if (!uid_eq(old->uid, kruid) && + !uid_eq(old->euid, kruid) && + !ns_capable_setid(old->user_ns, CAP_SETUID)) +@@ -557,7 +601,11 @@ long __sys_setreuid(uid_t ruid, uid_t euid) } - } - -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 9ed79128458c..970cc4f7068b 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -740,6 +740,15 @@ extern int __init __efi_memmap_init(struct efi_memory_map_data *data); - extern int __init efi_memmap_init_early(struct efi_memory_map_data *data); - extern int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size); - extern void __init efi_memmap_unmap(void); -+#ifdef CONFIG_PTP -+extern void __init efi_memmap_unmap_after_init(void); -+#endif -+extern int __init efi_memmap_install(struct efi_memory_map_data *data); -+extern int __init efi_memmap_split_count(efi_memory_desc_t *md, -+ struct range *range); -+extern void __init efi_memmap_insert(struct efi_memory_map *old_memmap, -+ void *buf, struct efi_mem_range *mem); -+extern void __init efi_print_memmap(void); - - #ifdef CONFIG_EFI_ESRT - extern void __init efi_esrt_init(void); -diff --git a/include/linux/iee-func.h b/include/linux/iee-func.h -new file mode 100644 -index 000000000000..79171de67c2a ---- /dev/null -+++ b/include/linux/iee-func.h -@@ -0,0 +1,27 @@ -+#ifndef _LINUX_IEE_FUNC_H -+#define _LINUX_IEE_FUNC_H -+ -+#ifdef CONFIG_IEE -+// Declare the __entry_task. -+__attribute__((aligned(PAGE_SIZE))) DECLARE_PER_CPU(struct task_struct *[PAGE_SIZE/sizeof(struct task_struct *)], __entry_task); -+ -+extern unsigned long long iee_rw_gate(int flag, ...); -+extern u32 get_cpu_asid_bits(void); -+extern unsigned long arm64_mm_context_get(struct mm_struct *mm); -+extern void set_iee_page_valid(unsigned long addr); -+extern void set_iee_page_invalid(unsigned long addr); -+extern void iee_set_logical_mem_ro(unsigned long addr); -+extern void iee_set_logical_mem_rw(unsigned long addr); -+extern void iee_set_token_mm(struct task_struct *tsk, struct mm_struct *mm); -+extern void iee_set_token_pgd(struct task_struct *tsk, pgd_t *pgd); -+extern void iee_init_token(struct task_struct *tsk, void *kernel_stack, void *iee_stack); -+extern void iee_free_token(struct task_struct *tsk); -+extern unsigned long iee_read_token_stack(struct task_struct *tsk); -+extern void iee_set_token_page_valid(void *token, void *new); -+extern void iee_set_token_page_invalid(void *token); -+extern void iee_set_kernel_ppage(unsigned long addr); -+extern void iee_set_kernel_upage(unsigned long addr); -+extern void iee_write_in_byte(void *ptr, u64 data, int length); -+#endif -+ -+#endif -\ No newline at end of file -diff --git a/include/linux/module.h b/include/linux/module.h -index 4db2878d9e42..ef8d51994017 100644 ---- a/include/linux/module.h -+++ b/include/linux/module.h -@@ -606,6 +606,7 @@ struct module { - KABI_RESERVE(2) - KABI_RESERVE(3) - KABI_RESERVE(4) -+ - } ____cacheline_aligned __randomize_layout; - #ifndef MODULE_ARCH_INIT - #define MODULE_ARCH_INIT {} -diff --git a/include/linux/sched.h b/include/linux/sched.h -index f40411aa7b70..297becfbc8e3 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -773,6 +773,24 @@ struct task_struct_resvd { - struct task_struct *task; - }; -+#if defined(CONFIG_IEE) || defined(CONFIG_KOI) -+struct task_token { -+#ifdef CONFIG_IEE -+ struct mm_struct *mm; /* VA */ -+ pgd_t *pgd; /* Logical VA */ -+ void *iee_stack; /* VA */ -+ bool valid; -+ void *kernel_stack; /* VA */ -+#endif -+#ifdef CONFIG_KOI -+ void *koi_kernel_stack; /* VA */ -+ void *koi_stack; /* VA */ -+ void *koi_stack_base; /* VA */ -+ unsigned long current_ttbr1; -+#endif -+}; -+#endif -+ - struct task_struct { - #ifdef CONFIG_THREAD_INFO_IN_TASK - /* -@@ -795,6 +813,7 @@ struct task_struct { - randomized_struct_fields_start - - void *stack; -+ - refcount_t usage; - /* Per task flags (PF_*), defined further below: */ - unsigned int flags; -diff --git a/init/main.c b/init/main.c -index 803332dd3d90..0f8d6e2744c2 100644 ---- a/init/main.c -+++ b/init/main.c -@@ -102,6 +102,12 @@ - #include - #include - -+#ifdef CONFIG_IEE -+#include -+#include -+#include -+#endif -+ - #include - #include - #include -@@ -112,6 +118,10 @@ + if (euid != (uid_t) -1) { ++ #ifdef CONFIG_CREDP ++ iee_set_cred_euid(new,keuid); ++ #else + new->euid = keuid; ++ #endif + if (!uid_eq(old->uid, keuid) && + !uid_eq(old->euid, keuid) && + !uid_eq(old->suid, keuid) && +@@ -572,8 +620,16 @@ long __sys_setreuid(uid_t ruid, uid_t euid) + } + if (ruid != (uid_t) -1 || + (euid != (uid_t) -1 && !uid_eq(keuid, old->uid))) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_suid(new,new->euid); ++ #else + new->suid = new->euid; ++ #endif ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(new,new->euid); ++ #else + new->fsuid = new->euid; ++ #endif - #include + retval = security_task_fix_setuid(new, old, LSM_SETID_RE); + if (retval < 0) +@@ -626,7 +682,12 @@ long __sys_setuid(uid_t uid) -+#ifdef CONFIG_PTP -+extern void *bm_pte_addr; -+#endif -+ - static int kernel_init(void *); + retval = -EPERM; + if (ns_capable_setid(old->user_ns, CAP_SETUID)) { ++ #ifdef CONFIG_CREDP ++ iee_set_cred_uid(new,kuid); ++ iee_set_cred_suid(new,kuid); ++ #else + new->suid = new->uid = kuid; ++ #endif + if (!uid_eq(kuid, old->uid)) { + retval = set_user(new); + if (retval < 0) +@@ -636,7 +697,12 @@ long __sys_setuid(uid_t uid) + goto error; + } - /* -@@ -880,6 +890,9 @@ void start_kernel(void) - { - char *command_line; - char *after_dashes; -+ #ifdef CONFIG_IEE -+ unsigned int cpu; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_euid(new,kuid); ++ iee_set_cred_fsuid(new,kuid); ++ #else + new->fsuid = new->euid = kuid; + #endif - set_task_stack_end_magic(&init_task); - smp_setup_processor_id(); -@@ -904,6 +917,16 @@ void start_kernel(void) - setup_command_line(command_line); - setup_nr_cpu_ids(); - setup_per_cpu_areas(); -+ #ifdef CONFIG_IEE -+ for_each_possible_cpu(cpu) -+ { -+ // Map the __entry_task to IEE. -+ set_iee_page_valid((unsigned long)__phys_to_iee(__pa(SHIFT_PERCPU_PTR(__entry_task,__per_cpu_offset[cpu])))); -+ // Set the __entry_task of cpu 0 readonly in lm. -+ if(cpu == smp_processor_id()) -+ iee_set_logical_mem_ro((unsigned long)SHIFT_PERCPU_PTR(__entry_task,__per_cpu_offset[cpu])); -+ } + retval = security_task_fix_setuid(new, old, LSM_SETID_ID); + if (retval < 0) +@@ -710,7 +776,11 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) + return -ENOMEM; + + if (ruid != (uid_t) -1) { ++ #ifdef CONFIG_CREDP ++ iee_set_cred_uid(new,kruid); ++ #else + new->uid = kruid; ++ #endif + if (!uid_eq(kruid, old->uid)) { + retval = set_user(new); + if (retval < 0) +@@ -718,10 +788,22 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) + } + } + if (euid != (uid_t) -1) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_euid(new,keuid); ++ #else + new->euid = keuid; ++ #endif + if (suid != (uid_t) -1) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_suid(new,ksuid); ++ #else + new->suid = ksuid; ++ #endif ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(new,new->euid); ++ #else + new->fsuid = new->euid; + #endif - smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ - boot_cpu_hotplug_init(); -@@ -1446,6 +1469,9 @@ static int __ref kernel_init(void *unused) - wait_for_completion(&kthreadd_done); + retval = security_task_fix_setuid(new, old, LSM_SETID_RES); + if (retval < 0) +@@ -810,12 +892,29 @@ long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) + return -ENOMEM; - kernel_init_freeable(); -+ #ifdef CONFIG_PTP -+ iee_set_logical_mem_ro((unsigned long)bm_pte_addr); + if (rgid != (gid_t) -1) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_gid(new,krgid); ++ #else + new->gid = krgid; ++ #endif + if (egid != (gid_t) -1) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_egid(new,kegid); ++ #else + new->egid = kegid; ++ #endif + if (sgid != (gid_t) -1) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_sgid(new,ksgid); ++ #else + new->sgid = ksgid; ++ #endif ++ ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsgid(new,new->egid); ++ #else + new->fsgid = new->egid; + #endif - /* need to finish all async __init code before freeing the memory */ - async_synchronize_full(); -@@ -1462,7 +1488,7 @@ static int __ref kernel_init(void *unused) - * to finalize PTI. - */ - pti_finalize(); -- -+ - system_state = SYSTEM_RUNNING; - numa_default_policy(); + retval = security_task_fix_setgid(new, old, LSM_SETID_RES); + if (retval < 0) +@@ -882,7 +981,11 @@ long __sys_setfsuid(uid_t uid) + uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) || + ns_capable_setid(old->user_ns, CAP_SETUID)) { + if (!uid_eq(kuid, old->fsuid)) { ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsuid(new,kuid); ++ #else + new->fsuid = kuid; ++ #endif + if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) + goto change_okay; + } +@@ -926,7 +1029,11 @@ long __sys_setfsgid(gid_t gid) + gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) || + ns_capable_setid(old->user_ns, CAP_SETGID)) { + if (!gid_eq(kgid, old->fsgid)) { ++ #ifdef CONFIG_CREDP ++ iee_set_cred_fsgid(new,kgid); ++ #else + new->fsgid = kgid; ++ #endif + if (security_task_fix_setgid(new,old,LSM_SETID_FS) == 0) + goto change_okay; + } +diff --git a/kernel/umh.c b/kernel/umh.c +index 1b13c5d34624..32f5c88e10bf 100644 +--- a/kernel/umh.c ++++ b/kernel/umh.c +@@ -32,6 +32,10 @@ -diff --git a/kernel/cred.c b/kernel/cred.c -index c033a201c808..2e44530976d5 100644 ---- a/kernel/cred.c -+++ b/kernel/cred.c -@@ -20,6 +20,11 @@ - #include - #include + #include +#ifdef CONFIG_CREDP +#include -+#include +#endif + - #if 0 - #define kdebug(FMT, ...) \ - printk("[%-5.5s%5u] " FMT "\n", \ -@@ -34,6 +39,9 @@ do { \ - #endif + static kernel_cap_t usermodehelper_bset = CAP_FULL_SET; + static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET; + static DEFINE_SPINLOCK(umh_sysctl_lock); +@@ -91,9 +95,15 @@ static int call_usermodehelper_exec_async(void *data) + goto out; - static struct kmem_cache *cred_jar; -+#ifdef CONFIG_CREDP -+static struct kmem_cache *rcu_jar; -+#endif + spin_lock(&umh_sysctl_lock); ++ #ifdef CONFIG_CREDP ++ iee_set_cred_cap_bset(new,cap_intersect(usermodehelper_bset, new->cap_bset)); ++ iee_set_cred_cap_inheritable(new,cap_intersect(usermodehelper_inheritable, ++ new->cap_inheritable)); ++ #else + new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset); + new->cap_inheritable = cap_intersect(usermodehelper_inheritable, + new->cap_inheritable); ++ #endif + spin_unlock(&umh_sysctl_lock); + + if (sub_info->init) { +diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c +index 1d8e47bed3f1..9f1921025539 100644 +--- a/kernel/user_namespace.c ++++ b/kernel/user_namespace.c +@@ -22,6 +22,10 @@ + #include + #include - /* init to 2 - one for init_task, one to ensure it is never freed */ - static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) }; -@@ -41,6 +49,32 @@ static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) }; - /* - * The initial credentials for the initial task - */ +#ifdef CONFIG_CREDP -+struct cred init_cred __section(".iee.cred") = { -+ .usage = ATOMIC_INIT(4), -+#ifdef CONFIG_DEBUG_CREDENTIALS -+ .subscribers = ATOMIC_INIT(2), -+ .magic = CRED_MAGIC, -+#endif -+ .uid = GLOBAL_ROOT_UID, -+ .gid = GLOBAL_ROOT_GID, -+ .suid = GLOBAL_ROOT_UID, -+ .sgid = GLOBAL_ROOT_GID, -+ .euid = GLOBAL_ROOT_UID, -+ .egid = GLOBAL_ROOT_GID, -+ .fsuid = GLOBAL_ROOT_UID, -+ .fsgid = GLOBAL_ROOT_GID, -+ .securebits = SECUREBITS_DEFAULT, -+ .cap_inheritable = CAP_EMPTY_SET, -+ .cap_permitted = CAP_FULL_SET, -+ .cap_effective = CAP_FULL_SET, -+ .cap_bset = CAP_FULL_SET, -+ .user = INIT_USER, -+ .user_ns = &init_user_ns, -+ .group_info = &init_groups, -+ .ucounts = &init_ucounts, -+}; -+#else - struct cred init_cred = { - .usage = ATOMIC_INIT(4), - .uid = GLOBAL_ROOT_UID, -@@ -61,13 +95,43 @@ struct cred init_cred = { - .group_info = &init_groups, - .ucounts = &init_ucounts, - }; -+#endif -+ -+static inline void set_cred_subscribers(struct cred *cred, int n) -+{ -+#ifdef CONFIG_DEBUG_CREDENTIALS -+ atomic_set(&cred->subscribers, n); ++#include +#endif -+} + -+static inline int read_cred_subscribers(const struct cred *cred) -+{ -+#ifdef CONFIG_DEBUG_CREDENTIALS -+ return atomic_read(&cred->subscribers); -+#else -+ return 0; + static struct kmem_cache *user_ns_cachep __read_mostly; + static DEFINE_MUTEX(userns_state_mutex); + +@@ -45,6 +49,19 @@ static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) + /* Start with the same capabilities as init but useless for doing + * anything as the capabilities are bound to the new user namespace. + */ ++ #ifdef CONFIG_CREDP ++ iee_set_cred_securebits(cred,SECUREBITS_DEFAULT); ++ iee_set_cred_cap_inheritable(cred,CAP_EMPTY_SET); ++ iee_set_cred_cap_permitted(cred,CAP_FULL_SET); ++ iee_set_cred_cap_effective(cred,CAP_FULL_SET); ++ iee_set_cred_cap_ambient(cred,CAP_EMPTY_SET); ++ iee_set_cred_cap_bset(cred,CAP_FULL_SET); ++#ifdef CONFIG_KEYS ++ key_put(cred->request_key_auth); ++ iee_set_cred_request_key_auth(cred,NULL); +#endif -+} ++ iee_set_cred_user_ns(cred,user_ns); ++ #else + cred->securebits = SECUREBITS_DEFAULT; + cred->cap_inheritable = CAP_EMPTY_SET; + cred->cap_permitted = CAP_FULL_SET; +@@ -57,6 +74,7 @@ static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) + #endif + /* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */ + cred->user_ns = user_ns; ++ #endif + } + + static unsigned long enforced_nproc_rlimit(void) +diff --git a/lib/digsig.c b/lib/digsig.c +index 04b5e55ed95f..0a10a459bdaa 100644 +--- a/lib/digsig.c ++++ b/lib/digsig.c +@@ -81,7 +81,11 @@ static int digsig_verify_rsa(struct key *key, + const struct user_key_payload *ukp; + struct pubkey_hdr *pkh; + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(key)); ++ #else + down_read(&key->sem); ++ #endif + ukp = user_key_payload_locked(key); + + if (!ukp) { +@@ -176,7 +180,11 @@ static int digsig_verify_rsa(struct key *key, + while (--i >= 0) + mpi_free(pkey[i]); + err1: ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + + return err; + } +diff --git a/mm/Kconfig b/mm/Kconfig +index 782c43f08e8f..7706340f189c 100644 +--- a/mm/Kconfig ++++ b/mm/Kconfig +@@ -530,6 +530,11 @@ config NUMA_KEEP_MEMINFO + config MEMORY_ISOLATION + bool + ++# Configs for pgtable isolation ++config PTP ++ depends on IEE ++ def_bool y + -+static inline void alter_cred_subscribers(const struct cred *_cred, int n) -+{ -+#ifdef CONFIG_DEBUG_CREDENTIALS -+ struct cred *cred = (struct cred *) _cred; + # IORESOURCE_SYSTEM_RAM regions in the kernel resource tree that are marked + # IORESOURCE_EXCLUSIVE cannot be mapped to user space, for example, via + # /dev/mem. +diff --git a/mm/damon/ops-common.c b/mm/damon/ops-common.c +index d25d99cb5f2b..2ea51f559d4e 100644 +--- a/mm/damon/ops-common.c ++++ b/mm/damon/ops-common.c +@@ -44,6 +44,7 @@ void damon_ptep_mkold(pte_t *pte, struct vm_area_struct *vma, unsigned long addr + if (!folio) + return; + + -+ atomic_add(n, &cred->subscribers); -+#endif -+} + if (ptep_clear_young_notify(vma, addr, pte)) + folio_set_young(folio); - /* - * The RCU callback to actually dispose of a set of credentials - */ - static void put_cred_rcu(struct rcu_head *rcu) - { -+ #ifdef CONFIG_CREDP -+ struct cred *cred = *(struct cred **)(rcu + 1); +diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c +index 68af76ca8bc9..2789784777dd 100644 +--- a/mm/debug_vm_pgtable.c ++++ b/mm/debug_vm_pgtable.c +@@ -437,7 +437,11 @@ static void __init pmd_huge_tests(struct pgtable_debug_args *args) + * X86 defined pmd_set_huge() verifies that the given + * PMD is not a populated non-leaf entry. + */ ++ #ifdef CONFIG_PTP ++ set_pmd(args->pmdp, __pmd(0)); ++ #else + WRITE_ONCE(*args->pmdp, __pmd(0)); ++ #endif + WARN_ON(!pmd_set_huge(args->pmdp, __pfn_to_phys(args->fixed_pmd_pfn), args->page_prot)); + WARN_ON(!pmd_clear_huge(args->pmdp)); + pmd = READ_ONCE(*args->pmdp); +@@ -457,7 +461,11 @@ static void __init pud_huge_tests(struct pgtable_debug_args *args) + * X86 defined pud_set_huge() verifies that the given + * PUD is not a populated non-leaf entry. + */ ++ #ifdef CONFIG_PTP ++ set_pud(args->pudp, __pud(0)); + #else - struct cred *cred = container_of(rcu, struct cred, rcu); + WRITE_ONCE(*args->pudp, __pud(0)); + #endif + WARN_ON(!pud_set_huge(args->pudp, __pfn_to_phys(args->fixed_pud_pfn), args->page_prot)); + WARN_ON(!pud_clear_huge(args->pudp)); + pud = READ_ONCE(*args->pudp); +@@ -496,6 +504,12 @@ static void __init pud_clear_tests(struct pgtable_debug_args *args) - kdebug("put_cred_rcu(%p)", cred); - -@@ -86,6 +150,9 @@ static void put_cred_rcu(struct rcu_head *rcu) - if (cred->ucounts) - put_ucounts(cred->ucounts); - put_user_ns(cred->user_ns); -+ #ifdef CONFIG_CREDP -+ kmem_cache_free(rcu_jar, (struct rcu_head *)(cred->rcu.func)); + pr_debug("Validating PUD clear\n"); + WARN_ON(pud_none(pud)); ++ pud = __pud(pud_val(pud) | RANDOM_ORVALUE); ++ #ifdef CONFIG_PTP ++ set_pud(args->pudp, pud); ++ #else ++ WRITE_ONCE(*args->pudp, pud); + #endif - kmem_cache_free(cred_jar, cred); - } - -@@ -104,10 +171,22 @@ void __put_cred(struct cred *cred) - BUG_ON(cred == current->cred); - BUG_ON(cred == current->real_cred); + pud_clear(args->pudp); + pud = READ_ONCE(*args->pudp); + WARN_ON(!pud_none(pud)); +@@ -532,6 +546,12 @@ static void __init p4d_clear_tests(struct pgtable_debug_args *args) -+ #ifdef CONFIG_CREDP -+ if (*(int *)(&(((struct rcu_head *)(cred->rcu.func))->next))) + pr_debug("Validating P4D clear\n"); + WARN_ON(p4d_none(p4d)); ++ p4d = __p4d(p4d_val(p4d) | RANDOM_ORVALUE); ++ #ifdef CONFIG_PTP ++ set_p4d(args->p4dp, p4d); + #else - if (cred->non_rcu) ++ WRITE_ONCE(*args->p4dp, p4d); + #endif -+ #ifdef CONFIG_CREDP -+ put_cred_rcu((struct rcu_head *)(cred->rcu.func)); -+ #else - put_cred_rcu(&cred->rcu); -+ #endif - else -+ #ifdef CONFIG_CREDP -+ call_rcu((struct rcu_head *)(cred->rcu.func), put_cred_rcu); -+ #else - call_rcu(&cred->rcu, put_cred_rcu); -+ #endif - } - EXPORT_SYMBOL(__put_cred); + p4d_clear(args->p4dp); + p4d = READ_ONCE(*args->p4dp); + WARN_ON(!p4d_none(p4d)); +@@ -565,6 +585,12 @@ static void __init pgd_clear_tests(struct pgtable_debug_args *args) -@@ -178,7 +257,18 @@ struct cred *cred_alloc_blank(void) - if (!new) - return NULL; + pr_debug("Validating PGD clear\n"); + WARN_ON(pgd_none(pgd)); ++ pgd = __pgd(pgd_val(pgd) | RANDOM_ORVALUE); ++ #ifdef CONFIG_PTP ++ set_pgd(args->pgdp, pgd); ++ #else ++ WRITE_ONCE(*args->pgdp, pgd); ++ #endif + pgd_clear(args->pgdp); + pgd = READ_ONCE(*args->pgdp); + WARN_ON(!pgd_none(pgd)); +@@ -630,6 +656,12 @@ static void __init pmd_clear_tests(struct pgtable_debug_args *args) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_rcu(new,kmem_cache_zalloc(rcu_jar, GFP_KERNEL)); -+ *(struct cred **)(((struct rcu_head *)(new->rcu.func)) + 1) = new; -+ iee_set_cred_atomic_set_usage(new,1); + pr_debug("Validating PMD clear\n"); + WARN_ON(pmd_none(pmd)); ++ pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE); ++ #ifdef CONFIG_PTP ++ set_pmd(args->pmdp, pmd); + #else - atomic_long_set(&new->usage, 1); ++ WRITE_ONCE(*args->pmdp, pmd); + #endif + pmd_clear(args->pmdp); + pmd = READ_ONCE(*args->pmdp); + WARN_ON(!pmd_none(pmd)); +diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c +index ce06b2884789..a039c7a50ec5 100644 +--- a/mm/early_ioremap.c ++++ b/mm/early_ioremap.c +@@ -147,7 +147,11 @@ __early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot) + if (after_paging_init) + __late_set_fixmap(idx, phys_addr, prot); + else ++ #ifdef CONFIG_PTP ++ __iee_set_fixmap_pre_init(idx, phys_addr, prot); ++ #else + __early_set_fixmap(idx, phys_addr, prot); ++ #endif + phys_addr += PAGE_SIZE; + --idx; + --nrpages; +@@ -199,13 +203,66 @@ void __init early_iounmap(void __iomem *addr, unsigned long size) + if (after_paging_init) + __late_clear_fixmap(idx); + else ++ #ifdef CONFIG_PTP ++ __iee_set_fixmap_pre_init(idx, 0, FIXMAP_PAGE_CLEAR); ++ #else + __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR); ++ #endif + --idx; + --nrpages; + } + prev_map[slot] = NULL; + } + ++#ifdef CONFIG_PTP ++void __init early_iounmap_after_init(void __iomem *addr, unsigned long size) ++{ ++ unsigned long virt_addr; ++ unsigned long offset; ++ unsigned int nrpages; ++ enum fixed_addresses idx; ++ int i, slot; + -+ #ifdef CONFIG_DEBUG_CREDENTIALS -+ new->magic = CRED_MAGIC; -+ #endif ++ slot = -1; ++ for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { ++ if (prev_map[i] == addr) { ++ slot = i; ++ break; ++ } ++ } + - if (security_cred_alloc_blank(new, GFP_KERNEL_ACCOUNT) < 0) - goto error; - -@@ -213,13 +303,25 @@ struct cred *prepare_creds(void) - if (!new) - return NULL; - -+ #ifdef CONFIG_CREDP -+ iee_set_cred_rcu(new,kmem_cache_alloc(rcu_jar, GFP_KERNEL)); -+ *(struct cred **)(((struct rcu_head *)(new->rcu.func)) + 1) = new; -+ #endif ++ if (WARN(slot < 0, "early_iounmap(%p, %08lx) not found slot\n", ++ addr, size)) ++ return; + - kdebug("prepare_creds() alloc %p", new); ++ if (WARN(prev_size[slot] != size, ++ "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n", ++ addr, size, slot, prev_size[slot])) ++ return; ++ ++ WARN(early_ioremap_debug, "early_iounmap(%p, %08lx) [%d]\n", ++ addr, size, slot); ++ ++ virt_addr = (unsigned long)addr; ++ if (WARN_ON(virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))) ++ return; ++ ++ offset = offset_in_page(virt_addr); ++ nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT; ++ ++ idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; ++ while (nrpages > 0) { ++ if (after_paging_init) ++ __late_clear_fixmap(idx); ++ else ++ __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR); ++ --idx; ++ --nrpages; ++ } ++ prev_map[slot] = NULL; ++} ++#endif ++ + /* Remap an IO device */ + void __init __iomem * + early_ioremap(resource_size_t phys_addr, unsigned long size) +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index ea560ea7b39e..c02723e26f5e 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -40,6 +40,10 @@ + #include + #include - old = task->cred; -+ #ifdef CONFIG_CREDP -+ iee_copy_cred(old,new); ++#ifdef CONFIG_PTP ++#include ++#endif + -+ iee_set_cred_non_rcu(new,0); -+ iee_set_cred_atomic_set_usage(new,1); -+ #else - memcpy(new, old, sizeof(struct cred)); + #include + #include + #include "internal.h" +@@ -2551,7 +2555,8 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma, + old_pmd = pmdp_huge_clear_flush(vma, haddr, pmd); - new->non_rcu = 0; - atomic_long_set(&new->usage, 1); -+ #endif - get_group_info(new->group_info); - get_uid(new->user); - get_user_ns(new->user_ns); -@@ -232,10 +334,18 @@ struct cred *prepare_creds(void) - #endif + pgtable = pgtable_trans_huge_withdraw(mm, pmd); +- pmd_populate(mm, &_pmd, pgtable); ++ //pmd_populate(mm, &_pmd, pgtable); ++ _pmd = __pmd(__phys_to_pmd_val(page_to_phys(pgtable)) | PMD_TYPE_TABLE); - #ifdef CONFIG_SECURITY -+#ifdef CONFIG_CREDP -+ iee_set_cred_security(new,NULL); -+#else - new->security = NULL; -+#endif - #endif + pte = pte_offset_map(&_pmd, haddr); + VM_BUG_ON(!pte); +@@ -2721,7 +2726,8 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, + * This's critical for some architectures (Power). + */ + pgtable = pgtable_trans_huge_withdraw(mm, pmd); +- pmd_populate(mm, &_pmd, pgtable); ++ //pmd_populate(mm, &_pmd, pgtable); ++ _pmd = __pmd(__phys_to_pmd_val(page_to_phys(pgtable)) | PMD_TYPE_TABLE); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_ucounts(new, get_ucounts(new->ucounts)); -+ #else - new->ucounts = get_ucounts(new->ucounts); -+ #endif - if (!new->ucounts) - goto error; + pte = pte_offset_map(&_pmd, haddr); + VM_BUG_ON(!pte); +diff --git a/mm/hugetlb_vmemmap.c b/mm/hugetlb_vmemmap.c +index 149ab629855c..93b6a7ebde82 100644 +--- a/mm/hugetlb_vmemmap.c ++++ b/mm/hugetlb_vmemmap.c +@@ -83,7 +83,7 @@ static int split_vmemmap_huge_pmd(pmd_t *pmd, unsigned long start) -@@ -265,15 +375,30 @@ struct cred *prepare_exec_creds(void) - #ifdef CONFIG_KEYS - /* newly exec'd tasks don't get a thread keyring */ - key_put(new->thread_keyring); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_thread_keyring(new,NULL); -+ #else - new->thread_keyring = NULL; -+ #endif + if (!head) + return 0; +- ++ + pgtable = pte_alloc_one_kernel(&init_mm); + if (!pgtable) + return -ENOMEM; +diff --git a/mm/init-mm.c b/mm/init-mm.c +index 24c809379274..4539eb8e7cce 100644 +--- a/mm/init-mm.c ++++ b/mm/init-mm.c +@@ -55,3 +55,19 @@ void setup_initial_init_mm(void *start_code, void *end_code, + init_mm.end_data = (unsigned long)end_data; + init_mm.brk = (unsigned long)brk; + } ++ ++#ifdef CONFIG_KOI ++/* ++ * This is used to init ko_mm when creating pgtable for a ko to be isolated ++ * the ko_mm belongs to a specific ko, pgdp is allocated by koi_pgd_alloc ++ */ ++void init_ko_mm(struct mm_struct *ko_mm, pgd_t *pgdp) { ++ ko_mm->pgd = pgdp; ++ ko_mm->mm_users = (atomic_t)ATOMIC_INIT(2); ++ ko_mm->mm_count = (atomic_t)ATOMIC_INIT(1); ++ ko_mm->mmap_lock = (struct rw_semaphore)__RWSEM_INITIALIZER(ko_mm->mmap_lock); ++ ko_mm->page_table_lock = __SPIN_LOCK_UNLOCKED(ko_mm.page_table_lock); ++ ko_mm->arg_lock = __SPIN_LOCK_UNLOCKED(ko_mm->arg_lock); ++ ko_mm->mmlist = (struct list_head)LIST_HEAD_INIT(ko_mm->mmlist); ++} ++#endif +diff --git a/mm/memory.c b/mm/memory.c +index e248b8338417..e291818c8ed0 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -80,6 +80,11 @@ + #include + #include - /* inherit the session keyring; new process keyring */ - key_put(new->process_keyring); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_process_keyring(new,NULL); -+ #else - new->process_keyring = NULL; -+ #endif - #endif ++#ifdef CONFIG_PTP ++#include ++extern void iee_copy_pte_range(pte_t *new_dst, pte_t *old_dst, pte_t *src_pte, struct vm_area_struct *src_vma, unsigned long dst_vm_flags, pte_t *end_pte); ++#endif ++ + #include -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(new,new->euid); -+ iee_set_cred_suid(new,new->euid); -+ iee_set_cred_fsgid(new,new->egid); -+ iee_set_cred_sgid(new,new->egid); -+ #else - new->suid = new->fsuid = new->euid; - new->sgid = new->fsgid = new->egid; -+ #endif + #include +@@ -809,7 +814,11 @@ copy_nonpresent_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, + /* Mark the swap entry as shared. */ + if (pte_swp_exclusive(orig_pte)) { + pte = pte_swp_clear_exclusive(orig_pte); ++ #ifdef CONFIG_PTP ++ iee_set_pte_at_delayed(src_mm, addr, src_pte, pte); ++ #else + set_pte_at(src_mm, addr, src_pte, pte); ++ #endif + } + rss[MM_SWAPENTS]++; + } else if (is_migration_entry(entry)) { +@@ -831,7 +840,11 @@ copy_nonpresent_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, + pte = pte_swp_mksoft_dirty(pte); + if (pte_swp_uffd_wp(orig_pte)) + pte = pte_swp_mkuffd_wp(pte); ++ #ifdef CONFIG_PTP ++ iee_set_pte_at_delayed(src_mm, addr, src_pte, pte); ++ #else + set_pte_at(src_mm, addr, src_pte, pte); ++ #endif + } + } else if (is_device_private_entry(entry)) { + page = pfn_swap_entry_to_page(entry); +@@ -865,7 +878,11 @@ copy_nonpresent_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, + pte = swp_entry_to_pte(entry); + if (pte_swp_uffd_wp(orig_pte)) + pte = pte_swp_mkuffd_wp(pte); ++ #ifdef CONFIG_PTP ++ iee_set_pte_at_delayed(src_mm, addr, src_pte, pte); ++ #else + set_pte_at(src_mm, addr, src_pte, pte); ++ #endif + } + } else if (is_device_exclusive_entry(entry)) { + /* +@@ -882,13 +899,22 @@ copy_nonpresent_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, + pte_marker marker = copy_pte_marker(entry, dst_vma); - return new; - } -@@ -327,7 +452,11 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) - * had one */ - if (new->thread_keyring) { - key_put(new->thread_keyring); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_thread_keyring(new,NULL); -+ #else - new->thread_keyring = NULL; -+ #endif - if (clone_flags & CLONE_THREAD) - install_thread_keyring_to_cred(new); - } -@@ -337,7 +466,11 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) - */ - if (!(clone_flags & CLONE_THREAD)) { - key_put(new->process_keyring); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_process_keyring(new,NULL); + if (marker) ++ #ifdef CONFIG_PTP ++ iee_set_pte_at(dst_mm, addr, dst_pte, ++ make_pte_marker(marker)); + #else - new->process_keyring = NULL; + set_pte_at(dst_mm, addr, dst_pte, + make_pte_marker(marker)); + #endif + return 0; } - #endif - -@@ -594,7 +727,11 @@ int set_cred_ucounts(struct cred *new) - if (!(new_ucounts = alloc_ucounts(new->user_ns, new->uid))) - return -EAGAIN; - -+ #ifdef CONFIG_CREDP -+ iee_set_cred_ucounts(new, new_ucounts); + if (!userfaultfd_wp(dst_vma)) + pte = pte_swp_clear_uffd_wp(pte); ++ #ifdef CONFIG_PTP ++ iee_set_pte_at(dst_mm, addr, dst_pte, pte); + #else - new->ucounts = new_ucounts; + set_pte_at(dst_mm, addr, dst_pte, pte); + #endif - put_ucounts(old_ucounts); - return 0; -@@ -606,8 +743,21 @@ int set_cred_ucounts(struct cred *new) - void __init cred_init(void) - { - /* allocate a slab in which we can store credentials */ -+ #ifdef CONFIG_CREDP - cred_jar = kmem_cache_create("cred_jar", sizeof(struct cred), 0, -+ SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT|SLAB_RED_ZONE, NULL); -+ rcu_jar = kmem_cache_create("rcu_jar", sizeof(struct rcu_head) + sizeof(struct cred *), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, NULL); -+ // Map init_cred -+ *((struct rcu_head **)(&(init_cred.rcu.func))) = (struct rcu_head *)kmem_cache_zalloc(rcu_jar, GFP_KERNEL); -+ *(struct cred **)(((struct rcu_head *)(init_cred.rcu.func)) + 1) = &init_cred; -+ set_iee_page_valid(__phys_to_iee(__pa_symbol(&init_cred))); -+ iee_set_logical_mem_ro((unsigned long)&init_cred); -+ iee_set_logical_mem_ro((unsigned long)__va(__pa_symbol(&init_cred))); -+ #else -+ cred_jar = kmem_cache_create("cred_jar", sizeof(struct cred), 0, -+ SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, NULL); -+ #endif } - /** -@@ -638,29 +788,56 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) - if (!new) - return NULL; - -+ #ifdef CONFIG_CREDP -+ iee_set_cred_rcu(new,kmem_cache_alloc(rcu_jar, GFP_KERNEL)); -+ *(struct cred **)(((struct rcu_head *)(new->rcu.func)) + 1) = new; -+ #endif -+ - kdebug("prepare_kernel_cred() alloc %p", new); - - old = get_task_cred(daemon); - -+ #ifdef CONFIG_CREDP -+ iee_copy_cred(old,new); -+ iee_set_cred_non_rcu(new,0); -+ iee_set_cred_atomic_set_usage(new,1); +@@ -936,7 +962,11 @@ copy_present_page(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma + if (userfaultfd_pte_wp(dst_vma, ptep_get(src_pte))) + /* Uffd-wp needs to be delivered to dest pte as well */ + pte = pte_mkuffd_wp(pte); ++ #ifdef CONFIG_PTP ++ iee_set_pte_at(dst_vma->vm_mm, addr, dst_pte, pte); + #else - *new = *old; - new->non_rcu = 0; - atomic_long_set(&new->usage, 1); + set_pte_at(dst_vma->vm_mm, addr, dst_pte, pte); + #endif - get_uid(new->user); - get_user_ns(new->user_ns); - get_group_info(new->group_info); - - #ifdef CONFIG_KEYS -+#ifdef CONFIG_CREDP -+ iee_set_cred_session_keyring(new,NULL); -+ iee_set_cred_process_keyring(new,NULL); -+ iee_set_cred_thread_keyring(new,NULL); -+ iee_set_cred_request_key_auth(new,NULL); -+ iee_set_cred_jit_keyring(new,KEY_REQKEY_DEFL_THREAD_KEYRING); -+#else - new->session_keyring = NULL; - new->process_keyring = NULL; - new->thread_keyring = NULL; - new->request_key_auth = NULL; - new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; - #endif -+#endif + return 0; + } - #ifdef CONFIG_SECURITY -+#ifdef CONFIG_CREDP -+ iee_set_cred_security(new,NULL); -+#else - new->security = NULL; - #endif -+#endif -+ #ifdef CONFIG_CREDP -+ iee_set_cred_ucounts(new, get_ucounts(new->ucounts)); -+ #else - new->ucounts = get_ucounts(new->ucounts); -+ #endif - if (!new->ucounts) - goto error; +@@ -960,7 +990,21 @@ static __always_inline void __copy_present_ptes(struct vm_area_struct *dst_vma, + if (!userfaultfd_wp(dst_vma)) + pte = pte_clear_uffd_wp(pte); -@@ -727,8 +904,13 @@ int set_create_files_as(struct cred *new, struct inode *inode) - { - if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid)) - return -EINVAL; -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(new,inode->i_uid); -+ iee_set_cred_fsgid(new,inode->i_gid); ++ #ifdef CONFIG_PTP ++ page_table_check_ptes_set(dst_vma->vm_mm, dst_pte, pte, nr); ++ __sync_cache_and_tags(pte, nr); ++ ++ for (;;) { ++ __check_safe_pte_update(dst_vma->vm_mm, dst_pte, pte); ++ iee_set_pte_at(dst_vma->vm_mm, addr, dst_pte, pte); ++ if (--nr == 0) ++ break; ++ dst_pte++; ++ pte = pte_advance_pfn(pte, 1); ++ } + #else - new->fsuid = inode->i_uid; - new->fsgid = inode->i_gid; + set_ptes(dst_vma->vm_mm, addr, dst_pte, pte, nr); + #endif - return security_kernel_create_files_as(new, inode); } - EXPORT_SYMBOL(set_create_files_as); -diff --git a/kernel/exit.c b/kernel/exit.c -index 21a59a6e1f2e..d21a109f0497 100644 ---- a/kernel/exit.c -+++ b/kernel/exit.c -@@ -74,6 +74,10 @@ - #include - #include -+#ifdef CONFIG_IEE -+#include -+#endif -+ /* - * The default value should be high enough to not crash a system that randomly - * crashes its kernel from time to time, but low enough to at least not permit -@@ -558,6 +562,10 @@ static void exit_mm(void) - smp_mb__after_spinlock(); - local_irq_disable(); - current->mm = NULL; -+ #ifdef CONFIG_IEE -+ iee_set_token_mm(current, NULL); -+ iee_set_token_pgd(current, NULL); +@@ -1087,6 +1131,12 @@ copy_pte_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma, + swp_entry_t entry = (swp_entry_t){0}; + struct folio *prealloc = NULL; + int nr; ++ #ifdef CONFIG_PTP ++ unsigned long orig_addr; ++ pmd_t pmd; ++ pte_t *old_dst; ++ void *new; + #endif - membarrier_update_current_mm(NULL); - enter_lazy_tlb(mm, current); - local_irq_enable(); -diff --git a/kernel/fork.c b/kernel/fork.c -index e033388b11bd..c93e18a4f0b3 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -115,6 +115,10 @@ - #define CREATE_TRACE_POINTS - #include -+#ifdef CONFIG_IEE -+#include + again: + progress = 0; +@@ -1105,6 +1155,13 @@ copy_pte_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma, + ret = -ENOMEM; + goto out; + } ++#ifdef CONFIG_PTP ++ orig_addr = addr; ++ new = (void *)iee_read_tmp_page(get_current()); ++ pmd = READ_ONCE(*dst_pmd); ++ dst_pte = (pte_t *)new + pte_index(addr); ++ old_dst = pte_offset_map(&pmd, addr); +#endif -+ - /* - * Minimum number of threads to boot the kernel - */ -@@ -128,14 +132,14 @@ - /* - * Protected counters by write_lock_irq(&tasklist_lock) - */ --unsigned long total_forks; /* Handle normal Linux uptimes. */ --int nr_threads; /* The idle threads do not count.. */ -+unsigned long total_forks; /* Handle normal Linux uptimes. */ -+int nr_threads; /* The idle threads do not count.. */ - --static int max_threads; /* tunable limit on nr_threads */ -+static int max_threads; /* tunable limit on nr_threads */ - --#define NAMED_ARRAY_INDEX(x) [x] = __stringify(x) -+#define NAMED_ARRAY_INDEX(x) [x] = __stringify(x) - --static const char * const resident_page_types[] = { -+static const char *const resident_page_types[] = { - NAMED_ARRAY_INDEX(MM_FILEPAGES), - NAMED_ARRAY_INDEX(MM_ANONPAGES), - NAMED_ARRAY_INDEX(MM_SWAPENTS), -@@ -144,7 +148,7 @@ static const char * const resident_page_types[] = { - - DEFINE_PER_CPU(unsigned long, process_counts) = 0; - --__cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */ -+__cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */ - - #ifdef CONFIG_PROVE_RCU - int lockdep_tasklist_lock_is_held(void) -@@ -159,7 +163,7 @@ int nr_processes(void) - int cpu; - int total = 0; - -- for_each_possible_cpu(cpu) -+ for_each_possible_cpu (cpu) - total += per_cpu(process_counts, cpu); - - return total; -@@ -190,7 +194,7 @@ static inline void free_task_struct(struct task_struct *tsk) - * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a - * kmemcache based allocator. - */ --# if THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK) -+#if THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK) + src_pte = pte_offset_map_nolock(src_mm, src_pmd, addr, &src_ptl); + if (!src_pte) { + pte_unmap_unlock(dst_pte, dst_ptl); +@@ -1183,6 +1240,12 @@ copy_pte_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma, + } while (dst_pte += nr, src_pte += nr, addr += PAGE_SIZE * nr, + addr != end); - # ifdef CONFIG_VMAP_STACK - /* -@@ -311,8 +315,8 @@ static int alloc_thread_stack_node(struct task_struct *tsk, int node) - * so memcg accounting is performed manually on assigning/releasing - * stacks to tasks. Drop __GFP_ACCOUNT. - */ -- stack = __vmalloc_node_range(THREAD_SIZE, THREAD_ALIGN, -- VMALLOC_START, VMALLOC_END, -+ stack = __vmalloc_node_range(THREAD_SIZE, THREAD_ALIGN, VMALLOC_START, -+ VMALLOC_END, - THREADINFO_GFP & ~__GFP_ACCOUNT, - PAGE_KERNEL, - 0, node, __builtin_return_address(0)); -@@ -410,9 +414,10 @@ static void free_thread_stack(struct task_struct *tsk) ++ #ifdef CONFIG_PTP ++ iee_copy_pte_range(orig_dst_pte, old_dst, orig_src_pte, src_vma, dst_vma->vm_flags, src_pte); ++ orig_dst_pte = pte_offset_map(&pmd, orig_addr); ++ dst_pte = pte_offset_map(&pmd, addr); ++ #endif ++ + arch_leave_lazy_mmu_mode(); + pte_unmap_unlock(orig_src_pte, src_ptl); + add_mm_rss_vec(dst_mm, rss); +@@ -6624,12 +6687,20 @@ bool ptlock_alloc(struct ptdesc *ptdesc) + ptl = kmem_cache_alloc(page_ptl_cachep, GFP_KERNEL); + if (!ptl) + return false; ++ #ifdef CONFIG_PTP ++ ((struct ptdesc_t *)(((struct slab *)ptdesc)->slab_cache)->ptl) = ptl; ++ #else + ptdesc->ptl = ptl; ++ #endif + return true; + } - void thread_stack_cache_init(void) + void ptlock_free(struct ptdesc *ptdesc) { -- thread_stack_cache = kmem_cache_create_usercopy("thread_stack", -- THREAD_SIZE, THREAD_SIZE, 0, 0, -- THREAD_SIZE, NULL); -+ thread_stack_cache = -+ kmem_cache_create_usercopy("thread_stack", THREAD_SIZE, -+ THREAD_SIZE, 0, 0, THREAD_SIZE, -+ NULL); - BUG_ON(thread_stack_cache == NULL); ++ #ifdef CONFIG_PTP ++ kmem_cache_free(page_ptl_cachep, ((struct ptdesc_t *)(((struct slab *)ptdesc)->slab_cache)->ptl)); ++ #else + kmem_cache_free(page_ptl_cachep, ptdesc->ptl); ++ #endif + } + #endif +diff --git a/mm/mmap.c b/mm/mmap.c +index 07ffb6c37b96..02d1f6f54e36 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -2375,7 +2375,11 @@ static void unmap_region(struct mm_struct *mm, struct ma_state *mas, + free_pgtables(&tlb, mas, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS, + next ? next->vm_start : USER_PGTABLES_CEILING, + mm_wr_locked); ++ #ifdef CONFIG_PTP ++ iee_tlb_finish_mmu(&tlb); ++ #else + tlb_finish_mmu(&tlb); ++ #endif } -@@ -502,7 +507,8 @@ struct vm_area_struct *vm_area_alloc(struct mm_struct *mm) - - struct vm_area_struct *vm_area_dup(struct vm_area_struct *orig) - { -- struct vm_area_struct *new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); -+ struct vm_area_struct *new = -+ kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); + /* +@@ -3286,7 +3290,11 @@ void exit_mmap(struct mm_struct *mm) + mas_set(&mas, vma->vm_end); + free_pgtables(&tlb, &mas, vma, FIRST_USER_ADDRESS, + USER_PGTABLES_CEILING, true); ++ #ifdef CONFIG_PTP ++ iee_tlb_finish_mmu(&tlb); ++ #else + tlb_finish_mmu(&tlb); ++ #endif - if (!new) - return NULL; -@@ -602,8 +608,15 @@ void put_task_stack(struct task_struct *tsk) + /* + * Walk the list again, actually closing and freeing it, with preemption +diff --git a/mm/mmu_gather.c b/mm/mmu_gather.c +index 99b3e9408aa0..16c79de60435 100644 +--- a/mm/mmu_gather.c ++++ b/mm/mmu_gather.c +@@ -347,6 +347,71 @@ void tlb_remove_table(struct mmu_gather *tlb, void *table) + tlb_table_flush(tlb); } - #endif -+#ifdef CONFIG_KOI -+extern s64 koi_offset; ++#ifdef CONFIG_PTP ++static void __iee_tlb_remove_table_free(struct mmu_table_batch *batch) ++{ ++ int i; ++ ++ for (i = 0; i < batch->nr; i++) ++ __iee_tlb_remove_table(batch->tables[i]); ++ ++ free_page((unsigned long)batch); ++} ++ ++#ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE ++static void iee_tlb_remove_table_rcu(struct rcu_head *head) ++{ ++ __iee_tlb_remove_table_free(container_of(head, struct mmu_table_batch, rcu)); ++} ++ ++static void iee_tlb_remove_table_free(struct mmu_table_batch *batch) ++{ ++ call_rcu(&batch->rcu, iee_tlb_remove_table_rcu); ++} ++#else ++static void iee_tlb_remove_table_free(struct mmu_table_batch *batch) ++{ ++ __iee_tlb_remove_table_free(batch); ++} +#endif + - void free_task(struct task_struct *tsk) ++static void iee_tlb_remove_table_one(void *table) ++{ ++ tlb_remove_table_sync_one(); ++ __iee_tlb_remove_table(table); ++} ++ ++static void iee_tlb_table_flush(struct mmu_gather *tlb) ++{ ++ struct mmu_table_batch **batch = &tlb->batch; ++ ++ if (*batch) { ++ tlb_table_invalidate(tlb); ++ iee_tlb_remove_table_free(*batch); ++ *batch = NULL; ++ } ++} ++ ++void iee_tlb_remove_table(struct mmu_gather *tlb, void *table) ++{ ++ struct mmu_table_batch **batch = &tlb->batch; ++ ++ if (*batch == NULL) { ++ *batch = (struct mmu_table_batch *)__get_free_page(GFP_NOWAIT | __GFP_NOWARN); ++ if (*batch == NULL) { ++ tlb_table_invalidate(tlb); ++ iee_tlb_remove_table_one(table); ++ return; ++ } ++ (*batch)->nr = 0; ++ } ++ ++ (*batch)->tables[(*batch)->nr++] = table; ++ if ((*batch)->nr == MAX_TABLE_BATCH) ++ iee_tlb_table_flush(tlb); ++} ++#endif ++ + static inline void tlb_table_init(struct mmu_gather *tlb) { -+ #ifdef CONFIG_IEE -+ void *iee_stack; + tlb->batch = NULL; +@@ -469,3 +534,55 @@ void tlb_finish_mmu(struct mmu_gather *tlb) + #endif + dec_tlb_flush_pending(tlb->mm); + } ++ ++#ifdef CONFIG_PTP ++static void iee_tlb_flush_mmu_free(struct mmu_gather *tlb) ++{ ++ iee_tlb_table_flush(tlb); ++#ifndef CONFIG_MMU_GATHER_NO_GATHER ++ tlb_batch_pages_flush(tlb); ++#endif ++} ++ ++void iee_tlb_flush_mmu(struct mmu_gather *tlb) ++{ ++ tlb_flush_mmu_tlbonly(tlb); ++ iee_tlb_flush_mmu_free(tlb); ++} ++ ++void iee_tlb_finish_mmu(struct mmu_gather *tlb) ++{ ++ /* ++ * If there are parallel threads are doing PTE changes on same range ++ * under non-exclusive lock (e.g., mmap_lock read-side) but defer TLB ++ * flush by batching, one thread may end up seeing inconsistent PTEs ++ * and result in having stale TLB entries. So flush TLB forcefully ++ * if we detect parallel PTE batching threads. ++ * ++ * However, some syscalls, e.g. munmap(), may free page tables, this ++ * needs force flush everything in the given range. Otherwise this ++ * may result in having stale TLB entries for some architectures, ++ * e.g. aarch64, that could specify flush what level TLB. ++ */ ++ if (mm_tlb_flush_nested(tlb->mm)) { ++ /* ++ * The aarch64 yields better performance with fullmm by ++ * avoiding multiple CPUs spamming TLBI messages at the ++ * same time. ++ * ++ * On x86 non-fullmm doesn't yield significant difference ++ * against fullmm. ++ */ ++ tlb->fullmm = 1; ++ __tlb_reset_range(tlb); ++ tlb->freed_tables = 1; ++ } ++ ++ iee_tlb_flush_mmu(tlb); ++ ++#ifndef CONFIG_MMU_GATHER_NO_GATHER ++ tlb_batch_list_free(tlb); ++#endif ++ dec_tlb_flush_pending(tlb->mm); ++} ++#endif +\ No newline at end of file +diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c +index 4fcd959dcc4d..bedc3522ddc3 100644 +--- a/mm/pgtable-generic.c ++++ b/mm/pgtable-generic.c +@@ -169,9 +169,17 @@ void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, + + /* FIFO */ + if (!pmd_huge_pte(mm, pmdp)) ++ #ifdef CONFIG_PTP ++ INIT_LIST_HEAD(&(((struct ptdesc_t *)(((struct slab_t *)pgtable)->slab_cache))->pt_list)); ++ #else + INIT_LIST_HEAD(&pgtable->lru); ++ #endif + else ++ #ifdef CONFIG_PTP ++ list_add(&(((struct ptdesc_t *)(((struct slab_t *)pgtable)->slab_cache))->pt_list), &(((struct ptdesc_t *)(((struct slab_t *)(pmd_huge_pte(mm, pmdp)))->slab_cache))->pt_list)); ++ #else + list_add(&pgtable->lru, &pmd_huge_pte(mm, pmdp)->lru); ++ #endif + pmd_huge_pte(mm, pmdp) = pgtable; + } + #endif +@@ -186,10 +194,22 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp) + + /* FIFO */ + pgtable = pmd_huge_pte(mm, pmdp); ++ #ifdef CONFIG_PTP ++ struct ptdesc_t *ptdesc = list_first_entry_or_null(&(((struct ptdesc_t *)(((struct slab_t *)pgtable)->slab_cache))->pt_list), struct ptdesc_t, pt_list); ++ if(ptdesc) ++ pmd_huge_pte(mm, pmdp) = (struct page *)ptdesc->slab; ++ else ++ pmd_huge_pte(mm, pmdp) = NULL; ++ #else + pmd_huge_pte(mm, pmdp) = list_first_entry_or_null(&pgtable->lru, + struct page, lru); + #endif - #ifdef CONFIG_SECCOMP - WARN_ON_ONCE(tsk->seccomp.filter); + if (pmd_huge_pte(mm, pmdp)) ++ #ifdef CONFIG_PTP ++ list_del(&(((struct ptdesc_t *)(((struct slab_t *)pgtable)->slab_cache))->pt_list)); ++ #else + list_del(&pgtable->lru); ++ #endif + return pgtable; + } #endif -@@ -633,6 +646,45 @@ void free_task(struct task_struct *tsk) - if (dynamic_affinity_enabled()) - sched_prefer_cpus_free(tsk); +@@ -238,7 +258,11 @@ static void pte_free_now(struct rcu_head *head) + { + struct page *page; + ++ #ifdef CONFIG_PTP ++ page = (struct page *)((container_of(head, struct ptdesc_t, pt_rcu_head))->slab); ++ #else + page = container_of(head, struct page, rcu_head); ++ #endif + pte_free(NULL /* mm not passed and not used */, (pgtable_t)page); + } + +@@ -247,7 +271,11 @@ void pte_free_defer(struct mm_struct *mm, pgtable_t pgtable) + struct page *page; + + page = pgtable; ++ #ifdef CONFIG_PTP ++ call_rcu(&(((struct ptdesc_t *)(((struct slab_t *)page)->slab_cache))->pt_rcu_head), pte_free_now); ++ #else + call_rcu(&page->rcu_head, pte_free_now); ++ #endif + } + #endif /* pte_free_defer */ + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +diff --git a/mm/slab.h b/mm/slab.h +index 3d07fb428393..69e3f4787ee1 100644 +--- a/mm/slab.h ++++ b/mm/slab.h +@@ -26,6 +26,24 @@ typedef u64 freelist_full_t; + #undef system_has_freelist_aba #endif + +#ifdef CONFIG_IEE -+ // Free iee stack. -+ iee_stack = (void *)iee_read_token_stack(tsk); -+ if (iee_stack) { -+ iee_set_kernel_ppage( -+ (unsigned long)(iee_stack - PAGE_SIZE * 4)); -+ free_pages((unsigned long)(iee_stack - PAGE_SIZE * 4), 3); -+ } -+ // Free task_token. -+ // Empty the token -+ iee_free_token(tsk); -+ -+#ifdef CONFIG_KOI -+ // Free koi stack. -+ unsigned long koi_stack = iee_rw_gate(IEE_READ_KOI_STACK_BASE, current); -+ if (koi_stack != 0) -+ free_pages(koi_stack, 2); ++extern struct kmem_cache *iee_stack_jar; ++extern struct kmem_cache *cred_jar; ++extern struct kmem_cache *key_jar; ++extern struct kmem_cache *pgtable_jar; ++extern struct kmem_cache *ptdesc_jar; ++extern struct kmem_cache *key_union_jar; ++extern struct kmem_cache *key_struct_jar; ++extern struct kmem_cache *key_payload_jar; ++extern void iee_memset(void *ptr, int data, size_t n); +#endif -+#else -+#ifdef CONFIG_KOI -+// free koi stack -+ struct task_token *token = (struct task_token *)((unsigned long)current + koi_offset); -+ unsigned long flags; -+ local_irq_save(flags); -+ asm volatile( -+ "at s1e1r, %0\n" -+ "isb\n" -+ : -+ :"r"(token)); -+ unsigned long res = read_sysreg(par_el1); -+ local_irq_restore(flags); -+ if (!(res & 0x1)) { -+ unsigned long koi_stack = token->koi_stack_base; -+ if (koi_stack != 0) -+ free_pages(koi_stack, 2); -+ } ++#if defined(CONFIG_KOI) || defined(CONFIG_IEE) ++extern struct kmem_cache *task_struct_cachep; +#endif ++#ifdef CONFIG_IEE_SELINUX_P ++extern struct kmem_cache *policy_jar; +#endif + - #ifdef CONFIG_QOS_SCHED_SMART_GRID - if (smart_grid_enabled()) - sched_grid_qos_free(tsk); -@@ -657,7 +709,7 @@ static void dup_mm_exe_file(struct mm_struct *mm, struct mm_struct *oldmm) + /* + * Freelist pointer and counter to cmpxchg together, avoids the typical ABA + * problems with cmpxchg of just a pointer. +@@ -843,6 +861,15 @@ static inline void cache_random_seq_destroy(struct kmem_cache *cachep) { } - #ifdef CONFIG_MMU - static __latent_entropy int dup_mmap(struct mm_struct *mm, -- struct mm_struct *oldmm) -+ struct mm_struct *oldmm) + static inline bool slab_want_init_on_alloc(gfp_t flags, struct kmem_cache *c) { - struct vm_area_struct *mpnt, *tmp; - int retval; -@@ -773,7 +825,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, - flush_dcache_mmap_lock(mapping); - /* insert tmp into the share list, just after mpnt */ - vma_interval_tree_insert_after(tmp, mpnt, -- &mapping->i_mmap); -+ &mapping->i_mmap); - flush_dcache_mmap_unlock(mapping); - i_mmap_unlock_write(mapping); - } -@@ -842,7 +894,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) - mmap_write_unlock(oldmm); - return 0; - } --#define mm_alloc_pgd(mm) (0) -+#define mm_alloc_pgd(mm) (0) - #define mm_free_pgd(mm) - #endif /* CONFIG_MMU */ ++ #ifdef CONFIG_IEE ++ if(c == iee_stack_jar) ++ return false; ++ #endif ++ #ifdef CONFIG_PTP ++ if(c == pgtable_jar) ++ return false; ++ #endif ++ + if (static_branch_maybe(CONFIG_INIT_ON_ALLOC_DEFAULT_ON, + &init_on_alloc)) { + if (c->ctor) +diff --git a/mm/slab_common.c b/mm/slab_common.c +index 8d431193c273..c755e7320111 100644 +--- a/mm/slab_common.c ++++ b/mm/slab_common.c +@@ -145,6 +145,24 @@ int slab_unmergeable(struct kmem_cache *s) + if (s->ctor) + return 1; -@@ -850,20 +902,22 @@ static void check_mm(struct mm_struct *mm) - { - int i; ++ #ifdef CONFIG_IEE ++ if(strcmp(s->name, "iee_stack_jar") == 0) ++ return 1; ++ #endif ++ #ifdef CONFIG_PTP ++ if(strcmp(s->name, "pgtable_jar") == 0) ++ return 1; ++ #endif ++ #ifdef CONFIG_KEYP ++ if((strcmp(s->name, "key_jar") == 0) || (strcmp(s->name, "key_payload_jar") == 0)) ++ return 1; ++ #endif ++ #ifdef CONFIG_IEE_SELINUX_P ++ if(strcmp(s->name, "policy_jar") == 0) ++ return 1; ++ #endif ++ ++ + #ifdef CONFIG_HARDENED_USERCOPY + if (s->usersize) + return 1; +@@ -170,6 +188,23 @@ struct kmem_cache *find_mergeable(unsigned int size, unsigned int align, + if (ctor) + return NULL; -- BUILD_BUG_ON_MSG(ARRAY_SIZE(resident_page_types) != NR_MM_COUNTERS, -- "Please make sure 'struct resident_page_types[]' is updated as well"); -+ BUILD_BUG_ON_MSG( -+ ARRAY_SIZE(resident_page_types) != NR_MM_COUNTERS, -+ "Please make sure 'struct resident_page_types[]' is updated as well"); ++ #ifdef CONFIG_IEE ++ if(strcmp(name, "iee_stack_jar") == 0) ++ return NULL; ++ #endif ++ #ifdef CONFIG_PTP ++ if(strcmp(name, "pgtable_jar") == 0) ++ return NULL; ++ #endif ++ #ifdef CONFIG_KEYP ++ if((strcmp(name, "key_jar") == 0) || (strcmp(name, "key_payload_jar") == 0)) ++ return NULL; ++ #endif ++ #ifdef CONFIG_PTP ++ if(strcmp(name, "policy_jar") == 0) ++ return NULL; ++ #endif ++ + size = ALIGN(size, sizeof(void *)); + align = calculate_alignment(flags, align, size); + size = ALIGN(size, align); +diff --git a/mm/slub.c b/mm/slub.c +index bcbfd720b574..3f05ad78eaf1 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -42,11 +42,27 @@ + #include + #include - for (i = 0; i < NR_MM_COUNTERS; i++) { - long x = mm_counter_sum(mm, i); ++#ifdef CONFIG_IEE ++#include ++#include ++#include ++#endif ++#ifdef CONFIG_PTP ++#include ++extern unsigned long pgtable_jar_offset; ++#endif ++ + #include + #include - if (unlikely(x)) -- pr_alert("BUG: Bad rss-counter state mm:%p type:%s val:%ld\n", -- mm, resident_page_types[i], x); -+ pr_alert( -+ "BUG: Bad rss-counter state mm:%p type:%s val:%ld\n", -+ mm, resident_page_types[i], x); - } + #include "internal.h" - if (mm_pgtables_bytes(mm)) - pr_alert("BUG: non-zero pgtables_bytes on freeing mm: %ld\n", -- mm_pgtables_bytes(mm)); -+ mm_pgtables_bytes(mm)); ++#ifdef CONFIG_KOI ++extern void koi_add_page_mapping(unsigned long dst, unsigned long src); ++extern void koi_remove_page_mapping(unsigned long addr); ++#endif ++ ++ + /* + * Lock order: + * 1. slab_mutex (Global Mutex) +@@ -317,6 +333,7 @@ static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s) + /* + * Tracking user of a slab. + */ ++#ifndef CONFIG_IEE + #define TRACK_ADDRS_COUNT 16 + struct track { + unsigned long addr; /* Called from address */ +@@ -329,6 +346,7 @@ struct track { + }; - #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS - VM_BUG_ON_MM(mm->pmd_huge_pte, mm); -@@ -1014,14 +1068,6 @@ void __put_task_struct(struct task_struct *tsk) - } - EXPORT_SYMBOL_GPL(__put_task_struct); + enum track_item { TRACK_ALLOC, TRACK_FREE }; ++#endif --void __put_task_struct_rcu_cb(struct rcu_head *rhp) --{ -- struct task_struct *task = container_of(rhp, struct task_struct, rcu); -- -- __put_task_struct(task); --} --EXPORT_SYMBOL_GPL(__put_task_struct_rcu_cb); -- - void __init __weak arch_task_cache_init(void) { } + #ifdef SLAB_SUPPORTS_SYSFS + static int sysfs_slab_add(struct kmem_cache *); +@@ -379,7 +397,9 @@ static struct workqueue_struct *flushwq; + * freeptr_t represents a SLUB freelist pointer, which might be encoded + * and not dereferenceable if CONFIG_SLAB_FREELIST_HARDENED is enabled. + */ ++#ifndef CONFIG_IEE + typedef struct { unsigned long v; } freeptr_t; ++#endif /* -@@ -1039,8 +1085,8 @@ static void set_max_threads(unsigned int max_threads_suggested) - if (fls64(nr_pages) + fls64(PAGE_SIZE) > 64) - threads = MAX_THREADS; - else -- threads = div64_u64((u64) nr_pages * (u64) PAGE_SIZE, -- (u64) THREAD_SIZE * 8UL); -+ threads = div64_u64((u64)nr_pages * (u64)PAGE_SIZE, -+ (u64)THREAD_SIZE * 8UL); + * Returns freelist pointer (ptr). With hardening, this is obfuscated +@@ -419,7 +439,14 @@ static inline void *get_freepointer(struct kmem_cache *s, void *object) - if (threads > max_threads_suggested) - threads = max_threads_suggested; -@@ -1075,17 +1121,24 @@ void __init fork_init(void) - int i; - #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR - #ifndef ARCH_MIN_TASKALIGN --#define ARCH_MIN_TASKALIGN 0 -+#define ARCH_MIN_TASKALIGN 0 + object = kasan_reset_tag(object); + ptr_addr = (unsigned long)object + s->offset; ++ #ifdef CONFIG_IEE ++ if(s == iee_stack_jar) ++ p.v = (unsigned long)iee_read_freeptr(ptr_addr); ++ else ++ p = *(freeptr_t *)(ptr_addr); ++ #else + p = *(freeptr_t *)(ptr_addr); ++ #endif + return freelist_ptr_decode(s, p, ptr_addr); + } + +@@ -464,7 +491,19 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp) #endif - int align = max_t(int, L1_CACHE_BYTES, ARCH_MIN_TASKALIGN); - unsigned long useroffset, usersize; - /* create a slab on which task_structs can be allocated */ - task_struct_whitelist(&useroffset, &usersize); + freeptr_addr = (unsigned long)kasan_reset_tag((void *)freeptr_addr); + #ifdef CONFIG_IEE - task_struct_cachep = kmem_cache_create_usercopy("task_struct", - arch_task_struct_size, align, -- SLAB_PANIC|SLAB_ACCOUNT, -+ SLAB_PANIC|SLAB_ACCOUNT|SLAB_RED_ZONE, - useroffset, usersize, NULL); ++ if((s == iee_stack_jar) || (IS_ENABLED(CONFIG_CREDP) && (s == cred_jar)) || (IS_ENABLED(CONFIG_PTP) && (s == pgtable_jar)) || ++ (IS_ENABLED(CONFIG_KEYP) && (s == key_payload_jar)) || (IS_ENABLED(CONFIG_KEYP) && (s == key_jar))) ++ iee_set_freeptr((freeptr_t *)freeptr_addr, freelist_ptr_encode(s, fp, freeptr_addr)); ++#ifdef CONFIG_IEE_SELINUX_P ++ else if (s == policy_jar) ++ iee_set_freeptr((freeptr_t *)freeptr_addr, freelist_ptr_encode(s, fp, freeptr_addr)); ++#endif ++ else ++ *(freeptr_t *)freeptr_addr = freelist_ptr_encode(s, fp, freeptr_addr); + #else -+ task_struct_cachep = -+ kmem_cache_create_usercopy("task_struct", arch_task_struct_size, -+ align, SLAB_PANIC | SLAB_ACCOUNT, -+ useroffset, usersize, NULL); + *(freeptr_t *)freeptr_addr = freelist_ptr_encode(s, fp, freeptr_addr); + #endif + } + + /* Loop over all objects in a slab */ +@@ -809,7 +848,34 @@ static void set_track_update(struct kmem_cache *s, void *object, + depot_stack_handle_t handle) + { + struct track *p = get_track(s, object, alloc); ++#ifdef CONFIG_IEE ++ struct track tmp; ++#endif + ++#ifdef CONFIG_IEE ++ if(IS_ENABLED(CONFIG_CREDP) && (s == cred_jar)) ++ { ++ tmp = *p; ++ #ifdef CONFIG_STACKDEPOT ++ tmp.handle = handle; ++ #endif ++ tmp.addr = addr; ++ tmp.cpu = smp_processor_id(); ++ tmp.pid = current->pid; ++ tmp.when = jiffies; ++ iee_set_track(p,&tmp); ++ } ++ else ++ { ++ #ifdef CONFIG_STACKDEPOT ++ p->handle = handle; ++ #endif ++ p->addr = addr; ++ p->cpu = smp_processor_id(); ++ p->pid = current->pid; ++ p->when = jiffies; ++ } ++#else + #ifdef CONFIG_STACKDEPOT + p->handle = handle; #endif +@@ -817,6 +883,7 @@ static void set_track_update(struct kmem_cache *s, void *object, + p->cpu = smp_processor_id(); + p->pid = current->pid; + p->when = jiffies; ++#endif + } - /* do the arch specific task caches init */ -@@ -1093,8 +1146,8 @@ void __init fork_init(void) + static __always_inline void set_track(struct kmem_cache *s, void *object, +@@ -835,7 +902,14 @@ static void init_tracking(struct kmem_cache *s, void *object) + return; - set_max_threads(MAX_THREADS); + p = get_track(s, object, TRACK_ALLOC); ++ #ifdef CONFIG_IEE ++ if(IS_ENABLED(CONFIG_CREDP) && (s == cred_jar)) ++ iee_memset(p, 0, 2*sizeof(struct track)); ++ else ++ memset(p, 0, 2*sizeof(struct track)); ++ #else + memset(p, 0, 2*sizeof(struct track)); ++ #endif + } -- init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2; -- init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2; -+ init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads / 2; -+ init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads / 2; - init_task.signal->rlim[RLIMIT_SIGPENDING] = - init_task.signal->rlim[RLIMIT_NPROC]; + static void print_track(const char *s, struct track *t, unsigned long pr_time) +@@ -1045,7 +1119,14 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) + unsigned int poison_size = s->object_size; -@@ -1107,8 +1160,8 @@ void __init fork_init(void) - set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK, RLIM_INFINITY); + if (s->flags & SLAB_RED_ZONE) { ++ #ifdef CONFIG_IEE ++ if(IS_ENABLED(CONFIG_CREDP) && (s == cred_jar)) ++ iee_memset(p - s->red_left_pad, val, s->red_left_pad); ++ else ++ memset(p - s->red_left_pad, val, s->red_left_pad); ++ #else + memset(p - s->red_left_pad, val, s->red_left_pad); ++ #endif - #ifdef CONFIG_VMAP_STACK -- cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "fork:vm_stack_cache", -- NULL, free_vm_stack_cache); -+ cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "fork:vm_stack_cache", NULL, -+ free_vm_stack_cache); - #endif + if (slub_debug_orig_size(s) && val == SLUB_RED_ACTIVE) { + /* +@@ -1058,12 +1139,34 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) + } - scs_init(); -@@ -1118,7 +1171,7 @@ void __init fork_init(void) + if (s->flags & __OBJECT_POISON) { ++ #ifdef CONFIG_IEE ++ if(IS_ENABLED(CONFIG_CREDP) && (s == cred_jar)) ++ { ++ iee_memset(p, POISON_FREE, poison_size - 1); ++ iee_memset(&p[poison_size - 1], POISON_END, 1); ++ } ++ else ++ { ++ memset(p, POISON_FREE, poison_size - 1); ++ p[poison_size - 1] = POISON_END; ++ } ++ #else + memset(p, POISON_FREE, poison_size - 1); + p[poison_size - 1] = POISON_END; ++ #endif + } + +- if (s->flags & SLAB_RED_ZONE) ++ if (s->flags & SLAB_RED_ZONE) { ++ #ifdef CONFIG_IEE ++ if(IS_ENABLED(CONFIG_CREDP) && (s == cred_jar)) ++ iee_memset(p + poison_size, val, s->inuse - poison_size); ++ else ++ memset(p + poison_size, val, s->inuse - poison_size); ++ #else + memset(p + poison_size, val, s->inuse - poison_size); ++ #endif ++ ++ } } - int __weak arch_dup_task_struct(struct task_struct *dst, -- struct task_struct *src) -+ struct task_struct *src) - { - *dst = *src; - return 0; -@@ -1129,14 +1182,14 @@ void set_task_stack_end_magic(struct task_struct *tsk) - unsigned long *stackend; + static void restore_bytes(struct kmem_cache *s, char *message, u8 data, +@@ -1433,7 +1536,14 @@ void setup_slab_debug(struct kmem_cache *s, struct slab *slab, void *addr) + return; - stackend = end_of_stack(tsk); -- *stackend = STACK_END_MAGIC; /* for overflow detection */ -+ *stackend = STACK_END_MAGIC; /* for overflow detection */ + metadata_access_enable(); ++ #ifdef CONFIG_IEE ++ if(IS_ENABLED(CONFIG_CREDP) && (s == cred_jar)) ++ iee_memset(kasan_reset_tag(addr), POISON_INUSE, slab_size(slab)); ++ else ++ memset(kasan_reset_tag(addr), POISON_INUSE, slab_size(slab)); ++ #else + memset(kasan_reset_tag(addr), POISON_INUSE, slab_size(slab)); ++ #endif + metadata_access_disable(); } - static bool dup_resvd_task_struct(struct task_struct *dst, - struct task_struct *orig, int node) - { -- dst->_resvd = kzalloc_node(sizeof(struct task_struct_resvd), -- GFP_KERNEL, node); -+ dst->_resvd = kzalloc_node(sizeof(struct task_struct_resvd), GFP_KERNEL, -+ node); - if (!dst->_resvd) - return false; +@@ -1984,6 +2094,21 @@ static bool shuffle_freelist(struct kmem_cache *s, struct slab *slab) + cur = setup_object(s, cur); + slab->freelist = cur; -@@ -1309,7 +1362,7 @@ static void mm_init_uprobes_state(struct mm_struct *mm) - } ++ #ifdef CONFIG_IEE ++ if(s == task_struct_cachep) ++ { ++ int i; ++ void *pstack; ++ void *obj; ++ for(i = 0; i < freelist_count; i++) ++ { ++ pstack = get_iee_stack(); ++ obj = start + s->random_seq[i]; ++ iee_init_token((struct task_struct *)obj, pstack + PAGE_SIZE * 4, (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 0)); ++ } ++ } ++ #endif ++ + for (idx = 1; idx < slab->objects; idx++) { + next = next_freelist_entry(s, &pos, start, page_limit, + freelist_count); +@@ -2015,6 +2140,9 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) + void *start, *p, *next; + int idx; + bool shuffle; ++ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++ unsigned int order; ++ #endif - static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, -- struct user_namespace *user_ns) -+ struct user_namespace *user_ns) - { - mt_init_flags(&mm->mm_mt, MM_MT_FLAGS); - mt_set_external_lock(&mm->mm_mt, &mm->mmap_lock); -@@ -1425,8 +1478,8 @@ EXPORT_SYMBOL_GPL(mmput); - #ifdef CONFIG_MMU - static void mmput_async_fn(struct work_struct *work) - { -- struct mm_struct *mm = container_of(work, struct mm_struct, -- async_put_work); -+ struct mm_struct *mm = -+ container_of(work, struct mm_struct, async_put_work); + flags &= gfp_allowed_mask; + +@@ -2028,15 +2156,45 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) + if ((alloc_gfp & __GFP_DIRECT_RECLAIM) && oo_order(oo) > oo_order(s->min)) + alloc_gfp = (alloc_gfp | __GFP_NOMEMALLOC) & ~__GFP_RECLAIM; + ++ #ifdef CONFIG_IEE ++ if(IS_ENABLED(CONFIG_PTP) && (s == pgtable_jar)) ++ alloc_gfp |= __GFP_ZERO; ++ #ifdef CONFIG_IEE_SELINUX_P ++ if(s == policy_jar) ++ alloc_gfp |= __GFP_ZERO; ++ #endif ++ #endif ++ #ifdef CONFIG_KEYP ++ if(s == key_jar) ++ alloc_gfp |= __GFP_ZERO; ++ #endif + slab = alloc_slab_page(alloc_gfp, node, oo); ++ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++ order = oo_order(oo); ++ #endif + if (unlikely(!slab)) { + oo = s->min; + alloc_gfp = flags; ++ #ifdef CONFIG_IEE ++ if(IS_ENABLED(CONFIG_PTP) && (s == pgtable_jar)) ++ alloc_gfp |= __GFP_ZERO; ++ #ifdef CONFIG_IEE_SELINUX_P ++ if(s == policy_jar) ++ alloc_gfp |= __GFP_ZERO; ++ #endif ++ #endif ++ #ifdef CONFIG_KEYP ++ if(s == key_jar) ++ alloc_gfp |= __GFP_ZERO; ++ #endif + /* + * Allocation may have failed due to fragmentation. + * Try a lower order alloc if possible + */ + slab = alloc_slab_page(alloc_gfp, node, oo); ++ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++ order = oo_order(oo); ++ #endif + if (unlikely(!slab)) + return NULL; + stat(s, ORDER_FALLBACK); +@@ -2046,9 +2204,71 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) + slab->inuse = 0; + slab->frozen = 0; + ++ #ifdef CONFIG_IEE ++ if(IS_ENABLED(CONFIG_PTP) && (s == pgtable_jar)) ++ { ++ int i; ++ struct page *page = folio_page(slab_folio(slab), 0); ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ set_page_refcounted(page + i); ++ (slab+i)->slab_cache = kmem_cache_alloc(ptdesc_jar, GFP_KERNEL); ++ ((struct ptdesc_t *)((slab+i)->slab_cache))->slab = (struct slab_t *)(slab+i); ++ __folio_set_slab((struct folio *)(slab+i)); ++ } ++ set_iee_page((unsigned long)page_address(page), order); ++ } ++ ++ if(IS_ENABLED(CONFIG_CREDP) && (s == cred_jar)) ++ { ++ set_iee_page((unsigned long)page_address(folio_page(slab_folio(slab), 0)), order); ++ } ++ ++ if(IS_ENABLED(CONFIG_KEYP) && ((s == key_jar) || (s == key_payload_jar))) ++ { ++ set_iee_page((unsigned long)page_address(folio_page(slab_folio(slab), 0)), order); ++ } ++ ++ #ifdef CONFIG_IEE_SELINUX_P ++ if(s == policy_jar) ++ { ++ set_iee_page((unsigned long)page_address(folio_page(slab_folio(slab), 0)), order); ++ } ++ #endif ++ ++ if(s == iee_stack_jar) ++ { ++ set_iee_stack_page((unsigned long)page_address(folio_page(slab_folio(slab), 0)), order); ++ } ++ ++ // If the page belongs to a task_struct, alloc token for it and set iee&lm va. ++ if(s == task_struct_cachep) ++ { ++ void *token_addr = (void *)__phys_to_iee(page_to_phys(folio_page(slab_folio(slab), 0))); ++ void *alloc_token = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order); ++ iee_set_token_page_valid(token_addr, alloc_token, order); ++ } ++ #else ++ #ifdef CONFIG_KOI ++ if (s == task_struct_cachep) { ++ int i; ++ for (i = 0; i < (0x1 << order); i++) { ++ unsigned long token_addr = __phys_to_virt(page_to_phys(folio_page(slab_folio(slab), i))) + (unsigned long)KOI_OFFSET; ++ unsigned long alloc_token = __get_free_page(GFP_KERNEL | __GFP_ZERO); ++ koi_add_page_mapping(token_addr, alloc_token); ++ } ++ } ++ #endif ++ #endif ++ + account_slab(slab, oo_order(oo), s, flags); - __mmput(mm); - } -@@ -1602,13 +1655,12 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) - struct mm_struct *mm; - int err; ++ #ifdef CONFIG_PTP ++ if(!(s == pgtable_jar)) ++ slab->slab_cache = s; ++ #else + slab->slab_cache = s; ++ #endif -- err = down_read_killable(&task->signal->exec_update_lock); -+ err = down_read_killable(&task->signal->exec_update_lock); - if (err) - return ERR_PTR(err); + kasan_poison_slab(slab); - mm = get_task_mm(task); -- if (mm && mm != current->mm && -- !ptrace_may_access(task, mode)) { -+ if (mm && mm != current->mm && !ptrace_may_access(task, mode)) { - mmput(mm); - mm = ERR_PTR(-EACCES); - } -@@ -1631,7 +1683,7 @@ static void complete_vfork_done(struct task_struct *tsk) +@@ -2098,6 +2318,98 @@ static void __free_slab(struct kmem_cache *s, struct slab *slab) + __folio_clear_slab(folio); + mm_account_reclaimed_pages(pages); + unaccount_slab(slab, order, s); ++ ++ #ifdef CONFIG_IEE ++ if(IS_ENABLED(CONFIG_PTP) && (s == pgtable_jar)) ++ { ++ int i; ++ unset_iee_page((unsigned long)page_address(folio_page(folio, 0)), order); ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ set_page_count(folio_page(folio, i), 0); ++ } ++ } ++ ++ if(IS_ENABLED(CONFIG_CREDP) && (s == cred_jar)) ++ { ++ unset_iee_page((unsigned long)page_address(folio_page(folio, 0)), order); ++ } ++ ++ if(IS_ENABLED(CONFIG_KEYP) && ((s == key_jar) || (s == key_payload_jar))) ++ { ++ unset_iee_page((unsigned long)page_address(folio_page(folio, 0)), order); ++ } ++ ++ #ifdef CONFIG_IEE_SELINUX_P ++ if(s == policy_jar) ++ { ++ unset_iee_page((unsigned long)page_address(folio_page(folio, 0)), order); ++ } ++ #endif ++ ++ if(s == iee_stack_jar) ++ { ++ unset_iee_stack_page((unsigned long)page_address(folio_page(folio, 0)), order); ++ } ++ ++ // If the page containing this token is empty, free it and restore iee&lm va. ++ if(s == task_struct_cachep) ++ { ++ // Free stack. ++ int i; ++ void *start = fixup_red_left(s, page_address(folio_page(folio, 0))); ++ void *obj; ++ void *iee_stack; ++ void *tmp_page; ++ void *token_addr; ++ for(i = 0; i < oo_objects(s->oo); i++) ++ { ++ obj = start + s->random_seq[i]; ++ tmp_page = iee_read_tmp_page((struct task_struct *)obj); ++ free_pages((unsigned long)tmp_page, 0); ++ iee_stack = (void *)iee_read_token_stack((struct task_struct *)obj); ++ if (iee_stack) { ++ free_iee_stack((void *)(iee_stack - PAGE_SIZE * 4)); ++ } ++ } ++ // Free token. ++ token_addr = (void *)__phys_to_iee(page_to_phys(folio_page(folio, 0))); ++ { ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, (unsigned long)token_addr); ++ p4d_t *p4dp = p4d_offset(pgdp, (unsigned long)token_addr); ++ pud_t *pudp = pud_offset(p4dp, (unsigned long)token_addr); ++ pmd_t *pmdp = pmd_offset(pudp, (unsigned long)token_addr); ++ pte_t *ptep = pte_offset_kernel(pmdp, (unsigned long)token_addr); ++ void *token_page = page_address(pte_page(*ptep)); ++ iee_set_token_page_invalid(token_addr, token_page, order); ++ free_pages((unsigned long)token_page, order); ++ } ++ } ++ #else ++ #ifdef CONFIG_KOI ++ if(s == task_struct_cachep) ++ { ++ int i; ++ for(i = 0; i < (0x1 << order); i++) ++ { ++ unsigned long token_addr = __phys_to_virt(page_to_phys(folio_page(folio, i))) + (unsigned long)KOI_OFFSET; ++ unsigned long flags; ++ local_irq_save(flags); ++ asm volatile("at s1e1r, %0"::"r"(token_addr)); ++ isb(); ++ unsigned long res = read_sysreg(par_el1); ++ local_irq_restore(flags); ++ if(!(res & 0x1)) ++ { ++ koi_remove_page_mapping(token_addr); ++ free_page((unsigned long)__va(res & PTE_ADDR_MASK)); ++ } ++ } ++ } ++ #endif ++ #endif ++ + __free_pages(&folio->page, order); } - static int wait_for_vfork_done(struct task_struct *child, -- struct completion *vfork) -+ struct completion *vfork) - { - unsigned int state = TASK_UNINTERRUPTIBLE|TASK_KILLABLE|TASK_FREEZABLE; - int killed; -@@ -1682,8 +1734,8 @@ static void mm_release(struct task_struct *tsk, struct mm_struct *mm) - * not set up a proper pointer then tough luck. - */ - put_user(0, tsk->clear_child_tid); -- do_futex(tsk->clear_child_tid, FUTEX_WAKE, -- 1, NULL, NULL, 0, 0); -+ do_futex(tsk->clear_child_tid, FUTEX_WAKE, 1, NULL, -+ NULL, 0, 0); - } - tsk->clear_child_tid = NULL; - } -@@ -1767,6 +1819,10 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) - #endif - - tsk->mm = NULL; -+#ifdef CONFIG_IEE -+ iee_set_token_mm(tsk, NULL); -+ iee_set_token_pgd(tsk, NULL); -+#endif - tsk->active_mm = NULL; - - /* -@@ -1798,6 +1854,10 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) +@@ -2118,6 +2430,23 @@ static void free_slab(struct kmem_cache *s, struct slab *slab) + check_object(s, slab, p, SLUB_RED_INACTIVE); } - tsk->mm = mm; -+#ifdef CONFIG_IEE -+ iee_set_token_mm(tsk, mm); -+ iee_set_token_pgd(tsk, mm->pgd); -+#endif - tsk->active_mm = mm; - sched_mm_cid_fork(tsk); - return 0; -@@ -2015,8 +2075,8 @@ static inline void init_task_pid_links(struct task_struct *task) - INIT_HLIST_NODE(&task->pid_links[type]); - } - --static inline void --init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid) -+static inline void init_task_pid(struct task_struct *task, enum pid_type type, -+ struct pid *pid) - { - if (type == PIDTYPE_PID) - task->thread_pid = pid; -@@ -2277,6 +2337,12 @@ static void copy_oom_score_adj(u64 clone_flags, struct task_struct *tsk) - mutex_unlock(&oom_adj_mutex); ++ #ifdef CONFIG_PTP ++ struct page *page = folio_page(slab_folio(slab), 0); ++ int order = compound_order(page); ++ if(s == pgtable_jar) ++ { ++ int i; ++ kmem_cache_free(ptdesc_jar, slab->slab_cache); ++ slab->slab_cache = s; ++ for(i = 1; i < (0x1 << order); i++) ++ { ++ kmem_cache_free(ptdesc_jar, (slab+i)->slab_cache); ++ set_compound_head(page+i,page); ++ __folio_clear_slab((struct folio *)(slab+i)); ++ } ++ } ++ #endif ++ + if (unlikely(s->flags & SLAB_TYPESAFE_BY_RCU)) + call_rcu(&slab->rcu_head, rcu_free_slab); + else +@@ -4285,6 +4614,35 @@ static void early_kmem_cache_node_alloc(int node) + __add_partial(n, slab, DEACTIVATE_TO_HEAD); } -+#if defined(CONFIG_KOI) && !defined(CONFIG_IEE) -+extern s64 koi_offset; -+extern int koi_add_page_mapping(unsigned long dst, unsigned long src); -+#endif ++#ifdef CONFIG_PTP ++void early_pgtable_jar_alloc(struct kmem_cache *pgtable_jar) ++{ ++ struct slab *slab; ++ int node = 0; ++ int i = 0; ++ ++ for(i = 0; i < nr_cpu_ids; i++) ++ { ++ node = cpupid_to_nid(i); ++ slab = new_slab(pgtable_jar, GFP_NOWAIT | __GFP_ZERO, node); + ++ BUG_ON(!slab); ++ if (slab_nid(slab) != node) { ++ pr_err("SLUB: Unable to allocate memory from node %d\n", node); ++ pr_err("SLUB: Allocating a useless per node structure in order to be able to continue\n"); ++ } + - #ifdef CONFIG_RV - static void rv_task_fork(struct task_struct *p) ++ slab->inuse = 0; ++ ++ /* ++ * No locks need to be taken here as it has just been ++ * initialized and there is no concurrent access. ++ */ ++ __add_partial(get_node(pgtable_jar, slab_nid(slab)), slab, DEACTIVATE_TO_HEAD); ++ } ++} ++#endif ++ + static void free_kmem_cache_nodes(struct kmem_cache *s) { -@@ -2309,15 +2375,21 @@ __latent_entropy struct task_struct *copy_process( - struct file *pidfile = NULL; - const u64 clone_flags = args->flags; - struct nsproxy *nsp = current->nsproxy; + int node; +@@ -4479,6 +4837,31 @@ static int calculate_sizes(struct kmem_cache *s) + s->reciprocal_size = reciprocal_value(size); + order = calculate_order(size); + + #ifdef CONFIG_IEE -+ gfp_t gfp; -+ void *pstack; ++ if(strcmp(s->name, "task_struct") == 0) ++ order = HUGE_PMD_ORDER; ++ if(strcmp(s->name, "iee_stack_jar") == 0) ++ order = HUGE_PMD_ORDER; ++ #endif ++ #ifdef CONFIG_PTP ++ if(strcmp(s->name, "pgtable_jar") == 0) ++ order = HUGE_PMD_ORDER; ++ #endif ++ #ifdef CONFIG_CREDP ++ if(strcmp(s->name, "cred_jar") == 0) ++ order = HUGE_PMD_ORDER; + #endif ++ #ifdef CONFIG_KEYP ++ if(strcmp(s->name, "key_jar") == 0) ++ order = HUGE_PMD_ORDER; ++ if(strcmp(s->name, "key_payload_jar") == 0) ++ order = HUGE_PMD_ORDER; ++ #endif ++ #ifdef CONFIG_IEE_SELINUX_P ++ if(strcmp(s->name, "policy_jar") == 0) ++ order = HUGE_PMD_ORDER; ++ #endif ++ + if ((int)order < 0) + return 0; - /* - * Don't allow sharing the root directory with processes in a different - * namespace - */ -- if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) -+ if ((clone_flags & (CLONE_NEWNS | CLONE_FS)) == -+ (CLONE_NEWNS | CLONE_FS)) - return ERR_PTR(-EINVAL); +@@ -4540,6 +4923,23 @@ static int kmem_cache_open(struct kmem_cache *s, slab_flags_t flags) + s->min_partial = min_t(unsigned long, MAX_PARTIAL, ilog2(s->size) / 2); + s->min_partial = max_t(unsigned long, MIN_PARTIAL, s->min_partial); -- if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS)) -+ if ((clone_flags & (CLONE_NEWUSER | CLONE_FS)) == -+ (CLONE_NEWUSER | CLONE_FS)) - return ERR_PTR(-EINVAL); ++ #ifdef CONFIG_IEE ++ if(strcmp(s->name, "task_struct") == 0) ++ s->min_partial *= (1 << TASK_ORDER); ++ if(strcmp(s->name, "iee_stack_jar") == 0) ++ s->min_partial *= (1 << TASK_ORDER); ++ #endif ++ #ifdef CONFIG_PTP ++ if(strcmp(s->name, "pgtable_jar") == 0) ++ s->min_partial = (1 << HUGE_PMD_ORDER); ++ #endif ++ #ifdef CONFIG_KEYP ++ if(strcmp(s->name, "key_jar") == 0) ++ s->min_partial = (1 << TASK_ORDER); ++ if(strcmp(s->name, "key_payload_jar") == 0) ++ s->min_partial = (1 << TASK_ORDER); ++ #endif ++ + set_cpu_partial(s); - /* -@@ -2342,7 +2414,7 @@ __latent_entropy struct task_struct *copy_process( - * from creating siblings. - */ - if ((clone_flags & CLONE_PARENT) && -- current->signal->flags & SIGNAL_UNKILLABLE) -+ current->signal->flags & SIGNAL_UNKILLABLE) - return ERR_PTR(-EINVAL); + #ifdef CONFIG_NUMA +@@ -5113,6 +5513,11 @@ int __kmem_cache_create(struct kmem_cache *s, slab_flags_t flags) + if (err) + return err; - /* -@@ -2387,6 +2459,15 @@ __latent_entropy struct task_struct *copy_process( - p = dup_task_struct(current, node); - if (!p) - goto fork_out; -+ #ifdef CONFIG_IEE -+ // Alloc iee stack. -+ gfp = GFP_KERNEL; -+ pstack = (void *)__get_free_pages(gfp, 3); -+ iee_set_kernel_upage((unsigned long)pstack); -+ // Init token. -+ iee_init_token(p, NULL, pstack + PAGE_SIZE * 4); ++ #ifdef CONFIG_PTP ++ if(strcmp(s->name, "pgtable_jar") == 0) ++ pgtable_jar_offset = s->offset; + #endif + - p->flags &= ~PF_KTHREAD; - if (args->kthread) - p->flags |= PF_KTHREAD; -@@ -2408,7 +2489,8 @@ __latent_entropy struct task_struct *copy_process( - /* - * Clear TID on mm_release()? - */ -- p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? args->child_tid : NULL; -+ p->clear_child_tid = -+ (clone_flags & CLONE_CHILD_CLEARTID) ? args->child_tid : NULL; + /* Mutex is not taken during early boot */ + if (slab_state <= UP) + return 0; +diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c +index a2cbe44c48e1..6b118447f197 100644 +--- a/mm/sparse-vmemmap.c ++++ b/mm/sparse-vmemmap.c +@@ -28,6 +28,10 @@ + #include + #include - ftrace_graph_init_task(p); ++#ifdef CONFIG_PTP ++#include ++#endif ++ + #include + #include -@@ -2519,10 +2601,10 @@ __latent_entropy struct task_struct *copy_process( - #endif - #ifdef CONFIG_TRACE_IRQFLAGS - memset(&p->irqtrace, 0, sizeof(p->irqtrace)); -- p->irqtrace.hardirq_disable_ip = _THIS_IP_; -- p->irqtrace.softirq_enable_ip = _THIS_IP_; -- p->softirqs_enabled = 1; -- p->softirq_context = 0; -+ p->irqtrace.hardirq_disable_ip = _THIS_IP_; -+ p->irqtrace.softirq_enable_ip = _THIS_IP_; -+ p->softirqs_enabled = 1; -+ p->softirq_context = 0; - #endif +@@ -146,6 +150,7 @@ pte_t * __meminit vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node, + struct page *reuse) + { + pte_t *pte = pte_offset_kernel(pmd, addr); ++ + if (pte_none(ptep_get(pte))) { + pte_t entry; + void *p; +@@ -167,6 +172,9 @@ pte_t * __meminit vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node, + get_page(reuse); + p = page_to_virt(reuse); + } ++#ifdef CONFIG_PTP ++ set_iee_page((unsigned long)p,0); ++#endif + entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL); + set_pte_at(&init_mm, addr, pte, entry); + } +@@ -181,6 +189,10 @@ static void * __meminit vmemmap_alloc_block_zero(unsigned long size, int node) + return NULL; + memset(p, 0, size); - p->pagefault_disabled = 0; -@@ -2535,8 +2617,8 @@ __latent_entropy struct task_struct *copy_process( - p->blocked_on = NULL; /* not blocked yet */ - #endif - #ifdef CONFIG_BCACHE -- p->sequential_io = 0; -- p->sequential_io_avg = 0; -+ p->sequential_io = 0; -+ p->sequential_io_avg = 0; - #endif - #ifdef CONFIG_BPF_SYSCALL - RCU_INIT_POINTER(p->bpf_storage, NULL); -@@ -2623,7 +2705,7 @@ __latent_entropy struct task_struct *copy_process( - /* - * sigaltstack should be cleared when sharing the same VM - */ -- if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM) -+ if ((clone_flags & (CLONE_VM | CLONE_VFORK)) == CLONE_VM) - sas_ss_reset(p); ++ #ifdef CONFIG_PTP ++ set_iee_page_valid(__phys_to_iee(__pa(p))); ++ #endif ++ + return p; + } - /* -@@ -2702,7 +2784,7 @@ __latent_entropy struct task_struct *copy_process( - write_lock_irq(&tasklist_lock); +diff --git a/mm/vmalloc.c b/mm/vmalloc.c +index cb0951fea238..6cefa902facb 100644 +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -3458,7 +3458,7 @@ static int vmap_pfn_apply(pte_t *pte, unsigned long addr, void *private) - /* CLONE_PARENT re-uses the old parent */ -- if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) { -+ if (clone_flags & (CLONE_PARENT | CLONE_THREAD)) { - p->real_parent = current->real_parent; - p->parent_exec_id = current->parent_exec_id; - if (clone_flags & CLONE_THREAD) -@@ -2766,8 +2848,9 @@ __latent_entropy struct task_struct *copy_process( - * tasklist_lock with adding child to the process tree - * for propagate_has_child_subreaper optimization. - */ -- p->signal->has_child_subreaper = p->real_parent->signal->has_child_subreaper || -- p->real_parent->signal->is_child_subreaper; -+ p->signal->has_child_subreaper = -+ p->real_parent->signal->has_child_subreaper || -+ p->real_parent->signal->is_child_subreaper; - list_add_tail(&p->sibling, &p->real_parent->children); - list_add_tail_rcu(&p->tasks, &init_task.tasks); - attach_pid(p, PIDTYPE_TGID); -@@ -2918,8 +3001,8 @@ struct task_struct * __init fork_idle(int cpu) - */ - struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node) + if (WARN_ON_ONCE(pfn_valid(pfn))) + return -EINVAL; +- ++ + ptent = pte_mkspecial(pfn_pte(pfn, data->prot)); + set_pte_at(&init_mm, addr, pte, ptent); + +diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c +index 4c6441536d55..2483f38d6eca 100644 +--- a/net/ceph/ceph_common.c ++++ b/net/ceph/ceph_common.c +@@ -385,7 +385,11 @@ static int get_secret(struct ceph_crypto_key *dst, const char *name, + goto out; + } + ++ #ifdef CONFIG_KEYP ++ ckey = ((union key_payload *)(ukey->name_link.next))->data[0]; ++ #else + ckey = ukey->payload.data[0]; ++ #endif + err = ceph_crypto_key_clone(dst, ckey); + if (err) + goto out_key; +diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c +index 051d22c0e4ad..cd5839ea3000 100644 +--- a/net/ceph/crypto.c ++++ b/net/ceph/crypto.c +@@ -336,7 +336,11 @@ static void ceph_key_free_preparse(struct key_preparsed_payload *prep) + + static void ceph_key_destroy(struct key *key) { -- unsigned long flags = CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD| -- CLONE_IO; -+ unsigned long flags = CLONE_FS | CLONE_FILES | CLONE_SIGHAND | -+ CLONE_THREAD | CLONE_IO; - struct kernel_clone_args args = { - .flags = ((lower_32_bits(flags) | CLONE_VM | - CLONE_UNTRACED) & ~CSIGNAL), -@@ -3083,8 +3166,8 @@ SYSCALL_DEFINE0(fork) - SYSCALL_DEFINE0(vfork) ++ #ifdef CONFIG_KEYP ++ struct ceph_crypto_key *ckey = ((union key_payload *)(key->name_link.next))->data[0]; ++ #else + struct ceph_crypto_key *ckey = key->payload.data[0]; ++ #endif + + ceph_crypto_key_destroy(ckey); + kfree(ckey); +diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c +index c42ddd85ff1f..8450eb924b62 100644 +--- a/net/dns_resolver/dns_key.c ++++ b/net/dns_resolver/dns_key.c +@@ -34,6 +34,13 @@ + #include + #include "internal.h" + ++#ifdef CONFIG_CREDP ++#include ++#endif ++#ifdef CONFIG_KEYP ++#include ++#endif ++ + MODULE_DESCRIPTION("DNS Resolver"); + MODULE_AUTHOR("Wang Lei"); + MODULE_LICENSE("GPL"); +@@ -295,7 +302,11 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m) { - struct kernel_clone_args args = { -- .flags = CLONE_VFORK | CLONE_VM, -- .exit_signal = SIGCHLD, -+ .flags = CLONE_VFORK | CLONE_VM, -+ .exit_signal = SIGCHLD, - }; + seq_puts(m, key->description); + if (key_is_positive(key)) { ++ #ifdef CONFIG_KEYP ++ int err = PTR_ERR(((union key_payload *)(key->name_link.next))->data[dns_key_error]); ++ #else + int err = PTR_ERR(key->payload.data[dns_key_error]); ++ #endif - return kernel_clone(&args); -@@ -3094,35 +3177,30 @@ SYSCALL_DEFINE0(vfork) - #ifdef __ARCH_WANT_SYS_CLONE - #ifdef CONFIG_CLONE_BACKWARDS - SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, -- int __user *, parent_tidptr, -- unsigned long, tls, -- int __user *, child_tidptr) -+ int __user *, parent_tidptr, unsigned long, tls, int __user *, -+ child_tidptr) - #elif defined(CONFIG_CLONE_BACKWARDS2) - SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags, -- int __user *, parent_tidptr, -- int __user *, child_tidptr, -- unsigned long, tls) --#elif defined(CONFIG_CLONE_BACKWARDS3) --SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp, -- int, stack_size, -- int __user *, parent_tidptr, -- int __user *, child_tidptr, -+ int __user *, parent_tidptr, int __user *, child_tidptr, - unsigned long, tls) -+#elif defined(CONFIG_CLONE_BACKWARDS3) -+SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp, int, -+ stack_size, int __user *, parent_tidptr, int __user *, -+ child_tidptr, unsigned long, tls) - #else - SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, -- int __user *, parent_tidptr, -- int __user *, child_tidptr, -- unsigned long, tls) -+ int __user *, parent_tidptr, int __user *, child_tidptr, -+ unsigned long, tls) - #endif + if (err) + seq_printf(m, ": %d", err); +@@ -311,7 +322,11 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m) + static long dns_resolver_read(const struct key *key, + char *buffer, size_t buflen) { - struct kernel_clone_args args = { -- .flags = (lower_32_bits(clone_flags) & ~CSIGNAL), -- .pidfd = parent_tidptr, -- .child_tid = child_tidptr, -- .parent_tid = parent_tidptr, -- .exit_signal = (lower_32_bits(clone_flags) & CSIGNAL), -- .stack = newsp, -- .tls = tls, -+ .flags = (lower_32_bits(clone_flags) & ~CSIGNAL), -+ .pidfd = parent_tidptr, -+ .child_tid = child_tidptr, -+ .parent_tid = parent_tidptr, -+ .exit_signal = (lower_32_bits(clone_flags) & CSIGNAL), -+ .stack = newsp, -+ .tls = tls, - }; ++ #ifdef CONFIG_KEYP ++ int err = PTR_ERR(((union key_payload *)(key->name_link.next))->data[dns_key_error]); ++ #else + int err = PTR_ERR(key->payload.data[dns_key_error]); ++ #endif - return kernel_clone(&args); -@@ -3178,21 +3256,21 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, - return -EINVAL; + if (err) + return err; +@@ -364,9 +379,18 @@ static int __init init_dns_resolver(void) - *kargs = (struct kernel_clone_args){ -- .flags = args.flags, -- .pidfd = u64_to_user_ptr(args.pidfd), -- .child_tid = u64_to_user_ptr(args.child_tid), -- .parent_tid = u64_to_user_ptr(args.parent_tid), -- .exit_signal = args.exit_signal, -- .stack = args.stack, -- .stack_size = args.stack_size, -- .tls = args.tls, -- .set_tid_size = args.set_tid_size, -- .cgroup = args.cgroup, -+ .flags = args.flags, -+ .pidfd = u64_to_user_ptr(args.pidfd), -+ .child_tid = u64_to_user_ptr(args.child_tid), -+ .parent_tid = u64_to_user_ptr(args.parent_tid), -+ .exit_signal = args.exit_signal, -+ .stack = args.stack, -+ .stack_size = args.stack_size, -+ .tls = args.tls, -+ .set_tid_size = args.set_tid_size, -+ .cgroup = args.cgroup, - }; + /* instruct request_key() to use this special keyring as a cache for + * the results it looks up */ ++ #ifdef CONFIG_KEYP ++ iee_set_key_flag_bit(keyring, KEY_FLAG_ROOT_CAN_CLEAR, SET_BIT_OP); ++ #else + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); ++ #endif ++ #ifdef CONFIG_CREDP ++ iee_set_cred_thread_keyring(cred,keyring); ++ iee_set_cred_jit_keyring(cred,KEY_REQKEY_DEFL_THREAD_KEYRING); ++ #else + cred->thread_keyring = keyring; + cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; ++ #endif + dns_resolver_cache = cred; - if (args.set_tid && -- copy_from_user(kset_tid, u64_to_user_ptr(args.set_tid), -- (kargs->set_tid_size * sizeof(pid_t)))) -+ copy_from_user(kset_tid, u64_to_user_ptr(args.set_tid), -+ (kargs->set_tid_size * sizeof(pid_t)))) - return -EFAULT; + kdebug("DNS resolver keyring: %d\n", key_serial(keyring)); +diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c +index 82b084cc1cc6..2bebc6eef501 100644 +--- a/net/dns_resolver/dns_query.c ++++ b/net/dns_resolver/dns_query.c +@@ -47,6 +47,10 @@ - kargs->set_tid = kset_tid; -@@ -3287,7 +3365,8 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size) - } - #endif + #include "internal.h" --void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data) -+void walk_process_tree(struct task_struct *top, proc_visitor visitor, -+ void *data) - { - struct task_struct *leader, *parent, *child; - int res; -@@ -3295,8 +3374,8 @@ void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data - read_lock(&tasklist_lock); - leader = top = top->group_leader; - down: -- for_each_thread(leader, parent) { -- list_for_each_entry(child, &parent->children, sibling) { -+ for_each_thread (leader, parent) { -+ list_for_each_entry (child, &parent->children, sibling) { - res = visitor(child, data); - if (res) { - if (res < 0) -@@ -3304,8 +3383,7 @@ void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data - leader = child; - goto down; - } --up: -- ; -+ up:; - } ++#ifdef CONFIG_KEYP ++#include ++#endif ++ + /** + * dns_query - Query the DNS + * @net: The network namespace to operate in. +@@ -133,16 +137,26 @@ int dns_query(struct net *net, + goto out; } -@@ -3382,11 +3460,11 @@ void __init proc_caches_init(void) - */ - static int check_unshare_flags(unsigned long unshare_flags) - { -- if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| -- CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| -- CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET| -- CLONE_NEWUSER|CLONE_NEWPID|CLONE_NEWCGROUP| -- CLONE_NEWTIME)) -+ if (unshare_flags & -+ ~(CLONE_THREAD | CLONE_FS | CLONE_NEWNS | CLONE_SIGHAND | CLONE_VM | -+ CLONE_FILES | CLONE_SYSVSEM | CLONE_NEWUTS | CLONE_NEWIPC | -+ CLONE_NEWNET | CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWCGROUP | -+ CLONE_NEWTIME)) - return -EINVAL; - /* - * Not implemented, but pretend it works if there is nothing -@@ -3497,7 +3575,7 @@ int ksys_unshare(unsigned long unshare_flags) - * to a new ipc namespace, the semaphore arrays from the old - * namespace are unreachable. - */ -- if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM)) -+ if (unshare_flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) - do_sysvsem = 1; - err = unshare_fs(unshare_flags, &new_fs); - if (err) -@@ -3508,8 +3586,8 @@ int ksys_unshare(unsigned long unshare_flags) - err = unshare_userns(unshare_flags, &new_cred); - if (err) - goto bad_unshare_cleanup_fd; -- err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, -- new_cred, new_fs); -+ err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, new_cred, -+ new_fs); - if (err) - goto bad_unshare_cleanup_cred; ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(rkey)); ++ iee_set_key_flag_bit(rkey, KEY_FLAG_ROOT_CAN_INVAL, SET_BIT_OP); ++ iee_set_key_perm(rkey, rkey->perm | KEY_USR_VIEW); ++ #else + down_read(&rkey->sem); + set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags); + rkey->perm |= KEY_USR_VIEW; ++ #endif + + ret = key_validate(rkey); + if (ret < 0) + goto put; -@@ -3606,8 +3684,8 @@ int unshare_files(void) - return 0; - } + /* If the DNS server gave an error, return that to the caller */ ++ #ifdef CONFIG_KEYP ++ ret = PTR_ERR(((union key_payload *)(rkey->name_link.next))->data[dns_key_error]); ++ #else + ret = PTR_ERR(rkey->payload.data[dns_key_error]); ++ #endif + if (ret) + goto put; --int sysctl_max_threads(struct ctl_table *table, int write, -- void *buffer, size_t *lenp, loff_t *ppos) -+int sysctl_max_threads(struct ctl_table *table, int write, void *buffer, -+ size_t *lenp, loff_t *ppos) - { - struct ctl_table t; - int ret; -diff --git a/kernel/groups.c b/kernel/groups.c -index 9b43da22647d..8045812e8a3c 100644 ---- a/kernel/groups.c -+++ b/kernel/groups.c -@@ -11,6 +11,9 @@ - #include - #include - #include -+#ifdef CONFIG_CREDP -+#include -+#endif +@@ -161,7 +175,11 @@ int dns_query(struct net *net, - struct group_info *groups_alloc(int gidsetsize) - { -@@ -119,7 +122,11 @@ void set_groups(struct cred *new, struct group_info *group_info) + ret = len; + put: ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(rkey)); ++ #else + up_read(&rkey->sem); ++ #endif + if (invalidate) + key_invalidate(rkey); + key_put(rkey); +diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c +index fa8aec78f63d..ba9d2feace7a 100644 +--- a/net/rxrpc/af_rxrpc.c ++++ b/net/rxrpc/af_rxrpc.c +@@ -307,7 +307,11 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, + + if (!key) + key = rx->key; ++ #ifdef CONFIG_KEYP ++ if (key && !((union key_payload *)(key->name_link.next))->data[0]) ++ #else + if (key && !key->payload.data[0]) ++ #endif + key = NULL; /* a no-security key */ + + memset(&p, 0, sizeof(p)); +diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c +index 598b4ee389fc..1d9574406c16 100644 +--- a/net/rxrpc/conn_event.c ++++ b/net/rxrpc/conn_event.c +@@ -247,8 +247,13 @@ static int rxrpc_process_event(struct rxrpc_connection *conn, + if (ret < 0) + return ret; + ++ #ifdef CONFIG_KEYP ++ ret = conn->security->init_connection_security( ++ conn, ((union key_payload *)(conn->key->name_link.next))->data[0]); ++ #else + ret = conn->security->init_connection_security( + conn, conn->key->payload.data[0]); ++ #endif + if (ret < 0) + return ret; + +diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c +index 33e8302a79e3..c4b755733ed2 100644 +--- a/net/rxrpc/key.c ++++ b/net/rxrpc/key.c +@@ -413,7 +413,11 @@ static void rxrpc_free_preparse(struct key_preparsed_payload *prep) + */ + static void rxrpc_destroy(struct key *key) { - put_group_info(new->group_info); - get_group_info(group_info); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_group_info(new,group_info); ++ #ifdef CONFIG_KEYP ++ rxrpc_free_token_list(((union key_payload *)(key->name_link.next))->data[0]); + #else - new->group_info = group_info; + rxrpc_free_token_list(key->payload.data[0]); + #endif } - EXPORT_SYMBOL(set_groups); -diff --git a/kernel/kthread.c b/kernel/kthread.c -index 1eea53050bab..317eac6eb2f2 100644 ---- a/kernel/kthread.c -+++ b/kernel/kthread.c -@@ -30,6 +30,10 @@ - #include - #include + /* +@@ -426,7 +430,11 @@ static void rxrpc_describe(const struct key *key, struct seq_file *m) -+#ifdef CONFIG_IEE -+#include -+#endif -+ + seq_puts(m, key->description); - static DEFINE_SPINLOCK(kthread_create_lock); - static LIST_HEAD(kthread_create_list); -@@ -1429,6 +1433,10 @@ void kthread_use_mm(struct mm_struct *mm) - tsk->active_mm = mm; - tsk->mm = mm; - membarrier_update_current_mm(mm); -+ #ifdef CONFIG_IEE -+ iee_set_token_mm(tsk, mm); -+ iee_set_token_pgd(tsk, mm->pgd); ++ #ifdef CONFIG_KEYP ++ for (token = ((union key_payload *)(key->name_link.next))->data[0]; token; token = token->next) { ++ #else + for (token = key->payload.data[0]; token; token = token->next) { + #endif - switch_mm_irqs_off(active_mm, mm, tsk); - local_irq_enable(); - task_unlock(tsk); -@@ -1473,7 +1481,12 @@ void kthread_unuse_mm(struct mm_struct *mm) - local_irq_disable(); - tsk->mm = NULL; - membarrier_update_current_mm(NULL); -+ #ifdef CONFIG_IEE -+ iee_set_token_mm(tsk, mm); -+ iee_set_token_pgd(tsk, NULL); + seq_puts(m, sep); + + switch (token->security_index) { +@@ -584,7 +592,11 @@ static long rxrpc_read(const struct key *key, + size += 1 * 4; /* token count */ + + ntoks = 0; ++ #ifdef CONFIG_KEYP ++ for (token = ((union key_payload *)(key->name_link.next))->data[0]; token; token = token->next) { ++ #else + for (token = key->payload.data[0]; token; token = token->next) { + #endif - mmgrab_lazy_tlb(mm); -+ - /* active_mm is still 'mm' */ - enter_lazy_tlb(mm, tsk); - local_irq_enable(); -diff --git a/kernel/smpboot.c b/kernel/smpboot.c -index f47d8f375946..60c7d365c0e1 100644 ---- a/kernel/smpboot.c -+++ b/kernel/smpboot.c -@@ -16,6 +16,10 @@ - #include - #include + toksize = 4; /* sec index */ -+#ifdef CONFIG_IEE -+#include + switch (token->security_index) { +@@ -654,7 +666,11 @@ static long rxrpc_read(const struct key *key, + ENCODE(ntoks); + + tok = 0; ++ #ifdef CONFIG_KEYP ++ for (token = ((union key_payload *)(key->name_link.next))->data[0]; token; token = token->next) { ++ #else + for (token = key->payload.data[0]; token; token = token->next) { ++ #endif + toksize = toksizes[tok++]; + ENCODE(toksize); + oldxdr = xdr; +diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c +index ad6c57a9f27c..b70b43f7c893 100644 +--- a/net/rxrpc/rxkad.c ++++ b/net/rxrpc/rxkad.c +@@ -21,6 +21,10 @@ + #include + #include "ar-internal.h" + ++#ifdef CONFIG_KEYP ++#include +#endif + - #include "smpboot.h" + #define RXKAD_VERSION 2 + #define MAXKRB5TICKETLEN 1024 + #define RXKAD_TKT_TYPE_KERBEROS_V5 256 +@@ -88,10 +92,19 @@ static void rxkad_free_preparse_server_key(struct key_preparsed_payload *prep) - #ifdef CONFIG_SMP -@@ -57,6 +61,11 @@ static __always_inline void idle_init(unsigned int cpu) - pr_err("SMP: fork_idle() failed for CPU %u\n", cpu); - else - per_cpu(idle_threads, cpu) = tsk; -+ #ifdef CONFIG_IEE -+ // Set the secondary __entry_task. -+ *(struct task_struct **)SHIFT_PERCPU_PTR(__entry_task,__per_cpu_offset[cpu]) = tsk; -+ iee_set_logical_mem_ro((unsigned long)SHIFT_PERCPU_PTR(__entry_task,__per_cpu_offset[cpu])); -+ #endif + static void rxkad_destroy_server_key(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ if (((union key_payload *)(key->name_link.next))->data[0]) { ++ crypto_free_skcipher(((union key_payload *)(key->name_link.next))->data[0]); ++ union key_payload key_payload = *((union key_payload *)(key->name_link.next)); ++ key_payload.data[0] = NULL; ++ iee_write_key_payload(key, key_payload); ++ } ++ #else + if (key->payload.data[0]) { + crypto_free_skcipher(key->payload.data[0]); + key->payload.data[0] = NULL; } ++ #endif } -diff --git a/kernel/sys.c b/kernel/sys.c -index 44b575990333..fbc47f83af50 100644 ---- a/kernel/sys.c -+++ b/kernel/sys.c -@@ -75,6 +75,10 @@ - #include - #include + /* +@@ -205,7 +218,11 @@ static int rxkad_prime_packet_security(struct rxrpc_connection *conn, + return -ENOMEM; + } -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - #include "uid16.h" ++ #ifdef CONFIG_KEYP ++ token = ((union key_payload *)(conn->key->name_link.next))->data[0]; ++ #else + token = conn->key->payload.data[0]; ++ #endif + memcpy(&iv, token->kad->session_key, sizeof(iv)); - #ifndef SET_UNALIGN_CTL -@@ -395,7 +399,11 @@ long __sys_setregid(gid_t rgid, gid_t egid) - if (gid_eq(old->gid, krgid) || - gid_eq(old->egid, krgid) || - ns_capable_setid(old->user_ns, CAP_SETGID)) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_gid(new,krgid); -+ #else - new->gid = krgid; -+ #endif - else - goto error; + tmpbuf[0] = htonl(conn->proto.epoch); +@@ -317,7 +334,11 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, } -@@ -404,15 +412,27 @@ long __sys_setregid(gid_t rgid, gid_t egid) - gid_eq(old->egid, kegid) || - gid_eq(old->sgid, kegid) || - ns_capable_setid(old->user_ns, CAP_SETGID)) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_egid(new,kegid); -+ #else - new->egid = kegid; -+ #endif - else - goto error; + + /* encrypt from the session key */ ++ #ifdef CONFIG_KEYP ++ token = ((union key_payload *)(call->conn->key->name_link.next))->data[0]; ++ #else + token = call->conn->key->payload.data[0]; ++ #endif + memcpy(&iv, token->kad->session_key, sizeof(iv)); + + sg_init_one(&sg, txb->data, txb->len); +@@ -507,7 +528,11 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb, } - if (rgid != (gid_t) -1 || - (egid != (gid_t) -1 && !gid_eq(kegid, old->gid))) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_sgid(new,new->egid); -+ #else - new->sgid = new->egid; -+ #endif -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsgid(new,new->egid); + /* decrypt from the session key */ ++ #ifdef CONFIG_KEYP ++ token = ((union key_payload *)(call->conn->key->name_link.next))->data[0]; + #else - new->fsgid = new->egid; + token = call->conn->key->payload.data[0]; + #endif + memcpy(&iv, token->kad->session_key, sizeof(iv)); - retval = security_task_fix_setgid(new, old, LSM_SETID_RE); - if (retval < 0) -@@ -454,9 +474,25 @@ long __sys_setgid(gid_t gid) + skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher); +@@ -824,7 +849,11 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn, + return rxrpc_abort_conn(conn, skb, RXKADLEVELFAIL, -EACCES, + rxkad_abort_chall_level); - retval = -EPERM; - if (ns_capable_setid(old->user_ns, CAP_SETGID)) -+ #ifdef CONFIG_CREDP -+ { -+ iee_set_cred_fsgid(new,kgid); -+ iee_set_cred_sgid(new,kgid); -+ iee_set_cred_egid(new,kgid); -+ iee_set_cred_gid(new,kgid); -+ } -+ #else - new->gid = new->egid = new->sgid = new->fsgid = kgid; -+ #endif - else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid)) -+ #ifdef CONFIG_CREDP -+ { -+ iee_set_cred_fsgid(new,kgid); -+ iee_set_cred_egid(new,kgid); -+ } -+ #else - new->egid = new->fsgid = kgid; -+ #endif - else - goto error; ++ #ifdef CONFIG_KEYP ++ token = ((union key_payload *)(conn->key->name_link.next))->data[0]; ++ #else + token = conn->key->payload.data[0]; ++ #endif + + /* build the response packet */ + resp = kzalloc(sizeof(struct rxkad_response), GFP_NOFS); +@@ -876,12 +905,24 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, + + *_expiry = 0; + ++ #ifdef CONFIG_KEYP ++ ASSERT(((union key_payload *)(server_key->name_link.next))->data[0] != NULL); ++ #else + ASSERT(server_key->payload.data[0] != NULL); ++ #endif + ASSERTCMP((unsigned long) ticket & 7UL, ==, 0); + ++ #ifdef CONFIG_KEYP ++ memcpy(&iv, &((union key_payload *)(server_key->name_link.next))->data[2], sizeof(iv)); ++ #else + memcpy(&iv, &server_key->payload.data[2], sizeof(iv)); ++ #endif + ++ #ifdef CONFIG_KEYP ++ req = skcipher_request_alloc(((union key_payload *)(server_key->name_link.next))->data[0], GFP_NOFS); ++ #else + req = skcipher_request_alloc(server_key->payload.data[0], GFP_NOFS); ++ #endif + if (!req) + return -ENOMEM; + +diff --git a/net/rxrpc/security.c b/net/rxrpc/security.c +index cb8dd1d3b1d4..6bffe9965040 100644 +--- a/net/rxrpc/security.c ++++ b/net/rxrpc/security.c +@@ -79,7 +79,11 @@ int rxrpc_init_client_call_security(struct rxrpc_call *call) + if (ret < 0) + return ret; + ++ #ifdef CONFIG_KEYP ++ for (token = ((union key_payload *)(key->name_link.next))->data[0]; token; token = token->next) { ++ #else + for (token = key->payload.data[0]; token; token = token->next) { ++ #endif + sec = rxrpc_security_lookup(token->security_index); + if (sec) + goto found; +@@ -103,7 +107,11 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) + + _enter("{%d},{%x}", conn->debug_id, key_serial(key)); + ++ #ifdef CONFIG_KEYP ++ for (token = ((union key_payload *)(key->name_link.next))->data[0]; token; token = token->next) { ++ #else + for (token = key->payload.data[0]; token; token = token->next) { ++ #endif + if (token->security_index == conn->security->security_index) + goto found; + } +diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c +index 8e0b94714e84..5cdd058d729c 100644 +--- a/net/rxrpc/sendmsg.c ++++ b/net/rxrpc/sendmsg.c +@@ -585,7 +585,11 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, + } + + key = rx->key; ++ #ifdef CONFIG_KEYP ++ if (key && !((union key_payload *)(rx->key->name_link.next))->data[0]) ++ #else + if (key && !rx->key->payload.data[0]) ++ #endif + key = NULL; + + memset(&cp, 0, sizeof(cp)); +diff --git a/net/rxrpc/server_key.c b/net/rxrpc/server_key.c +index e51940589ee5..1ea7e51b71f0 100644 +--- a/net/rxrpc/server_key.c ++++ b/net/rxrpc/server_key.c +@@ -100,7 +100,11 @@ static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep) + + static void rxrpc_destroy_s(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ const struct rxrpc_security *sec = ((union key_payload *)(key->name_link.next))->data[1]; ++ #else + const struct rxrpc_security *sec = key->payload.data[1]; ++ #endif + + if (sec && sec->destroy_server_key) + sec->destroy_server_key(key); +@@ -108,7 +112,11 @@ static void rxrpc_destroy_s(struct key *key) + + static void rxrpc_describe_s(const struct key *key, struct seq_file *m) + { ++ #ifdef CONFIG_KEYP ++ const struct rxrpc_security *sec = ((union key_payload *)(key->name_link.next))->data[1]; ++ #else + const struct rxrpc_security *sec = key->payload.data[1]; ++ #endif + + seq_puts(m, key->description); + if (sec && sec->describe_server_key) +diff --git a/security/commoncap.c b/security/commoncap.c +index bc0521104197..d7d3b7cc13e8 100644 +--- a/security/commoncap.c ++++ b/security/commoncap.c +@@ -26,6 +26,10 @@ + #include + #include + ++#ifdef CONFIG_CREDP ++#include ++#endif ++ + /* + * If a non-root user executes a setuid-root binary in + * !secure(SECURE_NOROOT) mode, then we raise capabilities. +@@ -266,6 +270,15 @@ int cap_capset(struct cred *new, + if (!cap_issubset(*effective, *permitted)) + return -EPERM; + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_cap_effective(new,*effective); ++ iee_set_cred_cap_inheritable(new,*inheritable); ++ iee_set_cred_cap_permitted(new,*permitted); ++ ++ iee_set_cred_cap_ambient(new,cap_intersect(new->cap_ambient, ++ cap_intersect(*permitted, ++ *inheritable))); ++ #else + new->cap_effective = *effective; + new->cap_inheritable = *inheritable; + new->cap_permitted = *permitted; +@@ -277,6 +290,7 @@ int cap_capset(struct cred *new, + new->cap_ambient = cap_intersect(new->cap_ambient, + cap_intersect(*permitted, + *inheritable)); ++ #endif + if (WARN_ON(!cap_ambient_invariant_ok(new))) + return -EINVAL; + return 0; +@@ -601,9 +615,16 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, + * pP' = (X & fP) | (pI & fI) + * The addition of pA' is handled later. + */ ++#ifdef CONFIG_CREDP ++ kernel_cap_t temp = new->cap_permitted; ++ temp.val = (new->cap_bset.val & caps->permitted.val) | ++ (new->cap_inheritable.val & caps->inheritable.val); ++ iee_set_cred_cap_permitted(new,temp); ++#else + new->cap_permitted.val = + (new->cap_bset.val & caps->permitted.val) | + (new->cap_inheritable.val & caps->inheritable.val); ++#endif -@@ -488,7 +524,11 @@ static int set_user(struct cred *new) - return -EAGAIN; + if (caps->permitted.val & ~new->cap_permitted.val) + /* insufficient to execute correctly */ +@@ -726,7 +747,15 @@ static int get_file_caps(struct linux_binprm *bprm, struct file *file, + int rc = 0; + struct cpu_vfs_cap_data vcaps; - free_uid(new->user); + #ifdef CONFIG_CREDP -+ iee_set_cred_user(new,new_user); ++ do { ++ kernel_cap_t tmp_cap = bprm->cred->cap_permitted; ++ tmp_cap.val = 0; ++ iee_set_cred_cap_permitted(bprm->cred, tmp_cap); ++ } while (0); + #else - new->user = new_user; + cap_clear(bprm->cred->cap_permitted); + #endif - return 0; - } -@@ -549,7 +589,11 @@ long __sys_setreuid(uid_t ruid, uid_t euid) + if (!file_caps_enabled) + return 0; +@@ -757,7 +786,15 @@ static int get_file_caps(struct linux_binprm *bprm, struct file *file, - retval = -EPERM; - if (ruid != (uid_t) -1) { + out: + if (rc) + #ifdef CONFIG_CREDP -+ iee_set_cred_uid(new,kruid); ++ do { ++ kernel_cap_t tmp_cap = bprm->cred->cap_permitted; ++ tmp_cap.val = 0; ++ iee_set_cred_cap_permitted(bprm->cred, tmp_cap); ++ } while (0); + #else - new->uid = kruid; + cap_clear(bprm->cred->cap_permitted); + #endif - if (!uid_eq(old->uid, kruid) && - !uid_eq(old->euid, kruid) && - !ns_capable_setid(old->user_ns, CAP_SETUID)) -@@ -557,7 +601,11 @@ long __sys_setreuid(uid_t ruid, uid_t euid) - } - if (euid != (uid_t) -1) { + return rc; + } +@@ -809,8 +846,13 @@ static void handle_privileged_root(struct linux_binprm *bprm, bool has_fcap, + */ + if (__is_eff(root_uid, new) || __is_real(root_uid, new)) { + /* pP' = (cap_bset & ~0) | (pI & ~0) */ + #ifdef CONFIG_CREDP -+ iee_set_cred_euid(new,keuid); ++ iee_set_cred_cap_permitted(new,cap_combine(old->cap_bset, ++ old->cap_inheritable)); + #else - new->euid = keuid; + new->cap_permitted = cap_combine(old->cap_bset, + old->cap_inheritable); + #endif - if (!uid_eq(old->uid, keuid) && - !uid_eq(old->euid, keuid) && - !uid_eq(old->suid, keuid) && -@@ -572,8 +620,16 @@ long __sys_setreuid(uid_t ruid, uid_t euid) } - if (ruid != (uid_t) -1 || - (euid != (uid_t) -1 && !uid_eq(keuid, old->uid))) + /* + * If only the real uid is 0, we do not set the effective bit. +@@ -919,34 +961,71 @@ int cap_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file) + /* downgrade; they get no more than they had, and maybe less */ + if (!ns_capable(new->user_ns, CAP_SETUID) || + (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) { ++ #ifdef CONFIG_CREDP ++ iee_set_cred_euid(new,new->uid); ++ iee_set_cred_egid(new,new->gid); ++ #else + new->euid = new->uid; + new->egid = new->gid; ++ #endif + } + #ifdef CONFIG_CREDP -+ iee_set_cred_suid(new,new->euid); ++ iee_set_cred_cap_permitted(new,cap_intersect(new->cap_permitted, ++ old->cap_permitted)); + #else - new->suid = new->euid; + new->cap_permitted = cap_intersect(new->cap_permitted, + old->cap_permitted); + #endif + } + + #ifdef CONFIG_CREDP + iee_set_cred_fsuid(new,new->euid); ++ iee_set_cred_suid(new,new->euid); ++ iee_set_cred_fsgid(new,new->egid); ++ iee_set_cred_sgid(new,new->egid); + #else - new->fsuid = new->euid; + new->suid = new->fsuid = new->euid; + new->sgid = new->fsgid = new->egid; + #endif - retval = security_task_fix_setuid(new, old, LSM_SETID_RE); - if (retval < 0) -@@ -626,7 +682,12 @@ long __sys_setuid(uid_t uid) - - retval = -EPERM; - if (ns_capable_setid(old->user_ns, CAP_SETUID)) { + /* File caps or setid cancels ambient. */ + if (has_fcap || is_setid) + #ifdef CONFIG_CREDP -+ iee_set_cred_uid(new,kuid); -+ iee_set_cred_suid(new,kuid); ++ do { ++ kernel_cap_t tmp_cap = new->cap_ambient; ++ tmp_cap.val = 0; ++ iee_set_cred_cap_ambient(new, tmp_cap); ++ } while (0); + #else - new->suid = new->uid = kuid; + cap_clear(new->cap_ambient); + #endif - if (!uid_eq(kuid, old->uid)) { - retval = set_user(new); - if (retval < 0) -@@ -636,7 +697,12 @@ long __sys_setuid(uid_t uid) - goto error; - } + /* + * Now that we've computed pA', update pP' to give: + * pP' = (X & fP) | (pI & fI) | pA' + */ + #ifdef CONFIG_CREDP -+ iee_set_cred_euid(new,kuid); -+ iee_set_cred_fsuid(new,kuid); ++ iee_set_cred_cap_permitted(new,cap_combine(new->cap_permitted, new->cap_ambient)); + #else - new->fsuid = new->euid = kuid; + new->cap_permitted = cap_combine(new->cap_permitted, new->cap_ambient); + #endif - retval = security_task_fix_setuid(new, old, LSM_SETID_ID); - if (retval < 0) -@@ -710,7 +776,11 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) - return -ENOMEM; - - if (ruid != (uid_t) -1) { -+ #ifdef CONFIG_CREDP -+ iee_set_cred_uid(new,kruid); -+ #else - new->uid = kruid; -+ #endif - if (!uid_eq(kruid, old->uid)) { - retval = set_user(new); - if (retval < 0) -@@ -718,10 +788,22 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) - } - } - if (euid != (uid_t) -1) + /* + * Set pE' = (fE ? pP' : pA'). Because pA' is zero if fE is set, + * this is the same as pE' = (fE ? pP' : 0) | pA'. + */ + if (effective) + #ifdef CONFIG_CREDP -+ iee_set_cred_euid(new,keuid); ++ iee_set_cred_cap_effective(new,new->cap_permitted); + #else - new->euid = keuid; + new->cap_effective = new->cap_permitted; + #endif - if (suid != (uid_t) -1) + else + #ifdef CONFIG_CREDP -+ iee_set_cred_suid(new,ksuid); ++ iee_set_cred_cap_effective(new,new->cap_ambient); + #else - new->suid = ksuid; + new->cap_effective = new->cap_ambient; + #endif + + if (WARN_ON(!cap_ambient_invariant_ok(new))) + return -EPERM; +@@ -957,7 +1036,11 @@ int cap_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file) + return ret; + } + + #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(new,new->euid); ++ iee_set_cred_securebits(new,new->securebits & ~issecure_mask(SECURE_KEEP_CAPS)); + #else - new->fsuid = new->euid; + new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); + #endif - retval = security_task_fix_setuid(new, old, LSM_SETID_RES); - if (retval < 0) -@@ -810,12 +892,29 @@ long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) - return -ENOMEM; + if (WARN_ON(!cap_ambient_invariant_ok(new))) + return -EPERM; +@@ -1092,8 +1175,21 @@ static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) + !uid_eq(new->euid, root_uid) && + !uid_eq(new->suid, root_uid))) { + if (!issecure(SECURE_KEEP_CAPS)) { ++ #ifdef CONFIG_CREDP ++ do { ++ kernel_cap_t tmp_cap = new->cap_permitted; ++ tmp_cap.val = 0; ++ iee_set_cred_cap_permitted(new, tmp_cap); ++ } while (0); ++ do { ++ kernel_cap_t tmp_cap = new->cap_effective; ++ tmp_cap.val = 0; ++ iee_set_cred_cap_effective(new, tmp_cap); ++ } while (0); ++ #else + cap_clear(new->cap_permitted); + cap_clear(new->cap_effective); ++ #endif + } - if (rgid != (gid_t) -1) + /* +@@ -1101,12 +1197,32 @@ static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) + * by exec to drop capabilities. We should make sure that + * this remains the case. + */ + #ifdef CONFIG_CREDP -+ iee_set_cred_gid(new,krgid); ++ do { ++ kernel_cap_t tmp_cap = new->cap_ambient; ++ tmp_cap.val = 0; ++ iee_set_cred_cap_ambient(new, tmp_cap); ++ } while (0); + #else - new->gid = krgid; + cap_clear(new->cap_ambient); + #endif - if (egid != (gid_t) -1) + } + if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid)) + #ifdef CONFIG_CREDP -+ iee_set_cred_egid(new,kegid); ++ do { ++ kernel_cap_t tmp_cap = new->cap_effective; ++ tmp_cap.val = 0; ++ iee_set_cred_cap_effective(new, tmp_cap); ++ } while (0); + #else - new->egid = kegid; + cap_clear(new->cap_effective); + #endif - if (sgid != (gid_t) -1) + if (!uid_eq(old->euid, root_uid) && uid_eq(new->euid, root_uid)) + #ifdef CONFIG_CREDP -+ iee_set_cred_sgid(new,ksgid); ++ iee_set_cred_cap_effective(new,new->cap_permitted); + #else - new->sgid = ksgid; + new->cap_effective = new->cap_permitted; + #endif -+ + } + + /** +@@ -1142,13 +1258,22 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags) + if (!issecure(SECURE_NO_SETUID_FIXUP)) { + kuid_t root_uid = make_kuid(old->user_ns, 0); + if (uid_eq(old->fsuid, root_uid) && !uid_eq(new->fsuid, root_uid)) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_cap_effective(new,cap_drop_fs_set(new->cap_effective)); ++ #else + new->cap_effective = + cap_drop_fs_set(new->cap_effective); ++ #endif + + if (!uid_eq(old->fsuid, root_uid) && uid_eq(new->fsuid, root_uid)) ++ #ifdef CONFIG_CREDP ++ iee_set_cred_cap_effective(new,cap_raise_fs_set(new->cap_effective, ++ new->cap_permitted)); ++ #else + new->cap_effective = + cap_raise_fs_set(new->cap_effective, + new->cap_permitted); ++ #endif + } + break; + +@@ -1243,7 +1368,15 @@ static int cap_prctl_drop(unsigned long cap) + new = prepare_creds(); + if (!new) + return -ENOMEM; + #ifdef CONFIG_CREDP -+ iee_set_cred_fsgid(new,new->egid); ++ { ++ kernel_cap_t tmp = new->cap_bset; ++ cap_lower(tmp, cap); ++ iee_set_cred_cap_bset(new, tmp); ++ } + #else - new->fsgid = new->egid; + cap_lower(new->cap_bset, cap); + #endif + return commit_creds(new); + } - retval = security_task_fix_setgid(new, old, LSM_SETID_RES); - if (retval < 0) -@@ -882,7 +981,11 @@ long __sys_setfsuid(uid_t uid) - uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) || - ns_capable_setid(old->user_ns, CAP_SETUID)) { - if (!uid_eq(kuid, old->fsuid)) { +@@ -1319,7 +1452,11 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, + new = prepare_creds(); + if (!new) + return -ENOMEM; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_securebits(new,arg2); ++ #else + new->securebits = arg2; ++ #endif + return commit_creds(new); + + case PR_GET_SECUREBITS: +@@ -1338,9 +1475,17 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, + if (!new) + return -ENOMEM; + if (arg2) + #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(new,kuid); ++ iee_set_cred_securebits(new,new->securebits | issecure_mask(SECURE_KEEP_CAPS)); + #else - new->fsuid = kuid; + new->securebits |= issecure_mask(SECURE_KEEP_CAPS); + #endif - if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) - goto change_okay; - } -@@ -926,7 +1029,11 @@ long __sys_setfsgid(gid_t gid) - gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) || - ns_capable_setid(old->user_ns, CAP_SETGID)) { - if (!gid_eq(kgid, old->fsgid)) { + else + #ifdef CONFIG_CREDP -+ iee_set_cred_fsgid(new,kgid); ++ iee_set_cred_securebits(new,new->securebits & ~issecure_mask(SECURE_KEEP_CAPS)); + #else - new->fsgid = kgid; + new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); + #endif - if (security_task_fix_setgid(new,old,LSM_SETID_FS) == 0) - goto change_okay; + return commit_creds(new); + + case PR_CAP_AMBIENT: +@@ -1351,7 +1496,15 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, + new = prepare_creds(); + if (!new) + return -ENOMEM; ++ #ifdef CONFIG_CREDP ++ do { ++ kernel_cap_t tmp_cap = new->cap_ambient; ++ tmp_cap.val = 0; ++ iee_set_cred_cap_ambient(new, tmp_cap); ++ } while (0); ++ #else + cap_clear(new->cap_ambient); ++ #endif + return commit_creds(new); } -diff --git a/kernel/umh.c b/kernel/umh.c -index 1b13c5d34624..32f5c88e10bf 100644 ---- a/kernel/umh.c -+++ b/kernel/umh.c -@@ -32,6 +32,10 @@ - #include +@@ -1375,9 +1528,25 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, + if (!new) + return -ENOMEM; + if (arg2 == PR_CAP_AMBIENT_RAISE) ++ #ifdef CONFIG_CREDP ++ { ++ kernel_cap_t tmp = new->cap_ambient; ++ cap_raise(tmp, arg3); ++ iee_set_cred_cap_ambient(new, tmp); ++ } ++ #else + cap_raise(new->cap_ambient, arg3); ++ #endif + else ++ #ifdef CONFIG_CREDP ++ { ++ kernel_cap_t tmp = new->cap_ambient; ++ cap_lower(tmp, arg3); ++ iee_set_cred_cap_ambient(new, tmp); ++ } ++ #else + cap_lower(new->cap_ambient, arg3); ++ #endif + return commit_creds(new); + } -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - static kernel_cap_t usermodehelper_bset = CAP_FULL_SET; - static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET; - static DEFINE_SPINLOCK(umh_sysctl_lock); -@@ -91,9 +95,15 @@ static int call_usermodehelper_exec_async(void *data) - goto out; +diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c +index 720e5913832f..41ecdd75961a 100644 +--- a/security/integrity/evm/evm_crypto.c ++++ b/security/integrity/evm/evm_crypto.c +@@ -466,14 +466,26 @@ int evm_init_key(void) + if (IS_ERR(evm_key)) + return -ENOENT; - spin_lock(&umh_sysctl_lock); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_bset(new,cap_intersect(usermodehelper_bset, new->cap_bset)); -+ iee_set_cred_cap_inheritable(new,cap_intersect(usermodehelper_inheritable, -+ new->cap_inheritable)); ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(evm_key)); + #else - new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset); - new->cap_inheritable = cap_intersect(usermodehelper_inheritable, - new->cap_inheritable); + down_read(&evm_key->sem); ++ #endif ++ #ifdef CONFIG_KEYP ++ ekp = ((union key_payload *)(evm_key->name_link.next))->data[0]; ++ #else + ekp = evm_key->payload.data[0]; + #endif - spin_unlock(&umh_sysctl_lock); - - if (sub_info->init) { -diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index 1d8e47bed3f1..9f1921025539 100644 ---- a/kernel/user_namespace.c -+++ b/kernel/user_namespace.c -@@ -22,6 +22,10 @@ - #include - #include -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - static struct kmem_cache *user_ns_cachep __read_mostly; - static DEFINE_MUTEX(userns_state_mutex); + rc = evm_set_key(ekp->decrypted_data, ekp->decrypted_datalen); -@@ -45,6 +49,19 @@ static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) - /* Start with the same capabilities as init but useless for doing - * anything as the capabilities are bound to the new user namespace. - */ -+ #ifdef CONFIG_CREDP -+ iee_set_cred_securebits(cred,SECUREBITS_DEFAULT); -+ iee_set_cred_cap_inheritable(cred,CAP_EMPTY_SET); -+ iee_set_cred_cap_permitted(cred,CAP_FULL_SET); -+ iee_set_cred_cap_effective(cred,CAP_FULL_SET); -+ iee_set_cred_cap_ambient(cred,CAP_EMPTY_SET); -+ iee_set_cred_cap_bset(cred,CAP_FULL_SET); -+#ifdef CONFIG_KEYS -+ key_put(cred->request_key_auth); -+ iee_set_cred_request_key_auth(cred,NULL); -+#endif -+ iee_set_cred_user_ns(cred,user_ns); + /* burn the original key contents */ + memset(ekp->decrypted_data, 0, ekp->decrypted_datalen); ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(evm_key)); + #else - cred->securebits = SECUREBITS_DEFAULT; - cred->cap_inheritable = CAP_EMPTY_SET; - cred->cap_permitted = CAP_FULL_SET; -@@ -57,6 +74,7 @@ static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) - #endif - /* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */ - cred->user_ns = user_ns; + up_read(&evm_key->sem); + #endif + key_put(evm_key); + return rc; } +diff --git a/security/keys/big_key.c b/security/keys/big_key.c +index c3367622c683..bc6a097f2f87 100644 +--- a/security/keys/big_key.c ++++ b/security/keys/big_key.c +@@ -164,7 +164,11 @@ void big_key_free_preparse(struct key_preparsed_payload *prep) + */ + void big_key_revoke(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ struct big_key_payload *payload = to_big_key_payload(*((union key_payload *)(key->name_link.next))); ++ #else + struct big_key_payload *payload = to_big_key_payload(key->payload); ++ #endif - static unsigned long enforced_nproc_rlimit(void) -diff --git a/mm/Kconfig b/mm/Kconfig -index 45d4139c959c..eb9d41768c15 100644 ---- a/mm/Kconfig -+++ b/mm/Kconfig -@@ -530,6 +530,18 @@ config NUMA_KEEP_MEMINFO - config MEMORY_ISOLATION - bool + /* clear the quota */ + key_payload_reserve(key, 0); +@@ -177,7 +181,11 @@ void big_key_revoke(struct key *key) + */ + void big_key_destroy(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ struct big_key_payload *payload = to_big_key_payload(*((union key_payload *)(key->name_link.next))); ++ #else + struct big_key_payload *payload = to_big_key_payload(key->payload); ++ #endif -+# Config for kernel module isolation -+config KOI -+ depends on ARM64 -+ depends on ARM64_VA_BITS_48 -+ depends on ARM64_4K_PAGES -+ def_bool n -+ -+# Configs for pgtable isolation -+config PTP -+ depends on IEE -+ def_bool y -+ - # IORESOURCE_SYSTEM_RAM regions in the kernel resource tree that are marked - # IORESOURCE_EXCLUSIVE cannot be mapped to user space, for example, via - # /dev/mem. -diff --git a/mm/damon/ops-common.c b/mm/damon/ops-common.c -index d25d99cb5f2b..2ea51f559d4e 100644 ---- a/mm/damon/ops-common.c -+++ b/mm/damon/ops-common.c -@@ -44,6 +44,7 @@ void damon_ptep_mkold(pte_t *pte, struct vm_area_struct *vma, unsigned long addr - if (!folio) - return; + if (payload->length > BIG_KEY_FILE_THRESHOLD) { + path_put(&payload->path); +@@ -210,7 +218,11 @@ int big_key_update(struct key *key, struct key_preparsed_payload *prep) + */ + void big_key_describe(const struct key *key, struct seq_file *m) + { ++ #ifdef CONFIG_KEYP ++ struct big_key_payload *payload = to_big_key_payload(*((union key_payload *)(key->name_link.next))); ++ #else + struct big_key_payload *payload = to_big_key_payload(key->payload); ++ #endif -+ - if (ptep_clear_young_notify(vma, addr, pte)) - folio_set_young(folio); + seq_puts(m, key->description); -diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c -index 13f0d1192707..60dc95c5b286 100644 ---- a/mm/debug_vm_pgtable.c -+++ b/mm/debug_vm_pgtable.c -@@ -452,7 +452,11 @@ static void __init pmd_huge_tests(struct pgtable_debug_args *args) - * X86 defined pmd_set_huge() verifies that the given - * PMD is not a populated non-leaf entry. - */ -+ #ifdef CONFIG_PTP -+ set_pmd(args->pmdp, __pmd(0)); +@@ -226,7 +238,11 @@ void big_key_describe(const struct key *key, struct seq_file *m) + */ + long big_key_read(const struct key *key, char *buffer, size_t buflen) + { ++ #ifdef CONFIG_KEYP ++ struct big_key_payload *payload = to_big_key_payload(*((union key_payload *)(key->name_link.next))); + #else - WRITE_ONCE(*args->pmdp, __pmd(0)); + struct big_key_payload *payload = to_big_key_payload(key->payload); + #endif - WARN_ON(!pmd_set_huge(args->pmdp, __pfn_to_phys(args->fixed_pmd_pfn), args->page_prot)); - WARN_ON(!pmd_clear_huge(args->pmdp)); - pmd = READ_ONCE(*args->pmdp); -@@ -472,7 +476,11 @@ static void __init pud_huge_tests(struct pgtable_debug_args *args) - * X86 defined pud_set_huge() verifies that the given - * PUD is not a populated non-leaf entry. - */ -+ #ifdef CONFIG_PTP -+ set_pud(args->pudp, __pud(0)); + size_t datalen = payload->length; + long ret; + +diff --git a/security/keys/dh.c b/security/keys/dh.c +index da64c358474b..f00a3e0c2c87 100644 +--- a/security/keys/dh.c ++++ b/security/keys/dh.c +@@ -32,7 +32,11 @@ static ssize_t dh_data_from_key(key_serial_t keyid, const void **data) + + ret = -EOPNOTSUPP; + if (key->type == &key_type_user) { ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(key)); ++ #else + down_read(&key->sem); ++ #endif + status = key_validate(key); + if (status == 0) { + const struct user_key_payload *payload; +@@ -49,7 +53,11 @@ static ssize_t dh_data_from_key(key_serial_t keyid, const void **data) + ret = -ENOMEM; + } + } ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + } + + key_put(key); +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index 1e313982af02..ef5e8f4f03f0 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -314,11 +314,19 @@ static struct key *request_user_key(const char *master_desc, const u8 **master_k + if (IS_ERR(ukey)) + goto error; + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(ukey)); + #else - WRITE_ONCE(*args->pudp, __pud(0)); + down_read(&ukey->sem); + #endif - WARN_ON(!pud_set_huge(args->pudp, __pfn_to_phys(args->fixed_pud_pfn), args->page_prot)); - WARN_ON(!pud_clear_huge(args->pudp)); - pud = READ_ONCE(*args->pudp); -@@ -511,7 +519,11 @@ static void __init pud_clear_tests(struct pgtable_debug_args *args) - - pr_debug("Validating PUD clear\n"); - pud = __pud(pud_val(pud) | RANDOM_ORVALUE); -+ #ifdef CONFIG_PTP -+ set_pud(args->pudp, pud); + upayload = user_key_payload_locked(ukey); + if (!upayload) { + /* key was revoked before we acquired its semaphore */ ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(ukey)); ++ #else + up_read(&ukey->sem); ++ #endif + key_put(ukey); + ukey = ERR_PTR(-EKEYREVOKED); + goto error; +@@ -729,7 +737,11 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, + if (ret < 0) + pr_err("encrypted_key: failed to decrypt key (%d)\n", ret); + out: ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(mkey)); + #else - WRITE_ONCE(*args->pudp, pud); + up_read(&mkey->sem); + #endif - pud_clear(args->pudp); - pud = READ_ONCE(*args->pudp); - WARN_ON(!pud_none(pud)); -@@ -548,7 +560,11 @@ static void __init p4d_clear_tests(struct pgtable_debug_args *args) - - pr_debug("Validating P4D clear\n"); - p4d = __p4d(p4d_val(p4d) | RANDOM_ORVALUE); -+ #ifdef CONFIG_PTP -+ set_p4d(args->p4dp, p4d); + key_put(mkey); + memzero_explicit(derived_key, sizeof(derived_key)); + return ret; +@@ -874,7 +886,11 @@ static void encrypted_rcu_free(struct rcu_head *rcu) + */ + static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) + { ++ #ifdef CONFIG_KEYP ++ struct encrypted_key_payload *epayload = ((union key_payload *)(key->name_link.next))->data[0]; + #else - WRITE_ONCE(*args->p4dp, p4d); + struct encrypted_key_payload *epayload = key->payload.data[0]; + #endif - p4d_clear(args->p4dp); - p4d = READ_ONCE(*args->p4dp); - WARN_ON(!p4d_none(p4d)); -@@ -582,7 +598,11 @@ static void __init pgd_clear_tests(struct pgtable_debug_args *args) + struct encrypted_key_payload *new_epayload; + char *buf; + char *new_master_desc = NULL; +@@ -974,7 +990,11 @@ static long encrypted_read(const struct key *key, char *buffer, + goto out; + } - pr_debug("Validating PGD clear\n"); - pgd = __pgd(pgd_val(pgd) | RANDOM_ORVALUE); -+ #ifdef CONFIG_PTP -+ set_pgd(args->pgdp, pgd); ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(mkey)); + #else - WRITE_ONCE(*args->pgdp, pgd); + up_read(&mkey->sem); + #endif - pgd_clear(args->pgdp); - pgd = READ_ONCE(*args->pgdp); - WARN_ON(!pgd_none(pgd)); -@@ -650,7 +670,11 @@ static void __init pmd_clear_tests(struct pgtable_debug_args *args) + key_put(mkey); + memzero_explicit(derived_key, sizeof(derived_key)); - pr_debug("Validating PMD clear\n"); - pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE); -+ #ifdef CONFIG_PTP -+ set_pmd(args->pmdp, pmd); +@@ -983,7 +1003,11 @@ static long encrypted_read(const struct key *key, char *buffer, + + return asciiblob_len; + out: ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(mkey)); + #else - WRITE_ONCE(*args->pmdp, pmd); + up_read(&mkey->sem); ++ #endif + key_put(mkey); + memzero_explicit(derived_key, sizeof(derived_key)); + return ret; +@@ -994,7 +1018,11 @@ static long encrypted_read(const struct key *key, char *buffer, + */ + static void encrypted_destroy(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ kfree_sensitive(((union key_payload *)(key->name_link.next))->data[0]); ++ #else + kfree_sensitive(key->payload.data[0]); + #endif - pmd_clear(args->pmdp); - pmd = READ_ONCE(*args->pmdp); - WARN_ON(!pmd_none(pmd)); -diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c -index ce06b2884789..a039c7a50ec5 100644 ---- a/mm/early_ioremap.c -+++ b/mm/early_ioremap.c -@@ -147,7 +147,11 @@ __early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot) - if (after_paging_init) - __late_set_fixmap(idx, phys_addr, prot); - else -+ #ifdef CONFIG_PTP -+ __iee_set_fixmap_pre_init(idx, phys_addr, prot); -+ #else - __early_set_fixmap(idx, phys_addr, prot); -+ #endif - phys_addr += PAGE_SIZE; - --idx; - --nrpages; -@@ -199,13 +203,66 @@ void __init early_iounmap(void __iomem *addr, unsigned long size) - if (after_paging_init) - __late_clear_fixmap(idx); - else -+ #ifdef CONFIG_PTP -+ __iee_set_fixmap_pre_init(idx, 0, FIXMAP_PAGE_CLEAR); -+ #else - __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR); -+ #endif - --idx; - --nrpages; - } - prev_map[slot] = NULL; } -+#ifdef CONFIG_PTP -+void __init early_iounmap_after_init(void __iomem *addr, unsigned long size) -+{ -+ unsigned long virt_addr; -+ unsigned long offset; -+ unsigned int nrpages; -+ enum fixed_addresses idx; -+ int i, slot; -+ -+ slot = -1; -+ for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { -+ if (prev_map[i] == addr) { -+ slot = i; -+ break; -+ } -+ } -+ -+ if (WARN(slot < 0, "early_iounmap(%p, %08lx) not found slot\n", -+ addr, size)) -+ return; -+ -+ if (WARN(prev_size[slot] != size, -+ "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n", -+ addr, size, slot, prev_size[slot])) -+ return; -+ -+ WARN(early_ioremap_debug, "early_iounmap(%p, %08lx) [%d]\n", -+ addr, size, slot); -+ -+ virt_addr = (unsigned long)addr; -+ if (WARN_ON(virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))) -+ return; -+ -+ offset = offset_in_page(virt_addr); -+ nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT; -+ -+ idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; -+ while (nrpages > 0) { -+ if (after_paging_init) -+ __late_clear_fixmap(idx); -+ else -+ __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR); -+ --idx; -+ --nrpages; -+ } -+ prev_map[slot] = NULL; -+} -+#endif -+ - /* Remap an IO device */ - void __init __iomem * - early_ioremap(resource_size_t phys_addr, unsigned long size) -diff --git a/mm/huge_memory.c b/mm/huge_memory.c -index 763bb25e4f99..80bb2c0abeda 100644 ---- a/mm/huge_memory.c -+++ b/mm/huge_memory.c -@@ -39,6 +39,10 @@ - #include - #include + struct key_type key_type_encrypted = { +diff --git a/security/keys/encrypted-keys/masterkey_trusted.c b/security/keys/encrypted-keys/masterkey_trusted.c +index e6d22ce77e98..13803e0f1a8f 100644 +--- a/security/keys/encrypted-keys/masterkey_trusted.c ++++ b/security/keys/encrypted-keys/masterkey_trusted.c +@@ -34,8 +34,13 @@ struct key *request_trusted_key(const char *trusted_desc, + if (IS_ERR(tkey)) + goto error; -+#ifdef CONFIG_PTP -+#include ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(tkey)); ++ tpayload = ((union key_payload *)(tkey->name_link.next))->data[0]; ++ #else + down_read(&tkey->sem); + tpayload = tkey->payload.data[0]; ++ #endif + *master_key = tpayload->key; + *master_keylen = tpayload->key_len; + error: +diff --git a/security/keys/gc.c b/security/keys/gc.c +index eaddaceda14e..d1a8e1e6bf22 100644 +--- a/security/keys/gc.c ++++ b/security/keys/gc.c +@@ -10,6 +10,11 @@ + #include + #include "internal.h" + ++#ifdef CONFIG_KEYP ++#include ++extern void iee_memset(void *ptr, int data, size_t n); +#endif + - #include - #include - #include "internal.h" -@@ -2489,6 +2493,10 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma, - unsigned long addr; - pte_t *pte; - int i; -+ #ifdef CONFIG_PTP -+ pte_t *ptep; -+ unsigned long iee_addr; -+ #endif + /* + * Delay between key revocation/expiry in seconds + */ +@@ -135,18 +140,30 @@ void key_gc_keytype(struct key_type *ktype) + static noinline void key_gc_unused_keys(struct list_head *keys) + { + while (!list_empty(keys)) { ++ #ifdef CONFIG_KEYP ++ struct key *key = list_entry(keys->next, struct key_union, graveyard_link)->key; ++ #else + struct key *key = + list_entry(keys->next, struct key, graveyard_link); ++ #endif + short state = key->state; - /* - * Leave pmd empty until pte is filled note that it is fine to delay -@@ -2501,7 +2509,14 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma, - old_pmd = pmdp_huge_clear_flush(vma, haddr, pmd); ++ #ifdef CONFIG_KEYP ++ list_del(&(((struct key_union *)(key->graveyard_link.next))->graveyard_link)); ++ #else + list_del(&key->graveyard_link); ++ #endif - pgtable = pgtable_trans_huge_withdraw(mm, pmd); -- pmd_populate(mm, &_pmd, pgtable); -+ #ifdef CONFIG_PTP -+ ptep = (pte_t *)page_address(pgtable); -+ iee_addr = __phys_to_iee(__pa(ptep)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)ptep); -+ #endif -+ //pmd_populate(mm, &_pmd, pgtable); -+ _pmd = __pmd(__phys_to_pmd_val(page_to_phys(pgtable)) | PMD_TYPE_TABLE); + kdebug("- %u", key->serial); + key_check(key); - pte = pte_offset_map(&_pmd, haddr); - VM_BUG_ON(!pte); -@@ -2534,6 +2549,10 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, - unsigned long addr; - pte_t *pte; - int i; -+ #ifdef CONFIG_PTP -+ pte_t *ptep; -+ unsigned long iee_addr; -+ #endif + #ifdef CONFIG_KEY_NOTIFICATIONS + remove_watch_list(key->watchers, key->serial); ++ #ifdef CONFIG_KEYP ++ iee_set_key_watchers(key, NULL); ++ #else + key->watchers = NULL; ++ #endif + #endif - VM_BUG_ON(haddr & ~HPAGE_PMD_MASK); - VM_BUG_ON_VMA(vma->vm_start > haddr, vma); -@@ -2671,7 +2690,14 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, - * This's critical for some architectures (Power). + /* Throw away the key data if the key is instantiated */ +@@ -171,7 +188,15 @@ static noinline void key_gc_unused_keys(struct list_head *keys) + key_put_tag(key->domain_tag); + kfree(key->description); + ++ #ifdef CONFIG_KEYP ++ kmem_cache_free(key_union_jar,(struct key_union *)(key->graveyard_link.next)); ++ kmem_cache_free(key_struct_jar, (struct key_struct *)(key->name_link.prev)); ++ kmem_cache_free(key_payload_jar, (union key_payload *)(key->name_link.next)); ++ iee_memset(key, 0, sizeof(*key)); ++ barrier_data(key); ++ #else + memzero_explicit(key, sizeof(*key)); ++ #endif + kmem_cache_free(key_jar, key); + } + } +@@ -223,7 +248,11 @@ static void key_garbage_collector(struct work_struct *work) + + continue_scanning: + while (cursor) { ++ #ifdef CONFIG_KEYP ++ key = rb_entry(cursor, struct key_union, serial_node)->key; ++ #else + key = rb_entry(cursor, struct key, serial_node); ++ #endif + cursor = rb_next(cursor); + + if (refcount_read(&key->usage) == 0) +@@ -232,8 +261,13 @@ static void key_garbage_collector(struct work_struct *work) + if (unlikely(gc_state & KEY_GC_REAPING_DEAD_1)) { + if (key->type == key_gc_dead_keytype) { + gc_state |= KEY_GC_FOUND_DEAD_KEY; ++ #ifdef CONFIG_KEYP ++ iee_set_key_flag_bit(key, KEY_FLAG_DEAD, SET_BIT_OP); ++ iee_set_key_perm(key, 0); ++ #else + set_bit(KEY_FLAG_DEAD, &key->flags); + key->perm = 0; ++ #endif + goto skip_dead_key; + } else if (key->type == &key_type_keyring && + key->restrict_link) { +@@ -339,10 +373,18 @@ static void key_garbage_collector(struct work_struct *work) */ - pgtable = pgtable_trans_huge_withdraw(mm, pmd); -- pmd_populate(mm, &_pmd, pgtable); -+ #ifdef CONFIG_PTP -+ ptep = (pte_t *)page_to_virt(pgtable); -+ iee_addr = __phys_to_iee(__pa(ptep)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)ptep); + found_unreferenced_key: + kdebug("unrefd key %d", key->serial); ++ #ifdef CONFIG_KEYP ++ rb_erase(&(((struct key_union *)(key->graveyard_link.next))->serial_node), &key_serial_tree); ++ #else + rb_erase(&key->serial_node, &key_serial_tree); + #endif -+ //pmd_populate(mm, &_pmd, pgtable); -+ _pmd = __pmd(__phys_to_pmd_val(page_to_phys(pgtable)) | PMD_TYPE_TABLE); + spin_unlock(&key_serial_lock); - pte = pte_offset_map(&_pmd, haddr); - VM_BUG_ON(!pte); -diff --git a/mm/init-mm.c b/mm/init-mm.c -index 24c809379274..07d060fca6f0 100644 ---- a/mm/init-mm.c -+++ b/mm/init-mm.c -@@ -55,3 +55,20 @@ void setup_initial_init_mm(void *start_code, void *end_code, - init_mm.end_data = (unsigned long)end_data; - init_mm.brk = (unsigned long)brk; ++ #ifdef CONFIG_KEYP ++ list_add_tail(&(((struct key_union *)(key->graveyard_link.next))->graveyard_link), &graveyard); ++ #else + list_add_tail(&key->graveyard_link, &graveyard); ++ #endif + gc_state |= KEY_GC_REAP_AGAIN; + goto maybe_resched; + +@@ -370,11 +412,21 @@ static void key_garbage_collector(struct work_struct *work) + destroy_dead_key: + spin_unlock(&key_serial_lock); + kdebug("destroy key %d", key->serial); ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(key)); ++ iee_set_key_type(key, &key_type_dead); ++ #else + down_write(&key->sem); + key->type = &key_type_dead; ++ #endif + if (key_gc_dead_keytype->destroy) + key_gc_dead_keytype->destroy(key); ++ #ifdef CONFIG_KEYP ++ iee_memset((key->name_link.next), KEY_DESTROY, sizeof(key->payload)); ++ up_write(&KEY_SEM(key)); ++ #else + memset(&key->payload, KEY_DESTROY, sizeof(key->payload)); + up_write(&key->sem); ++ #endif + goto maybe_resched; } -+ -+#ifdef CONFIG_KOI -+/* -+ * This is used to init ko_mm when creating pgtable for a ko to be isolated -+ * the ko_mm belongs to a specific ko, pgdp is allocated by koi_pgd_alloc -+ */ -+void init_ko_mm(struct mm_struct *ko_mm, pgd_t *pgdp) { -+ ko_mm->mm_rb = RB_ROOT; -+ ko_mm->pgd = pgdp; -+ ko_mm->mm_users = (atomic_t)ATOMIC_INIT(2); -+ ko_mm->mm_count = (atomic_t)ATOMIC_INIT(1); -+ ko_mm->mmap_lock = (struct rw_semaphore)__RWSEM_INITIALIZER(ko_mm->mmap_lock); -+ ko_mm->page_table_lock = __SPIN_LOCK_UNLOCKED(ko_mm.page_table_lock); -+ ko_mm->arg_lock = __SPIN_LOCK_UNLOCKED(ko_mm->arg_lock); -+ ko_mm->mmlist = (struct list_head)LIST_HEAD_INIT(ko_mm->mmlist); -+} +diff --git a/security/keys/internal.h b/security/keys/internal.h +index ec2ec335b613..00d76f89179c 100644 +--- a/security/keys/internal.h ++++ b/security/keys/internal.h +@@ -83,12 +83,20 @@ extern unsigned key_quota_maxbytes; + + + extern struct kmem_cache *key_jar; ++#ifdef CONFIG_KEYP ++extern struct kmem_cache *key_union_jar; ++extern struct kmem_cache *key_struct_jar; ++extern struct kmem_cache *key_payload_jar; +#endif -diff --git a/mm/memory.c b/mm/memory.c -index 4ef917a182f9..28da89a19e30 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -80,6 +80,10 @@ - #include - #include + extern struct rb_root key_serial_tree; + extern spinlock_t key_serial_lock; + extern struct mutex key_construction_mutex; + extern wait_queue_head_t request_key_conswq; + + extern void key_set_index_key(struct keyring_index_key *index_key); ++#ifdef CONFIG_KEYP ++extern void iee_key_set_index_key(struct keyring_index_key *index_key); ++#endif + extern struct key_type *key_type_lookup(const char *type); + extern void key_type_put(struct key_type *ktype); + +diff --git a/security/keys/key.c b/security/keys/key.c +index 35db23d05302..831c21329488 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -17,7 +17,18 @@ + #include + #include "internal.h" -+#ifdef CONFIG_PTP -+#include ++#ifdef CONFIG_KEYP ++#include ++#include ++extern void iee_memset(void *ptr, int data, size_t n); +#endif + - #include + struct kmem_cache *key_jar; ++#ifdef CONFIG_KEYP ++struct kmem_cache *key_union_jar; ++struct kmem_cache *key_struct_jar; ++struct kmem_cache *key_payload_jar; ++#endif + struct rb_root key_serial_tree; /* tree of keys indexed by serial */ + DEFINE_SPINLOCK(key_serial_lock); - #include -@@ -5872,6 +5876,11 @@ int __pud_alloc(struct mm_struct *mm, p4d_t *p4d, unsigned long address) +@@ -139,9 +150,16 @@ static inline void key_alloc_serial(struct key *key) + /* propose a random serial number and look for a hole for it in the + * serial number tree */ + do { ++ #ifdef CONFIG_KEYP ++ key_serial_t tmp; ++ get_random_bytes(&tmp, sizeof(key->serial)); ++ ++ iee_set_key_serial(key, tmp >> 1); ++ #else + get_random_bytes(&key->serial, sizeof(key->serial)); - spin_lock(&mm->page_table_lock); - if (!p4d_present(*p4d)) { -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr = __phys_to_iee(__pa(new)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)new); + key->serial >>= 1; /* negative numbers are not permitted */ + #endif - mm_inc_nr_puds(mm); - smp_wmb(); /* See comment in pmd_install() */ - p4d_populate(mm, p4d, new); -@@ -5896,6 +5905,11 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) + } while (key->serial < 3); - ptl = pud_lock(mm, pud); - if (!pud_present(*pud)) { -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr = __phys_to_iee(__pa(new)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)new); + spin_lock(&key_serial_lock); +@@ -152,7 +170,11 @@ static inline void key_alloc_serial(struct key *key) + + while (*p) { + parent = *p; ++ #ifdef CONFIG_KEYP ++ xkey = rb_entry(parent, struct key_union, serial_node)->key; ++ #else + xkey = rb_entry(parent, struct key, serial_node); + #endif - mm_inc_nr_pmds(mm); - smp_wmb(); /* See comment in pmd_install() */ - pud_populate(mm, pud, new); -diff --git a/mm/slub.c b/mm/slub.c -index ee3e32cdb7fd..20a45a7feed5 100644 ---- a/mm/slub.c -+++ b/mm/slub.c -@@ -42,6 +42,11 @@ - #include - #include -+#ifdef CONFIG_IEE -+#include -+#include -+#endif -+ - #include - #include + if (key->serial < xkey->serial) + p = &(*p)->rb_left; +@@ -163,8 +185,13 @@ static inline void key_alloc_serial(struct key *key) + } -@@ -317,6 +322,7 @@ static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s) - /* - * Tracking user of a slab. - */ -+#ifndef CONFIG_IEE - #define TRACK_ADDRS_COUNT 16 - struct track { - unsigned long addr; /* Called from address */ -@@ -329,6 +335,7 @@ struct track { - }; + /* we've found a suitable hole - arrange for this key to occupy it */ ++ #ifdef CONFIG_KEYP ++ rb_link_node(&(((struct key_union *)(key->graveyard_link.next))->serial_node), parent, p); ++ rb_insert_color(&(((struct key_union *)(key->graveyard_link.next))->serial_node), &key_serial_tree); ++ #else + rb_link_node(&key->serial_node, parent, p); + rb_insert_color(&key->serial_node, &key_serial_tree); ++ #endif - enum track_item { TRACK_ALLOC, TRACK_FREE }; -+#endif + spin_unlock(&key_serial_lock); + return; +@@ -175,7 +202,11 @@ static inline void key_alloc_serial(struct key *key) + for (;;) { + key->serial++; + if (key->serial < 3) { ++ #ifdef CONFIG_KEYP ++ iee_set_key_serial(key, 3); ++ #else + key->serial = 3; ++ #endif + goto attempt_insertion; + } - #ifdef SLAB_SUPPORTS_SYSFS - static int sysfs_slab_add(struct kmem_cache *); -@@ -379,7 +386,9 @@ static struct workqueue_struct *flushwq; - * freeptr_t represents a SLUB freelist pointer, which might be encoded - * and not dereferenceable if CONFIG_SLAB_FREELIST_HARDENED is enabled. - */ -+#ifndef CONFIG_IEE - typedef struct { unsigned long v; } freeptr_t; -+#endif +@@ -183,7 +214,11 @@ static inline void key_alloc_serial(struct key *key) + if (!parent) + goto attempt_insertion; - /* - * Returns freelist pointer (ptr). With hardening, this is obfuscated -@@ -464,7 +473,14 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp) - #endif ++ #ifdef CONFIG_KEYP ++ xkey = rb_entry(parent, struct key_union, serial_node)->key; ++ #else + xkey = rb_entry(parent, struct key, serial_node); ++ #endif + if (key->serial < xkey->serial) + goto attempt_insertion; + } +@@ -231,6 +266,9 @@ struct key *key_alloc(struct key_type *type, const char *desc, + struct key *key; + size_t desclen, quotalen; + int ret; ++ #ifdef CONFIG_KEYP ++ unsigned long kflags; ++ #endif + + key = ERR_PTR(-EINVAL); + if (!desc || !*desc) +@@ -274,17 +312,72 @@ struct key *key_alloc(struct key_type *type, const char *desc, + } - freeptr_addr = (unsigned long)kasan_reset_tag((void *)freeptr_addr); -+ #ifdef CONFIG_IEE -+ if(IS_ENABLED(CONFIG_CREDP) && strcmp(s->name, "cred_jar") == 0) -+ iee_set_freeptr((freeptr_t *)freeptr_addr, freelist_ptr_encode(s, fp, freeptr_addr)); -+ else -+ *(freeptr_t *)freeptr_addr = freelist_ptr_encode(s, fp, freeptr_addr); + /* allocate and initialise the key and its description */ ++ #ifdef CONFIG_KEYP ++ key = kmem_cache_alloc(key_jar, GFP_KERNEL); + #else - *(freeptr_t *)freeptr_addr = freelist_ptr_encode(s, fp, freeptr_addr); + key = kmem_cache_zalloc(key_jar, GFP_KERNEL); + #endif - } - - /* Loop over all objects in a slab */ -@@ -809,7 +825,34 @@ static void set_track_update(struct kmem_cache *s, void *object, - depot_stack_handle_t handle) - { - struct track *p = get_track(s, object, alloc); -+#ifdef CONFIG_IEE -+ struct track tmp; + if (!key) + goto no_memory_2; +- ++ #ifdef CONFIG_KEYP ++ struct key_union *key_union = kmem_cache_zalloc(key_union_jar, GFP_KERNEL); ++ key_union->key = key; ++ struct key_struct *key_struct = kmem_cache_zalloc(key_struct_jar, GFP_KERNEL); ++ key_struct->key = key; ++ iee_set_key_union(key, key_union); ++ iee_set_key_struct(key, key_struct); ++ iee_set_key_payload(key, kmem_cache_alloc(key_payload_jar, GFP_KERNEL)); ++ #endif ++ ++ #ifdef CONFIG_KEYP ++ struct keyring_index_key tmp = key->index_key; ++ tmp.desc_len = desclen; ++ tmp.description = kmemdup(desc, desclen + 1, GFP_KERNEL); ++ iee_set_key_index_key(key, tmp); ++ #else + key->index_key.desc_len = desclen; + key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL); ++ #endif + if (!key->index_key.description) + goto no_memory_3; ++ #ifdef CONFIG_KEYP ++ tmp = key->index_key; ++ tmp.type = type; ++ iee_set_key_index_key(key, tmp); ++ iee_key_set_index_key(&key->index_key); ++ #else + key->index_key.type = type; + key_set_index_key(&key->index_key); ++ #endif ++ ++ #ifdef CONFIG_KEYP ++ iee_set_key_usage(key, 1, REFCOUNT_SET); ++ init_rwsem(&KEY_SEM(key)); ++ lockdep_set_class(&KEY_SEM(key), &type->lock_class); ++ iee_set_key_user(key, user); ++ iee_set_key_quotalen(key, quotalen); ++ iee_set_key_datalen(key, type->def_datalen); ++ iee_set_key_uid(key, uid); ++ iee_set_key_gid(key, gid); ++ iee_set_key_perm(key, perm); ++ iee_set_key_restrict_link(key, restrict_link); ++ iee_set_key_last_used_at(key, ktime_get_real_seconds()); ++ ++ kflags = key->flags; ++ if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) ++ kflags |= 1 << KEY_FLAG_IN_QUOTA; ++ if (flags & KEY_ALLOC_BUILT_IN) ++ kflags |= 1 << KEY_FLAG_BUILTIN; ++ if (flags & KEY_ALLOC_UID_KEYRING) ++ kflags |= 1 << KEY_FLAG_UID_KEYRING; ++ if (flags & KEY_ALLOC_SET_KEEP) ++ kflags |= 1 << KEY_FLAG_KEEP; ++ iee_set_key_flags(key, kflags); + ++#ifdef KEY_DEBUGGING ++ iee_set_key_magic(key, KEY_DEBUG_MAGIC); +#endif - -+#ifdef CONFIG_IEE -+ if(IS_ENABLED(CONFIG_CREDP) && strcmp(s->name, "cred_jar") == 0) -+ { -+ tmp = *p; -+ #ifdef CONFIG_STACKDEPOT -+ tmp.handle = handle; -+ #endif -+ tmp.addr = addr; -+ tmp.cpu = smp_processor_id(); -+ tmp.pid = current->pid; -+ tmp.when = jiffies; -+ iee_set_track(p,&tmp); -+ } -+ else -+ { -+ #ifdef CONFIG_STACKDEPOT -+ p->handle = handle; -+ #endif -+ p->addr = addr; -+ p->cpu = smp_processor_id(); -+ p->pid = current->pid; -+ p->when = jiffies; -+ } -+#else - #ifdef CONFIG_STACKDEPOT - p->handle = handle; ++ #else + refcount_set(&key->usage, 1); + init_rwsem(&key->sem); + lockdep_set_class(&key->sem, &type->lock_class); +@@ -310,6 +403,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, + #ifdef KEY_DEBUGGING + key->magic = KEY_DEBUG_MAGIC; #endif -@@ -817,6 +860,7 @@ static void set_track_update(struct kmem_cache *s, void *object, - p->cpu = smp_processor_id(); - p->pid = current->pid; - p->when = jiffies; -+#endif - } ++ #endif - static __always_inline void set_track(struct kmem_cache *s, void *object, -@@ -835,7 +879,14 @@ static void init_tracking(struct kmem_cache *s, void *object) - return; + /* let the security module know about the key */ + ret = security_key_alloc(key, cred, flags); +@@ -326,6 +420,12 @@ struct key *key_alloc(struct key_type *type, const char *desc, + + security_error: + kfree(key->description); ++ #ifdef CONFIG_KEYP ++ kmem_cache_free(key_union_jar,(struct key_union *)(key->graveyard_link.next)); ++ kmem_cache_free(key_struct_jar, (struct key_struct *)(key->name_link.prev)); ++ kmem_cache_free(key_payload_jar, (union key_payload *)(key->name_link.next)); ++ iee_memset(key, 0, sizeof(struct key)); ++ #endif + kmem_cache_free(key_jar, key); + if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { + spin_lock(&user->lock); +@@ -338,6 +438,12 @@ struct key *key_alloc(struct key_type *type, const char *desc, + goto error; + + no_memory_3: ++ #ifdef CONFIG_KEYP ++ kmem_cache_free(key_union_jar,(struct key_union *)(key->graveyard_link.next)); ++ kmem_cache_free(key_struct_jar, (struct key_struct *)(key->name_link.prev)); ++ kmem_cache_free(key_payload_jar, (union key_payload *)(key->name_link.next)); ++ iee_memset(key, 0, sizeof(struct key)); ++ #endif + kmem_cache_free(key_jar, key); + no_memory_2: + if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { +@@ -391,14 +497,22 @@ int key_payload_reserve(struct key *key, size_t datalen) + } + else { + key->user->qnbytes += delta; ++ #ifdef CONFIG_KEYP ++ iee_set_key_quotalen(key, key->quotalen + delta); ++ #else + key->quotalen += delta; ++ #endif + } + spin_unlock(&key->user->lock); + } - p = get_track(s, object, TRACK_ALLOC); -+ #ifdef CONFIG_IEE -+ if(IS_ENABLED(CONFIG_CREDP) && strcmp(s->name, "cred_jar") == 0) -+ iee_memset(p, 0, 2*sizeof(struct track)); -+ else -+ memset(p, 0, 2*sizeof(struct track)); + /* change the recorded data length if that didn't generate an error */ + if (ret == 0) ++ #ifdef CONFIG_KEYP ++ iee_set_key_datalen(key, datalen); ++ #else + key->datalen = datalen; ++ #endif + + return ret; + } +@@ -412,8 +526,14 @@ static void mark_key_instantiated(struct key *key, int reject_error) + /* Commit the payload before setting the state; barrier versus + * key_read_state(). + */ ++ #ifdef CONFIG_KEYP ++ compiletime_assert_atomic_type(key->state); ++ barrier(); ++ iee_set_key_state(key, (reject_error < 0) ? reject_error : KEY_IS_POSITIVE); + #else - memset(p, 0, 2*sizeof(struct track)); + smp_store_release(&key->state, + (reject_error < 0) ? reject_error : KEY_IS_POSITIVE); + #endif } - static void print_track(const char *s, struct track *t, unsigned long pr_time) -@@ -1045,7 +1096,14 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) - unsigned int poison_size = s->object_size; + /* +@@ -449,13 +569,22 @@ static int __key_instantiate_and_link(struct key *key, + mark_key_instantiated(key, 0); + notify_key(key, NOTIFY_KEY_INSTANTIATED, 0); - if (s->flags & SLAB_RED_ZONE) { -+ #ifdef CONFIG_IEE -+ if(IS_ENABLED(CONFIG_CREDP) && strcmp(s->name, "cred_jar") == 0) -+ iee_memset(p - s->red_left_pad, val, s->red_left_pad); -+ else -+ memset(p - s->red_left_pad, val, s->red_left_pad); -+ #else - memset(p - s->red_left_pad, val, s->red_left_pad); -+ #endif ++ #ifdef CONFIG_KEYP ++ if (iee_set_key_flag_bit(key, KEY_FLAG_USER_CONSTRUCT, TEST_AND_CLEAR_BIT)) ++ awaken = 1; ++ #else + if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) + awaken = 1; ++ #endif - if (slub_debug_orig_size(s) && val == SLUB_RED_ACTIVE) { - /* -@@ -1058,12 +1116,34 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) + /* and link it into the destination keyring */ + if (keyring) { + if (test_bit(KEY_FLAG_KEEP, &keyring->flags)) ++ #ifdef CONFIG_KEYP ++ iee_set_key_flag_bit(key, KEY_FLAG_KEEP, SET_BIT_OP); ++ #else + set_bit(KEY_FLAG_KEEP, &key->flags); ++ #endif + + __key_link(keyring, key, _edit); + } +@@ -464,8 +593,14 @@ static int __key_instantiate_and_link(struct key *key, + if (authkey) + key_invalidate(authkey); + +- if (prep->expiry != TIME64_MAX) ++ if (prep->expiry != TIME64_MAX) { ++ #ifdef CONFIG_KEYP ++ iee_set_key_expiry(key, prep->expiry); ++ #else + key_set_expiry(key, prep->expiry); ++ #endif ++ key_schedule_gc(prep->expiry + key_gc_delay); ++ } + } } - if (s->flags & __OBJECT_POISON) { -+ #ifdef CONFIG_IEE -+ if(IS_ENABLED(CONFIG_CREDP) && strcmp(s->name, "cred_jar") == 0) -+ { -+ iee_memset(p, POISON_FREE, poison_size - 1); -+ iee_memset(&p[poison_size - 1], POISON_END, 1); -+ } -+ else -+ { -+ memset(p, POISON_FREE, poison_size - 1); -+ p[poison_size - 1] = POISON_END; -+ } +@@ -605,10 +740,20 @@ int key_reject_and_link(struct key *key, + atomic_inc(&key->user->nikeys); + mark_key_instantiated(key, -error); + notify_key(key, NOTIFY_KEY_INSTANTIATED, -error); ++ #ifdef CONFIG_KEYP ++ iee_set_key_expiry(key, ktime_get_real_seconds() + timeout); + #else - memset(p, POISON_FREE, poison_size - 1); - p[poison_size - 1] = POISON_END; + key_set_expiry(key, ktime_get_real_seconds() + timeout); + #endif - } ++ key_schedule_gc(key->expiry + key_gc_delay); -- if (s->flags & SLAB_RED_ZONE) -+ if (s->flags & SLAB_RED_ZONE) { -+ #ifdef CONFIG_IEE -+ if(IS_ENABLED(CONFIG_CREDP) && strcmp(s->name, "cred_jar") == 0) -+ iee_memset(p + poison_size, val, s->inuse - poison_size); -+ else -+ memset(p + poison_size, val, s->inuse - poison_size); ++ #ifdef CONFIG_KEYP ++ if (iee_set_key_flag_bit(key, KEY_FLAG_USER_CONSTRUCT, TEST_AND_CLEAR_BIT)) ++ awaken = 1; + #else - memset(p + poison_size, val, s->inuse - poison_size); + if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) + awaken = 1; + #endif -+ -+ } + + ret = 0; + +@@ -647,8 +792,13 @@ void key_put(struct key *key) + if (key) { + key_check(key); + ++ #ifdef CONFIG_KEYP ++ if (iee_set_key_usage(key, 0, REFCOUNT_DEC_AND_TEST)) ++ schedule_work(&key_gc_work); ++ #else + if (refcount_dec_and_test(&key->usage)) + schedule_work(&key_gc_work); ++ #endif + } } + EXPORT_SYMBOL(key_put); +@@ -666,7 +816,11 @@ struct key *key_lookup(key_serial_t id) + /* search the tree for the specified key */ + n = key_serial_tree.rb_node; + while (n) { ++ #ifdef CONFIG_KEYP ++ key = rb_entry(n, struct key_union, serial_node)->key; ++ #else + key = rb_entry(n, struct key, serial_node); ++ #endif - static void restore_bytes(struct kmem_cache *s, char *message, u8 data, -@@ -1433,7 +1513,14 @@ void setup_slab_debug(struct kmem_cache *s, struct slab *slab, void *addr) - return; + if (id < key->serial) + n = n->rb_left; +@@ -684,8 +838,13 @@ struct key *key_lookup(key_serial_t id) + /* A key is allowed to be looked up only if someone still owns a + * reference to it - otherwise it's awaiting the gc. + */ ++ #ifdef CONFIG_KEYP ++ if (!iee_set_key_usage(key, 0, REFCOUNT_INC_NOT_ZERO)) ++ goto not_found; ++ #else + if (!refcount_inc_not_zero(&key->usage)) + goto not_found; ++ #endif - metadata_access_enable(); -+ #ifdef CONFIG_IEE -+ if(IS_ENABLED(CONFIG_CREDP) && strcmp(s->name, "cred_jar") == 0) -+ iee_memset(kasan_reset_tag(addr), POISON_INUSE, slab_size(slab)); -+ else -+ memset(kasan_reset_tag(addr), POISON_INUSE, slab_size(slab)); + error: + spin_unlock(&key_serial_lock); +@@ -723,13 +882,27 @@ void key_set_timeout(struct key *key, unsigned timeout) + time64_t expiry = TIME64_MAX; + + /* make the changes with the locks held to prevent races */ ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(key)); + #else - memset(kasan_reset_tag(addr), POISON_INUSE, slab_size(slab)); + down_write(&key->sem); + #endif - metadata_access_disable(); - } -@@ -2015,6 +2102,9 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) - void *start, *p, *next; - int idx; - bool shuffle; -+ #ifdef CONFIG_IEE -+ unsigned int order; + if (timeout > 0) + expiry = ktime_get_real_seconds() + timeout; ++ ++ #ifdef CONFIG_KEYP ++ iee_set_key_expiry(key, expiry); ++ #else + key_set_expiry(key, expiry); + #endif ++ key_schedule_gc(key->expiry + key_gc_delay); - flags &= gfp_allowed_mask; ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(key)); ++ #else + up_write(&key->sem); ++ #endif + } + EXPORT_SYMBOL_GPL(key_set_timeout); -@@ -2029,6 +2119,9 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) - alloc_gfp = (alloc_gfp | __GFP_NOMEMALLOC) & ~__GFP_RECLAIM; +@@ -762,7 +935,11 @@ static inline key_ref_t __key_update(key_ref_t key_ref, + if (!key->type->update) + goto error; - slab = alloc_slab_page(alloc_gfp, node, oo); -+ #ifdef CONFIG_IEE -+ order = oo_order(oo); ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(key)); ++ #else + down_write(&key->sem); + #endif - if (unlikely(!slab)) { - oo = s->min; - alloc_gfp = flags; -@@ -2037,6 +2130,9 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) - * Try a lower order alloc if possible - */ - slab = alloc_slab_page(alloc_gfp, node, oo); -+ #ifdef CONFIG_IEE -+ order = oo_order(oo); -+ #endif - if (unlikely(!slab)) - return NULL; - stat(s, ORDER_FALLBACK); -@@ -2046,6 +2142,45 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) - slab->inuse = 0; - slab->frozen = 0; -+ #ifdef CONFIG_IEE -+ if(IS_ENABLED(CONFIG_CREDP) && strcmp(s->name, "cred_jar") == 0) -+ { -+ int i; -+ for(i = 0; i < (0x1 << order); i++) -+ { -+ unsigned long iee_addr = __phys_to_iee(page_to_phys(folio_page(slab_folio(slab), i))); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)page_address(folio_page(slab_folio(slab), i))); -+ } -+ } -+ -+ // If the page belongs to a task_struct, alloc token for it and set iee&lm va. -+ if(strcmp(s->name, "task_struct") == 0) -+ { -+ int i; -+ for(i = 0; i < (0x1 << order); i++) -+ { -+ void *token_addr = (void *)__phys_to_iee(page_to_phys(folio_page(slab_folio(slab), i))); -+ // Get lm va of the page. -+ void *alloc_token = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); -+ iee_set_token_page_valid(token_addr, alloc_token); -+ set_iee_page_valid(__phys_to_iee(__pa(alloc_token))); -+ iee_set_logical_mem_ro((unsigned long)alloc_token); -+ } -+ } -+ #else -+ #ifdef CONFIG_KOI -+ if (strcmp(s->name, "task_struct") == 0) { -+ int i; -+ for (i = 0; i < (0x1 << order); i++) { -+ void *token_addr = __phys_to_virt(page_to_phys(page + i)) + koi_offset; -+ void *alloc_token = __get_free_page(GFP_KERNEL | __GFP_ZERO); -+ koi_add_page_mapping(token_addr, alloc_token); -+ } -+ } -+ #endif + ret = key->type->update(key, prep); + if (ret == 0) { +@@ -771,7 +948,11 @@ static inline key_ref_t __key_update(key_ref_t key_ref, + notify_key(key, NOTIFY_KEY_UPDATED, 0); + } + ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(key)); ++ #else + up_write(&key->sem); + #endif -+ - account_slab(slab, oo_order(oo), s, flags); - slab->slab_cache = s; -@@ -2098,6 +2233,67 @@ static void __free_slab(struct kmem_cache *s, struct slab *slab) - __folio_clear_slab(folio); - mm_account_reclaimed_pages(pages); - unaccount_slab(slab, order, s); -+ -+ #ifdef CONFIG_IEE -+ if(IS_ENABLED(CONFIG_CREDP) && strcmp(s->name, "cred_jar") == 0) -+ { -+ int i; -+ for(i = 0; i < (0x1 << order); i++) -+ { -+ unsigned long iee_addr = __phys_to_iee(page_to_phys(folio_page(folio, i))); -+ set_iee_page_invalid(iee_addr); -+ iee_set_logical_mem_rw((unsigned long)page_address(folio_page(folio, i))); -+ } -+ } -+ // If the page containing this token is empty, free it and restore iee&lm va. -+ if(strcmp(s->name, "task_struct") == 0) -+ { -+ int i; -+ for(i = 0; i < (0x1 << order); i++) -+ { -+ void *token_addr = (void *)__phys_to_iee(page_to_phys(folio_page(folio, i))); -+ unsigned long flags; -+ unsigned long res; -+ local_irq_save(flags); -+ asm volatile("at s1e1r, %0"::"r"(token_addr)); -+ isb(); -+ res = read_sysreg(par_el1); -+ local_irq_restore(flags); -+ if(!(res & 0x1)) -+ { -+ // Get lm va of the page. -+ void *token_page = __va(res & PTE_ADDR_MASK); -+ iee_set_token_page_invalid(token_addr); -+ set_iee_page_invalid(__phys_to_iee(__pa(token_page))); -+ iee_set_logical_mem_rw((unsigned long)token_page); -+ free_page((unsigned long)token_page); -+ } -+ } -+ } -+ #else -+ #ifdef CONFIG_KOI -+ if(strcmp(s->name, "task_struct") == 0) -+ { -+ int i; -+ for(i = 0; i < (0x1 << order); i++) -+ { -+ void *token_addr = __phys_to_virt(page_to_phys(page + i)) + koi_offset; -+ unsigned long flags; -+ local_irq_save(flags); -+ asm volatile("at s1e1r, %0"::"r"(token_addr)); -+ isb(); -+ unsigned long res = read_sysreg(par_el1); -+ local_irq_restore(flags); -+ if(!(res & 0x1)) -+ { -+ koi_remove_page_mapping(token_addr); -+ free_page(__va(res & PTE_ADDR_MASK)); -+ } + if (ret < 0) + goto error; +@@ -1087,7 +1268,11 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) + goto error; + } + ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(key)); ++ #else + down_write(&key->sem); ++ #endif + + ret = key->type->update(key, &prep); + if (ret == 0) { +@@ -1096,7 +1281,11 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) + notify_key(key, NOTIFY_KEY_UPDATED, 0); + } + ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(key)); ++ #else + up_write(&key->sem); ++ #endif + + error: + if (key->type->preparse) +@@ -1125,6 +1314,23 @@ void key_revoke(struct key *key) + * authorisation key whilst holding the sem on a key we've just + * instantiated + */ ++ #ifdef CONFIG_KEYP ++ down_write_nested(&KEY_SEM(key), 1); ++ if (!iee_set_key_flag_bit(key, KEY_FLAG_REVOKED, TEST_AND_SET_BIT)) { ++ notify_key(key, NOTIFY_KEY_REVOKED, 0); ++ if (key->type->revoke) ++ key->type->revoke(key); ++ ++ /* set the death time to no more than the expiry time */ ++ time = ktime_get_real_seconds(); ++ if (key->revoked_at == 0 || key->revoked_at > time) { ++ iee_set_key_revoked_at(key, time); ++ key_schedule_gc(key->revoked_at + key_gc_delay); + } + } -+ #endif -+ #endif + - __free_pages(&folio->page, order); ++ up_write(&KEY_SEM(key)); ++ #else + down_write_nested(&key->sem, 1); + if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags)) { + notify_key(key, NOTIFY_KEY_REVOKED, 0); +@@ -1140,6 +1346,7 @@ void key_revoke(struct key *key) + } + + up_write(&key->sem); ++ #endif } + EXPORT_SYMBOL(key_revoke); -diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c -index a2cbe44c48e1..7cf05d293312 100644 ---- a/mm/sparse-vmemmap.c -+++ b/mm/sparse-vmemmap.c -@@ -28,6 +28,10 @@ - #include - #include +@@ -1157,12 +1364,21 @@ void key_invalidate(struct key *key) + key_check(key); -+#ifdef CONFIG_PTP -+#include + if (!test_bit(KEY_FLAG_INVALIDATED, &key->flags)) { ++ #ifdef CONFIG_KEYP ++ down_write_nested(&KEY_SEM(key), 1); ++ if (!iee_set_key_flag_bit(key, KEY_FLAG_INVALIDATED, TEST_AND_SET_BIT)) { ++ notify_key(key, NOTIFY_KEY_INVALIDATED, 0); ++ key_schedule_gc_links(); ++ } ++ up_write(&KEY_SEM(key)); ++ #else + down_write_nested(&key->sem, 1); + if (!test_and_set_bit(KEY_FLAG_INVALIDATED, &key->flags)) { + notify_key(key, NOTIFY_KEY_INVALIDATED, 0); + key_schedule_gc_links(); + } + up_write(&key->sem); ++ #endif + } + } + EXPORT_SYMBOL(key_invalidate); +@@ -1186,9 +1402,17 @@ int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep) + ret = key_payload_reserve(key, prep->quotalen); + if (ret == 0) { + rcu_assign_keypointer(key, prep->payload.data[0]); ++ #ifdef CONFIG_KEYP ++ union key_payload key_payload = *((union key_payload *)(key->name_link.next)); ++ key_payload.data[1] = prep->payload.data[1]; ++ key_payload.data[2] = prep->payload.data[2]; ++ key_payload.data[3] = prep->payload.data[3]; ++ iee_write_key_payload(key, key_payload); ++ #else + key->payload.data[1] = prep->payload.data[1]; + key->payload.data[2] = prep->payload.data[2]; + key->payload.data[3] = prep->payload.data[3]; ++ #endif + prep->payload.data[0] = NULL; + prep->payload.data[1] = NULL; + prep->payload.data[2] = NULL; +@@ -1262,6 +1486,11 @@ void __init key_init(void) + /* allocate a slab in which we can store keys */ + key_jar = kmem_cache_create("key_jar", sizeof(struct key), + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); ++ #ifdef CONFIG_KEYP ++ key_union_jar = kmem_cache_create("key_union_jar", sizeof(struct key_union), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); ++ key_struct_jar = kmem_cache_create("key_struct_jar", sizeof(struct key_struct), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); ++ key_payload_jar = kmem_cache_create("key_payload_jar", sizeof(union key_payload)*2, 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); ++ #endif + + /* add the special key types */ + list_add_tail(&key_type_keyring.link, &key_types_list); +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index aa1dc43b16dd..e92df31642d5 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -23,6 +23,12 @@ + #include + #include + #include "internal.h" ++#ifdef CONFIG_CREDP ++#include ++#endif ++#ifdef CONFIG_KEYP ++#include +#endif -+ - #include - #include -@@ -146,6 +150,9 @@ pte_t * __meminit vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node, - struct page *reuse) + #define KEY_MAX_DESC_SIZE 4096 + +@@ -804,11 +810,19 @@ static long __keyctl_read_key(struct key *key, char *buffer, size_t buflen) { - pte_t *pte = pte_offset_kernel(pmd, addr); -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; + long ret; + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(key)); ++ #else + down_read(&key->sem); + #endif - if (pte_none(ptep_get(pte))) { - pte_t entry; - void *p; -@@ -167,6 +174,11 @@ pte_t * __meminit vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node, - get_page(reuse); - p = page_to_virt(reuse); + ret = key_validate(key); + if (ret == 0) + ret = key->type->read(key, buffer, buflen); ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(key)); ++ #else + up_read(&key->sem); ++ #endif + return ret; + } + +@@ -978,7 +992,11 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) + + /* make the changes with the locks held to prevent chown/chown races */ + ret = -EACCES; ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(key)); ++ #else + down_write(&key->sem); ++ #endif + + { + bool is_privileged_op = false; +@@ -1036,19 +1054,32 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) } -+#ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(p)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)p); -+#endif - entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL); - set_pte_at(&init_mm, addr, pte, entry); + + zapowner = key->user; ++ #ifdef CONFIG_KEYP ++ iee_set_key_user(key, newowner); ++ iee_set_key_uid(key, uid); ++ #else + key->user = newowner; + key->uid = uid; ++ #endif } -@@ -176,11 +188,20 @@ pte_t * __meminit vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node, - static void * __meminit vmemmap_alloc_block_zero(unsigned long size, int node) - { - void *p = vmemmap_alloc_block(size, node); -+ #ifdef CONFIG_PTP -+ unsigned long iee_addr; + + /* change the GID */ + if (group != (gid_t) -1) ++ #ifdef CONFIG_KEYP ++ iee_set_key_gid(key, gid); ++ #else + key->gid = gid; ++ #endif + + notify_key(key, NOTIFY_KEY_SETATTR, 0); + ret = 0; + + error_put: ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(key)); ++ #else + up_write(&key->sem); ++ #endif + key_put(key); + if (zapowner) + key_user_put(zapowner); +@@ -1090,16 +1121,28 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) + + /* make the changes with the locks held to prevent chown/chmod races */ + ret = -EACCES; ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(key)); ++ #else + down_write(&key->sem); + #endif - if (!p) - return NULL; - memset(p, 0, size); + /* if we're not the sysadmin, we can only change a key that we own */ + if (uid_eq(key->uid, current_fsuid()) || capable(CAP_SYS_ADMIN)) { ++ #ifdef CONFIG_KEYP ++ iee_set_key_perm(key, perm); ++ #else + key->perm = perm; ++ #endif + notify_key(key, NOTIFY_KEY_SETATTR, 0); + ret = 0; + } -+ #ifdef CONFIG_PTP -+ iee_addr = __phys_to_iee(__pa(p)); -+ set_iee_page_valid(iee_addr); -+ iee_set_logical_mem_ro((unsigned long)p); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(key)); ++ #else + up_write(&key->sem); + #endif -+ - return p; - } + key_put(key); + error: + return ret; +@@ -1155,7 +1198,11 @@ static int keyctl_change_reqkey_auth(struct key *key) + return -ENOMEM; -diff --git a/mm/vmalloc.c b/mm/vmalloc.c -index e6058942a084..27a006728009 100644 ---- a/mm/vmalloc.c -+++ b/mm/vmalloc.c -@@ -3431,7 +3431,7 @@ static int vmap_pfn_apply(pte_t *pte, unsigned long addr, void *private) + key_put(new->request_key_auth); ++ #ifdef CONFIG_CREDP ++ iee_set_cred_request_key_auth(new,key_get(key)); ++ #else + new->request_key_auth = key_get(key); ++ #endif - if (WARN_ON_ONCE(pfn_valid(pfn))) - return -EINVAL; -- -+ - ptent = pte_mkspecial(pfn_pte(pfn, data->prot)); - set_pte_at(&init_mm, addr, pte, ptent); + return commit_creds(new); + } +@@ -1196,7 +1243,11 @@ static long keyctl_instantiate_key_common(key_serial_t id, + if (!instkey) + goto error; -diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c -index c42ddd85ff1f..4714b4f2be08 100644 ---- a/net/dns_resolver/dns_key.c -+++ b/net/dns_resolver/dns_key.c -@@ -34,6 +34,10 @@ - #include - #include "internal.h" ++ #ifdef CONFIG_KEYP ++ rka = ((union key_payload *)(instkey->name_link.next))->data[0]; ++ #else + rka = instkey->payload.data[0]; ++ #endif + if (rka->target_key->serial != id) + goto error; -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - MODULE_DESCRIPTION("DNS Resolver"); - MODULE_AUTHOR("Wang Lei"); - MODULE_LICENSE("GPL"); -@@ -365,8 +369,13 @@ static int __init init_dns_resolver(void) - /* instruct request_key() to use this special keyring as a cache for - * the results it looks up */ - set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_thread_keyring(cred,keyring); -+ iee_set_cred_jit_keyring(cred,KEY_REQKEY_DEFL_THREAD_KEYRING); +@@ -1358,7 +1409,11 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error, + if (!instkey) + goto error; + ++ #ifdef CONFIG_KEYP ++ rka = ((union key_payload *)(instkey->name_link.next))->data[0]; + #else - cred->thread_keyring = keyring; - cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; + rka = instkey->payload.data[0]; + #endif - dns_resolver_cache = cred; + if (rka->target_key->serial != id) + goto error; - kdebug("DNS resolver keyring: %d\n", key_serial(keyring)); -diff --git a/security/commoncap.c b/security/commoncap.c -index bc0521104197..d7d3b7cc13e8 100644 ---- a/security/commoncap.c -+++ b/security/commoncap.c -@@ -26,6 +26,10 @@ - #include - #include +@@ -1432,7 +1487,11 @@ long keyctl_set_reqkey_keyring(int reqkey_defl) + } -+#ifdef CONFIG_CREDP -+#include -+#endif -+ - /* - * If a non-root user executes a setuid-root binary in - * !secure(SECURE_NOROOT) mode, then we raise capabilities. -@@ -266,6 +270,15 @@ int cap_capset(struct cred *new, - if (!cap_issubset(*effective, *permitted)) - return -EPERM; + set: ++ #ifdef CONFIG_CREDP ++ iee_set_cred_jit_keyring(new,reqkey_defl); ++ #else + new->jit_keyring = reqkey_defl; ++ #endif + commit_creds(new); + return old_setting; + error: +@@ -1644,9 +1703,17 @@ long keyctl_session_to_parent(void) + cred = cred_alloc_blank(); + if (!cred) + goto error_keyring; ++ #ifdef CONFIG_CREDP ++ newwork = (struct rcu_head *)(cred->rcu.func); ++ #else + newwork = &cred->rcu; ++ #endif + #ifdef CONFIG_CREDP -+ iee_set_cred_cap_effective(new,*effective); -+ iee_set_cred_cap_inheritable(new,*inheritable); -+ iee_set_cred_cap_permitted(new,*permitted); -+ -+ iee_set_cred_cap_ambient(new,cap_intersect(new->cap_ambient, -+ cap_intersect(*permitted, -+ *inheritable))); ++ iee_set_cred_session_keyring(cred,key_ref_to_ptr(keyring_r)); + #else - new->cap_effective = *effective; - new->cap_inheritable = *inheritable; - new->cap_permitted = *permitted; -@@ -277,6 +290,7 @@ int cap_capset(struct cred *new, - new->cap_ambient = cap_intersect(new->cap_ambient, - cap_intersect(*permitted, - *inheritable)); + cred->session_keyring = key_ref_to_ptr(keyring_r); + #endif - if (WARN_ON(!cap_ambient_invariant_ok(new))) - return -EINVAL; - return 0; -@@ -601,9 +615,16 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, - * pP' = (X & fP) | (pI & fI) - * The addition of pA' is handled later. - */ -+#ifdef CONFIG_CREDP -+ kernel_cap_t temp = new->cap_permitted; -+ temp.val = (new->cap_bset.val & caps->permitted.val) | -+ (new->cap_inheritable.val & caps->inheritable.val); -+ iee_set_cred_cap_permitted(new,temp); -+#else - new->cap_permitted.val = - (new->cap_bset.val & caps->permitted.val) | - (new->cap_inheritable.val & caps->inheritable.val); -+#endif + keyring_r = NULL; + init_task_work(newwork, key_change_session_keyring); - if (caps->permitted.val & ~new->cap_permitted.val) - /* insufficient to execute correctly */ -@@ -726,7 +747,15 @@ static int get_file_caps(struct linux_binprm *bprm, struct file *file, - int rc = 0; - struct cpu_vfs_cap_data vcaps; +@@ -1705,7 +1772,11 @@ long keyctl_session_to_parent(void) + write_unlock_irq(&tasklist_lock); + rcu_read_unlock(); + if (oldwork) ++ #ifdef CONFIG_CREDP ++ put_cred(*(struct cred **)(oldwork + 1)); ++ #else + put_cred(container_of(oldwork, struct cred, rcu)); ++ #endif + if (newwork) + put_cred(cred); + return ret; +@@ -1814,25 +1885,45 @@ long keyctl_watch_key(key_serial_t id, int watch_queue_fd, int watch_id) + if (ret < 0) + goto err_watch; -+ #ifdef CONFIG_CREDP -+ do { -+ kernel_cap_t tmp_cap = bprm->cred->cap_permitted; -+ tmp_cap.val = 0; -+ iee_set_cred_cap_permitted(bprm->cred, tmp_cap); -+ } while (0); ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(key)); ++ #else + down_write(&key->sem); ++ #endif + if (!key->watchers) { ++ #ifdef CONFIG_KEYP ++ iee_set_key_watchers(key, wlist); ++ #else + key->watchers = wlist; ++ #endif + wlist = NULL; + } + + ret = add_watch_to_object(watch, key->watchers); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(key)); ++ #else + up_write(&key->sem); ++ #endif + + if (ret == 0) + watch = NULL; + } else { + ret = -EBADSLT; + if (key->watchers) { ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(key)); ++ #else + down_write(&key->sem); ++ #endif + ret = remove_watch_from_object(key->watchers, + wqueue, key_serial(key), + false); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(key)); ++ #else + up_write(&key->sem); ++ #endif + } + } + +diff --git a/security/keys/keyring.c b/security/keys/keyring.c +index 4448758f643a..a1677b1e600e 100644 +--- a/security/keys/keyring.c ++++ b/security/keys/keyring.c +@@ -21,6 +21,11 @@ + #include + #include "internal.h" + ++#ifdef CONFIG_KEYP ++#include ++extern void iee_memcpy(void *dst, void *src, size_t n); ++#endif ++ + /* + * When plumbing the depths of the key tree, this sets a hard limit + * set on how deep we're willing to go. +@@ -112,7 +117,11 @@ static void keyring_publish_name(struct key *keyring) + keyring->description[0] && + keyring->description[0] != '.') { + write_lock(&keyring_name_lock); ++ #ifdef CONFIG_KEYP ++ list_add_tail(&(((struct key_struct *)(keyring->name_link.prev))->name_link), &ns->keyring_name_list); ++ #else + list_add_tail(&keyring->name_link, &ns->keyring_name_list); ++ #endif + write_unlock(&keyring_name_lock); + } + } +@@ -140,7 +149,11 @@ static void keyring_free_preparse(struct key_preparsed_payload *prep) + static int keyring_instantiate(struct key *keyring, + struct key_preparsed_payload *prep) + { ++ #ifdef CONFIG_KEYP ++ assoc_array_init(&((struct key_struct *)(keyring->name_link.prev))->keys); + #else - cap_clear(bprm->cred->cap_permitted); + assoc_array_init(&keyring->keys); + #endif + /* make the keyring available by name if it has one */ + keyring_publish_name(keyring); + return 0; +@@ -207,6 +220,57 @@ static void hash_key_type_and_desc(struct keyring_index_key *index_key) + index_key->hash = hash; + } - if (!file_caps_enabled) - return 0; -@@ -757,7 +786,15 @@ static int get_file_caps(struct linux_binprm *bprm, struct file *file, ++#ifdef CONFIG_KEYP ++static void iee_hash_key_type_and_desc(struct keyring_index_key *index_key) ++{ ++ const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP; ++ const unsigned long fan_mask = ASSOC_ARRAY_FAN_MASK; ++ const char *description = index_key->description; ++ unsigned long hash, type; ++ u32 piece; ++ u64 acc; ++ int n, desc_len = index_key->desc_len; ++ ++ type = (unsigned long)index_key->type; ++ acc = mult_64x32_and_fold(type, desc_len + 13); ++ acc = mult_64x32_and_fold(acc, 9207); ++ piece = (unsigned long)index_key->domain_tag; ++ acc = mult_64x32_and_fold(acc, piece); ++ acc = mult_64x32_and_fold(acc, 9207); ++ ++ for (;;) { ++ n = desc_len; ++ if (n <= 0) ++ break; ++ if (n > 4) ++ n = 4; ++ piece = 0; ++ memcpy(&piece, description, n); ++ description += n; ++ desc_len -= n; ++ acc = mult_64x32_and_fold(acc, piece); ++ acc = mult_64x32_and_fold(acc, 9207); ++ } ++ ++ /* Fold the hash down to 32 bits if need be. */ ++ hash = acc; ++ if (ASSOC_ARRAY_KEY_CHUNK_SIZE == 32) ++ hash ^= acc >> 32; ++ ++ /* Squidge all the keyrings into a separate part of the tree to ++ * ordinary keys by making sure the lowest level segment in the hash is ++ * zero for keyrings and non-zero otherwise. ++ */ ++ if (index_key->type != &key_type_keyring && (hash & fan_mask) == 0) ++ hash |= (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1; ++ else if (index_key->type == &key_type_keyring && (hash & fan_mask) != 0) ++ hash = (hash + (hash << level_shift)) & ~fan_mask; ++ struct keyring_index_key tmp = *index_key; ++ tmp.hash = hash; ++ iee_set_key_index_key(container_of(index_key, struct key, index_key), tmp); ++} ++#endif ++ + /* + * Finalise an index key to include a part of the description actually in the + * index key, to set the domain tag and to calculate the hash. +@@ -228,6 +292,34 @@ void key_set_index_key(struct keyring_index_key *index_key) + hash_key_type_and_desc(index_key); + } - out: - if (rc) -+ #ifdef CONFIG_CREDP -+ do { -+ kernel_cap_t tmp_cap = bprm->cred->cap_permitted; -+ tmp_cap.val = 0; -+ iee_set_cred_cap_permitted(bprm->cred, tmp_cap); -+ } while (0); ++#ifdef CONFIG_KEYP ++void iee_key_set_index_key(struct keyring_index_key *index_key) ++{ ++ static struct key_tag default_domain_tag = { .usage = REFCOUNT_INIT(1), }; ++ size_t n = min_t(size_t, index_key->desc_len, sizeof(index_key->desc)); ++ struct keyring_index_key tmp; ++ ++ iee_memcpy(index_key->desc, index_key->description, n); ++ ++ if (!index_key->domain_tag) { ++ if (index_key->type->flags & KEY_TYPE_NET_DOMAIN) ++ { ++ tmp = *index_key; ++ tmp.domain_tag = current->nsproxy->net_ns->key_domain; ++ iee_set_key_index_key(container_of(index_key, struct key, index_key), tmp); ++ } ++ else ++ { ++ tmp = *index_key; ++ tmp.domain_tag = &default_domain_tag; ++ iee_set_key_index_key(container_of(index_key, struct key, index_key), tmp); ++ } ++ } ++ ++ iee_hash_key_type_and_desc(index_key); ++} ++#endif ++ + /** + * key_put_tag - Release a ref on a tag. + * @tag: The tag to release. +@@ -414,9 +506,15 @@ static void keyring_destroy(struct key *keyring) + if (keyring->description) { + write_lock(&keyring_name_lock); + ++ #ifdef CONFIG_KEYP ++ if(((struct key_struct *)(keyring->name_link.prev))->name_link.next != NULL && ++ !list_empty(&(((struct key_struct *)(keyring->name_link.prev))->name_link))) ++ list_del(&(((struct key_struct *)(keyring->name_link.prev))->name_link)); + #else - cap_clear(bprm->cred->cap_permitted); + if (keyring->name_link.next != NULL && + !list_empty(&keyring->name_link)) + list_del(&keyring->name_link); + #endif - return rc; + write_unlock(&keyring_name_lock); + } +@@ -428,7 +526,11 @@ static void keyring_destroy(struct key *keyring) + kfree(keyres); + } + ++ #ifdef CONFIG_KEYP ++ assoc_array_destroy(&((struct key_struct *)(keyring->name_link.prev))->keys, &keyring_assoc_array_ops); ++ #else + assoc_array_destroy(&keyring->keys, &keyring_assoc_array_ops); ++ #endif } -@@ -809,8 +846,13 @@ static void handle_privileged_root(struct linux_binprm *bprm, bool has_fcap, - */ - if (__is_eff(root_uid, new) || __is_real(root_uid, new)) { - /* pP' = (cap_bset & ~0) | (pI & ~0) */ -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_permitted(new,cap_combine(old->cap_bset, -+ old->cap_inheritable)); + + /* +@@ -442,8 +544,13 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) + seq_puts(m, "[anon]"); + + if (key_is_positive(keyring)) { ++ #ifdef CONFIG_KEYP ++ if (((struct key_struct *)(keyring->name_link.prev))->keys.nr_leaves_on_tree != 0) ++ seq_printf(m, ": %lu", ((struct key_struct *)(keyring->name_link.prev))->keys.nr_leaves_on_tree); + #else - new->cap_permitted = cap_combine(old->cap_bset, - old->cap_inheritable); + if (keyring->keys.nr_leaves_on_tree != 0) + seq_printf(m, ": %lu", keyring->keys.nr_leaves_on_tree); + #endif + else + seq_puts(m, ": empty"); } - /* - * If only the real uid is 0, we do not set the effective bit. -@@ -919,34 +961,71 @@ int cap_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file) - /* downgrade; they get no more than they had, and maybe less */ - if (!ns_capable(new->user_ns, CAP_SETUID) || - (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) { -+ #ifdef CONFIG_CREDP -+ iee_set_cred_euid(new,new->uid); -+ iee_set_cred_egid(new,new->gid); -+ #else - new->euid = new->uid; - new->egid = new->gid; -+ #endif - } -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_permitted(new,cap_intersect(new->cap_permitted, -+ old->cap_permitted)); +@@ -494,8 +601,13 @@ static long keyring_read(const struct key *keyring, + ctx.buffer = (key_serial_t *)buffer; + ctx.buflen = buflen; + ctx.count = 0; ++ #ifdef CONFIG_KEYP ++ ret = assoc_array_iterate(&((struct key_struct *)(keyring->name_link.prev))->keys, ++ keyring_read_iterator, &ctx); + #else - new->cap_permitted = cap_intersect(new->cap_permitted, - old->cap_permitted); + ret = assoc_array_iterate(&keyring->keys, + keyring_read_iterator, &ctx); + #endif + if (ret < 0) { + kleave(" = %ld [iterate]", ret); + return ret; +@@ -503,7 +615,11 @@ static long keyring_read(const struct key *keyring, } -+ #ifdef CONFIG_CREDP -+ iee_set_cred_fsuid(new,new->euid); -+ iee_set_cred_suid(new,new->euid); -+ iee_set_cred_fsgid(new,new->egid); -+ iee_set_cred_sgid(new,new->egid); + /* Return the size of the buffer needed */ ++ #ifdef CONFIG_KEYP ++ ret = ((struct key_struct *)(keyring->name_link.prev))->keys.nr_leaves_on_tree * sizeof(key_serial_t); + #else - new->suid = new->fsuid = new->euid; - new->sgid = new->fsgid = new->egid; + ret = keyring->keys.nr_leaves_on_tree * sizeof(key_serial_t); + #endif - - /* File caps or setid cancels ambient. */ - if (has_fcap || is_setid) -+ #ifdef CONFIG_CREDP -+ do { -+ kernel_cap_t tmp_cap = new->cap_ambient; -+ tmp_cap.val = 0; -+ iee_set_cred_cap_ambient(new, tmp_cap); -+ } while (0); + if (ret <= buflen) + kleave("= %ld [ok]", ret); + else +@@ -648,12 +764,22 @@ static int search_keyring(struct key *keyring, struct keyring_search_context *ct + if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_DIRECT) { + const void *object; + ++ #ifdef CONFIG_KEYP ++ object = assoc_array_find(&((struct key_struct *)(keyring->name_link.prev))->keys, ++ &keyring_assoc_array_ops, ++ &ctx->index_key); + #else - cap_clear(new->cap_ambient); + object = assoc_array_find(&keyring->keys, + &keyring_assoc_array_ops, + &ctx->index_key); + #endif - - /* - * Now that we've computed pA', update pP' to give: - * pP' = (X & fP) | (pI & fI) | pA' - */ -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_permitted(new,cap_combine(new->cap_permitted, new->cap_ambient)); + return object ? ctx->iterator(object, ctx) : 0; + } ++ #ifdef CONFIG_KEYP ++ return assoc_array_iterate(&((struct key_struct *)(keyring->name_link.prev))->keys, ctx->iterator, ctx); + #else - new->cap_permitted = cap_combine(new->cap_permitted, new->cap_ambient); + return assoc_array_iterate(&keyring->keys, ctx->iterator, ctx); + #endif + } - /* - * Set pE' = (fE ? pP' : pA'). Because pA' is zero if fE is set, - * this is the same as pE' = (fE ? pP' : 0) | pA'. - */ - if (effective) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_effective(new,new->cap_permitted); + /* +@@ -729,7 +855,11 @@ static bool search_nested_keyrings(struct key *keyring, + if (!(ctx->flags & KEYRING_SEARCH_RECURSE)) + goto not_this_keyring; + ++ #ifdef CONFIG_KEYP ++ ptr = READ_ONCE(((struct key_struct *)(keyring->name_link.prev))->keys.root); ++ #else + ptr = READ_ONCE(keyring->keys.root); ++ #endif + if (!ptr) + goto not_this_keyring; + +@@ -853,10 +983,17 @@ static bool search_nested_keyrings(struct key *keyring, + key = key_ref_to_ptr(ctx->result); + key_check(key); + if (!(ctx->flags & KEYRING_SEARCH_NO_UPDATE_TIME)) { ++ #ifdef CONFIG_KEYP ++ iee_set_key_last_used_at(key, ctx->now); ++ iee_set_key_last_used_at(keyring, ctx->now); ++ while (sp > 0) ++ iee_set_key_last_used_at(stack[--sp].keyring, ctx->now); + #else - new->cap_effective = new->cap_permitted; + key->last_used_at = ctx->now; + keyring->last_used_at = ctx->now; + while (sp > 0) + stack[--sp].keyring->last_used_at = ctx->now; + #endif - else -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_effective(new,new->cap_ambient); + } + kleave(" = true"); + return true; +@@ -1053,7 +1190,11 @@ int keyring_restrict(key_ref_t keyring_ref, const char *type, + goto error; + } + ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(keyring)); ++ #else + down_write(&keyring->sem); ++ #endif + down_write(&keyring_serialise_restrict_sem); + + if (keyring->restrict_link) { +@@ -1061,12 +1202,20 @@ int keyring_restrict(key_ref_t keyring_ref, const char *type, + } else if (keyring_detect_restriction_cycle(keyring, restrict_link)) { + ret = -EDEADLK; + } else { ++ #ifdef CONFIG_KEYP ++ iee_set_key_restrict_link(keyring, restrict_link); + #else - new->cap_effective = new->cap_ambient; + keyring->restrict_link = restrict_link; + #endif - - if (WARN_ON(!cap_ambient_invariant_ok(new))) - return -EPERM; -@@ -957,7 +1036,11 @@ int cap_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file) - return ret; + notify_key(keyring, NOTIFY_KEY_SETATTR, 0); } -+ #ifdef CONFIG_CREDP -+ iee_set_cred_securebits(new,new->securebits & ~issecure_mask(SECURE_KEEP_CAPS)); + up_write(&keyring_serialise_restrict_sem); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(keyring)); + #else - new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); + up_write(&keyring->sem); + #endif - if (WARN_ON(!cap_ambient_invariant_ok(new))) - return -EPERM; -@@ -1092,8 +1175,21 @@ static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) - !uid_eq(new->euid, root_uid) && - !uid_eq(new->suid, root_uid))) { - if (!issecure(SECURE_KEEP_CAPS)) { -+ #ifdef CONFIG_CREDP -+ do { -+ kernel_cap_t tmp_cap = new->cap_permitted; -+ tmp_cap.val = 0; -+ iee_set_cred_cap_permitted(new, tmp_cap); -+ } while (0); -+ do { -+ kernel_cap_t tmp_cap = new->cap_effective; -+ tmp_cap.val = 0; -+ iee_set_cred_cap_effective(new, tmp_cap); -+ } while (0); -+ #else - cap_clear(new->cap_permitted); - cap_clear(new->cap_effective); -+ #endif - } + if (ret < 0) { + key_put(restrict_link->key); +@@ -1106,8 +1255,13 @@ key_ref_t find_key_to_update(key_ref_t keyring_ref, + kenter("{%d},{%s,%s}", + keyring->serial, index_key->type->name, index_key->description); - /* -@@ -1101,12 +1197,32 @@ static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) - * by exec to drop capabilities. We should make sure that - * this remains the case. - */ -+ #ifdef CONFIG_CREDP -+ do { -+ kernel_cap_t tmp_cap = new->cap_ambient; -+ tmp_cap.val = 0; -+ iee_set_cred_cap_ambient(new, tmp_cap); -+ } while (0); ++ #ifdef CONFIG_KEYP ++ object = assoc_array_find(&((struct key_struct *)(keyring->name_link.prev))->keys, &keyring_assoc_array_ops, ++ index_key); ++ #else + object = assoc_array_find(&keyring->keys, &keyring_assoc_array_ops, + index_key); ++ #endif + + if (object) + goto found; +@@ -1151,7 +1305,13 @@ struct key *find_keyring_by_name(const char *name, bool uid_keyring) + /* Search this hash bucket for a keyring with a matching name that + * grants Search permission and that hasn't been revoked + */ ++ #ifdef CONFIG_KEYP ++ for(keyring = list_first_entry(&ns->keyring_name_list, struct key_struct, name_link)->key; ++ !(&(((struct key_struct *)(keyring->name_link.prev))->name_link) == (&ns->keyring_name_list)); ++ keyring = list_entry(((struct key_struct *)(keyring->name_link.prev))->name_link.next, struct key_struct, name_link)->key) { ++ #else + list_for_each_entry(keyring, &ns->keyring_name_list, name_link) { ++ #endif + if (!kuid_has_mapping(ns, keyring->user->uid)) + continue; + +@@ -1174,9 +1334,15 @@ struct key *find_keyring_by_name(const char *name, bool uid_keyring) + /* we've got a match but we might end up racing with + * key_cleanup() if the keyring is currently 'dead' + * (ie. it has a zero usage count) */ ++ #ifdef CONFIG_KEYP ++ if (!iee_set_key_usage(keyring, 0, REFCOUNT_INC_NOT_ZERO)) ++ continue; ++ iee_set_key_last_used_at(keyring, ktime_get_real_seconds()); + #else - cap_clear(new->cap_ambient); + if (!refcount_inc_not_zero(&keyring->usage)) + continue; + keyring->last_used_at = ktime_get_real_seconds(); + #endif + goto out; } - if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid)) -+ #ifdef CONFIG_CREDP -+ do { -+ kernel_cap_t tmp_cap = new->cap_effective; -+ tmp_cap.val = 0; -+ iee_set_cred_cap_effective(new, tmp_cap); -+ } while (0); + +@@ -1235,13 +1401,21 @@ static int keyring_detect_cycle(struct key *A, struct key *B) + */ + int __key_link_lock(struct key *keyring, + const struct keyring_index_key *index_key) ++ #ifdef CONFIG_KEYP ++ __acquires(&KEY_SEM(keyring)) ++ #else + __acquires(&keyring->sem) ++ #endif + __acquires(&keyring_serialise_link_lock) + { + if (keyring->type != &key_type_keyring) + return -ENOTDIR; + ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(keyring)); ++ #else + down_write(&keyring->sem); ++ #endif + + /* Serialise link/link calls to prevent parallel calls causing a cycle + * when linking two keyring in opposite orders. +@@ -1257,8 +1431,13 @@ int __key_link_lock(struct key *keyring, + */ + int __key_move_lock(struct key *l_keyring, struct key *u_keyring, + const struct keyring_index_key *index_key) ++ #ifdef CONFIG_KEYP ++ __acquires(&KEY_SEM(l_keyring)) ++ __acquires(&KEY_SEM(u_keyring)) ++ #else + __acquires(&l_keyring->sem) + __acquires(&u_keyring->sem) ++ #endif + __acquires(&keyring_serialise_link_lock) + { + if (l_keyring->type != &key_type_keyring || +@@ -1270,11 +1449,21 @@ int __key_move_lock(struct key *l_keyring, struct key *u_keyring, + * move operation. + */ + if (l_keyring < u_keyring) { ++ #ifdef CNOFIG_KEYP ++ down_write(&KEY_SEM(l_keyring)); ++ down_write_nested(&KEY_SEM(u_keyring), 1); + #else - cap_clear(new->cap_effective); + down_write(&l_keyring->sem); + down_write_nested(&u_keyring->sem, 1); + #endif - if (!uid_eq(old->euid, root_uid) && uid_eq(new->euid, root_uid)) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_effective(new,new->cap_permitted); + } else { ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(u_keyring)); ++ down_write_nested(&KEY_SEM(l_keyring), 1); + #else - new->cap_effective = new->cap_permitted; + down_write(&u_keyring->sem); + down_write_nested(&l_keyring->sem, 1); + #endif + } + + /* Serialise link/link calls to prevent parallel calls causing a cycle +@@ -1311,10 +1500,17 @@ int __key_link_begin(struct key *keyring, + /* Create an edit script that will insert/replace the key in the + * keyring tree. + */ ++ #ifdef CONFIG_KEYP ++ edit = assoc_array_insert(&((struct key_struct *)(keyring->name_link.prev))->keys, ++ &keyring_assoc_array_ops, ++ index_key, ++ NULL); ++ #else + edit = assoc_array_insert(&keyring->keys, + &keyring_assoc_array_ops, + index_key, + NULL); ++ #endif + if (IS_ERR(edit)) { + ret = PTR_ERR(edit); + goto error; +@@ -1382,7 +1578,11 @@ void __key_link(struct key *keyring, struct key *key, + void __key_link_end(struct key *keyring, + const struct keyring_index_key *index_key, + struct assoc_array_edit *edit) ++ #ifdef CONFIG_KEYP ++ __releases(&KEY_SEM(keyring)) ++ #else + __releases(&keyring->sem) ++ #endif + __releases(&keyring_serialise_link_lock) + { + BUG_ON(index_key->type == NULL); +@@ -1395,7 +1595,11 @@ void __key_link_end(struct key *keyring, + } + assoc_array_cancel_edit(edit); + } ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(keyring)); ++ #else + up_write(&keyring->sem); ++ #endif + + if (index_key->type == &key_type_keyring) + mutex_unlock(&keyring_serialise_link_lock); +@@ -1408,8 +1612,13 @@ static int __key_link_check_restriction(struct key *keyring, struct key *key) + { + if (!keyring->restrict_link || !keyring->restrict_link->check) + return 0; ++ #ifdef CONFIG_KEYP ++ return keyring->restrict_link->check(keyring, key->type, ((union key_payload *)(key->name_link.next)), ++ keyring->restrict_link->key); ++ #else + return keyring->restrict_link->check(keyring, key->type, &key->payload, + keyring->restrict_link->key); ++ #endif + } + + /** +@@ -1469,12 +1678,20 @@ EXPORT_SYMBOL(key_link); + * Lock a keyring for unlink. + */ + static int __key_unlink_lock(struct key *keyring) ++ #ifdef CONFIG_KEYP ++ __acquires(&KEY_SEM(keyring)) ++ #else + __acquires(&keyring->sem) ++ #endif + { + if (keyring->type != &key_type_keyring) + return -ENOTDIR; + ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(keyring)); ++ #else + down_write(&keyring->sem); ++ #endif + return 0; + } + +@@ -1488,8 +1705,13 @@ static int __key_unlink_begin(struct key *keyring, struct key *key, + + BUG_ON(*_edit != NULL); + ++ #ifdef CONFIG_KEYP ++ edit = assoc_array_delete(&((struct key_struct *)(keyring->name_link.prev))->keys, &keyring_assoc_array_ops, ++ &key->index_key); ++ #else + edit = assoc_array_delete(&keyring->keys, &keyring_assoc_array_ops, + &key->index_key); ++ #endif + if (IS_ERR(edit)) + return PTR_ERR(edit); + +@@ -1518,11 +1740,19 @@ static void __key_unlink(struct key *keyring, struct key *key, + static void __key_unlink_end(struct key *keyring, + struct key *key, + struct assoc_array_edit *edit) ++ #ifdef CONFIG_KEYP ++ __releases(&KEY_SEM(keyring)) ++ #else + __releases(&keyring->sem) ++ #endif + { + if (edit) + assoc_array_cancel_edit(edit); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(keyring)); ++ #else + up_write(&keyring->sem); ++ #endif } /** -@@ -1142,13 +1258,22 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags) - if (!issecure(SECURE_NO_SETUID_FIXUP)) { - kuid_t root_uid = make_kuid(old->user_ns, 0); - if (uid_eq(old->fsuid, root_uid) && !uid_eq(new->fsuid, root_uid)) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_effective(new,cap_drop_fs_set(new->cap_effective)); -+ #else - new->cap_effective = - cap_drop_fs_set(new->cap_effective); -+ #endif +@@ -1652,9 +1882,15 @@ int keyring_clear(struct key *keyring) + if (keyring->type != &key_type_keyring) + return -ENOTDIR; - if (!uid_eq(old->fsuid, root_uid) && uid_eq(new->fsuid, root_uid)) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_cap_effective(new,cap_raise_fs_set(new->cap_effective, -+ new->cap_permitted)); -+ #else - new->cap_effective = - cap_raise_fs_set(new->cap_effective, - new->cap_permitted); -+ #endif - } - break; ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(keyring)); ++ ++ edit = assoc_array_clear(&((struct key_struct *)(keyring->name_link.prev))->keys, &keyring_assoc_array_ops); ++ #else + down_write(&keyring->sem); -@@ -1243,7 +1368,15 @@ static int cap_prctl_drop(unsigned long cap) - new = prepare_creds(); - if (!new) - return -ENOMEM; -+ #ifdef CONFIG_CREDP -+ { -+ kernel_cap_t tmp = new->cap_bset; -+ cap_lower(tmp, cap); -+ iee_set_cred_cap_bset(new, tmp); -+ } + edit = assoc_array_clear(&keyring->keys, &keyring_assoc_array_ops); ++ #endif + if (IS_ERR(edit)) { + ret = PTR_ERR(edit); + } else { +@@ -1665,7 +1901,11 @@ int keyring_clear(struct key *keyring) + ret = 0; + } + ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(keyring)); + #else - cap_lower(new->cap_bset, cap); + up_write(&keyring->sem); + #endif - return commit_creds(new); + return ret; } + EXPORT_SYMBOL(keyring_clear); +@@ -1679,7 +1919,11 @@ static void keyring_revoke(struct key *keyring) + { + struct assoc_array_edit *edit; -@@ -1319,7 +1452,11 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, - new = prepare_creds(); - if (!new) - return -ENOMEM; -+ #ifdef CONFIG_CREDP -+ iee_set_cred_securebits(new,arg2); -+ #else - new->securebits = arg2; -+ #endif - return commit_creds(new); - - case PR_GET_SECUREBITS: -@@ -1338,9 +1475,17 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, - if (!new) - return -ENOMEM; - if (arg2) -+ #ifdef CONFIG_CREDP -+ iee_set_cred_securebits(new,new->securebits | issecure_mask(SECURE_KEEP_CAPS)); -+ #else - new->securebits |= issecure_mask(SECURE_KEEP_CAPS); -+ #endif - else -+ #ifdef CONFIG_CREDP -+ iee_set_cred_securebits(new,new->securebits & ~issecure_mask(SECURE_KEEP_CAPS)); -+ #else - new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); -+ #endif - return commit_creds(new); - - case PR_CAP_AMBIENT: -@@ -1351,7 +1496,15 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, - new = prepare_creds(); - if (!new) - return -ENOMEM; -+ #ifdef CONFIG_CREDP -+ do { -+ kernel_cap_t tmp_cap = new->cap_ambient; -+ tmp_cap.val = 0; -+ iee_set_cred_cap_ambient(new, tmp_cap); -+ } while (0); -+ #else - cap_clear(new->cap_ambient); -+ #endif - return commit_creds(new); - } ++ #ifdef CONFIG_KEYP ++ edit = assoc_array_clear(&((struct key_struct *)(keyring->name_link.prev))->keys, &keyring_assoc_array_ops); ++ #else + edit = assoc_array_clear(&keyring->keys, &keyring_assoc_array_ops); ++ #endif + if (!IS_ERR(edit)) { + if (edit) + assoc_array_apply_edit(edit); +@@ -1725,8 +1969,13 @@ void keyring_gc(struct key *keyring, time64_t limit) + + /* scan the keyring looking for dead keys */ + rcu_read_lock(); ++ #ifdef CONFIG_KEYP ++ result = assoc_array_iterate(&((struct key_struct *)(keyring->name_link.prev))->keys, ++ keyring_gc_check_iterator, &limit); ++ #else + result = assoc_array_iterate(&keyring->keys, + keyring_gc_check_iterator, &limit); ++ #endif + rcu_read_unlock(); + if (result == true) + goto do_gc; +@@ -1736,10 +1985,17 @@ void keyring_gc(struct key *keyring, time64_t limit) + return; + + do_gc: ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(keyring)); ++ assoc_array_gc(&((struct key_struct *)(keyring->name_link.prev))->keys, &keyring_assoc_array_ops, ++ keyring_gc_select_iterator, &limit); ++ up_write(&KEY_SEM(keyring)); ++ #else + down_write(&keyring->sem); + assoc_array_gc(&keyring->keys, &keyring_assoc_array_ops, + keyring_gc_select_iterator, &limit); + up_write(&keyring->sem); ++ #endif + kleave(" [gc]"); + } -@@ -1375,9 +1528,25 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, - if (!new) - return -ENOMEM; - if (arg2 == PR_CAP_AMBIENT_RAISE) -+ #ifdef CONFIG_CREDP -+ { -+ kernel_cap_t tmp = new->cap_ambient; -+ cap_raise(tmp, arg3); -+ iee_set_cred_cap_ambient(new, tmp); -+ } -+ #else - cap_raise(new->cap_ambient, arg3); -+ #endif - else -+ #ifdef CONFIG_CREDP -+ { -+ kernel_cap_t tmp = new->cap_ambient; -+ cap_lower(tmp, arg3); -+ iee_set_cred_cap_ambient(new, tmp); -+ } -+ #else - cap_lower(new->cap_ambient, arg3); -+ #endif - return commit_creds(new); - } +@@ -1778,7 +2034,11 @@ void keyring_restriction_gc(struct key *keyring, struct key_type *dead_type) + } -diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c -index 19be69fa4d05..6cb164dfc19b 100644 ---- a/security/keys/keyctl.c -+++ b/security/keys/keyctl.c -@@ -23,6 +23,9 @@ - #include - #include - #include "internal.h" -+#ifdef CONFIG_CREDP -+#include -+#endif + /* Lock the keyring to ensure that a link is not in progress */ ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(keyring)); ++ #else + down_write(&keyring->sem); ++ #endif - #define KEY_MAX_DESC_SIZE 4096 + keyres = keyring->restrict_link; -@@ -1155,7 +1158,11 @@ static int keyctl_change_reqkey_auth(struct key *key) - return -ENOMEM; +@@ -1788,7 +2048,11 @@ void keyring_restriction_gc(struct key *keyring, struct key_type *dead_type) + keyres->key = NULL; + keyres->keytype = NULL; - key_put(new->request_key_auth); -+ #ifdef CONFIG_CREDP -+ iee_set_cred_request_key_auth(new,key_get(key)); ++ #ifdef CONFIG_KEYP ++ up_write(&KEY_SEM(keyring)); + #else - new->request_key_auth = key_get(key); + up_write(&keyring->sem); + #endif - return commit_creds(new); + kleave(" [restriction gc]"); } -@@ -1432,7 +1439,11 @@ long keyctl_set_reqkey_keyring(int reqkey_defl) +diff --git a/security/keys/proc.c b/security/keys/proc.c +index 4f4e2c1824f1..5f72240ddd96 100644 +--- a/security/keys/proc.c ++++ b/security/keys/proc.c +@@ -67,7 +67,11 @@ static struct rb_node *key_serial_next(struct seq_file *p, struct rb_node *n) + + n = rb_next(n); + while (n) { ++ #ifdef CONFIG_KEYP ++ struct key *key = rb_entry(n, struct key_union, serial_node)->key; ++ #else + struct key *key = rb_entry(n, struct key, serial_node); ++ #endif + if (kuid_has_mapping(user_ns, key->user->uid)) + break; + n = rb_next(n); +@@ -82,7 +86,11 @@ static struct key *find_ge_key(struct seq_file *p, key_serial_t id) + struct key *minkey = NULL; + + while (n) { ++ #ifdef CONFIG_KEYP ++ struct key *key = rb_entry(n, struct key_union, serial_node)->key; ++ #else + struct key *key = rb_entry(n, struct key, serial_node); ++ #endif + if (id < key->serial) { + if (!minkey || minkey->serial > key->serial) + minkey = key; +@@ -102,10 +110,18 @@ static struct key *find_ge_key(struct seq_file *p, key_serial_t id) + for (;;) { + if (kuid_has_mapping(user_ns, minkey->user->uid)) + return minkey; ++ #ifdef CONFIG_KEYP ++ n = rb_next(&(((struct key_union *)(minkey->graveyard_link.next))->serial_node)); ++ #else + n = rb_next(&minkey->serial_node); ++ #endif + if (!n) + return NULL; ++ #ifdef CONFIG_KEYP ++ minkey = rb_entry(n, struct key_union, serial_node)->key; ++ #else + minkey = rb_entry(n, struct key, serial_node); ++ #endif } + } - set: -+ #ifdef CONFIG_CREDP -+ iee_set_cred_jit_keyring(new,reqkey_defl); +@@ -123,12 +139,20 @@ static void *proc_keys_start(struct seq_file *p, loff_t *_pos) + if (!key) + return NULL; + *_pos = key->serial; ++ #ifdef CONFIG_KEYP ++ return &(((struct key_union *)(key->graveyard_link.next))->serial_node); + #else - new->jit_keyring = reqkey_defl; + return &key->serial_node; + #endif - commit_creds(new); - return old_setting; - error: -@@ -1644,9 +1655,17 @@ long keyctl_session_to_parent(void) - cred = cred_alloc_blank(); - if (!cred) - goto error_keyring; -+ #ifdef CONFIG_CREDP -+ newwork = (struct rcu_head *)(cred->rcu.func); + } + + static inline key_serial_t key_node_serial(struct rb_node *n) + { ++ #ifdef CONFIG_KEYP ++ struct key *key = rb_entry(n, struct key_union, serial_node)->key; + #else - newwork = &cred->rcu; + struct key *key = rb_entry(n, struct key, serial_node); + #endif + return key->serial; + } -+ #ifdef CONFIG_CREDP -+ iee_set_cred_session_keyring(cred,key_ref_to_ptr(keyring_r)); +@@ -153,7 +177,11 @@ static void proc_keys_stop(struct seq_file *p, void *v) + static int proc_keys_show(struct seq_file *m, void *v) + { + struct rb_node *_p = v; ++ #ifdef CONFIG_KEYP ++ struct key *key = rb_entry(_p, struct key_union, serial_node)->key; + #else - cred->session_keyring = key_ref_to_ptr(keyring_r); + struct key *key = rb_entry(_p, struct key, serial_node); + #endif - keyring_r = NULL; - init_task_work(newwork, key_change_session_keyring); - -@@ -1705,7 +1724,11 @@ long keyctl_session_to_parent(void) - write_unlock_irq(&tasklist_lock); - rcu_read_unlock(); - if (oldwork) -+ #ifdef CONFIG_CREDP -+ put_cred(*(struct cred **)(oldwork + 1)); -+ #else - put_cred(container_of(oldwork, struct cred, rcu)); -+ #endif - if (newwork) - put_cred(cred); - return ret; + unsigned long flags; + key_ref_t key_ref, skey_ref; + time64_t now, expiry; diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c -index b5d5333ab330..aaa2a2347d84 100644 +index b5d5333ab330..bff026c9abbf 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c -@@ -19,6 +19,10 @@ +@@ -19,6 +19,13 @@ #include #include "internal.h" +#ifdef CONFIG_CREDP +#include +#endif ++#ifdef CONFIG_KEYP ++#include ++#endif + /* Session keyring create vs join semaphore */ static DEFINE_MUTEX(key_session_mutex); -@@ -232,7 +236,11 @@ int install_thread_keyring_to_cred(struct cred *new) +@@ -232,7 +239,11 @@ int install_thread_keyring_to_cred(struct cred *new) if (IS_ERR(keyring)) return PTR_ERR(keyring); @@ -13338,7 +19889,7 @@ index b5d5333ab330..aaa2a2347d84 100644 return 0; } -@@ -279,7 +287,11 @@ int install_process_keyring_to_cred(struct cred *new) +@@ -279,7 +290,11 @@ int install_process_keyring_to_cred(struct cred *new) if (IS_ERR(keyring)) return PTR_ERR(keyring); @@ -13350,7 +19901,7 @@ index b5d5333ab330..aaa2a2347d84 100644 return 0; } -@@ -338,7 +350,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) +@@ -338,7 +353,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) /* install the keyring */ old = cred->session_keyring; @@ -13362,7 +19913,93 @@ index b5d5333ab330..aaa2a2347d84 100644 if (old) key_put(old); -@@ -911,7 +927,11 @@ long join_session_keyring(const char *name) +@@ -378,9 +397,15 @@ void key_fsuid_changed(struct cred *new_cred) + { + /* update the ownership of the thread keyring */ + if (new_cred->thread_keyring) { ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(new_cred->thread_keyring)); ++ iee_set_key_uid(new_cred->thread_keyring, new_cred->fsuid); ++ up_write(&KEY_SEM(new_cred->thread_keyring)); ++ #else + down_write(&new_cred->thread_keyring->sem); + new_cred->thread_keyring->uid = new_cred->fsuid; + up_write(&new_cred->thread_keyring->sem); ++ #endif + } + } + +@@ -391,9 +416,15 @@ void key_fsgid_changed(struct cred *new_cred) + { + /* update the ownership of the thread keyring */ + if (new_cred->thread_keyring) { ++ #ifdef CONFIG_KEYP ++ down_write(&KEY_SEM(new_cred->thread_keyring)); ++ iee_set_key_gid(new_cred->thread_keyring, new_cred->fsgid); ++ up_write(&KEY_SEM(new_cred->thread_keyring)); ++ #else + down_write(&new_cred->thread_keyring->sem); + new_cred->thread_keyring->gid = new_cred->fsgid; + up_write(&new_cred->thread_keyring->sem); ++ #endif + } + } + +@@ -557,7 +588,11 @@ key_ref_t search_process_keyrings_rcu(struct keyring_search_context *ctx) + const struct cred *cred = ctx->cred; + + if (key_validate(cred->request_key_auth) == 0) { ++ #ifdef CONFIG_KEYP ++ rka = ((union key_payload *)(ctx->cred->request_key_auth->name_link.next))->data[0]; ++ #else + rka = ctx->cred->request_key_auth->payload.data[0]; ++ #endif + + //// was search_process_keyrings() [ie. recursive] + ctx->cred = rka->cred; +@@ -725,17 +760,29 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, + if (!ctx.cred->request_key_auth) + goto error; + ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(ctx.cred->request_key_auth)); ++ #else + down_read(&ctx.cred->request_key_auth->sem); ++ #endif + if (test_bit(KEY_FLAG_REVOKED, + &ctx.cred->request_key_auth->flags)) { + key_ref = ERR_PTR(-EKEYREVOKED); + key = NULL; + } else { ++ #ifdef CONFIG_KEYP ++ rka = ((union key_payload *)(ctx.cred->request_key_auth->name_link.next))->data[0]; ++ #else + rka = ctx.cred->request_key_auth->payload.data[0]; ++ #endif + key = rka->dest_keyring; + __key_get(key); + } ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(ctx.cred->request_key_auth)); ++ #else + up_read(&ctx.cred->request_key_auth->sem); ++ #endif + if (!key) + goto error; + key_ref = make_key_ref(key, 1); +@@ -804,7 +851,11 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, + if (ret < 0) + goto invalid_key; + ++ #ifdef CONFIG_KEYP ++ iee_set_key_last_used_at(key, ktime_get_real_seconds()); ++ #else + key->last_used_at = ktime_get_real_seconds(); ++ #endif + + error: + put_cred(ctx.cred); +@@ -911,7 +962,11 @@ long join_session_keyring(const char *name) void key_change_session_keyring(struct callback_head *twork) { const struct cred *old = current_cred(); @@ -13374,7 +20011,7 @@ index b5d5333ab330..aaa2a2347d84 100644 if (unlikely(current->flags & PF_EXITING)) { put_cred(new); -@@ -925,6 +945,38 @@ void key_change_session_keyring(struct callback_head *twork) +@@ -925,6 +980,38 @@ void key_change_session_keyring(struct callback_head *twork) return; } @@ -13410,19 +20047,188 @@ index b5d5333ab330..aaa2a2347d84 100644 + iee_set_cred_thread_keyring(new,key_get(old->thread_keyring)); + iee_set_cred_process_keyring(new,key_get(old->process_keyring)); + #else - new-> uid = old-> uid; - new-> euid = old-> euid; - new-> suid = old-> suid; -@@ -948,6 +1000,7 @@ void key_change_session_keyring(struct callback_head *twork) - new->jit_keyring = old->jit_keyring; - new->thread_keyring = key_get(old->thread_keyring); - new->process_keyring = key_get(old->process_keyring); + new-> uid = old-> uid; + new-> euid = old-> euid; + new-> suid = old-> suid; +@@ -948,6 +1035,7 @@ void key_change_session_keyring(struct callback_head *twork) + new->jit_keyring = old->jit_keyring; + new->thread_keyring = key_get(old->thread_keyring); + new->process_keyring = key_get(old->process_keyring); ++ #endif + + security_transfer_creds(new, old); + +diff --git a/security/keys/request_key.c b/security/keys/request_key.c +index a7673ad86d18..d281459651af 100644 +--- a/security/keys/request_key.c ++++ b/security/keys/request_key.c +@@ -17,6 +17,10 @@ + #include "internal.h" + #include + ++#ifdef CONFIG_KEYP ++#include ++#endif ++ + #define key_negative_timeout 60 /* default timeout on a negative key's existence */ + + static struct key *check_cached_key(struct keyring_search_context *ctx) +@@ -285,13 +289,21 @@ static int construct_get_dest_keyring(struct key **_dest_keyring) + case KEY_REQKEY_DEFL_REQUESTOR_KEYRING: + if (cred->request_key_auth) { + authkey = cred->request_key_auth; ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(authkey)); ++ #else + down_read(&authkey->sem); ++ #endif + rka = get_request_key_auth(authkey); + if (!test_bit(KEY_FLAG_REVOKED, + &authkey->flags)) + dest_keyring = + key_get(rka->dest_keyring); ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(authkey)); ++ #else + up_read(&authkey->sem); ++ #endif + if (dest_keyring) { + do_perm_check = false; + break; +@@ -398,7 +410,11 @@ static int construct_alloc_key(struct keyring_search_context *ctx, + if (IS_ERR(key)) + goto alloc_failed; + ++ #ifdef CONFIG_KEYP ++ iee_set_key_flag_bit(key, KEY_FLAG_USER_CONSTRUCT, SET_BIT_OP); ++ #else + set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); ++ #endif + + if (dest_keyring) { + ret = __key_link_lock(dest_keyring, &key->index_key); +diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c +index 8f33cd170e42..ddf86b3a2ecb 100644 +--- a/security/keys/request_key_auth.c ++++ b/security/keys/request_key_auth.c +@@ -145,7 +145,11 @@ static void request_key_auth_revoke(struct key *key) + */ + static void request_key_auth_destroy(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ struct request_key_auth *rka = rcu_access_pointer(((union key_payload *)(key->name_link.next))->rcu_data0); ++ #else + struct request_key_auth *rka = rcu_access_pointer(key->payload.rcu_data0); ++ #endif + + kenter("{%d}", key->serial); + if (rka) { +@@ -184,22 +188,38 @@ struct key *request_key_auth_new(struct key *target, const char *op, + * another process */ + if (cred->request_key_auth) { + /* it is - use that instantiation context here too */ ++ #ifdef CONFIG_KEYP ++ down_read(&KEY_SEM(cred->request_key_auth)); ++ #else + down_read(&cred->request_key_auth->sem); ++ #endif + + /* if the auth key has been revoked, then the key we're + * servicing is already instantiated */ + if (test_bit(KEY_FLAG_REVOKED, + &cred->request_key_auth->flags)) { ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(cred->request_key_auth)); ++ #else + up_read(&cred->request_key_auth->sem); ++ #endif + ret = -EKEYREVOKED; + goto error_free_rka; + } + ++ #ifdef CONFIG_KEYP ++ irka = ((union key_payload *)(cred->request_key_auth->name_link.next))->data[0]; ++ #else + irka = cred->request_key_auth->payload.data[0]; ++ #endif + rka->cred = get_cred(irka->cred); + rka->pid = irka->pid; + ++ #ifdef CONFIG_KEYP ++ up_read(&KEY_SEM(cred->request_key_auth)); ++ #else + up_read(&cred->request_key_auth->sem); ++ #endif + } + else { + /* it isn't - use this process as the context */ +diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c +index fee1ab2c734d..5ef67deb1df0 100644 +--- a/security/keys/trusted-keys/trusted_core.c ++++ b/security/keys/trusted-keys/trusted_core.c +@@ -233,7 +233,11 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) + + if (key_is_negative(key)) + return -ENOKEY; ++ #ifdef CONFIG_KEYP ++ p = ((union key_payload *)(key->name_link.next))->data[0]; ++ #else + p = key->payload.data[0]; ++ #endif + if (!p->migratable) + return -EPERM; + if (datalen <= 0 || datalen > 32767 || !prep->data) +@@ -307,7 +311,11 @@ static long trusted_read(const struct key *key, char *buffer, + */ + static void trusted_destroy(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ kfree_sensitive(((union key_payload *)(key->name_link.next))->data[0]); ++ #else + kfree_sensitive(key->payload.data[0]); + #endif + } - security_transfer_creds(new, old); + struct key_type key_type_trusted = { +diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c +index 749e2a4dcb13..a0a5e9ca620f 100644 +--- a/security/keys/user_defined.c ++++ b/security/keys/user_defined.c +@@ -14,6 +14,8 @@ + #include + #include "internal.h" + ++#include ++ + static int logon_vet_description(const char *desc); + + /* +@@ -109,7 +111,11 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) + return ret; + /* attach the new data, displacing the old */ ++ #ifdef CONFIG_KEYP ++ iee_set_key_expiry(key, prep->expiry); ++ #else + key->expiry = prep->expiry; ++ #endif + if (key_is_positive(key)) + zap = dereference_key_locked(key); + rcu_assign_keypointer(key, prep->payload.data[0]); +@@ -145,7 +151,11 @@ EXPORT_SYMBOL(user_revoke); + */ + void user_destroy(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ struct user_key_payload *upayload = ((union key_payload *)(key->name_link.next))->data[0]; ++ #else + struct user_key_payload *upayload = key->payload.data[0]; ++ #endif + + kfree_sensitive(upayload); + } diff --git a/security/security.c b/security/security.c -index 407b51719f79..74ffd7ea3f37 100644 +index 3aa2d295464e..0ab69c4ffa16 100644 --- a/security/security.c +++ b/security/security.c @@ -30,6 +30,9 @@ @@ -13467,6 +20273,624 @@ index 407b51719f79..74ffd7ea3f37 100644 } /** --- -2.34.1 - +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index d4a99d98ec77..70e5ca8c80df 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -104,9 +104,22 @@ + #include "audit.h" + #include "avc_ss.h" + ++#ifdef CONFIG_IEE_SELINUX_P ++#include ++#include ++#endif ++ ++#ifdef CONFIG_KEYP ++#include ++#endif ++ + #define SELINUX_INODE_INIT_XATTRS 1 + ++#ifdef CONFIG_IEE_SELINUX_P ++struct selinux_state selinux_state __section(".iee.selinux"); ++#else + struct selinux_state selinux_state; ++#endif + + /* SECMARK reference count */ + static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); +@@ -6585,7 +6598,11 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred, + else + ksec->sid = tsec->sid; + ++ #ifdef CONFIG_KEYP ++ iee_set_key_security(k, ksec); ++ #else + k->security = ksec; ++ #endif + return 0; + } + +@@ -6593,7 +6610,11 @@ static void selinux_key_free(struct key *k) + { + struct key_security_struct *ksec = k->security; + ++ #ifdef CONFIG_KEYP ++ iee_set_key_security(k, NULL); ++ #else + k->security = NULL; ++ #endif + kfree(ksec); + } + +@@ -7284,15 +7305,54 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { + #endif + }; + ++#ifdef CONFIG_IEE_SELINUX_P ++struct kmem_cache *policy_jar; ++ ++static void policy_cache_init(void) ++{ ++ struct selinux_policy* unused; ++ policy_jar = kmem_cache_create("policy_jar", sizeof(struct selinux_policy), 0, ++ SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); ++ /* Test this cache */ ++ unused = kmem_cache_alloc(policy_jar, GFP_KERNEL); ++ kmem_cache_free(policy_jar, unused); ++ ++ printk("IEE SELINUXP: policy cache created."); ++} ++#endif ++ + static __init int selinux_init(void) + { + pr_info("SELinux: Initializing.\n"); + + memset(&selinux_state, 0, sizeof(selinux_state)); ++#ifdef CONFIG_IEE_SELINUX_P ++ WRITE_ONCE(selinux_state.enforcing, selinux_enforcing_boot); ++#else + enforcing_set(selinux_enforcing_boot); ++#endif + selinux_avc_init(); ++ ++#ifdef CONFIG_IEE_SELINUX_P ++ /* Put selinux_status inside IEE. */ ++ /* Prepare mutex lock and write the ptr to mutex->owner. */ ++ struct mutex* status_lock = kzalloc(GFP_KERNEL, sizeof(struct mutex)); ++ struct mutex* policy_mutex = kzalloc(GFP_KERNEL, sizeof(struct mutex)); ++ mutex_init(status_lock); ++ mutex_init(policy_mutex); ++ selinux_state.status_lock.owner.counter = (s64)status_lock; ++ selinux_state.policy_mutex.owner.counter = (s64)policy_mutex; ++ ++ /* Setting lm addr to be RO, IEE addr valid. */ ++ set_iee_page_valid(__phys_to_iee(__pa_symbol(&selinux_state))); ++ iee_set_logical_mem_ro((unsigned long)&selinux_state); ++ iee_set_logical_mem_ro((unsigned long)__va(__pa_symbol(&selinux_state))); ++ printk("IEE SELINUXP: Succeeded on preparing selinux_state."); ++ policy_cache_init(); ++#else + mutex_init(&selinux_state.status_lock); + mutex_init(&selinux_state.policy_mutex); ++#endif + + /* Set the security state for the initial task. */ + cred_init_security(); +diff --git a/security/selinux/ima.c b/security/selinux/ima.c +index aa34da9b0aeb..022b3ce8d740 100644 +--- a/security/selinux/ima.c ++++ b/security/selinux/ima.c +@@ -12,6 +12,10 @@ + #include "security.h" + #include "ima.h" + ++#ifdef CONFIG_IEE_SELINUX_P ++#include ++#endif ++ + /* + * selinux_ima_collect_state - Read selinux configuration settings + * +@@ -74,7 +78,11 @@ void selinux_ima_measure_state_locked(void) + size_t policy_len; + int rc = 0; + ++#ifdef CONFIG_IEE_SELINUX_P ++ lockdep_assert_held(iee_get_selinux_policy_lock()); ++#else + lockdep_assert_held(&selinux_state.policy_mutex); ++#endif + + state_str = selinux_ima_collect_state(); + if (!state_str) { +@@ -112,9 +120,21 @@ void selinux_ima_measure_state_locked(void) + */ + void selinux_ima_measure_state(void) + { ++#ifdef CONFIG_IEE_SELINUX_P ++ lockdep_assert_not_held(iee_get_selinux_policy_lock()); ++#else + lockdep_assert_not_held(&selinux_state.policy_mutex); ++#endif + ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_lock(iee_get_selinux_policy_lock()); ++#else + mutex_lock(&selinux_state.policy_mutex); ++#endif + selinux_ima_measure_state_locked(); ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_policy_lock()); ++#else + mutex_unlock(&selinux_state.policy_mutex); ++#endif + } +diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h +index a9de89af8fdc..2eee89071a56 100644 +--- a/security/selinux/include/security.h ++++ b/security/selinux/include/security.h +@@ -113,11 +113,15 @@ static inline bool selinux_initialized(void) + return smp_load_acquire(&selinux_state.initialized); + } + ++#ifdef CONFIG_IEE_SELINUX_P ++extern void selinux_mark_initialized(void); ++#else + static inline void selinux_mark_initialized(void) + { + /* do a synchronized write to avoid race conditions */ + smp_store_release(&selinux_state.initialized, true); + } ++#endif + + #ifdef CONFIG_SECURITY_SELINUX_DEVELOP + static inline bool enforcing_enabled(void) +@@ -125,10 +129,14 @@ static inline bool enforcing_enabled(void) + return READ_ONCE(selinux_state.enforcing); + } + ++#ifdef CONFIG_IEE_SELINUX_P ++extern void enforcing_set(bool value); ++#else + static inline void enforcing_set(bool value) + { + WRITE_ONCE(selinux_state.enforcing, value); + } ++#endif + #else + static inline bool enforcing_enabled(void) + { +diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c +index 2c23a5a28608..f89b4fef4919 100644 +--- a/security/selinux/selinuxfs.c ++++ b/security/selinux/selinuxfs.c +@@ -43,6 +43,10 @@ + #include "conditional.h" + #include "ima.h" + ++#ifdef CONFIG_IEE_SELINUX_P ++#include ++#endif ++ + enum sel_inos { + SEL_ROOT_INO = 2, + SEL_LOAD, /* load policy */ +@@ -371,7 +375,11 @@ static int sel_open_policy(struct inode *inode, struct file *filp) + + BUG_ON(filp->private_data); + ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_lock(iee_get_selinux_policy_lock()); ++#else + mutex_lock(&selinux_state.policy_mutex); ++#endif + + rc = avc_has_perm(current_sid(), SECINITSID_SECURITY, + SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); +@@ -401,11 +409,19 @@ static int sel_open_policy(struct inode *inode, struct file *filp) + + filp->private_data = plm; + ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_policy_lock()); ++#else + mutex_unlock(&selinux_state.policy_mutex); ++#endif + + return 0; + err: ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_policy_lock()); ++#else + mutex_unlock(&selinux_state.policy_mutex); ++#endif + + if (plm) + vfree(plm->data); +@@ -587,7 +603,11 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, + ssize_t length; + void *data = NULL; + ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_lock(iee_get_selinux_policy_lock()); ++#else + mutex_lock(&selinux_state.policy_mutex); ++#endif + + length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); +@@ -630,13 +650,31 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, + from_kuid(&init_user_ns, audit_get_loginuid(current)), + audit_get_sessionid(current)); + out: ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_policy_lock()); ++#else + mutex_unlock(&selinux_state.policy_mutex); ++#endif + vfree(data); + return length; + } + ++// #ifdef CONFIG_IEE_SELINUX_P ++// /* Do sel_write_load twice to test free process of policy. */ ++// static ssize_t sel_write_load_test(struct file *file, const char __user *buf, ++// size_t count, loff_t *ppos) ++// { ++// sel_write_load(file, buf, count, ppos); ++// return sel_write_load(file, buf, count, ppos); ++// } ++// #endif ++ + static const struct file_operations sel_load_ops = { ++// #ifdef CONFIG_IEE_SELINUX_P ++// .write = sel_write_load_test, ++// #else + .write = sel_write_load, ++// #endif + .llseek = generic_file_llseek, + }; + +@@ -1214,7 +1252,11 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, + unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; + const char *name = filep->f_path.dentry->d_name.name; + ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_lock(iee_get_selinux_policy_lock()); ++#else + mutex_lock(&selinux_state.policy_mutex); ++#endif + + ret = -EINVAL; + if (index >= fsi->bool_num || strcmp(name, +@@ -1233,14 +1275,22 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, + } + length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, + fsi->bool_pending_values[index]); ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_policy_lock()); ++#else + mutex_unlock(&selinux_state.policy_mutex); ++#endif + ret = simple_read_from_buffer(buf, count, ppos, page, length); + out_free: + free_page((unsigned long)page); + return ret; + + out_unlock: ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_policy_lock()); ++#else + mutex_unlock(&selinux_state.policy_mutex); ++#endif + goto out_free; + } + +@@ -1265,7 +1315,11 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, + if (IS_ERR(page)) + return PTR_ERR(page); + ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_lock(iee_get_selinux_policy_lock()); ++#else + mutex_lock(&selinux_state.policy_mutex); ++#endif + + length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + SECCLASS_SECURITY, SECURITY__SETBOOL, +@@ -1289,7 +1343,11 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, + length = count; + + out: ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_policy_lock()); ++#else + mutex_unlock(&selinux_state.policy_mutex); ++#endif + kfree(page); + return length; + } +@@ -1320,7 +1378,11 @@ static ssize_t sel_commit_bools_write(struct file *filep, + if (IS_ERR(page)) + return PTR_ERR(page); + ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_lock(iee_get_selinux_policy_lock()); ++#else + mutex_lock(&selinux_state.policy_mutex); ++#endif + + length = avc_has_perm(current_sid(), SECINITSID_SECURITY, + SECCLASS_SECURITY, SECURITY__SETBOOL, +@@ -1341,7 +1403,11 @@ static ssize_t sel_commit_bools_write(struct file *filep, + length = count; + + out: ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_policy_lock()); ++#else + mutex_unlock(&selinux_state.policy_mutex); ++#endif + kfree(page); + return length; + } +diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c +index 93e011d5d684..dc78ec0b1aad 100644 +--- a/security/selinux/ss/services.c ++++ b/security/selinux/ss/services.c +@@ -68,6 +68,10 @@ + #include "policycap_names.h" + #include "ima.h" + ++#ifdef CONFIG_IEE_SELINUX_P ++#include ++#endif ++ + struct selinux_policy_convert_data { + struct convert_context_args args; + struct sidtab_convert_params sidtab_params; +@@ -2108,9 +2112,14 @@ static void security_load_policycaps(struct selinux_policy *policy) + + p = &policy->policydb; + ++#ifdef CONFIG_IEE_SELINUX_P ++ for (i = 0; i < ARRAY_SIZE(selinux_state.policycap); i++) ++ iee_set_sel_policy_cap(i, ebitmap_get_bit(&p->policycaps, i)); ++#else + for (i = 0; i < ARRAY_SIZE(selinux_state.policycap); i++) + WRITE_ONCE(selinux_state.policycap[i], + ebitmap_get_bit(&p->policycaps, i)); ++#endif + + for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++) + pr_info("SELinux: policy capability %s=%d\n", +@@ -2173,6 +2182,9 @@ void selinux_policy_commit(struct selinux_load_state *load_state) + { + struct selinux_state *state = &selinux_state; + struct selinux_policy *oldpolicy, *newpolicy = load_state->policy; ++#ifdef CONFIG_IEE_SELINUX_P ++ struct selinux_policy *temppolicy; ++#endif + unsigned long flags; + u32 seqno; + +@@ -2197,10 +2209,20 @@ void selinux_policy_commit(struct selinux_load_state *load_state) + /* Install the new policy. */ + if (oldpolicy) { + sidtab_freeze_begin(oldpolicy->sidtab, &flags); ++#ifdef CONFIG_IEE_SELINUX_P ++ iee_sel_rcu_assign_policy(newpolicy, kmem_cache_alloc(policy_jar, GFP_KERNEL)); ++ kfree(newpolicy); ++#else + rcu_assign_pointer(state->policy, newpolicy); ++#endif + sidtab_freeze_end(oldpolicy->sidtab, &flags); + } else { ++#ifdef CONFIG_IEE_SELINUX_P ++ iee_sel_rcu_assign_policy(newpolicy, kmem_cache_alloc(policy_jar, GFP_KERNEL)); ++ kfree(newpolicy); ++#else + rcu_assign_pointer(state->policy, newpolicy); ++#endif + } + + /* Load the policycaps from the new policy */ +@@ -2218,7 +2240,20 @@ void selinux_policy_commit(struct selinux_load_state *load_state) + + /* Free the old policy */ + synchronize_rcu(); ++#ifdef CONFIG_IEE_SELINUX_P ++ /* ++ * Normal free process includes setting freed objects pointers to be NULL, however it ++ * would be hard as old policy is already inside IEE. So Make a kernel copy of the old ++ * policy to free objects it points to. ++ */ ++ if (oldpolicy){ ++ temppolicy = kmemdup(oldpolicy, sizeof(*temppolicy), GFP_KERNEL); ++ selinux_policy_free(temppolicy); ++ kfree(oldpolicy); ++ } ++#else + selinux_policy_free(oldpolicy); ++#endif + kfree(load_state->convert_data); + + /* Notify others of the policy change */ +@@ -3016,6 +3051,9 @@ int security_set_bools(u32 len, int *values) + { + struct selinux_state *state = &selinux_state; + struct selinux_policy *newpolicy, *oldpolicy; ++#ifdef CONFIG_IEE_SELINUX_P ++ struct selinux_policy *temppolicy; ++#endif + int rc; + u32 i, seqno = 0; + +@@ -3068,8 +3106,13 @@ int security_set_bools(u32 len, int *values) + newpolicy->latest_granting = oldpolicy->latest_granting + 1; + seqno = newpolicy->latest_granting; + ++#ifdef CONFIG_IEE_SELINUX_P ++ iee_sel_rcu_assign_policy(newpolicy, kmem_cache_alloc(policy_jar, GFP_KERNEL)); ++ kfree(newpolicy); ++#else + /* Install the new policy */ + rcu_assign_pointer(state->policy, newpolicy); ++#endif + + /* + * Free the conditional portions of the old policydb +@@ -3077,7 +3120,20 @@ int security_set_bools(u32 len, int *values) + * structure itself but not what it references. + */ + synchronize_rcu(); ++#ifdef CONFIG_IEE_SELINUX_P ++ /* ++ * Normal free process includes setting freed objects pointers to be NULL, however it ++ * would be hard as old policy is already inside IEE. So Make a kernel copy of the old ++ * policy to free objects it points to. ++ */ ++ temppolicy = kmemdup(oldpolicy, sizeof(*temppolicy), GFP_KERNEL); ++ if (!temppolicy) ++ return -ENOMEM; ++ selinux_policy_cond_free(temppolicy); ++ kfree(oldpolicy); ++#else + selinux_policy_cond_free(oldpolicy); ++#endif + + /* Notify others of the policy change */ + selinux_notify_policy_change(seqno); +diff --git a/security/selinux/status.c b/security/selinux/status.c +index dffca22ce6f7..642965684325 100644 +--- a/security/selinux/status.c ++++ b/security/selinux/status.c +@@ -13,6 +13,10 @@ + #include "avc.h" + #include "security.h" + ++#ifdef CONFIG_IEE_SELINUX_P ++#include ++#endif ++ + /* + * The selinux_status_page shall be exposed to userspace applications + * using mmap interface on /selinux/status. +@@ -44,9 +48,17 @@ struct page *selinux_kernel_status_page(void) + struct selinux_kernel_status *status; + struct page *result = NULL; + ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_lock(iee_get_selinux_status_lock()); ++#else + mutex_lock(&selinux_state.status_lock); ++#endif + if (!selinux_state.status_page) { ++ #ifdef CONFIG_IEE_SELINUX_P ++ iee_set_selinux_status_pg(alloc_page(GFP_KERNEL|__GFP_ZERO)); ++ #else + selinux_state.status_page = alloc_page(GFP_KERNEL|__GFP_ZERO); ++ #endif + + if (selinux_state.status_page) { + status = page_address(selinux_state.status_page); +@@ -66,7 +78,11 @@ struct page *selinux_kernel_status_page(void) + } + } + result = selinux_state.status_page; ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_status_lock()); ++#else + mutex_unlock(&selinux_state.status_lock); ++#endif + + return result; + } +@@ -80,7 +96,11 @@ void selinux_status_update_setenforce(bool enforcing) + { + struct selinux_kernel_status *status; + ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_lock(iee_get_selinux_status_lock()); ++#else + mutex_lock(&selinux_state.status_lock); ++#endif + if (selinux_state.status_page) { + status = page_address(selinux_state.status_page); + +@@ -92,7 +112,11 @@ void selinux_status_update_setenforce(bool enforcing) + smp_wmb(); + status->sequence++; + } ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_status_lock()); ++#else + mutex_unlock(&selinux_state.status_lock); ++#endif + } + + /* +@@ -105,7 +129,11 @@ void selinux_status_update_policyload(u32 seqno) + { + struct selinux_kernel_status *status; + ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_lock(iee_get_selinux_status_lock()); ++#else + mutex_lock(&selinux_state.status_lock); ++#endif + if (selinux_state.status_page) { + status = page_address(selinux_state.status_page); + +@@ -118,5 +146,9 @@ void selinux_status_update_policyload(u32 seqno) + smp_wmb(); + status->sequence++; + } ++#ifdef CONFIG_IEE_SELINUX_P ++ mutex_unlock(iee_get_selinux_status_lock()); ++#else + mutex_unlock(&selinux_state.status_lock); ++#endif + } +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index 7d608b39362c..2ef869927c82 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -45,6 +45,10 @@ + #include + #include "smack.h" + ++#ifdef CONFIG_KEYP ++#include ++#endif ++ + #define TRANS_TRUE "TRUE" + #define TRANS_TRUE_SIZE 4 + +@@ -4411,7 +4415,11 @@ static int smack_key_alloc(struct key *key, const struct cred *cred, + { + struct smack_known *skp = smk_of_task(smack_cred(cred)); + ++ #ifdef CONFIG_KEYP ++ iee_set_key_security(key, skp); ++ #else + key->security = skp; ++ #endif + return 0; + } + +@@ -4423,7 +4431,11 @@ static int smack_key_alloc(struct key *key, const struct cred *cred, + */ + static void smack_key_free(struct key *key) + { ++ #ifdef CONFIG_KEYP ++ iee_set_key_security(key, NULL); ++ #else + key->security = NULL; ++ #endif + } + + /** diff --git a/haoc-kernel.spec b/haoc-kernel.spec index 27d305c06f727df0fb878b0f1dfa65d206565994..f6bab16e0a0fc772d5daf7357f517d2d9da97fb8 100644 --- a/haoc-kernel.spec +++ b/haoc-kernel.spec @@ -40,9 +40,9 @@ rm -f test_openEuler_sign.ko test_openEuler_sign.ko.sig %global upstream_version 6.6 %global upstream_sublevel 0 -%global devel_release 27 +%global devel_release 48 %global maintenance_release .0.0 -%global pkg_release .32 +%global pkg_release .55 %global openeuler_lts 1 %global openeuler_major 2403 @@ -87,8 +87,8 @@ rm -f test_openEuler_sign.ko test_openEuler_sign.ko.sig #default is enabled. You can disable it with --without option %define with_perf %{?_without_perf: 0} %{?!_without_perf: 1} -Name: haoc-kernel -Version: 6.6.0 +Name: kernel%{?package64kb} +Version: %{upstream_version}.%{upstream_sublevel} Release: %{devel_release}%{?maintenance_release}%{?pkg_release} Summary: Linux Kernel License: GPLv2 @@ -388,6 +388,10 @@ cp -a tools/perf tools/python3-perf %build cd linux-%{KernelVer} +# Workaround for flask.h and av_permissions.h +gcc scripts/selinux/genheaders/genheaders.c -o scripts/selinux/genheaders/genheaders -Iinclude/uapi -Iinclude -Isecurity/selinux/include +scripts/selinux/genheaders/genheaders security/selinux/flask.h security/selinux/av_permissions.h + perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = -%{release}.%{_target_cpu}/" Makefile perl -p -i -e "s/^OPENEULER_LTS.*/OPENEULER_LTS = %{openeuler_lts}/" Makefile.oever perl -p -i -e "s/^OPENEULER_MAJOR.*/OPENEULER_MAJOR = %{openeuler_major}/" Makefile.oever @@ -713,6 +717,12 @@ find $RPM_BUILD_ROOT/usr/include -name "\.*" -exec rm -rf {} \; rm -f $(find arch/$Arch/boot -name "*.dtb") %endif +# deal with riscv SoC dtb search path +%ifarch riscv64 + mkdir -p $RPM_BUILD_ROOT/boot/dtb-%{KernelVer}/thead + mv $(find $RPM_BUILD_ROOT/boot/dtb-%{KernelVer}/ -name "th1520*.dtb") $RPM_BUILD_ROOT/boot/dtb-%{KernelVer}/thead +%endif + # deal with vdso %ifnarch ppc64le %{make} -s ARCH=%{Arch} INSTALL_MOD_PATH=$RPM_BUILD_ROOT vdso_install KERNELRELEASE=%{KernelVer} @@ -1083,8 +1093,6630 @@ fi %endif %changelog -* Thu May 23 2024 Liu Zhehui - 6.6.0-27.0.0.32 -- update HAOC patch and spec for 6.6.0-27.0.0 +* Wed Nov 6 2024 Liu Zhehui - 6.6.0-48.0.0.55 +- add some optimization, update haoc to 6.6.0-48.0.0 + +* Wed Oct 30 2024 jchzhou - 6.6.0-48.0.0.54 +- create & package symvers-kernelver.gz unconditionally to fix ISO installation +faliures like in issue #I7MARC + +* Wed Oct 30 2024 ZhangPeng - 6.6.0-48.0.0.53 +- !12565 KEYS: prevent NULL pointer dereference in find_asymmetric_key() +- KEYS: prevent NULL pointer dereference in find_asymmetric_key() +- !12498 nbd: fix race between timeout and normal completion +- nbd: fix race between timeout and normal completion +- !10861 [OLK-6.6] perf/x86/uncore: Add support for Hygon family 18h model 4h-7h and 10h DF PMU +- perf/x86/uncore: Add DF PMU support for Hygon family 18h model 4h-7h and 10h +- !12673 ocfs2: remove unreasonable unlock in ocfs2_read_blocks +- ocfs2: remove unreasonable unlock in ocfs2_read_blocks +- !12653 usb: typec: tipd: Free IRQ only if it was requested before +- usb: typec: tipd: Free IRQ only if it was requested before +- !12632 ALSA: asihpi: Fix potential OOB array access +- ALSA: asihpi: Fix potential OOB array access +- !12635 bpf: lsm: Set bpf_lsm_blob_sizes.lbs_task to 0 +- bpf: lsm: Set bpf_lsm_blob_sizes.lbs_task to 0 +- !12491 LoongArch: fix some 3C6000&LS7A related problems +- LoongArch: Add workaround for 3C6000 about io wr/rd +- Loongarch: Dynamic enable writecombine +- acpi: mcfg quirk: Increased multi-chip support for the 3C6000 +- pci/quirks: LS7A2000 enable msi +- !12331 LoongArch: prevent LS7A Bus Master clearing on kexec +- LoongArch: prevent LS7A Bus Master clearing on kexec +- !12321 LoongArch: backport 3 patches from upstream +- LoongArch: Define __ARCH_WANT_NEW_STAT in unistd.h +- LoongArch: Add writecombine support for DMW-based ioremap() +- LoongArch: Change SHMLBA from SZ_64K to PAGE_SIZE +- !12557 ntfs3: Change to non-blocking allocation in ntfs_d_hash +- ntfs3: Change to non-blocking allocation in ntfs_d_hash +- !12554 NFSv4: Prevent NULL-pointer dereference in nfs42_complete_copies() +- NFSv4: Prevent NULL-pointer dereference in nfs42_complete_copies() +- !12444 nilfs2: fix potential oob read in nilfs_btree_check_delete() +- nilfs2: fix potential oob read in nilfs_btree_check_delete() +- !12631 some bugfixs for khuegpaged +- mm: khugepaged: fix the incorrect statistics when collapsing large file folios +- mm: khugepaged: fix the arguments order in khugepaged_collapse_file trace point +- selftests: mm: support shmem mTHP collapse testing +- mm: khugepaged: support shmem mTHP collapse +- mm: khugepaged: support shmem mTHP copy +- mm: khugepaged: use the number of pages in the folio to check the reference count +- mm: khugepaged: expand the is_refcount_suitable() to support file folios +- khugepaged: use a folio throughout hpage_collapse_scan_file() +- khugepaged: use a folio throughout collapse_file() +- khugepaged: remove hpage from collapse_file() +- khugepaged: pass a folio to __collapse_huge_page_copy() +- khugepaged: remove hpage from collapse_huge_page() +- khugepaged: convert alloc_charge_hpage to alloc_charge_folio +- khugepaged: inline hpage_collapse_alloc_folio() +- !12634 [openEuler-24.03-LTS][linux-6.6.y sync] Backport 6.6.53-6.6.54 LTS Patches +- Revert: "dm-verity: restart or panic on an I/O error" +- spi: atmel-quadspi: Fix wrong register value written to MR +- x86/tdx: Fix "in-kernel MMIO" check +- thunderbolt: Fix NULL pointer dereference in tb_port_update_credits() +- thunderbolt: Fix minimum allocated USB 3.x and PCIe bandwidth +- thunderbolt: Send uevent after asymmetric/symmetric switch +- wifi: brcmfmac: add linefeed at end of file +- iio: magnetometer: ak8975: Fix 'Unexpected device' error +- perf/arm-cmn: Fail DTC counter allocation correctly +- usb: yurex: Fix inconsistent locking bug in yurex_read() +- Documentation: KVM: fix warning in "make htmldocs" +- i2c: isch: Add missed 'else' +- i2c: aspeed: Update the stop sw state when the bus recovery occurs +- mm/damon/vaddr: protect vma traversal in __damon_va_thre_regions() with rcu read lock +- module: Fix KCOV-ignored file name +- spi: fspi: add support for imx8ulp +- mm: only enforce minimum stack gap size if it's sensible +- lockdep: fix deadlock issue between lockdep and rcu +- dm-verity: restart or panic on an I/O error +- bpf: lsm: Set bpf_lsm_blob_sizes.lbs_task to 0 +- thunderbolt: Improve DisplayPort tunnel setup process to be more robust +- thunderbolt: Configure asymmetric link if needed and bandwidth allows +- thunderbolt: Add support for asymmetric link +- thunderbolt: Introduce tb_switch_depth() +- thunderbolt: Introduce tb_for_each_upstream_port_on_path() +- thunderbolt: Introduce tb_port_path_direction_downstream() +- thunderbolt: Change bandwidth reservations to comply USB4 v2 +- thunderbolt: Make is_gen4_link() available to the rest of the driver +- thunderbolt: Use weight constants in tb_usb3_consumed_bandwidth() +- thunderbolt: Use constants for path weight and priority +- thunderbolt: Create multiple DisplayPort tunnels if there are more DP IN/OUT pairs +- thunderbolt: Expose tb_tunnel_xxx() log macros to the rest of the driver +- thunderbolt: Use tb_tunnel_dbg() where possible to make logging more consistent +- thunderbolt: Fix debug log when DisplayPort adapter not available for pairing +- dt-bindings: spi: nxp-fspi: add imx8ulp support +- dt-bindings: spi: nxp-fspi: support i.MX93 and i.MX95 +- btrfs: reorder btrfs_inode to fill gaps +- btrfs: subpage: fix the bitmap dump which can cause bitmap corruption +- lib/bitmap: add bitmap_{read,write}() +- x86/entry: Remove unwanted instrumentation in common_interrupt() +- x86/idtentry: Incorporate definitions/declarations of the FRED entries +- serial: don't use uninitialized value in uart_poll_init() +- tty: serial: kgdboc: Fix 8250_* kgdb over serial +- pps: add an error check in parport_attach +- pps: remove usage of the deprecated ida_simple_xx() API +- usb: xhci: fix loss of data on Cadence xHC +- xhci: Add a quirk for writing ERST in high-low order +- USB: misc: yurex: fix race between read and write +- usb: yurex: Replace snprintf() with the safer scnprintf() variant +- soc: versatile: realview: fix soc_dev leak during device remove +- soc: versatile: realview: fix memory leak during device remove +- ARM: dts: imx6ul-geam: fix fsl,pins property in tscgrp pinctrl +- spi: fspi: involve lut_num for struct nxp_fspi_devtype_data +- padata: use integer wrap around to prevent deadlock on seq_nr overflow +- cpuidle: riscv-sbi: Use scoped device node handling to fix missing of_node_put +- icmp: change the order of rate limits +- EDAC/igen6: Fix conversion of system address to physical memory address +- fs: Fix file_set_fowner LSM hook inconsistencies +- vfs: fix race between evice_inodes() and find_inode()&iput() +- arm64: dts: rockchip: Correct the Pinebook Pro battery design capacity +- arm64: dts: qcom: sa8775p: Mark APPS and PCIe SMMUs as DMA coherent +- arm64: dts: rockchip: Raise Pinebook Pro's panel backlight PWM frequency +- arm64: esr: Define ESR_ELx_EC_* constants as UL +- hwrng: cctrng - Add missing clk_disable_unprepare in cctrng_resume +- hwrng: bcm2835 - Add missing clk_disable_unprepare in bcm2835_rng_init +- hwrng: mtk - Use devm_pm_runtime_enable +- f2fs: fix to check atomic_file in f2fs ioctl interfaces +- f2fs: Require FMODE_WRITE for atomic write ioctls +- f2fs: avoid potential int overflow in sanity_check_area_boundary() +- f2fs: prevent possible int overflow in dir_block_index() +- f2fs: fix several potential integer overflows in file offsets +- btrfs: always update fstrim_range on failure in FITRIM ioctl +- btrfs: tree-checker: fix the wrong output of data backref objectid +- debugobjects: Fix conditions in fill_pool() +- wifi: mt76: mt7615: check devm_kasprintf() returned value +- wifi: rtw88: 8822c: Fix reported RX band width +- wifi: rtw88: 8821cu: Remove VID/PID 0bda:c82c +- wifi: mt76: mt7915: check devm_kasprintf() returned value +- wifi: mt76: mt7921: Check devm_kasprintf() returned value +- perf/x86/intel/pt: Fix sampling synchronization +- efistub/tpm: Use ACPI reclaim memory for event log to avoid corruption +- ACPI: resource: Add another DMI match for the TongFang GMxXGxx +- ACPI: sysfs: validate return type of _STR method +- drbd: Add NULL check for net_conf to prevent dereference in state validation +- drbd: Fix atomicity violation in drbd_uuid_set_bm() +- crypto: ccp - Properly unregister /dev/sev on sev PLATFORM_STATUS failure +- serial: qcom-geni: fix fifo polling timeout +- xhci: Set quirky xHC PCI hosts to D3 _after_ stopping and freeing them. +- tty: rp2: Fix reset with non forgiving PCIe host bridges +- firmware_loader: Block path traversal +- bus: mhi: host: pci_generic: Fix the name for the Telit FE990A +- bus: integrator-lm: fix OF node leak in probe() +- usb: dwc2: drd: fix clock gating on USB role switch +- usb: cdnsp: Fix incorrect usb_request status +- USB: class: CDC-ACM: fix race between get_serial and set_serial +- USB: misc: cypress_cy7c63: check for short transfer +- USB: appledisplay: close race between probe and completion handler +- arm64: dts: mediatek: mt8195-cherry: Mark USB 3.0 on xhci1 as disabled +- usbnet: fix cyclical race on disconnect with work queue +- wifi: rtw88: Fix USB/SDIO devices not transmitting beacons +- can: esd_usb: Remove CAN_CTRLMODE_3_SAMPLES for CAN-USB/3-FD +- scsi: mac_scsi: Disallow bus errors during PDMA send +- scsi: mac_scsi: Refactor polling loop +- scsi: mac_scsi: Revise printk(KERN_DEBUG ...) messages +- scsi: ufs: qcom: Update MODE_MAX cfg_bw value +- scsi: sd: Fix off-by-one error in sd_read_block_characteristics() +- ata: libata-scsi: Fix ata_msense_control() CDL page reporting +- ksmbd: handle caseless file creation +- ksmbd: allow write with FILE_APPEND_DATA +- ksmbd: make __dir_empty() compatible with POSIX +- fs: Create a generic is_dot_dotdot() utility +- powerpc/atomic: Use YZ constraints for DS-form instructions +- KEYS: prevent NULL pointer dereference in find_asymmetric_key() +- drm/amd/display: Validate backlight caps are sane +- drm/amd/display: Round calculated vtotal +- drm/amd/display: Add HDMI DSC native YCbCr422 support +- drm/amd/display: Skip Recompute DSC Params if no Stream on Link +- KVM: Use dedicated mutex to protect kvm_usage_count to avoid deadlock +- KVM: x86: Move x2APIC ICR helper above kvm_apic_write_nodecode() +- KVM: x86: Enforce x2APIC's must-be-zero reserved ICR bits +- KVM: arm64: Add memory length checks and remove inline in do_ffa_mem_xfer +- Input: i8042 - add another board name for TUXEDO Stellaris Gen5 AMD line +- Input: i8042 - add TUXEDO Stellaris 15 Slim Gen6 AMD to i8042 quirk table +- Input: i8042 - add TUXEDO Stellaris 16 Gen5 AMD to i8042 quirk table +- Input: adp5588-keys - fix check on return code +- iommufd: Protect against overflow of ALIGN() during iova allocation +- Revert "media: tuners: fix error return code of hybrid_tuner_request_state()" +- soc: versatile: integrator: fix OF node leak in probe() error path +- soc: fsl: cpm1: tsa: Fix tsa_write8() +- ASoC: rt5682: Return devm_of_clk_add_hw_provider to transfer the error +- Revert "soc: qcom: smd-rpm: Match rpmsg channel instead of compatible" +- PCI: xilinx-nwl: Fix off-by-one in INTx IRQ handler +- PCI: Use an error code with PCIe failed link retraining +- PCI: Correct error reporting with PCIe failed link retraining +- PCI: imx6: Fix missing call to phy_power_off() in error handling +- PCI: dra7xx: Fix threaded IRQ request for "dra7xx-pcie-main" IRQ +- PCI: Clear the LBMS bit after a link retrain +- PCI: Revert to the original speed after PCIe failed link retraining +- Remove *.orig pattern from .gitignore +- io_uring/sqpoll: do not put cpumask on stack +- io_uring/sqpoll: retain test for whether the CPU is valid +- xen: move checks for e820 conflicts further up +- Revert "net: libwx: fix alloc msix vectors failed" +- drm/vmwgfx: Prevent unmapping active read buffers +- drm/amd/display: Fix Synaptics Cascaded Panamera DSC Determination +- mm: call the security_mmap_file() LSM hook in remap_file_pages() +- io_uring: check for presence of task_work rather than TIF_NOTIFY_SIGNAL +- io_uring/sqpoll: do not allow pinning outside of cpuset +- netfilter: nf_tables: use rcu chain hook list iterator from netlink dump path +- netfilter: ctnetlink: compile ctnetlink_label_size with CONFIG_NF_CONNTRACK_EVENTS +- netfilter: nf_tables: Keep deleted flowtable hooks until after RCU +- net: stmmac: set PP_FLAG_DMA_SYNC_DEV only if XDP is enabled +- virtio_net: Fix mismatched buf address when unmapping for small packets +- bonding: Fix unnecessary warnings and logs from bond_xdp_get_xmit_slave() +- net: qrtr: Update packets cloning when broadcasting +- tcp: check skb is non-NULL in tcp_rto_delta_us() +- net: ipv6: select DST_CACHE from IPV6_RPL_LWTUNNEL +- net: seeq: Fix use after free vulnerability in ether3 Driver Due to Race Condition +- net: xilinx: axienet: Fix packet counting +- net: xilinx: axienet: Schedule NAPI in two steps +- Revert "dm: requeue IO if mapping table not yet available" +- ep93xx: clock: Fix off by one in ep93xx_div_recalc_rate() +- vhost_vdpa: assign irq bypass producer token correctly +- cxl/pci: Fix to record only non-zero ranges +- interconnect: icc-clk: Add missed num_nodes initialization +- coresight: tmc: sg: Do not leak sg_table +- serial: 8250: omap: Cleanup on error in request_irq +- driver core: Fix a potential null-ptr-deref in module_add_driver() +- dt-bindings: iio: asahi-kasei,ak8975: drop incorrect AK09116 compatible +- iio: magnetometer: ak8975: drop incorrect AK09116 compatible +- iio: magnetometer: ak8975: Convert enum->pointer for data in the match tables +- iio: chemical: bme680: Fix read/write ops to device by adding mutexes +- ABI: testing: fix admv8818 attr description +- driver core: Fix error handling in driver API device_rename() +- iio: adc: ad7606: fix standby gpio state to match the documentation +- iio: adc: ad7606: fix oversampling gpio array +- nvme-multipath: system fails to create generic nvme device +- spi: atmel-quadspi: Avoid overwriting delay register settings +- spi: spi-fsl-lpspi: Undo runtime PM changes at driver exit time +- spi: atmel-quadspi: Undo runtime PM changes at driver exit time +- f2fs: get rid of online repaire on corrupted directory +- f2fs: clean up w/ dotdot_name +- f2fs: prevent atomic file from being dirtied before commit +- f2fs: compress: don't redirty sparse cluster during {,de}compress +- f2fs: compress: do sanity check on cluster when CONFIG_F2FS_CHECK_FS is on +- f2fs: fix to avoid use-after-free in f2fs_stop_gc_thread() +- f2fs: support .shutdown in f2fs_sops +- f2fs: atomic: fix to truncate pagecache before on-disk metadata truncation +- f2fs: fix to wait page writeback before setting gcing flag +- f2fs: Create COW inode from parent dentry for atomic write +- f2fs: fix to avoid racing in between read and OPU dio write +- f2fs: reduce expensive checkpoint trigger frequency +- f2fs: atomic: fix to avoid racing w/ GC +- crypto: powerpc/p10-aes-gcm - Disable CRYPTO_AES_GCM_P10 +- crypto: caam - Pad SG length when allocating hash edesc +- ntb: Force physically contiguous allocation of rx ring buffers +- ntb_perf: Fix printk format +- RDMA/irdma: fix error message in irdma_modify_qp_roce() +- RDMA/cxgb4: Added NULL check for lookup_atid +- riscv: Fix fp alignment bug in perf_callchain_user() +- RDMA/mlx5: Obtain upper net device only when needed +- watchdog: imx_sc_wdt: Don't disable WDT in suspend +- RDMA/mlx5: Limit usage of over-sized mkeys from the MR cache +- RDMA/erdma: Return QP state in erdma_query_qp +- PCI: kirin: Fix buffer overflow in kirin_pcie_parse_port() +- IB/core: Fix ib_cache_setup_one error flow cleanup +- pinctrl: mvebu: Fix devinit_dove_pinctrl_probe function +- nfsd: fix refcount leak when file is unhashed after being found +- nfsd: remove unneeded EEXIST error check in nfsd_do_file_acquire +- clk: rockchip: rk3588: Fix 32k clock name for pmu_24m_32k_100m_src_p +- clk: starfive: Use pm_runtime_resume_and_get to fix pm_runtime_get_sync() usage +- clk: ti: dra7-atl: Fix leak of of_nodes +- RDMA/rtrs-clt: Reset cid to con_num - 1 to stay in bounds +- RDMA/rtrs: Reset hb_missed_cnt after receiving other traffic from peer +- media: mediatek: vcodec: Fix H264 stateless decoder smatch warning +- media: mediatek: vcodec: Fix VP8 stateless decoder smatch warning +- media: mediatek: vcodec: Fix H264 multi stateless decoder smatch warning +- clk: at91: sama7g5: Allocate only the needed amount of memory for PLLs +- pinctrl: single: fix missing error code in pcs_probe() +- RDMA/iwcm: Fix WARNING:at_kernel/workqueue.c:#check_flush_dependency +- media: platform: rzg2l-cru: rzg2l-csi2: Add missing MODULE_DEVICE_TABLE +- PCI: xilinx-nwl: Clean up clock on probe failure/removal +- PCI: xilinx-nwl: Fix register misspelling +- nvdimm: Fix devs leaks in scan_labels() +- x86/PCI: Check pcie_find_root_port() return for NULL +- leds: pca995x: Fix device child node usage in pca995x_probe() +- leds: pca995x: Use device_for_each_child_node() to access device child nodes +- leds: leds-pca995x: Add support for NXP PCA9956B +- clk: qcom: dispcc-sm8250: use special function for Lucid 5LPE PLL +- clk: qcom: ipq5332: Register gcc_qdss_tsctr_clk_src +- PCI: keystone: Fix if-statement expression in ks_pcie_quirk() +- firewire: core: correct range of block for case of switch statement +- PCI: Wait for Link before restoring Downstream Buses +- drivers: media: dvb-frontends/rtl2830: fix an out-of-bounds write error +- Input: ilitek_ts_i2c - add report id message validation +- Input: ilitek_ts_i2c - avoid wrong input subsystem sync +- pinctrl: ti: ti-iodelay: Fix some error handling paths +- pinctrl: ti: iodelay: Use scope based of_node_put() cleanups +- pinctrl: Use device_get_match_data() +- pinctrl: ti: ti-iodelay: Convert to platform remove callback returning void +- leds: bd2606mvv: Fix device child node usage in bd2606mvv_probe() +- clk: qcom: dispcc-sm8550: use rcg2_shared_ops for ESC RCGs +- clk: qcom: dispcc-sm8650: Update the GDSC flags +- clk: qcom: dispcc-sm8550: use rcg2_ops for mdss_dptx1_aux_clk_src +- clk: qcom: dispcc-sm8550: fix several supposed typos +- clk: rockchip: Set parent rate for DCLK_VOP clock on RK3228 +- remoteproc: imx_rproc: Initialize workqueue earlier +- remoteproc: imx_rproc: Correct ddr alias for i.MX8M +- clk: imx: imx8qxp: Parent should be initialized earlier than the clock +- clk: imx: imx8qxp: Register dc0_bypass0_clk before disp clk +- clk: imx: imx8mp: fix clock tree update of TF-A managed clocks +- clk: imx: fracn-gppll: fix fractional part of PLL getting lost +- clk: imx: composite-7ulp: Check the PCC present bit +- clk: imx: composite-93: keep root clock on when mcore enabled +- clk: imx: composite-8m: Enable gate clk with mcore_booted +- clk: imx: composite-8m: Less function calls in __imx8m_clk_hw_composite() after error detection +- clk: imx: imx6ul: fix default parent for enet*_ref_sel +- clk: imx: clk-audiomix: Correct parent clock for earc_phy and audpll +- nilfs2: fix potential oob read in nilfs_btree_check_delete() +- nilfs2: determine empty node blocks as corrupted +- nilfs2: fix potential null-ptr-deref in nilfs_btree_insert() +- ext4: check stripe size compatibility on remount as well +- ext4: avoid OOB when system.data xattr changes underneath the filesystem +- ext4: return error on ext4_find_inline_entry +- ext4: avoid negative min_clusters in find_group_orlov() +- ext4: avoid potential buffer_head leak in __ext4_new_inode() +- ext4: avoid buffer_head leak in ext4_mark_inode_used() +- smackfs: Use rcu_assign_pointer() to ensure safe assignment in smk_set_cipso +- ext4: clear EXT4_GROUP_INFO_WAS_TRIMMED_BIT even mount with discard +- kthread: fix task state in kthread worker if being frozen +- xz: cleanup CRC32 edits from 2018 +- bpf: correctly handle malformed BPF_CORE_TYPE_ID_LOCAL relos +- samples/bpf: Fix compilation errors with cf-protection option +- selftests/bpf: Fix error compiling tc_redirect.c with musl libc +- selftests/bpf: Fix compile if backtrace support missing in libc +- selftests/bpf: Fix redefinition errors compiling lwt_reroute.c +- selftests/bpf: Fix flaky selftest lwt_redirect/lwt_reroute +- selftests/bpf: Fix C++ compile error from missing _Bool type +- selftests/bpf: Fix error compiling test_lru_map.c +- selftests/bpf: Fix arg parsing in veristat, test_progs +- selftests/bpf: Fix errors compiling cg_storage_multi.h with musl libc +- selftests/bpf: Fix errors compiling decap_sanity.c with musl libc +- selftests/bpf: Fix errors compiling lwt_redirect.c with musl libc +- selftests/bpf: Fix compiling core_reloc.c with musl-libc +- selftests/bpf: Fix compiling tcp_rtt.c with musl-libc +- selftests/bpf: Fix compiling flow_dissector.c with musl-libc +- selftests/bpf: Fix compiling kfree_skb.c with musl-libc +- selftests/bpf: Fix compiling parse_tcp_hdr_opt.c with musl-libc +- selftests/bpf: Fix include of +- selftests/bpf: Add a cgroup prog bpf_get_ns_current_pid_tgid() test +- selftests/bpf: Refactor out some functions in ns_current_pid_tgid test +- selftests/bpf: Replace CHECK with ASSERT_* in ns_current_pid_tgid test +- selftests/bpf: Fix missing BUILD_BUG_ON() declaration +- selftests/bpf: Fix missing UINT_MAX definitions in benchmarks +- selftests/bpf: Fix missing ARRAY_SIZE() definition in bench.c +- selftests/bpf: Drop unneeded error.h includes +- selftests/bpf: Implement get_hw_ring_size function to retrieve current and max interface size +- selftests/bpf: Fix error compiling bpf_iter_setsockopt.c with musl libc +- selftests/bpf: Fix compile error from rlim_t in sk_storage_map.c +- selftests/bpf: Use pid_t consistently in test_progs.c +- tools/runqslower: Fix LDFLAGS and add LDLIBS support +- selftests/bpf: Fix wrong binary in Makefile log output +- selftests/bpf: Add CFLAGS per source file and runner +- bpf: Temporarily define BPF_NO_PRESEVE_ACCESS_INDEX for GCC +- bpf: Disable some `attribute ignored' warnings in GCC +- bpf: Use -Wno-error in certain tests when building with GCC +- selftests/bpf: Fix error linking uprobe_multi on mips +- selftests/bpf: Workaround strict bpf_lsm return value check. +- tpm: Clean up TPM space after command failure +- xen/swiotlb: fix allocated size +- xen/swiotlb: add alignment check for dma buffers +- xen: tolerate ACPI NVS memory overlapping with Xen allocated memory +- xen: add capability to remap non-RAM pages to different PFNs +- xen: move max_pfn in xen_memory_setup() out of function scope +- xen: introduce generic helper checking for memory map conflicts +- minmax: avoid overly complex min()/max() macro arguments in xen +- ata: libata: Clear DID_TIME_OUT for ATA PT commands with sense data +- HID: wacom: Do not warn about dropped packets for first packet +- HID: wacom: Support sequence numbers smaller than 16-bit +- xen: use correct end address of kernel for conflict checking +- drivers:drm:exynos_drm_gsc:Fix wrong assignment in gsc_bind() +- drm/msm: fix %s null argument error +- drm/msm/dsi: correct programming sequence for SM8350 / SM8450 +- ipmi: docs: don't advertise deprecated sysfs entries +- drm/msm/a5xx: workaround early ring-buffer emptiness check +- drm/msm/a5xx: fix races in preemption evaluation stage +- drm/msm/a5xx: properly clear preemption records on resume +- drm/msm/a5xx: disable preemption in submits by default +- drm/msm: Fix incorrect file name output in adreno_request_fw() +- powerpc/vdso: Inconditionally use CFUNC macro +- powerpc/8xx: Fix kernel vs user address comparison +- powerpc/8xx: Fix initial memory mapping +- drm/mediatek: Use spin_lock_irqsave() for CRTC event lock +- drm/mediatek: Fix missing configuration flags in mtk_crtc_ddp_config() +- jfs: fix out-of-bounds in dbNextAG() and diAlloc() +- scsi: elx: libefc: Fix potential use after free in efc_nport_vport_del() +- drm/vc4: hdmi: Handle error case of pm_runtime_resume_and_get +- drm/bridge: lontium-lt8912b: Validate mode in drm_bridge_funcs::mode_valid() +- drm/radeon/evergreen_cs: fix int overflow errors in cs track offsets +- drm/rockchip: dw_hdmi: Fix reading EDID when using a forced mode +- drm/rockchip: vop: Allow 4096px width scaling +- drm/amd/amdgpu: Properly tune the size of struct +- scsi: NCR5380: Check for phase match during PDMA fixup +- scsi: smartpqi: revert propagate-the-multipath-failure-to-SML-quickly +- drm/radeon: properly handle vbios fake edid sizing +- drm/amdgpu: properly handle vbios fake edid sizing +- drm/stm: ltdc: check memory returned by devm_kzalloc() +- drm/stm: Fix an error handling path in stm_drm_platform_probe() +- pmdomain: core: Harden inter-column space in debug summary +- iommu/arm-smmu-qcom: apply num_context_bank fixes for SDM630 / SDM660 +- iommu/arm-smmu-qcom: Work around SDM845 Adreno SMMU w/ 16K pages +- iommu/arm-smmu-qcom: hide last LPASS SMMU context bank from linux +- mtd: rawnand: mtk: Fix init error path +- mtd: rawnand: mtk: Factorize out the logic cleaning mtk chips +- mtd: rawnand: mtk: Use for_each_child_of_node_scoped() +- rcu/nocb: Fix RT throttling hrtimer armed from offline CPU +- mtd: powernv: Add check devm_kasprintf() returned value +- iommu/amd: Do not set the D bit on AMD v2 table entries +- fbdev: hpfb: Fix an error handling path in hpfb_dio_probe() +- power: supply: max17042_battery: Fix SOC threshold calc w/ no current sense +- power: supply: axp20x_battery: Remove design from min and max voltage +- hwmon: (ntc_thermistor) fix module autoloading +- mtd: slram: insert break after errors in parsing the map +- hwmon: (max16065) Fix alarm attributes +- hwmon: (max16065) Remove use of i2c_match_id() +- hwmon: (max16065) Fix overflows seen when writing limits +- ASoC: loongson: fix error release +- m68k: Fix kernel_clone_args.flags in m68k_clone() +- ALSA: hda: cs35l41: fix module autoloading +- selftests/ftrace: Add required dependency for kprobe tests +- ASoC: tas2781-i2c: Get the right GPIO line +- ASoC: tas2781-i2c: Drop weird GPIO code +- ASoC: tas2781: Use of_property_read_reg() +- ASoC: tas2781: remove unused acpi_subysystem_id +- ASoC: rt5682s: Return devm_of_clk_add_hw_provider to transfer the error +- x86/mm: Use IPIs to synchronize LAM enablement +- arm64: dts: mediatek: mt8195: Correct clock order for dp_intf* +- clocksource/drivers/qcom: Add missing iounmap() on errors in msm_dt_timer_init() +- reset: k210: fix OF node leak in probe() error path +- reset: berlin: fix OF node leak in probe() error path +- ARM: versatile: fix OF node leak in CPUs prepare +- ARM: dts: imx7d-zii-rmu2: fix Ethernet PHY pinctrl property +- ARM: dts: microchip: sama7g5: Fix RTT clock +- spi: bcmbca-hsspi: Fix missing pm_runtime_disable() +- arm64: dts: ti: k3-j721e-beagleboneai64: Fix reversed C6x carveout locations +- arm64: dts: ti: k3-j721e-sk: Fix reversed C6x carveout locations +- arm64: dts: rockchip: Correct vendor prefix for Hardkernel ODROID-M1 +- ARM: dts: microchip: sam9x60: Fix rtc/rtt clocks +- arm64: dts: renesas: r9a07g044: Correct GICD and GICR sizes +- arm64: dts: renesas: r9a07g054: Correct GICD and GICR sizes +- arm64: dts: renesas: r9a07g043u: Correct GICD and GICR sizes +- regulator: Return actual error in of_regulator_bulk_get_all() +- spi: ppc4xx: Avoid returning 0 when failed to parse and map IRQ +- firmware: arm_scmi: Fix double free in OPTEE transport +- arm64: dts: mediatek: mt8186: Fix supported-hw mask for GPU OPPs +- arm64: dts: exynos: exynos7885-jackpotlte: Correct RAM amount to 4GB +- spi: ppc4xx: handle irq_of_parse_and_map() errors +- block: fix potential invalid pointer dereference in blk_add_partition +- block: print symbolic error name instead of error code +- io_uring/io-wq: inherit cpuset of cgroup in io worker +- io_uring/io-wq: do not allow pinning outside of cpuset +- block, bfq: fix procress reference leakage for bfqq in merge chain +- block, bfq: fix uaf for accessing waker_bfqq after splitting +- erofs: fix incorrect symlink detection in fast symlink +- cachefiles: Fix non-taking of sb_writers around set/removexattr +- block, bfq: don't break merge chain in bfq_split_bfqq() +- block, bfq: choose the last bfqq from merge chain in bfq_setup_cooperator() +- block, bfq: fix possible UAF for bfqq->bic with merge chain +- nbd: fix race between timeout and normal completion +- ublk: move zone report data out of request pdu +- ipv6: avoid possible NULL deref in rt6_uncached_list_flush_dev() +- net: tipc: avoid possible garbage value +- net: ipv6: rpl_iptunnel: Fix memory leak in rpl_input +- r8169: disable ALDPS per default for RTL8125 +- net: enetc: Use IRQF_NO_AUTOEN flag in request_irq() +- bareudp: Pull inner IP header on xmit. +- bareudp: Pull inner IP header in bareudp_udp_encap_recv(). +- Bluetooth: btusb: Fix not handling ZPL/short-transfer +- can: m_can: m_can_close(): stop clocks after device has been shut down +- can: m_can: enable NAPI before enabling interrupts +- sock_map: Add a cond_resched() in sock_hash_free() +- Bluetooth: hci_sync: Ignore errors from HCI_OP_REMOTE_NAME_REQ_CANCEL +- Bluetooth: hci_core: Fix sending MGMT_EV_CONNECT_FAILED +- wifi: wilc1000: fix potential RCU dereference issue in wilc_parse_join_bss_param +- wifi: mac80211: use two-phase skb reclamation in ieee80211_do_stop() +- wifi: cfg80211: fix two more possible UBSAN-detected off-by-one errors +- wifi: mt76: mt7996: fix uninitialized TLV data +- wifi: mt76: mt7996: ensure 4-byte alignment for beacon commands +- wifi: mt76: mt7915: fix rx filter setting for bfee functionality +- wifi: cfg80211: fix UBSAN noise in cfg80211_wext_siwscan() +- wifi: mt76: mt7603: fix mixed declarations and code +- crypto: hisilicon/qm - inject error before stopping queue +- pm:cpupower: Add missing powercap_set_enabled() stub function +- x86/sgx: Fix deadlock in SGX NUMA node search +- wifi: mt76: mt7996: fix EHT beamforming capability check +- wifi: mt76: mt7996: fix HE and EHT beamforming capabilities +- wifi: mt76: mt7996: fix wmm set of station interface to 3 +- wifi: mt76: mt7996: fix traffic delay when switching back to working channel +- wifi: mt76: mt7996: use hweight16 to get correct tx antenna +- wifi: mt76: mt7915: fix oops on non-dbdc mt7986 +- cpufreq: ti-cpufreq: Introduce quirks to handle syscon fails appropriately +- perf/arm-cmn: Ensure dtm_idx is big enough +- perf/arm-cmn: Fix CCLA register offset +- perf/arm-cmn: Refactor node ID handling. Again. +- perf/arm-cmn: Improve debugfs pretty-printing for large configs +- perf/arm-cmn: Rework DTC counters (again) +- netfilter: nf_tables: remove annotation to access set timeout while holding lock +- netfilter: nf_tables: reject expiration higher than timeout +- netfilter: nf_tables: reject element expiration with no timeout +- netfilter: nf_tables: elements with timeout below CONFIG_HZ never expire +- ACPI: CPPC: Fix MASK_VAL() usage +- can: j1939: use correct function name in comment +- kselftest/arm64: Actually test SME vector length changes via sigreturn +- padata: Honor the caller's alignment in case of chunk_size 0 +- wifi: iwlwifi: mvm: increase the time between ranging measurements +- wifi: iwlwifi: config: label 'gl' devices as discrete +- wifi: iwlwifi: remove AX101, AX201 and AX203 support from LNL +- wifi: mac80211: don't use rate mask for offchannel TX either +- kselftest/arm64: signal: fix/refactor SVE vector length enumeration +- powercap: intel_rapl: Fix off by one in get_rpi() +- ARM: 9410/1: vfp: Use asm volatile in fmrx/fmxr macros +- mount: handle OOM on mnt_warn_timestamp_expiry +- RISC-V: KVM: Fix to allow hpmcounter31 from the guest +- RISC-V: KVM: Allow legacy PMU access from guest +- RISC-V: KVM: Fix sbiret init before forwarding to userspace +- wifi: rtw88: remove CPT execution branch never used +- arm64: signal: Fix some under-bracketed UAPI macros +- wifi: ath12k: fix invalid AMPDU factor calculation in ath12k_peer_assoc_h_he() +- wifi: ath12k: match WMI BSS chan info structure with firmware definition +- wifi: ath12k: fix BSS chan info request WMI command +- wifi: ath9k: Remove error checks when creating debugfs entries +- wifi: brcmfmac: introducing fwil query functions +- wifi: brcmfmac: export firmware interface functions +- ACPI: PMIC: Remove unneeded check in tps68470_pmic_opregion_probe() +- crypto: xor - fix template benchmarking +- wifi: rtw88: always wait for both firmware loading attempts +- EDAC/synopsys: Fix error injection on Zynq UltraScale+ +- EDAC/synopsys: Fix ECC status and IRQ control race condition +- !12612 Hygon model 4h~fh and 10h ATL issue fix +- EDAC/amd64: Don't use the ATL for Hygon model 4h~fh and 10h processors +- !12464 f2fs: fix to don't set SB_RDONLY in f2fs_handle_critical_error() +- f2fs: fix to don't set SB_RDONLY in f2fs_handle_critical_error() +- !12584 drm/amd/display: Add null check for set_output_gamma in dcn30_set_output_transfer_func +- drm/amd/display: Add null check for set_output_gamma in dcn30_set_output_transfer_func +- !12461 NFSD: Limit the number of concurrent async COPY operations +- NFSD: Limit the number of concurrent async COPY operations +- !12559 fix CVE-2024-49900 +- jfs: Fix uninit-value access of new_ea in ea_buffer +- !12462 drm/amd/display: Fix index out of bounds in DCN30 degamma hardware format translation +- drm/amd/display: Fix index out of bounds in DCN30 degamma hardware format translation +- !12455 drm/amd/display: Add NULL check for function pointer in dcn20_set_output_transfer_func +- drm/amd/display: Add NULL check for function pointer in dcn20_set_output_transfer_func +- !12448 drm/amd/display: Add null check for head_pipe in dcn201_acquire_free_pipe_for_layer +- drm/amd/display: Add null check for head_pipe in dcn201_acquire_free_pipe_for_layer +- !12443 drm/amd/display: Fix index out of bounds in DCN30 color transformation +- drm/amd/display: Fix index out of bounds in DCN30 color transformation +- !12533 drm/amd/display: Add null check for head_pipe in dcn32_acquire_idle_pipe_for_head_pipe_in_layer +- drm/amd/display: Add null check for head_pipe in dcn32_acquire_idle_pipe_for_head_pipe_in_layer +- !12065 Fix VMAPP/VMOVP races +- irqchip/gic-v4: Fix ordering between vmapp and vpe locks +- irqchip/gic-v4: Make sure a VPE is locked when VMAPP is issued +- irqchip/gic-v4: Substitute vmovp_lock for a per-VM lock +- irqchip/gic-v4: Always configure affinity on VPE activation +- !12400 drivers: media: dvb-frontends/rtl2832: fix an out-of-bounds write error +- drivers: media: dvb-frontends/rtl2832: fix an out-of-bounds write error +- !12429 jfs: Fix uaf in dbFreeBits +- jfs: Fix uaf in dbFreeBits +- !12428 jfs: check if leafidx greater than num leaves per dmap tree +- jfs: check if leafidx greater than num leaves per dmap tree +- !12426 btrfs: fix a NULL pointer dereference when failed to start a new trasacntion +- btrfs: fix a NULL pointer dereference when failed to start a new trasacntion +- !12427 btrfs: wait for fixup workers before stopping cleaner kthread during umount +- btrfs: wait for fixup workers before stopping cleaner kthread during umount +- !12524 netfilter: nf_reject_ipv6: fix nf_reject_ip6_tcphdr_put() +- netfilter: nf_reject_ipv6: fix nf_reject_ip6_tcphdr_put() +- !12515 drm/amd/display: Validate function returns +- drm/amd/display: Validate function returns +- !12365 x86/ioapic: Handle allocation failures gracefully +- x86/ioapic: Handle allocation failures gracefully +- !12361 cpufreq: Avoid a bad reference count on CPU node +- cpufreq: Avoid a bad reference count on CPU node +- !12476 fix CVE-2024-40965 +- i2c: lpi2c: Avoid calling clk_get_rate during transfer +- clk: Provide !COMMON_CLK dummy for devm_clk_rate_exclusive_get() +- clk: Add a devm variant of clk_rate_exclusive_get() +- !12300 [OLK-6.6] AMD Address Translation Library (ATL) patches +- RAS/AMD/ATL: Fix MI300 bank hash +- RAS/AMD/ATL: Use system settings for MI300 DRAM to normalized address translation +- RAS/AMD/ATL: Fix array overflow in get_logical_coh_st_fabric_id_mi300() +- RAS/AMD/ATL: Fix bit overflow in denorm_addr_df4_np2() +- RAS: Avoid build errors when CONFIG_DEBUG_FS=n +- RAS/AMD/FMPM: Use atl internal.h for INVALID_SPA +- RAS/AMD/FMPM: Safely handle saved records of various sizes +- RAS/AMD/FMPM: Avoid NULL ptr deref in get_saved_records() +- RAS/AMD/FMPM: Fix off by one when unwinding on error +- RAS/AMD/FMPM: Add debugfs interface to print record entries +- RAS/AMD/FMPM: Save SPA values +- RAS: Introduce a FRU memory poison manager +- RAS/AMD/ATL: Implement DF 4.5 NP2 denormalization +- RAS/AMD/ATL: Validate address map when information is gathered +- RAS/AMD/ATL: Expand helpers for adding and removing base and hole +- RAS/AMD/ATL: Read DRAM hole base early +- RAS/AMD/ATL: Add amd_atl pr_fmt() prefix +- EDAC/amd64: Use new AMD Address Translation Library +- RAS: Export helper to get ras_debugfs_dir +- RAS/AMD/ATL: Add MI300 row retirement support +- RAS/AMD/ATL: Add MI300 DRAM to normalized address translation support +- RAS/AMD/ATL: Add MI300 support +- RAS: Introduce AMD Address Translation Library +- !12440 CVE-2024-35964 +- Bluetooth: ISO: Fix not validating setsockopt user input +- !12438 CVE-2024-35949 +- btrfs: make sure that WRITTEN is set on all metadata blocks +- !12410 iommu/arm-smmu: Use the correct type in nvidia_smmu_context_fault() +- iommu/arm-smmu: Use the correct type in nvidia_smmu_context_fault() +- !12389 mm/swapfile: skip HugeTLB pages for unuse_vma +- mm/swapfile: skip HugeTLB pages for unuse_vma +- !12363 md: use RCU lock to protect traversal in md_spares_need_change() +- md: use RCU lock to protect traversal in md_spares_need_change() +- !12351 i2c: stm32f7: Do not prepare/unprepare clock during runtime suspend/resume +- i2c: stm32f7: Do not prepare/unprepare clock during runtime suspend/resume +- !12394 tracing/timerlat: Fix a race during cpuhp processing +- tracing/timerlat: Fix a race during cpuhp processing +- !12397 tracing/timerlat: Drop interface_lock in stop_kthread() +- tracing/timerlat: Drop interface_lock in stop_kthread() +- !12399 wifi: mt76: mt7996: fix NULL pointer dereference in mt7996_mcu_sta_bfer_he +- wifi: mt76: mt7996: fix NULL pointer dereference in mt7996_mcu_sta_bfer_he +- !12390 RDMA/hns: Fix missing spin_lock_init() for qp flush lock +- RDMA/hns: Fix missing spin_lock_init() for qp flush lock +- !12273 drm/amdgpu: fix mc_data out-of-bounds read warning +- drm/amdgpu: fix mc_data out-of-bounds read warning +- !12263 drm/amd/display: Avoid overflow from uint32_t to uint8_t +- drm/amd/display: Avoid overflow from uint32_t to uint8_t +- !12288 [OLK-6.6] AMD Turin perf vendor event patches +- perf vendor events amd: Add Zen 5 mapping +- perf vendor events amd: Add Zen 5 metrics +- perf vendor events amd: Add Zen 5 uncore events +- perf vendor events amd: Add Zen 5 core events +- tracing: Add the ::microcode field to the mce_record tracepoint +- tracing: Add the ::ppin field to the mce_record tracepoint +- x86/mce: Clean up TP_printk() output line of the 'mce_record' tracepoint +- !12322 LoongArch: fix dma-direct.h not found +- LoongArch: fix dma-direct.h not found +- !12293 nfsd: return -EINVAL when namelen is 0 +- nfsd: return -EINVAL when namelen is 0 +- !12335 ntb: intel: Fix the NULL vs IS_ERR() bug for debugfs_create_dir() +- ntb: intel: Fix the NULL vs IS_ERR() bug for debugfs_create_dir() +- !12338 drm/amd/display: Add NULL pointer check for kzalloc +- drm/amd/display: Add NULL pointer check for kzalloc +- !12317 nfsd: call cache_put if xdr_reserve_space returns NULL +- nfsd: call cache_put if xdr_reserve_space returns NULL +- !12066 drm/amd/display: added NULL check at start of dc_validate_stream +- drm/amd/display: added NULL check at start of dc_validate_stream + +* Wed Oct 23 2024 ZhangPeng - 6.6.0-47.0.0.52 +- !12168 crypto: stm32/cryp - call finalize with bh disabled +- crypto: stm32/cryp - call finalize with bh disabled +- !11502 Virtcca feature: modify vfio/msi/iommu driver to enable confidential device assignment +- virtcca feature: msi place modify +- virtcca feature: fix msi iova map +- virtcca feature: extract the function to the virtcca_coda.c file +- virtcca feature: read or write msi forwarding to the secure world +- virtcca feature: read or write bar space forwarding to the secure world +- virtcca feature: read or write config space forwarding to secure world +- virtcca feature: activate confidential vm to set security device s_s2ttbr +- virtcca feature: set device security properties +- virtcca feature: secure device page fault +- virtcca feature: vfio driver dma map +- virtcca feature: bind the kvm handle of cvm with smmu domain +- virtcca feature: vfio attach the device list to secure world +- !12304 btrfs: fix race setting file private on concurrent lseek using same fd +- btrfs: fix race setting file private on concurrent lseek using same fd +- !12314 [openEuler-24.03-LTS][linux-6.6.y sync] Backport 6.6.52-6.6.53 LTS Patches +- USB: serial: pl2303: add device id for Macrosilicon MS3020 +- can: mcp251xfd: move mcp251xfd_timestamp_start()/stop() into mcp251xfd_chip_start/stop() +- can: mcp251xfd: properly indent labels +- x86/mm: Switch to new Intel CPU model defines +- nvme-pci: qdepth 1 quirk +- gpiolib: cdev: Ignore reconfiguration without direction +- Revert "wifi: cfg80211: check wiphy mutex is held for wdev mutex" +- netfilter: nf_tables: missing iterator type in lookup walk +- netfilter: nft_set_pipapo: walk over current view on netlink dump +- netfilter: nft_socket: Fix a NULL vs IS_ERR() bug in nft_socket_cgroup_subtree_level() +- netfilter: nft_socket: make cgroupsv2 matching work with namespaces +- powercap/intel_rapl: Add support for AMD family 1Ah +- drm: Expand max DRM device number to full MINORBITS +- accel: Use XArray instead of IDR for minors +- drm: Use XArray instead of IDR for minors +- spi: spidev: Add missing spi_device_id for jg10309-01 +- block: Fix where bio IO priority gets set +- tools: hv: rm .*.cmd when make clean +- x86/hyperv: Set X86_FEATURE_TSC_KNOWN_FREQ when Hyper-V provides frequency +- smb: client: fix hang in wait_for_response() for negproto +- spi: bcm63xx: Enable module autoloading +- drm: komeda: Fix an issue related to normalized zpos +- ALSA: hda: add HDMI codec ID for Intel PTL +- ASoC: amd: yc: Add a quirk for MSI Bravo 17 (D7VEK) +- spi: spidev: Add an entry for elgin,jg10309-01 +- ASoC: fix module autoloading +- ASoC: tda7419: fix module autoloading +- ASoC: google: fix module autoloading +- ASoC: intel: fix module autoloading +- ASoC: Intel: soc-acpi-cht: Make Lenovo Yoga Tab 3 X90F DMI match less strict +- can: mcp251xfd: mcp251xfd_ring_init(): check TX-coalescing configuration +- wifi: iwlwifi: clear trans->state earlier upon error +- wifi: mac80211: free skb on error path in ieee80211_beacon_get_ap() +- wifi: iwlwifi: mvm: pause TCM when the firmware is stopped +- wifi: iwlwifi: mvm: fix iwl_mvm_max_scan_ie_fw_cmd_room() +- wifi: iwlwifi: mvm: fix iwl_mvm_scan_fits() calculation +- wifi: iwlwifi: lower message level for FW buffer destination +- LoongArch: Define ARCH_IRQ_INIT_FLAGS as IRQ_NOPROBE +- net: ftgmac100: Ensure tx descriptor updates are visible +- platform/x86: x86-android-tablets: Make Lenovo Yoga Tab 3 X90F DMI match less strict +- microblaze: don't treat zero reserved memory regions as error +- hwmon: (asus-ec-sensors) remove VRM temp X570-E GAMING +- pinctrl: at91: make it work with current gpiolib +- scsi: lpfc: Fix overflow build issue +- ALSA: hda/realtek - FIxed ALC285 headphone no sound +- ALSA: hda/realtek - Fixed ALC256 headphone no sound +- ASoC: allow module autoloading for table board_ids +- ASoC: allow module autoloading for table db1200_pids +- ASoC: mediatek: mt8188: Mark AFE_DAC_CON0 register as volatile +- ASoC: SOF: mediatek: Add missing board compatible +- !12151 nfc: pn533: Add poll mod list filling check +- nfc: pn533: Add poll mod list filling check +- !12141 drm/vmwgfx: Fix prime with external buffers +- drm/vmwgfx: Fix prime with external buffers +- !12129 bpf: Remove tst_run from lwt_seg6local_prog_ops. +- bpf: Remove tst_run from lwt_seg6local_prog_ops. +- !12296 drivers/perf: Fix ali_drw_pmu driver interrupt status clearing +- drivers/perf: Fix ali_drw_pmu driver interrupt status clearing +- !12200 CVE-2024-38608 +- net/mlx5e: Fix netif state handling +- net/mlx5e: Add wrapping for auxiliary_driver ops and remove unused args +- !12201 netfilter: nf_tables: use timestamp to check for set element timeout +- netfilter: nf_tables: use timestamp to check for set element timeout +- !12295 i3c: mipi-i3c-hci: Error out instead on BUG_ON() in IBI DMA setup +- i3c: mipi-i3c-hci: Error out instead on BUG_ON() in IBI DMA setup +- !12306 [openEuler-24.03-LTS][linux-6.6.y sync] Backport 6.6.51-6.6.52 LTS Patches +- riscv: dts: starfive: add assigned-clock* to limit frquency +- pinctrl: meteorlake: Add Arrow Lake-H/U ACPI ID +- cifs: Fix signature miscalculation +- ASoC: codecs: avoid possible garbage value in peb2466_reg_read() +- drm/i915/guc: prevent a possible int overflow in wq offsets +- spi: geni-qcom: Fix incorrect free_irq() sequence +- spi: geni-qcom: Undo runtime PM changes at driver exit time +- drm/amd/amdgpu: apply command submission parser for JPEG v1 +- drm/amdgpu/atomfirmware: Silence UBSAN warning +- drm/nouveau/fb: restore init() for ramgp102 +- drm/syncobj: Fix syncobj leak in drm_syncobj_eventfd_ioctl +- soundwire: stream: Revert "soundwire: stream: fix programming slave ports for non-continous port maps" +- spi: nxp-fspi: fix the KASAN report out-of-bounds bug +- tracing/osnoise: Fix build when timerlat is not enabled +- net: dsa: felix: ignore pending status of TAS module when it's disabled +- selftests: net: csum: Fix checksums for packets with non-zero padding +- net: ftgmac100: Enable TX interrupt to avoid TX timeout +- octeontx2-af: Modify SMQ flush sequence to drop packets +- fou: fix initialization of grc +- net/mlx5: Verify support for scheduling element and TSAR type +- net/mlx5: Correct TASR typo into TSAR +- net/mlx5: Add missing masks and QoS bit masks for scheduling elements +- net/mlx5: Explicitly set scheduling element and TSAR type +- net/mlx5e: Add missing link mode to ptys2ext_ethtool_map +- IB/mlx5: Rename 400G_8X speed to comply to naming convention +- net/mlx5e: Add missing link modes to ptys2ethtool_map +- net/mlx5: Update the list of the PCI supported devices +- igb: Always call igb_xdp_ring_update_tail() under Tx lock +- ice: fix VSI lists confusion when adding VLANs +- ice: fix accounting for filters shared by multiple VSIs +- ice: Fix lldp packets dropping after changing the number of channels +- hwmon: (pmbus) Conditionally clear individual status bits for pmbus rev >= 1.2 +- selftests/bpf: Support SOCK_STREAM in unix_inet_redir_to_connected() +- cxl/core: Fix incorrect vendor debug UUID define +- eeprom: digsy_mtc: Fix 93xx46 driver probe failure +- drm/amd/display: Fix FEC_READY write on DP LT +- drm/amd/display: Disable error correction if it's not supported +- arm64: dts: rockchip: fix PMIC interrupt pin in pinctrl for ROCK Pi E +- net: xilinx: axienet: Fix race in axienet_stop +- mm: avoid leaving partial pfn mappings around in error case +- x86/hyperv: fix kexec crash due to VP assist page corruption +- dm-integrity: fix a race condition when accessing recalc_sector +- net: tighten bad gso csum offset check in virtio_net_hdr +- minmax: reduce min/max macro expansion in atomisp driver +- arm64: dts: rockchip: override BIOS_DISABLE signal via GPIO hog on RK3399 Puma +- arm64: dts: rockchip: fix eMMC/SPI corruption when audio has been used on RK3399 Puma +- selftests: mptcp: join: restrict fullmesh endp on 1st sf +- platform/x86: panasonic-laptop: Allocate 1 entry extra in the sinf array +- NFS: Avoid unnecessary rescanning of the per-server delegation list +- NFSv4: Fix clearing of layout segments in layoutreturn +- smb/server: fix return value of smb2_open() +- Input: i8042 - add Fujitsu Lifebook E756 to i8042 quirk table +- drm/msm/adreno: Fix error return if missing firmware-name +- platform/surface: aggregator_registry: Add support for Surface Laptop Go 3 +- platform/surface: aggregator_registry: Add Support for Surface Pro 10 +- scripts: kconfig: merge_config: config files: add a trailing newline +- HID: multitouch: Add support for GT7868Q +- Input: synaptics - enable SMBus for HP Elitebook 840 G2 +- Input: ads7846 - ratelimit the spi_sync error message +- btrfs: update target inode's ctime on unlink +- wifi: mt76: mt7921: fix NULL pointer access in mt7921_ipv6_addr_change +- powerpc/mm: Fix boot warning with hugepages and CONFIG_DEBUG_VIRTUAL +- net: phy: vitesse: repair vsc73xx autonegotiation +- drm: panel-orientation-quirks: Add quirk for Ayn Loki Max +- drm: panel-orientation-quirks: Add quirk for Ayn Loki Zero +- net: ethernet: use ip_hdrlen() instead of bit shift +- usbnet: ipheth: fix carrier detection in modes 1 and 4 +- usbnet: ipheth: do not stop RX on failing RX callback +- usbnet: ipheth: drop RX URBs with no payload +- usbnet: ipheth: remove extraneous rx URB length check +- ksmbd: override fsids for smb2_query_info() +- ksmbd: override fsids for share path check +- nvmem: u-boot-env: error if NVMEM device is too small +- nvmem: u-boot-env: improve coding style +- nvmem: u-boot-env: use nvmem device helpers +- nvmem: u-boot-env: use nvmem_add_one_cell() nvmem subsystem helper +- nvmem: core: add nvmem_dev_size() helper +- iio: adc: ad7124: fix DT configuration parsing +- iio: adc: ad7124: Switch from of specific to fwnode based property handling +- device property: Introduce device_for_each_child_node_scoped() +- device property: Add cleanup.h based fwnode_handle_put() scope based cleanup. +- !12301 bpf: Fix use-after-free in bpf_uprobe_multi_link_attach() +- bpf: Fix use-after-free in bpf_uprobe_multi_link_attach() +- !12291 [openEuler-24.03-LTS][linux-6.6.y sync] Backport 6.6.50-6.6.51 LTS Patches +- Bluetooth: hci_sync: Fix UAF on hci_abort_conn_sync +- Bluetooth: hci_sync: Fix UAF on create_le_conn_complete +- Bluetooth: hci_sync: Fix UAF in hci_acl_create_conn_sync +- spi: spi-fsl-lpspi: Fix off-by-one in prescale max +- x86/mm: Fix PTI for i386 some more +- membarrier: riscv: Add full memory barrier in switch_mm() +- ublk_drv: fix NULL pointer dereference in ublk_ctrl_start_recovery() +- riscv: Do not restrict memory size because of linear mapping on nommu +- riscv: Fix toolchain vector detection +- gpio: modepin: Enable module autoloading +- gpio: rockchip: fix OF node leak in probe() +- drm/i915/fence: Mark debug_fence_free() with __maybe_unused +- drm/i915/fence: Mark debug_fence_init_onstack() with __maybe_unused +- clk: qcom: gcc-sm8550: Don't park the USB RCG at registration time +- clk: qcom: gcc-sm8550: Don't use parking clk_ops for QUPs +- ASoC: sunxi: sun4i-i2s: fix LRCLK polarity in i2s mode +- ASoc: SOF: topology: Clear SOF link platform name upon unload +- nvme-pci: allocate tagset on reset if necessary +- ASoC: tegra: Fix CBB error during probe() +- powerpc/vdso: Don't discard rela sections +- powerpc/64e: Define mmu_pte_psize static +- powerpc/64e: split out nohash Book3E 64-bit code +- powerpc/64e: remove unused IBM HTW code +- clk: qcom: ipq9574: Update the alpha PLL type for GPLLs +- crypto: starfive - Fix nent assignment in rsa dec +- crypto: starfive - Align rsa input data to 32-bit +- ata: libata-scsi: Check ATA_QCFLAG_RTF_FILLED before using result_tf +- ata: libata-scsi: Remove redundant sense_buffer memsets +- drm/amdgpu: handle gfx12 in amdgpu_display_verify_sizes +- drm/amd: Add gfx12 swizzle mode defs +- can: mcp251xfd: rx: add workaround for erratum DS80000789E 6 of mcp2518fd +- can: mcp251xfd: clarify the meaning of timestamp +- can: mcp251xfd: rx: prepare to workaround broken RX FIFO head index erratum +- can: mcp251xfd: mcp251xfd_handle_rxif_ring_uinc(): factor out in separate function +- ACPI: processor: Fix memory leaks in error paths of processor_add() +- ACPI: processor: Return an error if acpi_processor_get_info() fails in processor_add() +- workqueue: Improve scalability of workqueue watchdog touch +- workqueue: wq_watchdog_touch is always called with valid CPU +- Revert "mm: skip CMA pages when they are not available" +- mm/vmscan: use folio_migratetype() instead of get_pageblock_migratetype() +- uprobes: Use kzalloc to allocate xol area +- clocksource/drivers/timer-of: Remove percpu irq related code +- clocksource/drivers/imx-tpm: Fix next event not taking effect sometime +- clocksource/drivers/imx-tpm: Fix return -ETIME when delta exceeds INT_MAX +- Drivers: hv: vmbus: Fix rescind handling in uio_hv_generic +- nvmem: Fix return type of devm_nvmem_device_get() in kerneldoc +- usb: dwc3: Avoid waking up gadget during startxfer +- usb: cdns2: Fix controller reset issue +- usb: dwc3: core: update LC timer as per USB Spec V3.2 +- iio: adc: ad7124: fix chip ID mismatch +- iio: adc: ad7606: remove frstdata check for serial mode +- iio: adc: ad7124: fix config comparison +- iio: fix scale application in iio_convert_raw_to_processed_unlocked +- iio: buffer-dmaengine: fix releasing dma channel on error +- staging: iio: frequency: ad9834: Validate frequency parameter value +- intel: legacy: Partial revert of field get conversion +- tcp: process the 3rd ACK with sk_socket for TFO/MPTCP +- cpufreq: amd-pstate: fix the highest frequency issue which limits performance +- cpufreq: amd-pstate: Enable amd-pstate preferred core support +- ACPI: CPPC: Add helper to get the highest performance value +- riscv: Use accessors to page table entries instead of direct dereference +- riscv: mm: Only compile pgtable.c if MMU +- mm: Introduce pudp/p4dp/pgdp_get() functions +- riscv: Use WRITE_ONCE() when setting page table entries +- NFSv4: Add missing rescheduling points in nfs_client_return_marked_delegations +- ata: pata_macio: Use WARN instead of BUG +- spi: spi-fsl-lpspi: limit PRESCALE bit in TCR register +- MIPS: cevt-r4k: Don't call get_c0_compare_int if timer irq is installed +- lib/generic-radix-tree.c: Fix rare race in __genradix_ptr_alloc() +- of/irq: Prevent device address out-of-bounds read in interrupt map walk +- usbnet: ipheth: race between ipheth_close and error handling +- s390/vmlinux.lds.S: Move ro_after_init section behind rodata section +- btrfs: initialize location to fix -Wmaybe-uninitialized in btrfs_lookup_dentry() +- kselftests: dmabuf-heaps: Ensure the driver name is null-terminated +- i3c: mipi-i3c-hci: Error out instead on BUG_ON() in IBI DMA setup +- i3c: master: svc: resend target address when get NACK +- vfs: Fix potential circular locking through setxattr() and removexattr() +- regmap: maple: work around gcc-14.1 false-positive warning +- LoongArch: Use correct API to map cmdline in relocate_kernel() +- net: dpaa: avoid on-stack arrays of NR_CPUS elements +- Bluetooth: btnxpuart: Fix Null pointer dereference in btnxpuart_flush() +- tcp: Don't drop SYN+ACK for simultaneous connect(). +- riscv: set trap vector earlier +- cxl/region: Verify target positions using the ordered target list +- btrfs: replace BUG_ON with ASSERT in walk_down_proc() +- fs/ntfs3: Check more cases when directory is corrupted +- smp: Add missing destroy_work_on_stack() call in smp_call_on_cpu() +- drm/amdgpu: reject gang submit on reserved VMIDs +- dma-mapping: benchmark: Don't starve others when doing the test +- ext4: fix possible tid_t sequence overflows +- drm/amdgpu: Set no_hw_access when VF request full GPU fails +- libbpf: Add NULL checks to bpf_object__{prev_map,next_map} +- ASoc: TAS2781: replace beXX_to_cpup with get_unaligned_beXX for potentially broken alignment +- hwmon: (nct6775-core) Fix underflows seen when writing limit attributes +- crypto: qat - fix unintentional re-enabling of error interrupts +- scsi: pm80xx: Set phy->enable_completion only when we wait for it +- virtio_ring: fix KMSAN error for premapped mode +- devres: Initialize an uninitialized struct member +- cgroup: Protect css->cgroup write under css_set_lock +- iommu/vt-d: Handle volatile descriptor status read +- dm init: Handle minors larger than 255 +- ASoC: topology: Properly initialize soc_enum values +- phy: zynqmp: Take the phy mutex in xlate +- firmware: cs_dsp: Don't allow writes to read-only controls +- xen: privcmd: Fix possible access to a freed kirqfd instance +- selftests: net: enable bind tests +- net: dsa: vsc73xx: fix possible subblocks range of CAPT block +- net: bridge: br_fdb_external_learn_add(): always set EXT_LEARN +- r8152: fix the firmware doesn't work +- fou: Fix null-ptr-deref in GRO. +- bareudp: Fix device stats updates. +- bpf, net: Fix a potential race in do_sock_getsockopt() +- net/socket: Break down __sys_getsockopt +- net/socket: Break down __sys_setsockopt +- bpf: Add sockptr support for setsockopt +- bpf: Add sockptr support for getsockopt +- usbnet: modern method to get random MAC +- ice: do not bring the VSI up, if it was down before the XDP setup +- ice: protect XDP configuration with a mutex +- igc: Unlock on error in igc_io_resume() +- Bluetooth: MGMT: Fix not generating command complete for MGMT_OP_DISCONNECT +- Bluetooth: hci_sync: Introduce hci_cmd_sync_run/hci_cmd_sync_run_once +- Bluetooth: hci_sync: Attempt to dequeue connection attempt +- Bluetooth: hci_sync: Add helper functions to manipulate cmd_sync queue +- Bluetooth: hci_conn: Fix UAF Write in __hci_acl_create_connection_sync +- Bluetooth: Remove pending ACL connection attempts +- Bluetooth: hci_conn: Only do ACL connections sequentially +- Bluetooth: hci_event: Use HCI error defines instead of magic values +- Bluetooth: qca: If memdump doesn't work, re-enable IBS +- can: kvaser_pciefd: Use a single write when releasing RX buffers +- can: kvaser_pciefd: Move reset of DMA RX buffers to the end of the ISR +- can: kvaser_pciefd: Rename board_irq to pci_irq +- can: kvaser_pciefd: Remove unnecessary comment +- can: kvaser_pciefd: Skip redundant NULL pointer check in ISR +- regulator: core: Stub devm_regulator_bulk_get_const() if !CONFIG_REGULATOR +- platform/x86: dell-smbios: Fix error path in dell_smbios_init() +- ice: Add netif_device_attach/detach into PF reset flow +- igb: Fix not clearing TimeSync interrupts for 82580 +- cifs: Fix FALLOC_FL_ZERO_RANGE to preflush buffered part of target region +- rust: kbuild: fix export of bss symbols +- rust: Use awk instead of recent xargs +- can: mcp251xfd: fix ring configuration when switching from CAN-CC to CAN-FD mode +- can: m_can: Release irq on error in m_can_open +- drm/amdgpu: check for LINEAR_ALIGNED correctly in check_tiling_flags_gfx6 +- pcmcia: Use resource_size function on resource object +- media: qcom: camss: Add check for v4l2_fwnode_endpoint_parse +- Input: ili210x - use kvmalloc() to allocate buffer for firmware update +- PCI: keystone: Add workaround for Errata #i2037 (AM65x SR 1.0) +- ice: Check all ice_vsi_rebuild() errors in function +- vfio/spapr: Always clear TCEs before unsetting the window +- media: vivid: don't set HDMI TX controls if there are no HDMI outputs +- drm/amdgpu: clear RB_OVERFLOW bit when enabling interrupts +- drm/amdgpu: Fix smatch static checker warning +- drm/amd/display: Check HDCP returned status +- usb: uas: set host status byte on data completion error +- wifi: brcmsmac: advertise MFP_CAPABLE to enable WPA3 +- leds: spi-byte: Call of_node_put() on error path +- media: vivid: fix wrong sizeimage value for mplane +- riscv: kprobes: Use patch_text_nosync() for insn slots +- fs/ntfs3: One more reason to mark inode bad +- wifi: iwlwifi: mvm: use IWL_FW_CHECK for link ID check +- netfilter: nf_conncount: fix wrong variable type +- iommu: sun50i: clear bypass register +- x86/kmsan: Fix hook for unaligned accesses +- af_unix: Remove put_pid()/put_cred() in copy_peercred(). +- irqchip/armada-370-xp: Do not allow mapping IRQ 0 and 1 +- accel/habanalabs/gaudi2: unsecure edma max outstanding register +- bpf, verifier: Correct tail_call_reachable for bpf prog +- smack: unix sockets: fix accept()ed socket label +- wifi: ath12k: fix uninitialize symbol error on ath12k_peer_assoc_h_he() +- ALSA: hda: Add input value sanity checks to HDMI channel map controls +- ALSA: control: Apply sanity check of input values for user elements +- drm/i915: Do not attempt to load the GSC multiple times +- nilfs2: fix state management in error path of log writing function +- sched: sch_cake: fix bulk flow accounting logic for host fairness +- ila: call nf_unregister_net_hooks() sooner +- tcp_bpf: fix return value of tcp_bpf_sendmsg() +- Revert "drm/amdgpu: align pp_power_profile_mode with kernel docs" +- x86/apic: Make x2apic_disable() work correctly +- x86/fpu: Avoid writing LBR bit to IA32_XSS unless supported +- net: mctp-serial: Fix missing escapes on transmit +- tracing/timerlat: Add interface_lock around clearing of kthread in stop_kthread() +- tracing: Avoid possible softlockup in tracing_iter_reset() +- tracing/timerlat: Only clear timer if a kthread exists +- mm: vmalloc: ensure vmap_block is initialised before adding to queue +- kexec_file: fix elfcorehdr digest exclusion when CONFIG_CRASH_HOTPLUG=y +- clk: qcom: clk-alpha-pll: Fix the trion pll postdiv set rate API +- clk: qcom: clk-alpha-pll: Fix the pll post div mask +- clk: starfive: jh7110-sys: Add notifier for PLL0 clock +- fuse: fix memory leak in fuse_create_open +- fuse: use unsigned type for getxattr/listxattr size truncation +- fuse: update stats for pages in dropped aux writeback list +- mmc: cqhci: Fix checking of CQHCI_HALT state +- mmc: sdhci-of-aspeed: fix module autoloading +- mmc: dw_mmc: Fix IDMAC operation with pages bigger than 4K +- mmc: core: apply SD quirks earlier during probe +- Bluetooth: MGMT: Ignore keys being loaded with invalid type +- Revert "Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE" +- rust: macros: provide correct provenance when constructing THIS_MODULE +- rust: types: Make Opaque::get const +- nvme-pci: Add sleep quirk for Samsung 990 Evo +- x86/kaslr: Expose and use the end of the physical memory address space +- irqchip/gic-v2m: Fix refcount leak in gicv2m_of_init() +- x86/tdx: Fix data leak in mmio_read() +- ksmbd: Unlock on in ksmbd_tcp_set_interfaces() +- ALSA: hda/realtek: Support mute LED on HP Laptop 14-dq2xxx +- ALSA: hda/realtek: add patch for internal mic in Lenovo V145 +- ALSA: hda/conexant: Add pincfg quirk to enable top speakers on Sirius devices +- KVM: SVM: Don't advertise Bus Lock Detect to guest if SVM support is missing +- KVM: SVM: fix emulation of msr reads/writes of MSR_FS_BASE and MSR_GS_BASE +- net: microchip: vcap: Fix use-after-free error in kunit test +- !12289 CVE-2024-46691 +- usb: typec: ucsi: Move unregister out of atomic section +- !12223 [sync] PR-11910: ext4: dax: Fix inconsistent isize during writing +- ext4: dax: keep orphan list before truncate overflow allocated blocks +- ext4: dax: fix overflowing extents beyond inode size when partially writing +- !12146 mm: page_cache_ra_order: Restore 'PF_MEMALLOC_NOFS' flag in 'fallback' branch +- mm: page_cache_ra_order: Restore 'PF_MEMALLOC_NOFS' flag in 'fallback' branch +- !12090 USB: usbtmc: prevent kernel-usb-infoleak +- USB: usbtmc: prevent kernel-usb-infoleak +- !12286 [openEuler-24.03-LTS][linux-6.6.y sync] Backport 6.6.49-6.6.50 LTS Patches +- i2c: Use IS_REACHABLE() for substituting empty ACPI functions +- virtio_net: Fix napi_skb_cache_put warning +- media: uvcvideo: Enforce alignment of frame and interval +- drm/amd/display: Check BIOS images before it is used +- drm/amd/display: use preferred link settings for dp signal only +- drm/amd/display: Correct the defined value for AMDGPU_DMUB_NOTIFICATION_MAX +- drm/amd/display: added NULL check at start of dc_validate_stream +- drm/amd/display: Don't use fsleep for PSR exit waits on dmub replay +- drm/amdgpu: add lock in kfd_process_dequeue_from_device +- drm/amdgpu: add lock in amdgpu_gart_invalidate_tlb +- drm/amdgpu: add skip_hw_access checks for sriov +- block: remove the blk_flush_integrity call in blk_integrity_unregister +- f2fs: fix to do sanity check on blocks for inline_data inode +- wifi: cfg80211: make hash table duplicates more survivable +- dmaengine: altera-msgdma: properly free descriptor in msgdma_free_descriptor +- dmaengine: altera-msgdma: use irq variant of spin_lock/unlock while invoking callbacks +- gfs2: Revert "Add quota_change type" +- crypto: stm32/cryp - call finalize with bh disabled +- drm/meson: plane: Add error handling +- platform/chrome: cros_ec_lpc: MEC access can use an AML mutex +- smack: tcp: ipv4, fix incorrect labeling +- regmap: spi: Fix potential off-by-one when calculating reserved size +- drm/amdgu: fix Unintentional integer overflow for mall size +- net: remove NULL-pointer net parameter in ip_metrics_convert +- fsnotify: clear PARENT_WATCHED flags lazily +- usb: typec: ucsi: Fix null pointer dereference in trace +- usbip: Don't submit special requests twice +- media: v4l2-cci: Always assign *val +- rcu/nocb: Remove buggy bypass lock contention mitigation +- pwm: xilinx: Fix u32 overflow issue in 32-bit width PWM mode. +- ionic: fix potential irq name truncation +- RDMA/efa: Properly handle unexpected AQ completions +- soc: qcom: smem: Add qcom_smem_bust_hwspin_lock_by_host() +- hwspinlock: Introduce hwspin_lock_bust() +- wifi: mac80211: check ieee80211_bss_info_change_notify() against MLD +- PCI: al: Check IORESOURCE_BUS existence during probe +- cpufreq: scmi: Avoid overflow of target_freq in fast switch +- wifi: iwlwifi: remove fw_running op +- drm/amdgpu: update type of buf size to u32 for eeprom functions +- drm/kfd: Correct pinned buffer handling at kfd restore and validate process +- wifi: rtw89: ser: avoid multiple deinit on same CAM +- drm/amd/pm: check negtive return for table entries +- drm/amd/pm: check specific index for smu13 +- drm/amd/pm: check specific index for aldebaran +- drm/amdgpu/pm: Check input value for CUSTOM profile mode setting on legacy SOCs +- wifi: ath11k: initialize 'ret' in ath11k_qmi_load_file_target_mem() +- wifi: ath12k: initialize 'ret' in ath12k_qmi_load_file_target_mem() +- drm/amdkfd: Reconcile the definition and use of oem_id in struct kfd_topology_device +- drm/amdgpu: fix mc_data out-of-bounds read warning +- drm/amdgpu: Fix out-of-bounds read of df_v1_7_channel_number +- drm/amdkfd: Check debug trap enable before write dbg_ev_file +- drm/amdgpu: Fix the uninitialized variable warning +- drm/amdgpu/pm: Fix uninitialized variable agc_btc_response +- drm/amdgpu/pm: Fix uninitialized variable warning for smu10 +- drm/amd/pm: fix uninitialized variable warnings for vangogh_ppt +- drm/amd/amdgpu: Check tbo resource pointer +- drm/amd/display: Fix Coverity INTEGER_OVERFLOW within decide_fallback_link_setting_max_bw_policy +- drm/amd/display: Spinlock before reading event +- drm/amd/display: Fix Coverity INTEGER_OVERFLOW within dal_gpio_service_create +- drm/amd/display: Fix Coverity INTERGER_OVERFLOW within construct_integrated_info +- drm/amd/display: Check num_valid_sets before accessing reader_wm_sets[] +- drm/amd/display: Stop amdgpu_dm initialize when stream nums greater than 6 +- drm/amdgpu: avoid reading vf2pf info size from FB +- drm/amd/pm: fix uninitialized variable warnings for vega10_hwmgr +- drm/amd/pm: fix warning using uninitialized value of max_vid_step +- drm/amd/pm: fix uninitialized variable warning for smu8_hwmgr +- drm/amd/pm: fix uninitialized variable warning +- drm/amdgpu/pm: Check the return value of smum_send_msg_to_smc +- drm/amdgpu: fix overflowed array index read warning +- drm/amdgpu: Fix uninitialized variable warning in amdgpu_afmt_acr +- selftests: mptcp: join: stop transfer when check is done (part 2.2) +- selftests: mptcp: join: disable get and dump addr checks +- selftests: mptcp: join: test for flush/re-add endpoints +- selftests: mptcp: join: check re-adding init endp with != id +- selftests: mptcp: join: check re-using ID of unused ADD_ADDR +- selftests: mptcp: add explicit test case for remove/readd +- selftests: mptcp: join: cannot rm sf if closed +- selftests: mptcp: declare event macros in mptcp_lib +- selftests: mptcp: userspace pm get addr tests +- selftests: mptcp: dump userspace addrs list +- mptcp: pm: fix RM_ADDR ID for the initial subflow +- mptcp: make pm_remove_addrs_and_subflows static +- ASoC: codecs: ES8326: button detect issue +- ASoC: amd: yc: Support mic on Lenovo Thinkpad E14 Gen 6 +- net: usb: qmi_wwan: add MeiG Smart SRM825L +- dma-debug: avoid deadlock between dma debug vs printk and netconsole +- i2c: Fix conditional for substituting empty ACPI functions +- ASoC: amd: yc: Support mic on HP 14-em0002la +- smb: client: fix FSCTL_GET_REPARSE_POINT against NetApp +- net/mlx5: DR, Fix 'stack guard page was hit' error in dr_rule +- ALSA: seq: ump: Explicitly reset RPN with Null RPN +- ALSA: seq: ump: Transmit RPN/NRPN message at each MSB/LSB data reception +- ALSA: seq: ump: Use the common RPN/bank conversion context +- ALSA: ump: Explicitly reset RPN with Null RPN +- ALSA: ump: Transmit RPN/NRPN message at each MSB/LSB data reception +- ALSA: hda/conexant: Mute speakers at suspend / shutdown +- ALSA: hda/generic: Add a helper to mute speakers at suspend/shutdown +- btrfs: tree-checker: validate dref root and objectid +- scsi: ufs: core: Bypass quick recovery if force reset is needed +- scsi: ufs: core: Check LSDBS cap when !mcq +- drm: panel-orientation-quirks: Add quirk for OrangePi Neo +- drm/fb-helper: Don't schedule_work() to flush frame buffer during panic() +- !12281 [openEuler-24.03-LTS][linux-6.6.y sync] Backport 6.6.48-6.6.49 LTS Patches +- apparmor: fix policy_unpack_test on big endian systems +- arm64: dts: freescale: imx93-tqma9352-mba93xxla: fix typo +- arm64: dts: freescale: imx93-tqma9352: fix CMA alloc-ranges +- arm64: dts: imx93: update default value for snps,clk-csr +- arm64: dts: imx93: add nvmem property for eqos +- arm64: dts: imx93: add nvmem property for fec1 +- arm64: dts: imx8mp-beacon-kit: Fix Stereo Audio on WM8962 +- ARM: dts: omap3-n900: correct the accelerometer orientation +- usb: cdnsp: fix for Link TRB with TC +- usb: cdnsp: fix incorrect index in cdnsp_get_hw_deq function +- usb: core: sysfs: Unmerge @usb3_hardware_lpm_attr_group in remove_power_attributes() +- usb: dwc3: st: add missing depopulate in probe error path +- usb: dwc3: core: Prevent USB core invalid event buffer address access +- usb: dwc3: omap: add missing depopulate in probe error path +- ARM: dts: imx6dl-yapp43: Increase LED current to match the yapp4 HW design +- USB: serial: option: add MeiG Smart SRM825L +- scsi: sd: Ignore command SYNCHRONIZE CACHE error if format in progress +- firmware: qcom: scm: Mark get_wq_ctx() as atomic call +- cdc-acm: Add DISABLE_ECHO quirk for GE HealthCare UI Controller +- soc: qcom: pmic_glink: Fix race during initialization +- soc: qcom: pmic_glink: Actually communicate when remote goes down +- soc: qcom: cmd-db: Map shared memory as WC, not WB +- nfc: pn533: Add poll mod list filling check +- net: busy-poll: use ktime_get_ns() instead of local_clock() +- drm/amd/display: avoid using null object of framebuffer +- sctp: fix association labeling in the duplicate COOKIE-ECHO case +- gtp: fix a potential NULL pointer dereference +- bonding: change ipsec_lock from spin lock to mutex +- bonding: extract the use of real_device into local variable +- bonding: implement xdo_dev_state_free and call it after deletion +- selftests: forwarding: local_termination: Down ports on cleanup +- selftests: forwarding: no_forwarding: Down ports on cleanup +- netfilter: nf_tables_ipv6: consider network offset in netdev/egress validation +- wifi: iwlwifi: fw: fix wgds rev 3 exact size +- netfilter: nf_tables: restore IP sanity checks for netdev/egress +- iommu: Do not return 0 from map_pages if it doesn't do anything +- Bluetooth: hci_core: Fix not handling hibernation actions +- Bluetooth: btnxpuart: Fix random crash seen while removing driver +- Bluetooth: btnxpuart: Handle FW Download Abort scenario +- Bluetooth: btnxpuart: Resolve TX timeout error in power save stress test +- dmaengine: dw: Add memory bus width verification +- dmaengine: dw: Add peripheral bus width verification +- phy: xilinx: phy-zynqmp: Fix SGMII linkup failure on resume +- dmaengine: dw-edma: Do not enable watermark interrupts for HDMA +- dmaengine: dw-edma: Fix unmasking STOP and ABORT interrupts for HDMA +- soundwire: stream: fix programming slave ports for non-continous port maps +- phy: fsl-imx8mq-usb: fix tuning parameter name +- iommufd: Do not allow creating areas without READ or WRITE +- cifs: Fix FALLOC_FL_PUNCH_HOLE support +- mm: Fix missing folio invalidation calls during truncation +- ovl: ovl_parse_param_lowerdir: Add missed ' +- pinctrl: starfive: jh7110: Correct the level trigger configuration of iev register +- pinctrl: mediatek: common-v2: Fix broken bias-disable for PULL_PU_PD_RSEL_TYPE +- ASoC: SOF: amd: Fix for acp init sequence +- ASoC: amd: acp: fix module autoloading +- thermal: of: Fix OF node leak in of_thermal_zone_find() error paths +- thermal: of: Fix OF node leak in thermal_of_trips_init() error path +- of: Introduce for_each_*_child_of_node_scoped() to automate of_node_put() handling +- usb: typec: fix up incorrectly backported "usb: typec: tcpm: unregister existing source caps before re-registration" +- drm/vmwgfx: Fix prime with external buffers +- drm/amdgpu/swsmu: always force a state reprogram on init +- drm/amdgpu: align pp_power_profile_mode with kernel docs +- selftests: mptcp: join: check re-re-adding ID 0 endp +- selftests: mptcp: join: no extra msg if no counter +- selftests: mptcp: join: check removing ID 0 endpoint +- mptcp: pm: ADD_ADDR 0 is not a new address +- mptcp: pm: fix ID 0 endp usage after multiple re-creations +- mptcp: pm: do not remove already closed subflows +- mptcp: pm: send ACK on an active subflow +- mptcp: pm: reset MPC endp ID when re-added +- mptcp: pm: skip connecting to already established sf +- mptcp: pm: reuse ID 0 after delete and re-add +- mptcp: sched: check both backup in retrans +- mptcp: close subflow when receiving TCP+FIN +- net: mana: Fix race of mana_hwc_post_rx_wqe and new hwc response +- wifi: mwifiex: duplicate static structs used in driver instances +- wifi: wfx: repair open network AP mode +- of: Add cleanup.h based auto release via __free(device_node) markings +- pinctrl: single: fix potential NULL dereference in pcs_get_function() +- pinctrl: rockchip: correct RK3328 iomux width flag for GPIO2-B pins +- btrfs: run delayed iputs when flushing delalloc +- LoongArch: Remove the unused dma-direct.h +- ALSA: seq: Skip event type filtering for UMP events +- !12276 mm: mem_reliable: Initialize reliable_nr_page when mm_init() +- mm: mem_reliable: Initialize reliable_nr_page when mm_init() +- !12178 net: stmmac: move the EST lock to struct stmmac_priv +- net: stmmac: move the EST lock to struct stmmac_priv +- !12181 net: ena: Add validation for completion descriptors consistency +- net: ena: Add validation for completion descriptors consistency +- !12255 drm/amd/display: Ensure index calculation will not overflow +- drm/amd/display: Ensure index calculation will not overflow +- !12214 platform/x86: panasonic-laptop: Fix SINF array out of bounds accesses +- platform/x86: panasonic-laptop: Fix SINF array out of bounds accesses +- !12147 wifi: iwlwifi: mvm: don't wait for tx queues if firmware is dead +- wifi: iwlwifi: mvm: don't wait for tx queues if firmware is dead +- !9955 [OLK-6.6]HYGON: CSV3 patch series part 1 (Secure memory management and initialization for CSV3) +- crypto: ccp: Add SET_SMR/SET_SMCR commands for CSV3 +- x86/mm: Manage CSV3 guest's private memory by CMA +- crypto: ccp: Define CSV3 key management command id +- KVM: SEV: Pin SEV guest memory out of CMA area +- !12253 RDMA/hns: Fix flush cqe error when racing with destroy qp +- RDMA/hns: Fix flush cqe error when racing with destroy qp +- !12217 v2 RDMA/hns: Fix new mmaped pages during resetting +- RDMA/hns: Fix new mmaped pages during resetting +- !12216 ACPI/IORT: Add PMCG platform information for HiSilicon HIP10/11 +- ACPI/IORT: Add PMCG platform information for HiSilicon HIP10/11 +- !12209 net/hinic3: fix version showed in ethtool +- net/hinic3: fix version showed in ethtool +- !12218 KVM: x86: Acquire kvm->srcu when handling KVM_SET_VCPU_EVENTS +- KVM: x86: Acquire kvm->srcu when handling KVM_SET_VCPU_EVENTS +- !11667 Adds Nebula S1000 series network snic driver +- Net:nbl_core: Add nbl_core-driver for nebula-matrix S1055AS series smart NIC. +- !12036 KVM: arm64: Add new HiSi CPU type for supporting DVMBM +- KVM: arm64: Add new HiSi CPU type for supporting DVMBM +- !12112 [openEuler-24.03-LTS][linux-6.6.y sync] Backport 6.6.47-6.6.48 LTS Patches +- Revert "s390/dasd: Establish DMA alignment" +- ksmbd: fix race condition between destroy_previous_session() and smb2 operations() +- drm/amdgpu/vcn: not pause dpg for unified queue +- drm/amdgpu/vcn: identify unified queue in sw init +- selftests/bpf: Add a test to verify previous stacksafe() fix +- ALSA: timer: Relax start tick time check for slave timer elements +- igc: Fix qbv tx latency by setting gtxoffset +- drm/panel: nt36523: Set 120Hz fps for xiaomi,elish panels +- drm/msm/mdss: specify cfg bandwidth for SDM670 +- hwmon: (ltc2992) Fix memory leak in ltc2992_parse_dt() +- Revert "drm/amd/display: Validate hw_points_num before using it" +- Revert "usb: gadget: uvc: cleanup request when not in correct state" +- selftests: mptcp: join: check re-using ID of closed subflow +- selftests: mptcp: join: validate fullmesh endp on 1st sf +- mptcp: pm: fullmesh: select the right ID later +- mptcp: pm: only in-kernel cannot have entries with ID 0 +- mptcp: pm: check add_addr_accept_max before accepting new ADD_ADDR +- mptcp: pm: only mark 'subflow' endp as available +- mptcp: pm: remove mptcp_pm_remove_subflow() +- mptcp: pm: re-using ID of unused flushed subflows +- mptcp: pm: re-using ID of unused removed subflows +- mptcp: pm: re-using ID of unused removed ADD_ADDR +- nouveau/firmware: use dma non-coherent allocator +- pmdomain: imx: wait SSAR when i.MX93 power domain on +- pmdomain: imx: scu-pd: Remove duplicated clocks +- mmc: dw_mmc: allow biu and ciu clocks to defer +- mmc: mtk-sd: receive cmd8 data when hs400 tuning fail +- KVM: arm64: Make ICC_*SGI*_EL1 undef in the absence of a vGICv3 +- cxgb4: add forgotten u64 ivlan cast before shift +- Input: i8042 - use new forcenorestore quirk to replace old buggy quirk combination +- Input: i8042 - add forcenorestore quirk to leave controller untouched even on s3 +- HID: wacom: Defer calculation of resolution until resolution_code is known +- MIPS: Loongson64: Set timer mode in cpu-probe +- net: dsa: microchip: fix PTP config failure when using multiple ports +- drm/amdgpu: Validate TA binary size +- ksmbd: the buffer of smb2 query dir response has at least 1 byte +- scsi: core: Fix the return value of scsi_logical_block_count() +- smb: client: ignore unhandled reparse tags +- drm/msm: fix the highest_bank_bit for sc7180 +- drm/msm/mdss: Handle the reg bus ICC path +- drm/msm/mdss: Rename path references to mdp_path +- drm/msm/mdss: switch mdss to use devm_of_icc_get() +- drm/msm/dpu: take plane rotation into account for wide planes +- drm/msm/dpu: try multirect based on mdp clock limits +- drm/msm/dpu: cleanup FB if dpu_format_populate_layout fails +- drm/msm/dp: reset the link phy params before link training +- drm/msm/dpu: move dpu_encoder's connector assignment to atomic_enable() +- drm/msm/dpu: capture snapshot on the first commit_done timeout +- drm/msm/dpu: split dpu_encoder_wait_for_event into two functions +- drm/msm/dpu: drop MSM_ENC_VBLANK support +- drm/msm/dpu: use drmm-managed allocation for dpu_encoder_phys +- drm/msm/dp: fix the max supported bpp logic +- drm/msm/dpu: don't play tricks with debug macros +- net: ovs: fix ovs_drop_reasons error +- net: xilinx: axienet: Fix dangling multicast addresses +- net: xilinx: axienet: Always disable promiscuous mode +- octeontx2-af: Fix CPT AF register offset calculation +- netfilter: flowtable: validate vlan header +- udp: fix receiving fraglist GSO packets +- igb: cope with large MAX_SKB_FRAGS +- dpaa2-switch: Fix error checking in dpaa2_switch_seed_bp() +- ice: fix truesize operations for PAGE_SIZE >= 8192 +- ice: fix ICE_LAST_OFFSET formula +- ice: fix page reuse when PAGE_SIZE is over 8k +- bonding: fix xfrm state handling when clearing active slave +- bonding: fix xfrm real_dev null pointer dereference +- bonding: fix null pointer deref in bond_ipsec_offload_ok +- bonding: fix bond_ipsec_offload_ok return type +- ip6_tunnel: Fix broken GRO +- netfilter: nft_counter: Synchronize nft_counter_reset() against reader. +- netfilter: nft_counter: Disable BH in nft_counter_offload_stats(). +- net: mctp: test: Use correct skb for route input check +- selftests: udpgro: report error when receive failed +- tc-testing: don't access non-existent variable on exception +- net: mscc: ocelot: serialize access to the injection/extraction groups +- net: mscc: ocelot: fix QoS class for injected packets with "ocelot-8021q" +- net: mscc: ocelot: use ocelot_xmit_get_vlan_info() also for FDMA and register injection +- Bluetooth: SMP: Fix assumption of Central always being Initiator +- Bluetooth: hci_core: Fix LE quote calculation +- drm/amdkfd: reserve the BO before validating it +- ALSA: hda/tas2781: Use correct endian conversion +- platform/surface: aggregator: Fix warning when controller is destroyed in probe +- drm/amd/amdgpu: command submission parser for JPEG +- drm/amd/display: fix cursor offset on rotation 180 +- drm/amd/display: Enable otg synchronization logic for DCN321 +- drm/amd/display: Adjust cursor position +- btrfs: send: allow cloning non-aligned extent if it ends at i_size +- btrfs: replace sb::s_blocksize by fs_info::sectorsize +- mm/vmalloc: fix page mapping if vm_area_alloc_pages() with high order fallback to order 0 +- selftests: memfd_secret: don't build memfd_secret test on unsupported arches +- selftests/mm: log run_vmtests.sh results in TAP format +- tools/testing/selftests/mm/run_vmtests.sh: lower the ptrace permissions +- dm suspend: return -ERESTARTSYS instead of -EINTR +- riscv: entry: always initialize regs->a0 to -ENOSYS +- i2c: stm32f7: Add atomic_xfer method to driver +- jfs: define xtree root and page independently +- nvme: fix namespace removal list +- EDAC/skx_common: Allow decoding of SGX addresses +- ionic: check cmd_regs before copying in or out +- ionic: use pci_is_enabled not open code +- hrtimer: Prevent queuing of hrtimer without a function callback +- drm/amdgpu: fix dereference null return value for the function amdgpu_vm_pt_parent +- nvme: use srcu for iterating namespace list +- selftests/bpf: Fix a few tests for GCC related warnings. +- nvmet-rdma: fix possible bad dereference when freeing rsps +- irqchip/gic-v3-its: Remove BUG_ON in its_vpe_irq_domain_alloc +- usb: dwc3: core: Skip setting event buffers for host only controllers +- platform/x86: lg-laptop: fix %s null argument warning +- clocksource: Make watchdog and suspend-timing multiplication overflow safe +- irqchip/renesas-rzg2l: Do not set TIEN and TINT source at the same time +- s390/iucv: fix receive buffer virtual vs physical address confusion +- openrisc: Call setup_memory() earlier in the init sequence +- NFS: avoid infinite loop in pnfs_update_layout. +- nvmet-tcp: do not continue for invalid icreq +- rtc: nct3018y: fix possible NULL dereference +- firmware: cirrus: cs_dsp: Initialize debugfs_root to invalid +- Bluetooth: bnep: Fix out-of-bound access +- nvme: clear caller pointer on identify failure +- usb: gadget: fsl: Increase size of name buffer for endpoints +- f2fs: fix to do sanity check in update_sit_entry +- btrfs: delete pointless BUG_ON check on quota root in btrfs_qgroup_account_extent() +- btrfs: change BUG_ON to assertion in tree_move_down() +- btrfs: send: handle unexpected inode in header process_recorded_refs() +- btrfs: send: handle unexpected data in header buffer in begin_cmd() +- btrfs: handle invalid root reference found in may_destroy_subvol() +- btrfs: push errors up from add_async_extent() +- btrfs: tests: allocate dummy fs_info and root in test_find_delalloc() +- btrfs: change BUG_ON to assertion when checking for delayed_node root +- btrfs: defrag: change BUG_ON to assertion in btrfs_defrag_leaves() +- btrfs: delayed-inode: drop pointless BUG_ON in __btrfs_remove_delayed_item() +- powerpc/boot: Only free if realloc() succeeds +- powerpc/boot: Handle allocation failure in simple_realloc() +- f2fs: stop checkpoint when get a out-of-bounds segment +- rxrpc: Don't pick values out of the wire header when setting up security +- parisc: Use irq_enter_rcu() to fix warning at kernel/context_tracking.c:367 +- memory: stm32-fmc2-ebi: check regmap_read return value +- x86: Increase brk randomness entropy for 64-bit systems +- md: clean up invalid BUG_ON in md_ioctl +- netlink: hold nlk->cb_mutex longer in __netlink_dump_start() +- tick: Move got_idle_tick away from common flags +- clocksource/drivers/arm_global_timer: Guard against division by zero +- accel/habanalabs: fix debugfs files permissions +- virtiofs: forbid newlines in tags +- hrtimer: Select housekeeping CPU during migration +- gpio: sysfs: extend the critical section for unregistering sysfs devices +- drm/lima: set gp bus_stop bit before hard reset +- net/sun3_82586: Avoid reading past buffer in debug output +- wifi: iwlwifi: mvm: avoid garbage iPN +- media: drivers/media/dvb-core: copy user arrays safely +- scsi: lpfc: Initialize status local variable in lpfc_sli4_repost_sgl_list() +- fs: binfmt_elf_efpic: don't use missing interpreter's properties +- media: pci: cx23885: check cx23885_vdev_init() return +- kernfs: fix false-positive WARN(nr_mmapped) in kernfs_drain_open_files +- riscv: blacklist assembly symbols for kprobe +- quota: Remove BUG_ON from dqget() +- wifi: ath12k: Add missing qmi_txn_cancel() calls +- fuse: fix UAF in rcu pathwalks +- afs: fix __afs_break_callback() / afs_drop_open_mmap() race +- btrfs: zlib: fix and simplify the inline extent decompression +- ext4: do not trim the group with corrupted block bitmap +- nvmet-trace: avoid dereferencing pointer too early +- EDAC/skx_common: Filter out the invalid address +- gfs2: Refcounting fix in gfs2_thaw_super +- Bluetooth: hci_conn: Check non NULL function before calling for HFP offload +- evm: don't copy up 'security.evm' xattr +- drm/rockchip: vop2: clear afbc en and transform bit for cluster window at linear mode +- ionic: no fw read when PCI reset failed +- ionic: prevent pci disable of already disabled device +- powerpc/pseries/papr-sysparm: Validate buffer object lengths +- hwmon: (pc87360) Bounds check data->innr usage +- ASoC: SOF: ipc4: check return value of snd_sof_ipc_msg_data +- powerpc/xics: Check return value of kasprintf in icp_native_map_one_cpu +- memory: tegra: Skip SID programming if SID registers aren't set +- drm/msm: Reduce fallout of fence signaling vs reclaim hangs +- arm64: Fix KASAN random tag seed initialization +- powerpc/topology: Check if a core is online +- cpu/SMT: Enable SMT only if a core is online +- rust: fix the default format for CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT +- rust: suppress error messages from CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT +- rust: work around `bindgen` 0.69.0 issue +- hwmon: (ltc2992) Avoid division by zero +- IB/hfi1: Fix potential deadlock on &irq_src_lock and &dd->uctxt_lock +- clk: visconti: Add bounds-checking coverage for struct visconti_pll_provider +- wifi: iwlwifi: check for kmemdup() return value in iwl_parse_tlv_firmware() +- wifi: iwlwifi: fw: Fix debugfs command sending +- wifi: iwlwifi: abort scan when rfkill on but device enabled +- gfs2: setattr_chown: Add missing initialization +- wifi: mac80211: flush STA queues on unauthorization +- scsi: spi: Fix sshdr use +- ASoC: SOF: Intel: hda-dsp: Make sure that no irq handler is pending before suspend +- iommu/arm-smmu-qcom: Add SDM670 MDSS compatible +- media: qcom: venus: fix incorrect return value +- drm/tegra: Zero-initialize iosys_map +- binfmt_misc: cleanup on filesystem umount +- accel/habanalabs: fix bug in timestamp interrupt handling +- accel/habanalabs: export dma-buf only if size/offset multiples of PAGE_SIZE +- accel/habanalabs/gaudi2: unsecure tpc count registers +- media: s5p-mfc: Fix potential deadlock on condlock +- staging: ks7010: disable bh on tx_dev_lock +- drm/amd/display: Validate hw_points_num before using it +- usb: gadget: uvc: cleanup request when not in correct state +- wifi: mt76: fix race condition related to checking tx queue fill status +- staging: iio: resolver: ad2s1210: fix use before initialization +- wifi: ath11k: fix ath11k_mac_op_remain_on_channel() stack usage +- media: radio-isa: use dev_name to fill in bus_info +- drm/amdkfd: Move dma unmapping after TLB flush +- i3c: mipi-i3c-hci: Do not unmap region not mapped for transfer +- i3c: mipi-i3c-hci: Remove BUG() when Ring Abort request times out +- wifi: ath12k: fix WARN_ON during ath12k_mac_update_vif_chan +- drm/bridge: tc358768: Attempt to fix DSI horizontal timings +- s390/smp,mcck: fix early IPI handling +- RDMA/rtrs: Fix the problem of variable not initialized fully +- i2c: riic: avoid potential division by zero +- cgroup: Avoid extra dereference in css_populate_dir() +- wifi: cw1200: Avoid processing an invalid TIM IE +- sched/topology: Handle NUMA_NO_NODE in sched_numa_find_nth_cpu() +- net: ethernet: mtk_wed: check update_wo_rx_stats in mtk_wed_update_rx_stats() +- rcu: Eliminate rcu_gp_slow_unregister() false positive +- rcu: Dump memory object info if callback function is invalid +- mm: Remove kmem_valid_obj() +- wifi: iwlwifi: mvm: fix recovery flow in CSA +- wifi: mac80211: fix BA session teardown race +- wifi: cfg80211: check wiphy mutex is held for wdev mutex +- wifi: mac80211: lock wiphy in IP address notifier +- ASoC: cs35l45: Checks index of cs35l45_irqs[] +- ssb: Fix division by zero issue in ssb_calc_clock_rate +- drm/amdgpu: access RLC_SPM_MC_CNTL through MMIO in SRIOV runtime +- drm/amd/amdgpu/imu_v11_0: Increase buffer size to ensure all possible values can be stored +- drm/amd/pm: fix error flow in sensor fetching +- ALSA: hda/realtek: Fix noise from speakers on Lenovo IdeaPad 3 15IAU7 +- gpio: mlxbf3: Support shutdown() function +- netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests +- netfilter: nf_tables: Introduce nf_tables_getobj_single +- netfilter: nf_tables: Carry reset boolean in nft_obj_dump_ctx +- netfilter: nf_tables: nft_obj_filter fits into cb->ctx +- netfilter: nf_tables: Carry s_idx in nft_obj_dump_ctx +- netfilter: nf_tables: A better name for nft_obj_filter +- netfilter: nf_tables: Unconditionally allocate nft_obj_filter +- netfilter: nf_tables: Drop pointless memset in nf_tables_dump_obj +- netfilter: nf_tables: Audit log dump reset after the fact +- netfilter: nf_queue: drop packets with cloned unconfirmed conntracks +- netfilter: flowtable: initialise extack before use +- netfilter: allow ipv6 fragments to arrive on different devices +- tcp: Update window clamping condition +- mptcp: correct MPTCP_SUBFLOW_ATTR_SSN_OFFSET reserved size +- mlxbf_gige: disable RX filters until RX path initialized +- net: ethernet: mtk_wed: fix use-after-free panic in mtk_wed_setup_tc_block_cb() +- net: dsa: vsc73xx: check busy flag in MDIO operations +- net: dsa: vsc73xx: use read_poll_timeout instead delay loop +- net: dsa: vsc73xx: pass value in phy_write operation +- net: axienet: Fix register defines comment description +- atm: idt77252: prevent use after free in dequeue_rx() +- net/mlx5e: Correctly report errors for ethtool rx flows +- igc: Fix reset adapter logics when tx mode change +- igc: Fix qbv_config_change_errors logics +- igc: Fix packet still tx after gate close by reducing i226 MAC retry buffer +- bpf: Fix updating attached freplace prog in prog_array map +- s390/uv: Panic for set and remove shared access UVC errors +- drm/amdgpu/jpeg4: properly set atomics vmid field +- drm/amdgpu/jpeg2: properly set atomics vmid field +- memcg_write_event_control(): fix a user-triggerable oops +- drm/amdgpu: Actually check flags for all context ops. +- btrfs: tree-checker: add dev extent item checks +- btrfs: zoned: properly take lock to read/update block group's zoned variables +- btrfs: tree-checker: reject BTRFS_FT_UNKNOWN dir type +- mm/memory-failure: use raw_spinlock_t in struct memory_failure_cpu +- selinux: add the processing of the failure of avc_add_xperms_decision() +- selinux: fix potential counting error in avc_add_xperms_decision() +- wifi: brcmfmac: cfg80211: Handle SSID based pmksa deletion +- net: mana: Fix RX buf alloc_size alignment and atomic op panic +- i2c: qcom-geni: Add missing geni_icc_disable in geni_i2c_runtime_resume +- btrfs: rename bitmap_set_bits() -> btrfs_bitmap_set_bits() +- dm persistent data: fix memory allocation failure +- dm resume: don't return EINVAL when signalled +- arm64: ACPI: NUMA: initialize all values of acpi_early_node_map to NUMA_NO_NODE +- ACPI: EC: Evaluate _REG outside the EC scope more carefully +- ACPICA: Add a depth argument to acpi_execute_reg_methods() +- riscv: change XIP's kernel_map.size to be size of the entire kernel +- KVM: s390: fix validity interception issue when gisa is switched off +- s390/dasd: fix error recovery leading to data corruption on ESE devices +- ALSA: hda/tas2781: fix wrong calibrated data order +- thunderbolt: Mark XDomain as unplugged when router is removed +- xhci: Fix Panther point NULL pointer deref at full-speed re-enumeration +- ALSA: usb-audio: Support Yamaha P-125 quirk entry +- ALSA: usb-audio: Add delay quirk for VIVO USB-C-XE710 HEADSET +- char: xillybus: Refine workqueue handling +- char: xillybus: Don't destroy workqueue from work item running on it +- selinux: revert our use of vma_is_initial_heap() +- Revert "usb: typec: tcpm: clear pd_event queue in PORT_RESET" +- Revert "misc: fastrpc: Restrict untrusted app to attach to privileged PD" +- Revert "ACPI: EC: Evaluate orphan _REG under EC device" +- tty: atmel_serial: use the correct RTS flag. +- !12087 arm64: acpi: Harden get_cpu_for_acpi_id() against missing CPU entry +- arm64: acpi: Harden get_cpu_for_acpi_id() against missing CPU entry +- !6996 sched/fair: Optimize performance by inlining cpu_util_without() and cpu_util() +- sched/fair: Optimize performance by inlining cpu_util_without() and cpu_util() +- !12080 btrfs: clean up our handling of refs == 0 in snapshot delete +- btrfs: clean up our handling of refs == 0 in snapshot delete +- !12052 drm/amdgpu: the warning dereferencing obj for nbio_v7_4 +- drm/amdgpu: the warning dereferencing obj for nbio_v7_4 +- !12082 userfaultfd: don't BUG_ON() if khugepaged yanks our page table +- userfaultfd: don't BUG_ON() if khugepaged yanks our page table +- !12077 ELF: fix kernel.randomize_va_space double read +- ELF: fix kernel.randomize_va_space double read +- !12068 usb: gadget: aspeed_udc: validate endpoint index for ast udc +- usb: gadget: aspeed_udc: validate endpoint index for ast udc +- !12057 netfilter: nft_socket: fix sk refcount leaks +- netfilter: nft_socket: fix sk refcount leaks +- !11954 drm/amdgpu: fix the waring dereferencing hive +- drm/amdgpu: fix the waring dereferencing hive +- !12059 mptcp: pm: Fix uaf in __timer_delete_sync +- mptcp: pm: Fix uaf in __timer_delete_sync +- !12058 net: dpaa: Pad packets to ETH_ZLEN +- net: dpaa: Pad packets to ETH_ZLEN +- !12076 drm/bridge: tc358767: Check if fully initialized before signalling HPD event via IRQ +- drm/bridge: tc358767: Check if fully initialized before signalling HPD event via IRQ +- !11966 drm/amd/pm: Fix negative array index read +- drm/amd/pm: Fix negative array index read + +' for pr_err +* Thu Oct 10 2024 ZhangPeng - 6.6.0-46.0.0.51 +- !12061 net/mlx5: Fix bridge mode operations when there are no VFs +- net/mlx5: Fix bridge mode operations when there are no VFs +- !12074 drm/amd/display: Check index for aux_rd_interval before using +- drm/amd/display: Check index for aux_rd_interval before using +- !12063 cpufreq: intel_pstate: Revise global turbo disable check +- cpufreq: intel_pstate: Revise global turbo disable check +- !12051 um: line: always fill *error_out in setup_one_line() +- um: line: always fill *error_out in setup_one_line() +- !12023 ASoC: meson: axg-card: fix 'use-after-free' +- ASoC: meson: axg-card: fix 'use-after-free' +- !12022 drm/amd/display: Check gpio_id before used as array index +- drm/amd/display: Check gpio_id before used as array index +- !12049 drm/amd/display: Skip inactive planes within ModeSupportAndSystemConfiguration +- drm/amd/display: Skip inactive planes within ModeSupportAndSystemConfiguration +- !11949 mptcp: pm: only decrement add_addr_accepted for MPJ req +- mptcp: pm: only decrement add_addr_accepted for MPJ req +- !11763 [OLK-6.6] Intel: Backport to support Intel IFS(In Field Scan) SBAF on GNR +- platform/x86/intel/ifs: Fix SBAF title underline length +- trace: platform/x86/intel/ifs: Add SBAF trace support +- platform/x86/intel/ifs: Add SBAF test support +- platform/x86/intel/ifs: Add SBAF test image loading support +- platform/x86/intel/ifs: Refactor MSR usage in IFS test code +- selftests: ifs: verify IFS ARRAY BIST functionality +- selftests: ifs: verify IFS scan test functionality +- selftests: ifs: verify test image loading functionality +- selftests: ifs: verify test interfaces are created by the driver +- platform/x86/intel/ifs: Disable irq during one load stage +- platform/x86/intel/ifs: trace: display batch num in hex +- platform/x86/intel/ifs: Classify error scenarios correctly +- platform/x86/intel/ifs: Remove unnecessary initialization of 'ret' +- platform/x86/intel/ifs: Add an entry rendezvous for SAF +- platform/x86/intel/ifs: Replace the exit rendezvous with an entry rendezvous for ARRAY_BIST +- platform/x86/intel/ifs: Add current batch number to trace output +- platform/x86/intel/ifs: Trace on all HT threads when executing a test +- !12039 drm/amd/display: Stop amdgpu_dm initialize when link nums greater than max_links +- drm/amd/display: Stop amdgpu_dm initialize when link nums greater than max_links +- !12033 sysctl: always initialize i_uid/i_gid +- sysctl: always initialize i_uid/i_gid +- !12014 dma-buf: heaps: Fix off-by-one in CMA heap fault handler +- dma-buf: heaps: Fix off-by-one in CMA heap fault handler +- !12009 rtmutex: Drop rt_mutex::wait_lock before scheduling +- rtmutex: Drop rt_mutex::wait_lock before scheduling +- !11617 v2 Fix VSYNC referencing an unmapped VPE on GIC v4.0/v4.1 +- irqchip/gic-v3-its: Fix VSYNC referencing an unmapped VPE on GIC v4.0 +- irqchip/gic-v3-its: Fix VSYNC referencing an unmapped VPE on GIC v4.1 +- !12016 perf/x86/intel: Limit the period on Haswell +- perf/x86/intel: Limit the period on Haswell +- !12017 cppc_cpufreq: Fix possible null pointer dereference +- cppc_cpufreq: Fix possible null pointer dereference +- !11995 drm/amd/display: Assign linear_pitch_alignment even for VM +- drm/amd/display: Assign linear_pitch_alignment even for VM +- !11796 bpf: Take return from set_memory_rox() into account with bpf_jit_binary_lock_ro() +- bpf: Take return from set_memory_rox() into account with bpf_jit_binary_lock_ro() +- !12004 spi: rockchip: Resolve unbalanced runtime PM / system PM handling +- spi: rockchip: Resolve unbalanced runtime PM / system PM handling +- !12000 nvmet-tcp: fix kernel crash if commands allocation fails +- nvmet-tcp: fix kernel crash if commands allocation fails +- !11969 drm/amd/display: Run DC_LOG_DC after checking link->link_enc +- drm/amd/display: Run DC_LOG_DC after checking link->link_enc +- !11963 serial: sc16is7xx: fix invalid FIFO access with special register set +- serial: sc16is7xx: fix invalid FIFO access with special register set +- !11985 Fix CVE-2024-46845 +- tracing/osnoise: Fix build when timerlat is not enabled +- tracing/timerlat: Only clear timer if a kthread exists +- !11909 ksmbd: unset the binding mark of a reused connection +- ksmbd: unset the binding mark of a reused connection +- !11983 wifi: ath12k: fix firmware crash due to invalid peer nss +- wifi: ath12k: fix firmware crash due to invalid peer nss +- !11984 drm/amd/display: Add array index check for hdcp ddc access +- drm/amd/display: Add array index check for hdcp ddc access +- !11989 drm/amd/display: Fix index may exceed array range within fpu_update_bw_bounding_box +- drm/amd/display: Fix index may exceed array range within fpu_update_bw_bounding_box +- !11992 scsi: lpfc: Handle mailbox timeouts in lpfc_get_sfp_info +- scsi: lpfc: Handle mailbox timeouts in lpfc_get_sfp_info +- !11979 CVE-2024-46814 +- drm/amd/display: Check msg_id before processing transcation +- !11960 scsi: ufs: core: Remove SCSI host only if added +- scsi: ufs: core: Remove SCSI host only if added +- !11944 drm/amdgpu: Fix the warning division or modulo by zero +- drm/amdgpu: Fix the warning division or modulo by zero +- !11971 sched: Support to enable/disable dynamic_affinity +- sched: Support to enable/disable dynamic_affinity +- !11951 net: phy: Fix missing of_node_put() for leds +- net: phy: Fix missing of_node_put() for leds +- !11956 Fix CVE-2024-44958 6.6 +- sched/smt: Fix unbalance sched_smt_present dec/inc +- sched/smt: Introduce sched_smt_present_inc/dec() helper +- !11945 btrfs: don't BUG_ON on ENOMEM from btrfs_lookup_extent_info() in walk_down_proc() +- btrfs: don't BUG_ON on ENOMEM from btrfs_lookup_extent_info() in walk_down_proc() +- !11919 btrfs: fix race between direct IO write and fsync when using same fd +- btrfs: fix race between direct IO write and fsync when using same fd +- !11920 hwmon: (lm95234) Fix underflows seen when writing limit attributes +- hwmon: (lm95234) Fix underflows seen when writing limit attributes +- !11820 powerpc/qspinlock: Fix deadlock in MCS queue +- powerpc/qspinlock: Fix deadlock in MCS queue +- !11915 ethtool: check device is present when getting link settings +- ethtool: check device is present when getting link settings +- !11936 btrfs: remove NULL transaction support for btrfs_lookup_extent_info() +- btrfs: remove NULL transaction support for btrfs_lookup_extent_info() +- !11929 Merge some hns RoCE patches from the mainline to OLK-6.6 +- RDMA/hns: Fix the overflow risk of hem_list_calc_ba_range() +- RDMA/hns: Fix Use-After-Free of rsv_qp on HIP08 +- Revert "RDMA/hns: Fix Use-After-Free of rsv_qp" +- Revert "RDMA/hns: Fix the overflow risk of hem_list_calc_ba_range()" +- !11912 smb: client: fix double put of @cfile in smb2_set_path_size() +- smb: client: fix double put of @cfile in smb2_set_path_size() +- !11908 HID: amd_sfh: free driver_data after destroying hid device +- HID: amd_sfh: free driver_data after destroying hid device +- !11926 nilfs2: protect references to superblock parameters exposed in sysfs +- nilfs2: protect references to superblock parameters exposed in sysfs +- !11927 hwmon: (hp-wmi-sensors) Check if WMI event data exists +- hwmon: (hp-wmi-sensors) Check if WMI event data exists +- !11844 fix CVE-2024-46771 +- can: bcm: Clear bo->bcm_proc_read after remove_proc_entry(). +- can: bcm: Remove proc entry when dev is unregistered. +- !11885 pci/hotplug/pnv_php: Fix hotplug driver crash on Powernv +- pci/hotplug/pnv_php: Fix hotplug driver crash on Powernv +- !11795 i2c: tegra: Do not mark ACPI devices as irq safe +- i2c: tegra: Do not mark ACPI devices as irq safe +- !11804 drm/amdgpu: Fix out-of-bounds write warning +- drm/amdgpu: Fix out-of-bounds write warning +- !11901 scsi: aacraid: Fix double-free on probe failure +- scsi: aacraid: Fix double-free on probe failure +- !11859 char: xillybus: Check USB endpoints when probing device +- char: xillybus: Check USB endpoints when probing device +- !11865 pktgen: use cpus_read_lock() in pg_net_init() +- pktgen: use cpus_read_lock() in pg_net_init() +- !11876 btrfs: handle errors from btrfs_dec_ref() properly +- btrfs: handle errors from btrfs_dec_ref() properly +- !11893 tracing/osnoise: Use a cpumask to know what threads are kthreads +- tracing/osnoise: Use a cpumask to know what threads are kthreads +- !11840 userfaultfd: fix checks for huge PMDs +- userfaultfd: fix checks for huge PMDs +- !11891 wifi: rtw88: usb: schedule rx work after everything is set up +- wifi: rtw88: usb: schedule rx work after everything is set up +- !11860 VMCI: Fix use-after-free when removing resource in vmci_resource_remove() +- VMCI: Fix use-after-free when removing resource in vmci_resource_remove() +- !11870 NFSD: Reset cb_seq_status after NFS4ERR_DELAY +- NFSD: Reset cb_seq_status after NFS4ERR_DELAY +- !11874 fix CVE-2024-46701 +- libfs: fix infinite directory reads for offset dir +- fs: fix kabi kroken in struct offset_ctx +- libfs: Convert simple directory offsets to use a Maple Tree +- test_maple_tree: testing the cyclic allocation +- maple_tree: Add mtree_alloc_cyclic() +- libfs: Add simple_offset_empty() +- libfs: Define a minimum directory offset +- libfs: Re-arrange locking in offset_iterate_dir() +- !11689 smb: client: fix double put of @cfile in smb2_rename_path() +- smb: client: fix double put of @cfile in smb2_rename_path() +- !11883 usb: dwc3: st: fix probed platform device ref count on probe error path +- usb: dwc3: st: fix probed platform device ref count on probe error path +- !11884 PCI: Add missing bridge lock to pci_bus_lock() +- PCI: Add missing bridge lock to pci_bus_lock() +- !11862 hwmon: (w83627ehf) Fix underflows seen when writing limit attributes +- hwmon: (w83627ehf) Fix underflows seen when writing limit attributes +- !11758 smb/client: avoid dereferencing rdata=NULL in smb2_new_read_req() +- smb/client: avoid dereferencing rdata=NULL in smb2_new_read_req() +- !11857 arm64/mpam: Fix redefined reference of 'mpam_detect_is_enabled' +- arm64/mpam: Fix redefined reference of 'mpam_detect_is_enabled' +- !11823 mmc: mmc_test: Fix NULL dereference on allocation failure +- mmc: mmc_test: Fix NULL dereference on allocation failure +- !11819 uio_hv_generic: Fix kernel NULL pointer dereference in hv_uio_rescind +- uio_hv_generic: Fix kernel NULL pointer dereference in hv_uio_rescind +- !11495 ext4: Fix race in buffer_head read fault injection +- ext4: Fix race in buffer_head read fault injection +- !11845 bpf: verifier: prevent userspace memory access +- bpf: verifier: prevent userspace memory access +- !11748 ASoC: dapm: Fix UAF for snd_soc_pcm_runtime object +- ASoC: dapm: Fix UAF for snd_soc_pcm_runtime object +- !11624 Fix iBMA bug and change version +- BMA: Fix edma driver initialization problem and change the version number. +- !11850 misc: fastrpc: Fix double free of 'buf' in error path +- misc: fastrpc: Fix double free of 'buf' in error path +- !11655 drm/amd/display: Check denominator pbn_div before used +- drm/amd/display: Check denominator pbn_div before used +- !11686 udf: Avoid excessive partition lengths +- udf: Avoid excessive partition lengths +- !11685 binder: fix UAF caused by offsets overwrite +- binder: fix UAF caused by offsets overwrite +- !11798 CVE-2024-46784 +- net: mana: Fix error handling in mana_create_txq/rxq's NAPI cleanup +- net: mana: Fix doorbell out of order violation and avoid unnecessary doorbell rings +- !11814 selinux,smack: don't bypass permissions check in inode_setsecctx hook +- selinux,smack: don't bypass permissions check in inode_setsecctx hook +- !11811 apparmor: fix possible NULL pointer dereference +- apparmor: fix possible NULL pointer dereference +- !11681 net/mlx5e: SHAMPO, Fix incorrect page release +- net/mlx5e: SHAMPO, Fix incorrect page release +- !11679 wifi: mwifiex: Do not return unused priv in mwifiex_get_priv_by_id() +- wifi: mwifiex: Do not return unused priv in mwifiex_get_priv_by_id() +- !11672 netem: fix return value if duplicate enqueue fails +- netem: fix return value if duplicate enqueue fails +- !11783 mm: hwpoison: two more poison recovery +- mm: support poison recovery from copy_present_page() +- mm: support poison recovery from do_cow_fault() +- !11787 nilfs2: fix missing cleanup on rollforward recovery error +- nilfs2: fix missing cleanup on rollforward recovery error +- !11744 powerpc/rtas: Prevent Spectre v1 gadget construction in sys_rtas() +- powerpc/rtas: Prevent Spectre v1 gadget construction in sys_rtas() +- !11766 drm/amd/display: Check denominator crb_pipes before used +- drm/amd/display: Check denominator crb_pipes before used +- !11790 efi/libstub: add checking validity of memory regions +- efi/libstub: add checking validity of memory regions +- !11802 can: mcp251x: fix deadlock if an interrupt occurs during mcp251x_open +- can: mcp251x: fix deadlock if an interrupt occurs during mcp251x_open +- !11747 [OLK 6.6] some bugfixes for hns3 +- net: hns3: fix concurrent setting vlan filter issue +- net: hns3: fix snprintf() is printing too much problem +- net: hns3: make sure ptp clock is unregister and freed if hclge_ptp_get_cycle returns an error +- net: hns3: fix spelling mistake "reg_um" -> "reg_num" +- net: hns3: fixed hclge_fetch_pf_reg accesses bar space out of bounds issue +- net: hns3:support enable or disable pfc strom prevent +- net: hns3: fix wrong use of semaphore up + +* Wed Sep 25 2024 ZhangPeng - 6.6.0-44.0.0.50 +- !11769 tools: move alignment-related macros to new +- tools: move alignment-related macros to new +- !11753 driver: iio: add missing checks on iio_info's callback access +- driver: iio: add missing checks on iio_info's callback access +- !11740 hwmon: (adc128d818) Fix underflows seen when writing limit attributes +- hwmon: (adc128d818) Fix underflows seen when writing limit attributes +- !11733 Input: MT - limit max slots +- Input: MT - limit max slots +- !11757 arm64/mpam: Check mpam_detect_is_enabled() before accessing MPAM registers +- arm64/mpam: Check mpam_detect_is_enabled() before accessing MPAM registers +- Revert "arm64: head.S: Initialise MPAM EL2 registers and disable traps" +- !11543 Fix CVE-2024-45025 +- fix bitmap corruption on close_range() with CLOSE_RANGE_UNSHARE +- bitmap: introduce generic optimized bitmap_size() +- fs/ntfs3: add prefix to bitmap_size() and use BITS_TO_U64() +- s390/cio: rename bitmap_size() -> idset_bitmap_size() +- !11713 btrfs: fix qgroup reserve leaks in cow_file_range +- btrfs: fix qgroup reserve leaks in cow_file_range +- !11725 Squashfs: sanity check symbolic link size +- Squashfs: sanity check symbolic link size +- !11715 btrfs: replace BUG_ON() with error handling at update_ref_for_cow() +- btrfs: replace BUG_ON() with error handling at update_ref_for_cow() +- !11714 CVE-2024-46751 +- btrfs: don't BUG_ON() when 0 reference count at btrfs_lookup_extent_info() +- btrfs: reduce nesting for extent processing at btrfs_lookup_extent_info() +- btrfs: remove superfluous metadata check at btrfs_lookup_extent_info() +- !11717 CVE-2024-43904 +- drm/amd/display: Add null checks for 'stream' and 'plane' before dereferencing +- !11718 CVE-2024-41008 +- drm/amdgpu: change vm->task_info handling +- !11691 sch/netem: fix use after free in netem_dequeue +- sch/netem: fix use after free in netem_dequeue +- !11719 rtla/osnoise: Prevent NULL dereference in error handling +- rtla/osnoise: Prevent NULL dereference in error handling +- !11626 smb/server: fix potential null-ptr-deref of lease_ctx_info in smb2_open() +- smb/server: fix potential null-ptr-deref of lease_ctx_info in smb2_open() +- !11651 large folio: Performance and bugfix +- mm: remove invalidate_inode_page() +- mm: convert isolate_page() to mf_isolate_folio() +- mm: convert soft_offline_in_use_page() to use a folio +- mm: use mapping_evict_folio() in truncate_error_page() +- mm: convert __do_fault() to use a folio +- mm: make mapping_evict_folio() the preferred way to evict clean folios +- tmpfs: fault in smaller chunks if large folio allocation not allowed +- mm,tmpfs: consider end of file write in shmem_is_huge +- mm: shmem: move shmem_huge_global_enabled() into shmem_allowable_huge_orders() +- mm: shmem: rename shmem_is_huge() to shmem_huge_global_enabled() +- mm: shmem: simplify the suitable huge orders validation for tmpfs +- !11644 drm/amdgpu: fix dereference after null check +- drm/amdgpu: fix dereference after null check +- !11675 【OLK 6.6】net: hns3: some bugfixes for hns3 driver +- net: hns3: Resolved the issue that the debugfs query result is inconsistent. +- net: hns3: fixed reset failure issues caused by the incorrect reset type +- net: hns3: fix missing features due to dev->features configuration too early +- net: hns3: fix a deadlock problem when config TC during resetting +- net: hns3: add sync command to sync io-pgtable +- net: hns3: default enable tx bounce buffer when smmu enabled +- net: hns3: don't add the len of vlan head if skb_vlan_pop failed +- net: hns3: void array out of bound when loop tnl_num +- net: hns3: use correct release function during uninitialization +- net: hns3: delete redundant enabling actions for Layer 2 fowarding +- !11721 v3 mm/migration: do not folio copy in MIGRATE_SYNC_NO_COPY mode +- mm/migration: do not folio copy in MIGRATE_SYNC_NO_COPY mode +- !8819 Add support for Hygon model 7h processors +- perf/x86/uncore: Add L3 PMU support for Hygon family 18h model 7h +- EDAC/amd64: Add support for Hygon family 18h model 7h +- x86/amd_nb: Add support for Hygon family 18h model 7h +- !11157 [OLK-6.6] Support Hygon Trusted Key Management run on CSV Guest +- drivers/crypto/ccp: add ioctl API to pin TKM hugepage +- driver/crypto/ccp: fix vtkm without C-bit when host SME deactivate +- drivers/crypto/ccp: support TKM run on CSV +- drivers/crypto/ccp: remove multi-level pointers processing for vpsp +- !11669 cgroup-psi-add-PSI_STATE_LAST-for-kabi-reserve +- cgroup/psi: add PSI_STATE_LAST for kabi reserve +- !11666 drm/amd/pm: fix the Out-of-bounds read warning +- drm/amd/pm: fix the Out-of-bounds read warning +- !11607 tty: serial: fsl_lpuart: mark last busy before uart_add_one_port +- tty: serial: fsl_lpuart: mark last busy before uart_add_one_port +- !11646 net: hns3: fix a deadlock problem when config TC during resetting +- net: hns3: fix a deadlock problem when config TC during resetting +- !11648 vsock: fix recursive ->recvmsg calls +- vsock: fix recursive ->recvmsg calls +- !11656 fix CVE-2024-46714 +- drm/amd/display: Skip wbscl_set_scaler_filter if filter is null +- !11631 fix CVE-2024-46723 +- drm/amdgpu: fix ucode out-of-bounds read warning +- !11642 HID: cougar: fix slab-out-of-bounds Read in cougar_report_fixup +- HID: cougar: fix slab-out-of-bounds Read in cougar_report_fixup +- !11638 Fix CVE-2024-44991 +- tcp: do not export tcp_twsk_purge() +- tcp: prevent concurrent execution of tcp_sk_exit_batch +- tcp/dccp: do not care about families in inet_twsk_purge() +- tcp/dccp: bypass empty buckets in inet_twsk_purge() +- !11608 v3 arm64: perf: Add support for event counting threshold +- perf: arm_pmuv3: Avoid assigning fixed cycle counter with threshold +- arm: perf: Fix ARCH=arm build with GCC +- Revert "perf/arm_dmc620: Remove duplicate format attribute #defines" +- Documentation: arm64: Document the PMU event counting threshold feature +- arm64: perf: Add support for event counting threshold +- arm: pmu: Move error message and -EOPNOTSUPP to individual PMUs +- perf/arm_dmc620: Remove duplicate format attribute #defines +- arm: pmu: Share user ABI format mechanism with SPE +- arm64: perf: Include threshold control fields in PMEVTYPER mask +- arm: perf: Convert remaining fields to use GENMASK +- arm: perf: Use GENMASK for PMMIR fields +- arm: perf/kvm: Use GENMASK for ARMV8_PMU_PMCR_N +- arm: perf: Remove inlines from arm_pmuv3.c +- drivers: perf: arm_pmuv3: Add new macro PMUV3_INIT_MAP_EVENT() +- KVM: arm64: PMU: Add a helper to read a vCPU's PMCR_EL0 +- KVM: arm64: Add PMU event filter bits required if EL3 is implemented +- KVM: arm64: Make PMEVTYPER_EL0.NSH RES0 if EL2 isn't advertised +- drivers: perf: arm_pmuv3: Drop some unused arguments from armv8_pmu_init() +- drivers: perf: arm_pmuv3: Read PMMIR_EL1 unconditionally +- !11629 CVE-2024-46785 +- eventfs: Use list_del_rcu() for SRCU protected list variable +- !11641 mm: set hugepage to false when anon mthp allocation +- mm: set hugepage to false when anon mthp allocation +- !11559 mm/ksm: fix possible UAF of stable_node +- mm/ksm: fix possible UAF of stable_node +- !11613 Input: uinput - reject requests with unreasonable number of slots +- Input: uinput - reject requests with unreasonable number of slots +- !11460 mptcp: pm: avoid possible UaF when selecting endp +- mptcp: pm: avoid possible UaF when selecting endp +- !11598 net/mlx5e: Take state lock during tx timeout reporter +- net/mlx5e: Take state lock during tx timeout reporter +- !11618 RDMA/hns: Fix ah error counter in sw stat not increasing +- RDMA/hns: Fix ah error counter in sw stat not increasing +- !11554 Some patches of RDMA from Linux to openEuler-6.6 +- RDMA/hns: Fix restricted __le16 degrades to integer issue +- RDMA/hns: Optimize hem allocation performance +- RDMA/hns: Fix 1bit-ECC recovery address in non-4K OS +- RDMA/hns: Fix VF triggering PF reset in abnormal interrupt handler +- RDMA/hns: Fix spin_unlock_irqrestore() called with IRQs enabled +- !11566 v2 tracefs: Use generic inode RCU for synchronizing freeing +- tracefs: Use generic inode RCU for synchronizing freeing +- !11609 fscache: delete fscache_cookie_lru_timer when fscache exits to avoid UAF +- fscache: delete fscache_cookie_lru_timer when fscache exits to avoid UAF +- !11474 fs/netfs/fscache_cookie: add missing "n_accesses" check +- fs/netfs/fscache_cookie: add missing "n_accesses" check +- !11563 iommu: Restore lost return in iommu_report_device_fault() +- iommu: Restore lost return in iommu_report_device_fault() +- !11569 support poison recover from migrate folio +- fs: hugetlbfs: support poisoned recover from hugetlbfs_migrate_folio() +- mm: migrate: support poisoned recover from migrate folio +- mm: migrate: split folio_migrate_mapping() +- mm: add folio_mc_copy() +- mm: move memory_failure_queue() into copy_mc_[user]_highpage() +- mm: migrate: remove migrate_folio_extra() +- mm: migrate_device: unify migrate folio for MIGRATE_SYNC_NO_COPY +- mm: migrate: simplify __buffer_migrate_folio() +- !8822 Add support for Hygon model 10h processors +- ALSA: hda: Add support for Hygon family 18h model 10h HD-Audio +- hwmon/k10temp: Add support for Hygon family 18h model 10h +- EDAC/amd64: Add support for Hygon family 18h model 10h +- x86/amd_nb: Add support for Hygon family 18h model 10h +- x86/cpu: Get LLC ID for Hygon family 18h model 10h +- !11594 gtp: pull network headers in gtp_dev_xmit() +- gtp: pull network headers in gtp_dev_xmit() +- !11573 btrfs: fix a use-after-free when hitting errors inside btrfs_submit_chunk() +- btrfs: fix a use-after-free when hitting errors inside btrfs_submit_chunk() +- !11585 vfs: Don't evict inode under the inode lru traversing context +- vfs: Don't evict inode under the inode lru traversing context +- !11461 bnxt_en: Fix double DMA unmapping for XDP_REDIRECT +- bnxt_en: Fix double DMA unmapping for XDP_REDIRECT + +* Wed Sep 18 2024 ZhangPeng - 6.6.0-42.0.0.49 +- !11556 bpf: Fix a kernel verifier crash in stacksafe() +- bpf: Fix a kernel verifier crash in stacksafe() +- !11496 virtcca feature:Fix warnings +- virtcca feature: fix warnings +- !11531 [OLK-6.6]Some updates for HiSilicon PCIe PMU +- drivers/perf: hisi_pcie: Export supported Root Ports [bdf_min, bdf_max] +- drivers/perf: hisi_pcie: Fix TLP headers bandwidth counting +- drivers/perf: hisi_pcie: Record hardware counts correctly +- !11546 ata: libata: Fix memory leak for error path in ata_host_alloc() +- ata: libata: Fix memory leak for error path in ata_host_alloc() +- !11551 mm/memory_hotplug: prevent accessing by index=-1 +- mm/memory_hotplug: prevent accessing by index=-1 +- !11522 ipv6: prevent UAF in ip6_send_skb() +- ipv6: prevent UAF in ip6_send_skb() +- !11518 ipv6: fix possible UAF in ip6_finish_output2() +- ipv6: fix possible UAF in ip6_finish_output2() +- !11515 net: dsa: mv88e6xxx: Fix out-of-bound access +- net: dsa: mv88e6xxx: Fix out-of-bound access +- !11513 ipv6: prevent possible UAF in ip6_xmit() +- ipv6: prevent possible UAF in ip6_xmit() +- !11503 mm: mTHP user controls to pagecache large folio +- mm/huge_memory: allow to enable 64K anouymous mapping align alone +- mm/huge_memory: mTHP user controls to pagecache large folio +- !5453 Add GM Driver Support for Hygon platform(Cryptographic Coprocessor,OLK-6.6) +- hct: fix fork issue when use hct in virtual machine +- hct: support 1024 processes simutaneously in the hct-mdev mode. +- hct: change the maximum number of supported ccps from 16 to 48. +- hct: fix build issue when the module mdev is disabled. +- hct: supporting memory encryption in host and wb set in vm +- hct: add mediated ccp driver support for hygon crypto technology. +- crypto: ccp: support sm2 on Hygon generation 4th CPU +- crypto: ccp: remove repeated sm4-hs mode +- crypto: ccp: Process multiple VQ commands once for SM4/SM4-CTR ccp. +- crypto: ccp: Process multiple VQ commands once for SM3 ccp. +- crypto: ccp: Modify value of COMMANDS_PER_QUEUE from 16 to 8192. +- crypto: ccp: fix bug that SM2 encryption of long data causes kernel crash +- crypto: ccp: fix sm2 test failed in testmgr because of missing DER coding +- crypto: ccp: Fix a problem that vq thread may stuck when do multi process test. +- crypto: ccp: Only handle interrupts by completion. +- crypto: ccp: It prompt ILLEGAL_MEM_ADDR when using PSPCCP. +- crypto: ccp: fix sm2 not return due to wrong complete callback parameter +- crypto: ccp: Support SM4 algorithm for hygon ccp. +- crypto: ccp: Support SM3 algorithm for hygon ccp. +- crypto: ccp: Support SM2 algorithm for hygon ccp. +- !11485 Bugfix introduced when support folio +- mm/shmem: replace HPAGE_PMD_ORDER with PMD_ORDER in shmem_alloc_folio() +- mm: huge_memory: add memory reliable count in __discard_anon_folio_pmd_locked() +- mm: limit order to 0 when allocated from dynamic pool +- !11469 OLK-6.6 Revert gpiolib bugfix +- gpiolib: acpi: Fix failed in acpi_gpiochip_find() by adding parent node match +- Revert "gpiolib: acpi: Fix failed in acpi_gpiochip_find() by adding parent node match" +- !11464 mm/ksm: fix ksm_zero_pages accounting +- mm_types: Fix kabi breakage in struct mm_struct +- mm/ksm: fix ksm_zero_pages accounting +- !11411 f2fs: fix null reference error when checking end of zone +- f2fs: fix null reference error when checking end of zone +- !11465 【olk 6.6】net: hns3: some bugfixes for netdev +- net: hns3: fix kernel crash when 1588 is sent on HIP08 devices +- net: hns3: initialize reset_timer before hclgevf_misc_irq_init() +- net: hns3: don't auto enable misc vector +- !11454 nfs: fix memory leak in error path of nfs4_do_reclaim +- nfs: fix memory leak in error path of nfs4_do_reclaim +- !11421 Some fixes About cpuset partition +- cgroup/cpuset: Clear effective_xcpus on cpus_allowed clearing only if cpus.exclusive not set +- cgroup/cpuset: fix panic caused by partcmd_update +- cgroup/cpuset: Fix remote root partition creation problem +- cgroup/cpuset: Optimize isolated partition only generate_sched_domains() calls +- !11455 v2 CVE-2024-44972 +- btrfs: fix invalid mapping of extent xarray state +- btrfs: do not clear page dirty inside extent_write_locked_range() + +* Fri Sep 06 2024 ZhangPeng - 6.6.0-41.0.0.48 +- !11443 v2 drm/amd/display: Fix null pointer deref in dcn20_resource.c +- drm/amd/display: Fix null pointer deref in dcn20_resource.c +- !11433 ext4: Track data blocks freeing operation in journal +- ext4: Track data blocks freeing operation in journal +- !11063 virtcca feature: secure smmu init +- virtcca feature: secure smmu doc +- virtcca feature: secure smmu init +- !11206 kprobe support %pd/%pD type +- selftests/ftrace: Fix required features for VFS type test case +- selftests/ftrace: add fprobe test cases for VFS type "%pd" and "%pD" +- selftests/ftrace: add kprobe test cases for VFS type "%pd" and "%pD" +- Documentation: tracing: add new type '%pd' and '%pD' for kprobe +- tracing/probes: support '%pD' type for print struct file's name +- tracing/probes: support '%pd' type for print struct dentry's name +- !10875 Incorporate some bonding patches as follows(OLK-6.6) +- RDMA/hns: Fix concurrency issue between bond work and bond event +- RDMA/hns: Fix UAF in clear bond printing +- RDMA/hns: Encapsulate upper event and lowerstate event handlers +- RDMA/hns: Register notifier block of bonding events in bond_grp +- !11304 iomap: fault in smaller chunks for non-large folio mappings +- iomap: fault in smaller chunks for non-large folio mappings +- !11397 fuse: Initialize beyond-EOF page contents before setting uptodate +- fuse: Initialize beyond-EOF page contents before setting uptodate +- !11303 【OLK-6.6】ROH sync patch from OLK-5.10 +- roh/core: Avoid null pointer access and optimize code. +- Revert "RDMA/hns: Support RDMA_CM in ROH mode" +- RDMA/hns: Support getting GRH for UD in RoH mode when NLP = 0 +- roh/core: Support macvlan in roh. +- roh/hns3: Add ROH client case in hclgevf_init_client_instance. +- roh/hns3: Fix IMP reset vlan unusable. +- !11363 kcm: Serialise kcm_sendmsg() for the same socket. +- kcm: Serialise kcm_sendmsg() for the same socket. +- !11381 mm/dynamic_pool: use batch to add free pages to dpool +- mm/dynamic_pool: use batch to add free pages to dpool +- !11355 ext4: Fix wrong da count caused by concurrent racing on extent tree +- ext4: Fix wrong da count caused by concurrent racing on extent tree +- !11335 Revert SPI bugfixs +- spi: hisi-kunpeng: Add validation for the minimum value of speed_hz +- spi: hisi-kunpeng: Add verification for the max_frequency provided by the firmware +- Revert "spi: hisi-kunpeng: Add validation for the minimum value of speed_hz" +- Revert "spi: Add verification for the max_frequency provided by the firmware" +- !11336 nfsd: map the EBADMSG to nfserr_io to avoid warning +- nfsd: map the EBADMSG to nfserr_io to avoid warning +- !11342 large folios swap-in: handle refault cases first +- mm: remove folio_test_anon(folio)==false path in __folio_add_anon_rmap() +- mm: use folio_add_new_anon_rmap() if folio_test_anon(folio)==false +- mm: extend rmap flags arguments for folio_add_new_anon_rmap +- mm: rmap: abstract updating per-node and per-memcg stats +- mm: swap: reuse exclusive folio directly instead of wp page faults +- mm: swap: entirely map large folios found in swapcache +- mm: swap: make should_try_to_free_swap() support large-folio +- mm: introduce arch_do_swap_page_nr() which allows restore metadata for nr pages +- mm: introduce pte_move_swp_offset() helper which can move offset bidirectionally +- mm: remove the implementation of swap_free() and always use swap_free_nr() +- mm: swap: introduce swap_free_nr() for batched swap_free() +- mm: remove page_add_new_anon_rmap and lru_cache_add_inactive_or_unevictable +- mm: userswap: page_add_new_anon_rmap() -> folio_add_new_anon_rmap() +- mm: convert collapse_huge_page() to use a folio +- mm: convert migrate_vma_insert_page() to use a folio +- mm: remove references to page_add_new_anon_rmap in comments +- mm: remove stale example from comment +- mm: remove some calls to page_add_new_anon_rmap() +- mm: convert unuse_pte() to use a folio throughout +- mm: convert ksm_might_need_to_copy() to work on folios +- mm: memory: use a folio in validate_page_before_insert() +- mm: ksm: use more folio api in ksm_might_need_to_copy() +- !11328 jbd2: avoid mount failed when commit block is partial submitted +- jbd2: avoid mount failed when commit block is partial submitted +- !11222 nfs: pass explicit offset/count to trace events +- nfs: pass explicit offset/count to trace events +- !11321 NFSD: simplify error paths in nfsd_svc() +- NFSD: simplify error paths in nfsd_svc() +- !11314 nvme-fabrics: use reserved tag for reg read/write command +- nvme-fabrics: use reserved tag for reg read/write command +- !11119 virtcca compile warning clean +- virtcca bugfix: compile warning clean +- !10762 CVE-2024-41016 +- ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry() +- ocfs2: add bounds checking to ocfs2_xattr_find_entry() +- !11300 v3 mm/shmem: mTHP support for anon shmem +- mm: shmem: rename mTHP shmem counters +- mm: add docs for per-order mTHP split counters +- mm: add per-order mTHP split counters +- mm: shmem: fix incorrect aligned index when checking conflicts +- mm: shmem: avoid allocating huge pages larger than MAX_PAGECACHE_ORDER for shmem +- mm: thp: support "THPeligible" semantics for mTHP with anonymous shmem +- mm/shmem: fix input and output inconsistencies +- mm: shmem: add mTHP counters for anonymous shmem +- mm: shmem: add mTHP size alignment in shmem_get_unmapped_area +- mm: shmem: add mTHP support for anonymous shmem +- mm: shmem: add multi-size THP sysfs interface for anonymous shmem +- mm: shmem: add THP validation for PMD-mapped THP related statistics +- mm: memory: extend finish_fault() to support large folio +- mm: shmem: Merge shmem_alloc_hugefolio() with shmem_alloc_folio() +- mm: use update_mmu_tlb_range() to simplify code +- mm: implement update_mmu_tlb() using update_mmu_tlb_range() +- mm: add update_mmu_tlb_range() +- shmem: move the shmem_mapping assert into shmem_get_folio_gfp +- shmem: set a_ops earlier in shmem_symlink +- shmem,percpu_counter: add _limited_add(fbc, limit, amount) +- shmem: _add_to_page_cache() before shmem_inode_acct_blocks() +- shmem: move memcg charge out of shmem_add_to_page_cache() +- shmem: shmem_acct_blocks() and shmem_inode_acct_blocks() +- shmem: trivial tidyups, removing extra blank lines, etc +- shmem: factor shmem_falloc_wait() out of shmem_fault() +- shmem: remove vma arg from shmem_get_folio_gfp() +- shmem: shrink shmem_inode_info: dir_offsets in a union +- !11270 nvme: apple: fix device reference counting +- nvme: apple: fix device reference counting +- !11279 ice: Don't process extts if PTP is disabled +- ice: Don't process extts if PTP is disabled +- !11280 ice: Fix improper extts handling +- ice: Fix improper extts handling +- !11233 CVE-2024-43892 +- memcg: protect concurrent access to mem_cgroup_idr +- !11229 tracing: Have format file honor EVENT_FILE_FL_FREED +- tracing: Have format file honor EVENT_FILE_FL_FREED +- !11228 Bluetooth: MGMT: Add error handling to pair_device() +- Bluetooth: MGMT: Add error handling to pair_device() +- !10698 wifi: mac80211: Avoid address calculations via out of bounds array indexing +- wifi: mac80211: Avoid address calculations via out of bounds array indexing +- !11158 usb: vhci-hcd: Do not drop references before new references are gained +- usb: vhci-hcd: Do not drop references before new references are gained +- !11040 mm: lazyfree THP support +- mm/huge_memory.c: fix used-uninitialized +- mm/vmscan: avoid split lazyfree THP during shrink_folio_list() +- mm/rmap: integrate PMD-mapped folio splitting into pagewalk loop +- mm/rmap: remove duplicated exit code in pagewalk loop +- mm: arm64: fix the out-of-bounds issue in contpte_clear_young_dirty_ptes +- mm/madvise: optimize lazyfreeing with mTHP in madvise_free +- mm/memory: add any_dirty optional pointer to folio_pte_batch() +- mm/arm64: override clear_young_dirty_ptes() batch helper +- mm/madvise: introduce clear_young_dirty_ptes() batch helper +- mm: add pmd_folio() +- mm: make HPAGE_PXD_* macros even if !THP +- mm/Kconfig: CONFIG_PGTABLE_HAS_HUGE_LEAVES + +* Tue Aug 27 2024 ZhangPeng - 6.6.0-39.0.0.47 +- !11156 v3 Fix CVE-2024-43869 +- perf: Fix kabi broken of struct perf_event +- perf: Fix event leak upon exec and file release +- !11168 [openEuler-24.03-LTS][linux-6.6.y sync] Backport 6.6.46-47 LTS Patches +- Revert "ata: libata-scsi: Honor the D_SENSE bit for CK_COND=1 and no error" +- media: Revert "media: dvb-usb: Fix unexpected infinite loop in dvb_usb_read_remote_control()" +- KVM: arm64: Don't pass a TLBI level hint when zapping table entries +- KVM: arm64: Don't defer TLB invalidation when zapping table entries +- mm/debug_vm_pgtable: drop RANDOM_ORVALUE trick +- Revert "Input: bcm5974 - check endpoint type before starting traffic" +- Revert "jfs: fix shift-out-of-bounds in dbJoin" +- binfmt_flat: Fix corruption when not offsetting data start +- ALSA: usb: Fix UBSAN warning in parse_audio_unit() +- fs/ntfs3: Do copy_to_user out of run_lock +- jfs: Fix shift-out-of-bounds in dbDiscardAG +- jfs: fix null ptr deref in dtInsertEntry +- fou: remove warn in gue_gro_receive on unsupported protocol +- f2fs: fix to cover read extent cache access with lock +- f2fs: fix to do sanity check on F2FS_INLINE_DATA flag in inode during GC +- bpf, net: Use DEV_STAT_INC() +- ext4: sanity check for NULL pointer after ext4_force_shutdown +- ext4: convert ext4_da_do_write_end() to take a folio +- mm/page_table_check: support userfault wr-protect entries +- nfc: llcp: fix nfc_llcp_setsockopt() unsafe copies +- net: add copy_safe_from_sockptr() helper +- mISDN: fix MISDN_TIME_STAMP handling +- fs: Annotate struct file_handle with __counted_by() and use struct_size() +- bpf: Avoid kfree_rcu() under lock in bpf_lpm_trie. +- bpf: Replace bpf_lpm_trie_key 0-length array with flexible array +- pppoe: Fix memory leak in pppoe_sendmsg() +- net: sctp: fix skb leak in sctp_inq_free() +- net:rds: Fix possible deadlock in rds_message_put +- quota: Detect loops in quota tree +- Input: bcm5974 - check endpoint type before starting traffic +- net: tls, add test to capture error on large splice +- erofs: avoid debugging output for (de)compressed data +- reiserfs: fix uninit-value in comp_keys +- Squashfs: fix variable overflow triggered by sysbot +- squashfs: squashfs_read_data need to check if the length is 0 +- jfs: fix shift-out-of-bounds in dbJoin +- net: don't dump stack on queue timeout +- jfs: fix log->bdev_handle null ptr deref in lbmStartIO +- wifi: mac80211: fix change_address deadlock during unregister +- wifi: mac80211: take wiphy lock for MAC addr change +- tcp_metrics: optimize tcp_metrics_flush_all() +- genirq/cpuhotplug: Retry with cpu_online_mask when migration fails +- genirq/cpuhotplug: Skip suspended interrupts when restoring affinity +- nvme/pci: Add APST quirk for Lenovo N60z laptop +- nfsd: make svc_stat per-network namespace instead of global +- nfsd: remove nfsd_stats, make th_cnt a global counter +- nfsd: make all of the nfsd stats per-network namespace +- nfsd: expose /proc/net/sunrpc/nfsd in net namespaces +- nfsd: rename NFSD_NET_* to NFSD_STATS_* +- sunrpc: use the struct net as the svc proc private +- sunrpc: remove ->pg_stats from svc_program +- sunrpc: pass in the sv_stats struct through svc_create_pooled +- nfsd: stop setting ->pg_stats for unused stats +- sunrpc: don't change ->sv_stats if it doesn't exist +- NFSD: Fix frame size warning in svc_export_parse() +- NFSD: Rewrite synopsis of nfsd_percpu_counters_init() +- LoongArch: Define __ARCH_WANT_NEW_STAT in unistd.h +- btrfs: fix double inode unlock for direct IO sync writes +- Revert "selftests: mptcp: simult flows: mark 'unbalanced' tests as flaky" +- selftests: mptcp: join: test both signal & subflow +- selftests: mptcp: join: ability to invert ADD_ADDR check +- mptcp: pm: do not ignore 'subflow' if 'signal' flag is also set +- mptcp: pm: don't try to create sf if alloc failed +- mptcp: pm: reduce indentation blocks +- nouveau: set placement to original placement on uvmm validate. +- mm/hugetlb: fix potential race in __update_and_free_hugetlb_folio() +- tools headers arm64: Sync arm64's cputype.h with the kernel sources +- ipv6: fix source address selection with route leak +- btrfs: fix corruption after buffer fault in during direct IO append write +- mm: huge_memory: use !CONFIG_64BIT to relax huge page alignment on 32 bit machines +- mm: huge_memory: don't force huge page alignment on 32 bit +- Revert "drm/amd/display: Add NULL check for 'afb' before dereferencing in amdgpu_dm_plane_handle_cursor_update" +- block: use the right type for stub rq_integrity_vec() +- mptcp: pm: deny endp with signal + subflow + port +- selftests: mptcp: fix error path +- mptcp: fully established after ADD_ADDR echo on MPJ +- drm/radeon: Remove __counted_by from StateArray.states[] +- drm/mgag200: Bind I2C lifetime to DRM device +- drm/mgag200: Set DDC timeout in milliseconds +- drm/lima: Mark simple_ondemand governor as softdep +- drm/dp_mst: Skip CSN if topology probing is not done yet +- drm/bridge: analogix_dp: properly handle zero sized AUX transactions +- x86/mtrr: Check if fixed MTRRs exist before saving them +- x86/paravirt: Fix incorrect virt spinlock setting on bare metal +- selftests: mm: add s390 to ARCH check +- eventfs: Use SRCU for freeing eventfs_inodes +- eventfs: Don't return NULL in eventfs_create_dir() +- smb3: fix setting SecurityFlags when encryption is required +- padata: Fix possible divide-by-0 panic in padata_mt_helper() +- tracing: Fix overflow in get_free_elt() +- power: supply: axp288_charger: Round constant_charge_voltage writes down +- power: supply: axp288_charger: Fix constant_charge_voltage writes +- power: supply: qcom_battmgr: return EAGAIN when firmware service is not up +- LoongArch: Enable general EFI poweroff method +- genirq/irqdesc: Honor caller provided affinity in alloc_desc() +- irqchip/xilinx: Fix shift out of bounds +- kcov: properly check for softirq context +- ASoC: amd: yc: Add quirk entry for OMEN by HP Gaming Laptop 16-n0xxx +- parisc: fix a possible DMA corruption +- parisc: fix unaligned accesses in BPF +- serial: core: check uartclk for zero to avoid divide by zero +- timekeeping: Fix bogus clock_was_set() invocation in do_adjtimex() +- ntp: Safeguard against time_constant overflow +- tracefs: Fix inode allocation +- driver core: Fix uevent_show() vs driver detach race +- clocksource: Fix brown-bag boolean thinko in cs_watchdog_read() +- clocksource: Scale the watchdog read retries automatically +- vhost-vdpa: switch to use vmf_insert_pfn() in the fault handler +- tick/broadcast: Move per CPU pointer access into the atomic section +- scsi: ufs: core: Fix hba->last_dme_cmd_tstamp timestamp updating logic +- scsi: ufs: core: Do not set link to OFF state while waking up from hibernation +- scsi: mpi3mr: Avoid IOMMU page faults on REPORT ZONES +- usb: gadget: u_audio: Check return codes from usb_ep_enable and config_ep_by_speed. +- usb: gadget: u_serial: Set start_delayed during suspend +- usb: gadget: midi2: Fix the response for FB info with block 0xff +- usb: gadget: core: Check for unset descriptor +- USB: serial: debug: do not echo input by default +- usb: vhci-hcd: Do not drop references before new references are gained +- ALSA: hda/hdmi: Yet more pin fix for HP EliteDesk 800 G4 +- ALSA: hda/realtek: Add Framework Laptop 13 (Intel Core Ultra) to quirks +- ALSA: hda: Add HP MP9 G4 Retail System AMS to force connect list +- ALSA: line6: Fix racy access to midibuf +- drm/client: fix null pointer dereference in drm_client_modeset_probe +- drm/i915/gem: Adjust vma offset for framebuffer mmap offset +- drm/amdgpu: Forward soft recovery errors to userspace +- drm/amd/display: Skip Recompute DSC Params if no Stream on Link +- drm/i915/gem: Fix Virtual Memory mapping boundaries calculation +- module: make waiting for a concurrent module loader interruptible +- module: warn about excessively long module waits +- cifs: cifs_inval_name_dfs_link_error: correct the check for fullpath +- ASoC: meson: axg-fifo: fix irq scheduling issue with PREEMPT_RT +- ALSA: usb-audio: Re-add ScratchAmp quirk entries +- spi: spi-fsl-lpspi: Fix scldiv calculation +- i2c: qcom-geni: Add missing geni_icc_disable in geni_i2c_runtime_resume +- i2c: qcom-geni: Add missing clk_disable_unprepare in geni_i2c_runtime_resume +- kprobes: Fix to check symbol prefixes correctly +- bpf: kprobe: remove unused declaring of bpf_kprobe_override +- i2c: smbus: Send alert notifications to all devices if source not found +- ASoC: SOF: Remove libraries from topology lookups +- spi: spidev: Add missing spi_device_id for bh2228fv +- ASoC: sti: add missing probe entry for player and reader +- ASoC: codecs: wsa884x: Correct Soundwire ports mask +- ASoC: codecs: wsa884x: parse port-mapping information +- ASoC: codecs: wsa883x: Correct Soundwire ports mask +- ASoC: codecs: wsa883x: parse port-mapping information +- ASoC: codecs: wsa881x: Correct Soundwire ports mask +- ASoC: codecs: wcd938x-sdw: Correct Soundwire ports mask +- i2c: smbus: Improve handling of stuck alerts +- arm64: cputype: Add Cortex-A725 definitions +- arm64: cputype: Add Cortex-X1C definitions +- arm64: cputype: Add Cortex-X925 definitions +- arm64: cputype: Add Cortex-A720 definitions +- arm64: cputype: Add Cortex-X3 definitions +- arm64: cputype: Add Neoverse-V3 definitions +- arm64: cputype: Add Cortex-X4 definitions +- arm64: barrier: Restore spec_bar() macro +- arm64: Add Neoverse-V2 part +- net: drop bad gso csum_start and offset in virtio_net_hdr +- irqchip/loongarch-cpu: Fix return value of lpic_gsi_to_irq() +- irqchip/meson-gpio: Convert meson_gpio_irq_controller::lock to 'raw_spinlock_t' +- scsi: mpt3sas: Avoid IOMMU page faults on REPORT ZONES +- SUNRPC: Fix a race to wake a sync task +- s390/sclp: Prevent release of buffer in I/O +- jbd2: avoid memleak in jbd2_journal_write_metadata_buffer +- ext4: fix uninitialized variable in ext4_inlinedir_to_tree +- media: xc2028: avoid use-after-free in load_firmware_cb() +- media: uvcvideo: Fix the bandwdith quirk on USB 3.x +- media: uvcvideo: Ignore empty TS packets +- drm/amd/display: Add null checker before passing variables +- drm/amd/display: Add NULL check for 'afb' before dereferencing in amdgpu_dm_plane_handle_cursor_update +- media: amphion: Remove lock in s_ctrl callback +- drm/amd/pm: Fix the null pointer dereference for vega10_hwmgr +- drm/amdgpu: Add lock around VF RLCG interface +- drm/admgpu: fix dereferencing null pointer context +- drm/amdgpu/pm: Fix the null pointer dereference in apply_state_adjust_rules +- drm/amdgpu: Fix the null pointer dereference to ras_manager +- drm/amdgpu/pm: Fix the null pointer dereference for smu7 +- drm/amdgpu/pm: Fix the param type of set_power_profile_mode +- drm/amdgpu: fix potential resource leak warning +- drm/amd/display: Add delay to improve LTTPR UHBR interop +- Bluetooth: btnxpuart: Shutdown timer and prevent rearming when driver unloading +- btrfs: fix bitmap leak when loading free space cache on duplicate entry +- net: stmmac: qcom-ethqos: enable SGMII loopback during DMA reset on sa8775p-ride-r3 +- can: mcp251xfd: tef: update workaround for erratum DS80000789E 6 of mcp2518fd +- can: mcp251xfd: tef: prepare to workaround broken TEF FIFO tail index erratum +- wifi: nl80211: don't give key data to userspace +- udf: prevent integer overflow in udf_bitmap_free_blocks() +- PCI: Add Edimax Vendor ID to pci_ids.h +- af_unix: Don't retry after unix_state_lock_nested() in unix_stream_connect(). +- selftests/bpf: Fix send_signal test with nested CONFIG_PARAVIRT +- net/mlx5e: SHAMPO, Fix invalid WQ linked list unlink +- wifi: ath12k: fix memory leak in ath12k_dp_rx_peer_frag_setup() +- wifi: nl80211: disallow setting special AP channel widths +- xen: privcmd: Switch from mutex to spinlock for irqfds +- ACPI: SBS: manage alarm sysfs attribute through psy core +- ACPI: battery: create alarm sysfs attribute atomically +- clocksource/drivers/sh_cmt: Address race condition for clock events +- rcu: Fix rcu_barrier() VS post CPUHP_TEARDOWN_CPU invocation +- block: change rq_integrity_vec to respect the iterator +- md/raid5: avoid BUG_ON() while continue reshape after reassembling +- rcutorture: Fix rcu_torture_fwd_cb_cr() data race +- hwmon: corsair-psu: add USB id of HX1200i Series 2023 psu +- gpio: prevent potential speculation leaks in gpio_device_get_desc() +- net: fec: Stop PPS on driver remove +- net: bcmgenet: Properly overlay PHY and MAC Wake-on-LAN capabilities +- l2tp: fix lockdep splat +- net: dsa: bcm_sf2: Fix a possible memory leak in bcm_sf2_mdio_register() +- net/smc: add the max value of fallback reason count +- Bluetooth: hci_sync: avoid dup filtering when passive scanning with adv monitor +- Bluetooth: l2cap: always unlock channel in l2cap_conless_channel() +- ice: Fix reset handler +- net: linkwatch: use system_unbound_wq +- net: bridge: mcast: wait for previous gc cycles when removing port +- sctp: Fix null-ptr-deref in reuseport_add_sock(). +- wifi: ath12k: fix soft lockup on suspend +- wifi: ath12k: add CE and ext IRQ flag to indicate irq_handler +- wifi: ath12k: rename the sc naming convention to ab +- smb: client: handle lack of FSCTL_GET_REPARSE_POINT support +- x86/mm: Fix pti_clone_entry_text() for i386 +- x86/mm: Fix pti_clone_pgtable() alignment assumption +- jump_label: Fix the fix, brown paper bags galore +- platform/x86/intel/ifs: Initialize union ifs_status to zero +- !11100 exec: Fix ToCToU between perm check and set-uid/gid usage +- exec: Fix ToCToU between perm check and set-uid/gid usage +- !11106 CVE-2024-43868 +- riscv/purgatory: align riscv_kernel_entry +- riscv: Use SYM_*() assembly macros instead of deprecated ones +- !11094 v4 Backport bugfix of folio from v6.11 +- ext4: Fix WARNON in generic write begin path for iomap mode +- mm/huge_memory: fix comment errors of thp_mapping_align +- mm/slub: mark racy accesses on slab->slabs +- mm/slub: mark racy access on slab->freelist +- mm/swapfile: mark racy access on si->highest_bit +- mm/mmap: simplify vma link and unlink +- mm/readahead: limit page cache size in page_cache_ra_order() +- readahead: use ilog2 instead of a while loop in page_cache_ra_order() +- filemap: Convert generic_perform_write() to support large folios +- mm/huge_memory: avoid PMD-size page cache if needed +- mm: simplify folio_migrate_mapping() +- mm: refactor folio_undo_large_rmappable() +- mm: fix crashes from deferred split racing folio migration +- mm: page_alloc: allowing mTHP compaction to capture the freed page directly +- mm/migrate: fix deadlock in migrate_pages_batch() on large folios +- mm: fix khugepaged activation policy +- mm/huge_memory: mark racy access onhuge_anon_orders_always +- mm/migrate: putback split folios when numa hint migration fails +- mm/migrate: make migrate_pages_batch() stats consistent +- !11125 mm/memory-failure: fix handling of dissolved but not taken off from buddy pages +- mm/memory-failure: fix handling of dissolved but not taken off from buddy pages +- !11077 IMA: Support the measurement extending of TSI TMM +- IMA: Support the measurement extending of TSI TMM +- !11108 cpufreq: CPPC: Eliminate the impact of cpc_read() latency error +- cpufreq: CPPC: Eliminate the impact of cpc_read() latency error +- !11081 Backport LTS conflicting patches +- ALSA: hda/realtek: Fix conflicting quirk for PCI SSID 17aa:3820 +- vfio/pci: Restore zero affected bus reset devices warning +- cxl/region: check interleave capability +- EDAC/amd64: Convert PCIBIOS_* return codes to errnos +- ALSA: hda/realtek: Enable headset mic on IdeaPad 330-17IKB 81DM +- vfio/pci: Init the count variable in collecting hot-reset devices +- vfio/pci: Collect hot-reset devices to local buffer +- platform/chrome: cros_ec: Handle events during suspend after resume completion +- !10998 PCI: endpoint: pci-epf-test: Make use of cached 'epc_features' in pci_epf_test_core_init() +- PCI: endpoint: pci-epf-test: Make use of cached 'epc_features' in pci_epf_test_core_init() +- !10942 add support for arm virtcca attestation +- cvm_tsi: add support virtcca attestation +- !11043 [OLK-6.6] drivers: add GPU Peer Memory support +- drivers: Fix kabi check failure +- drivers: Add GDR(GPU Direct RDMA) support +- !11044 ext4: some bugfixs for large iomap&folio +- iomap: improve iomap_folio_mkwrite_iter and ifs_clear_range_dirty +- iomap: optimize setting uptodate bit +- iomap: reduce unnecessary state_lock when setting ifs uptodate and dirty bits +- iomap: don't mark blocks uptodate after partial zeroing +- ext4: ext4_iomap_map_blocks: Fix null pointer deference in nojournal mode +- xfs: reserve blocks for truncating large realtime inode +- xfs: hoist multi-fsb allocation unit detection to a helper +- !11018 net: usb: qmi_wwan: fix memory leak for not ip packets +- net: usb: qmi_wwan: fix memory leak for not ip packets +- !10927 block: Fix lockdep warning in blk_mq_mark_tag_wait +- block: Fix lockdep warning in blk_mq_mark_tag_wait +- !11004 kvm: s390: Reject memory region operations for ucontrol VMs +- kvm: s390: Reject memory region operations for ucontrol VMs +- !10969 bpf, arm64: Fix trampoline for BPF_TRAMP_F_CALL_ORIG +- bpf, arm64: Fix trampoline for BPF_TRAMP_F_CALL_ORIG +- !10407 Intel: Backport SPR/EMR CXL and HBM perfmon support to kernel 6.6 +- perf/x86/intel/uncore: Support HBM and CXL PMON counters +- perf/x86/uncore: Cleanup unused unit structure +- perf/x86/uncore: Apply the unit control RB tree to PCI uncore units +- perf/x86/uncore: Apply the unit control RB tree to MSR uncore units +- perf/x86/uncore: Apply the unit control RB tree to MMIO uncore units +- perf/x86/uncore: Retrieve the unit ID from the unit control RB tree +- perf/x86/uncore: Support per PMU cpumask +- perf/x86/uncore: Save the unit control address of all units +- !10411 Intel: Backport 3 core PMU bugfixes to kernel 6.6 +- perf/x86/intel: Correct incorrect 'or' operation for PMU capabilities +- perf/x86/intel: Fix broken fixed event constraints extension +- perf/x86/intel: Add a distinct name for Granite Rapids +- perf/x86/intel: Hide Topdown metrics events if the feature is not enumerated +- perf/x86/intel: Add common intel_pmu_init_hybrid() +- perf/x86/intel: Clean up the hybrid CPU type handling code +- perf/x86/intel: Apply the common initialization code for ADL +- perf/x86/intel: Factor out the initialization code for ADL e-core +- perf/x86/intel: Factor out the initialization code for SPR +- perf/x86/intel: Use the common uarch name for the shared functions +- !10911 Fix CVE-2024-40966 +- tty: fix kabi breakage in struct tty_operations +- tty: add the option to have a tty reject a new ldisc +- !10918 【OLK 6.6】net: hns3: use the user's cfg after reset +- net: hns3: use the user's cfg after reset +- !10907 v2 perf/x86: Fix smp_processor_id()-in-preemptible warnings +- perf/x86: Fix smp_processor_id()-in-preemptible warnings +- !10585 Fix the issue that vm can't access to host with virtio-net +- vhost: move smp_rmb() into vhost_get_avail_idx() +- vhost: correct misleading printing information +- !10812 ima: dont disable digest_list if the file is not processed +- ima: dont disable digest_list if the file is not processed +- !10819 [OLK-6.6] Support Hygon Trusted Key Management virtualization +- drivers/crypto/ccp: memmove is used instead of memcpy in overlapped memmory for tkm +- drivers/crypto/ccp: Eliminate dependence of the kvm module on the ccp module +- drivers/crypto/ccp: Allow VM without a configured vid to use TKM +- drivers/crypto/ccp: support tkm key isolation +- arch/x86/kvm: Support tkm virtualization +- arch/x86/kvm: Support psp virtualization +- drivers/crypto/ccp: Add psp mutex enable ioctl support +- drivers/crypto/ccp: concurrent psp access support between user and kernel space +- !6863 sdei_watchdog: don't update last_check_time when no watchdog_hardlockup_check is performed +- sdei_watchdog: do not update last_check_time when no watchdog_hardlockup_check is performed +- !10899 selftests/bpf: Add netlink helper library +- selftests/bpf: Add netlink helper library +- !10690 [OLK-6.6] Support Trusted computing(TC) feature for hygon CPU +- crypto: command co-processor: Add config to openeuler_defconfig +- linux: tcm: add Hygon TCM2 driver +- linux: tpm: add Hygon TPM2 driver +- crypto: tdm: Support dynamic protection for SCT and IDT by HYGON TDM +- crypto: tdm: Add Hygon TDM driver +- crypto: command co-processor: Add another mailbox interrupt support for PSP sending command to X86 +- crypto: ccp: Add a new interface for X86 sending command to PSP +- !10720 v2 s390/pkey: Wipe copies of clear-key structures on failure +- s390/pkey: Wipe copies of clear-key structures on failure + +* Wed Aug 14 2024 Mingzheng Xing - 6.6.0-38.0.0.46 +- riscv kernel upgrade to 6.6.0-38.0.0 +- bugfix for sg2042 accessing kernel page tables +- revert sg2042 high memory +- revert sg2042 kexec image +- add support th1520 modules: + pinctrl, eMMC, gpio, usb, pwm, ethernet, th1520 perf, ADC, clock, + mailbox, reset, qspi, pvt, gpio, dma, mmc, cpufreq, rtc, dwmac, + light-event, rpmsg, i2c, i2s, light-aon, light-aon-pd, codec, gpu. + +- th1520: riscv: dtb: Add gpu node +- riscv: config: Disable RISCV_ISA_V in openEuler +- th1520: riscv: config: disable RISCV_ISA_V in th1520_defconfig +- riscv: config: Set NVMe driver builtin +- th1520: riscv: config: Enable PowerVR GPU +- th1520: riscv: Add GPU to th1520_defconfig +- th1520: riscv: config: Enable th1520 support +- sg2042: riscv: config: Enable sg2042 support +- sg2042: riscv: config: Add sg2042_defconfig +- riscv: Use accessors to page table entries instead of direct dereference +- riscv: mm: Only compile pgtable.c if MMU +- mm: Introduce pudp/p4dp/pgdp_get() functions +- riscv: Use WRITE_ONCE() when setting page table entries +- Merge patch series "membarrier: riscv: Core serializing command" +- membarrier: riscv: Add full memory barrier in switch_mm() +- stmmac: bitmain: use DWMAC_SOPHGO module config +- pcie: whitelist and support mellanox connectx-2 +- riscv: input: Fixup input_event +- drm: Fix HDMI hot-plug problem +- gpu/drm: hdmi: Add hdmi debounce to enhance hdmi plugin/out stable +- audio: th1520: fixup compile warning of i2s driver +- DPU: fix bugs of DPU and resolve compilation warnings +- riscv: binrpm: Add dtbs install +- th1520: gpu: Add driver for PowerVR Rogue GPU +- dmaengine: dw-axi-dmac: Add support for Xuantie TH1520 DMA +- arch:rsicv:select ARCH_HAS_DMA_WRITE_COMBINE +- configs: enable rtw88 for 8723ds +- drivers: pinctrl: correct th1520 audio i2c1 bit mapping table +- driver:padctrl:correct th1520 gpio_1 24/25 cfg +- dts: th1520: add adc vref-supply regulator +- dts: th1520: add cpu thermal node and device thermal node +- drivers: event: add macro definition to control SW_PANIC event +- chore: use thead instead of xuantie +- chore: use xuantie instead of thead +- riscv: ptrace: Fix ptrace using uninitialized riscv_v_vsize +- audio: th1520: enable soundcard feature +- audio: th1520: support audiosys pinctrl feature +- dts: th1520: fix interrupt number config error in dts +- th1520: defconfig: add configs to align the functionality and performance of previous related versions +- DPU: add DPU driver for Lichee-Pi-4A board +- dts: th1520: add npu device node +- codec: audio: add codec driver for Lichee-Pi-4A board +- drivers: cpufreq: add cpufreq driver. +- riscv: dts: Introduce lichee-pi-4a fixed regulator support. +- th1520: defconfig: to remove unnecessary configs for th1520 +- i2s: remove debug message +- riscv:dts: fix the aon gpio range configuration error +- riscv:dts: fix spi/qspi1 cs pin duplicate configuration error +- riscv:dts: fix the gpio range configuration error +- drivers: regulator: add th1520 AON virtual regulator control support. +- dt-bindings: add AON resource id headfile +- drivers: pmdomain: support th1520 Power domain control. +- i2s: add i2s driver for XuanTie TH1520 SoC +- configs: xuantie: correct definition of SoC Architecture +- configs: enable th1520 xgene rtc and rtc prescale in th1520_defconfig +- riscv: mm: update T-Head memory type definitions +- i2c: designware: add support for hcnt/lcnt got from dt +- add 902 share mem log +- th1520_defconfig: add usb config +- refine thead,th1520-usb.yaml +- drivers: usb: dwc3: add usb_mode usb_speed param for mode speed change when insmod ko +- drivers: usb: add dwc3-thead.c +- th1520.dtsi: refine usb dts +- configs: enable th1520 event and watchdog +- riscv:dts:thead: Add TH1520 event and watchdog device node +- dt-bindings:wdt: Add Documentation for THEAD TH1520 pmic watchdog +- drivers/watchdog: Add THEAD TH1520 pmic watchdog driver +- dt-bindings:event: Add Documentation for THEAD TH1520 event driver +- drivers/soc/event: Add THEAD TH1520 event driver +- Open I2C config +- fix rpmsg addr cast warning +- fix lp32 compile warnoing for rpmsg +- fix proc log warning +- fix rpmsg warning +- add c906 audio support +- Kconfig: Enable APM X-Gene RTC for XuanTie TH1520 +- drivers/rtc/rtc-xgene: Add "snps,dw-apb-rtc" into the "compatible" +- riscv: dts: thead: Add XuanTie TH1520 RTC device node +- dt-bindings: rtc: Add optional property "prescaler" in APM X-Gene RTC Document +- drivers/rtc/rtc-xgene: Add prescaler support in APM X-Gene RTC driver +- th1520: defconfig: to add th1520_defconfig +- net:stmmac: increase timeout for dma reset +- stmmac:dwmac-thead: add support for suspend/resume feature +- net:dwmac-thead: dd ptp clk set and enable +- configs: Enable th1520 mailbox. +- drivers:ipc: update th1520 rpc msg version 2 +- firmware: thead: c910_aon: add th1520 Aon protocol driver +- mmc:sdhci-of-dwcmshc: th1520 add delay line in different mode and sdio rxclk delay +- mmc:sdhci-of-dwcmshc: th1520 larger tuning max loop count to 128 +- dts: th1520: enable sdio1 for wifi card in lichee-pi-4a +- mmc:sdhci-of-dwcmshc: th1520 sdhci add fix io voltage 1v8 +- mmc:sdhci-of-dwcmshc: th1520 resolve accss rpmb error in hs400 +- drivers/dmac: add pm suspend/resume for dma driver +- audio: th1520: add dma chan str for dmaengine +- riscv: dts: thead: Add THEAD TH1520 dmac1 and dmac2 device node +- STR: fix pca953x resume bug +- drivers/iio/adc: add sysfs_remove_file when adc driver removed +- drivers/pvt: add mr75203 driver pm feature and correct temperature coefficient +- riscv: dts: thead: Add THEAD TH1520 SPI/QSPI device node +- dt-bindings: spi/qspi: Add Documentation for THEAD TH1520 SPI/QSPI +- drivers/spi: Add THEAD TH1520 QSPI driver +- reset: th1520: to support npu/fce reset feature +- riscv: dts: Add th1520 reset device tree +- dt-bindings: reset: Document th1520 reset control +- reset: Add th1520 reset driver support +- riscv: dts: thead: Add XuanTie TH1520 Mailbox device node +- mailbox: add XuanTie TH1520 Mailbox IPC driver +- dt-bindings: mailbox: Add a binding file for XuanTie TH1520 Mailbox +- riscv: dts: thead: to add th1520 clk nodes +- drivers: clk: to add thead th1520 clk driver +- configs: enable th1520 clk +- dt-bindings: adc: Add Documentation for THEAD TH1520 ADC +- riscv: dts: thead: Add THEAD TH1520 ADC device node +- drivers/iio/adc: Add THEAD TH1520 ADC driver +- riscv: dts: thead: Enable Lichee Pi 4A USB +- riscv: dts: thead: Add Lichee Pi 4A IO expansions +- riscv: dts: thead: Add TH1520 USB nodes +- riscv: dts: thead: Add TH1520 I2C nodes +- usb: dwc3: add T-HEAD TH1520 usb driver +- dt-bindings: usb: Add T-HEAD TH1520 USB controller +- riscv: dts: thead: Add BeagleV Ahead SDIO0 pins +- riscv: dts: thead: Add Lichee Pi 4A SDIO0 pins +- riscv: dts: thead: Add TH1520 ethernet nodes +- net: stmmac: add glue layer for T-HEAD TH1520 SoC +- dt-bindings: net: add T-HEAD dwmac support +- dt-bindings: net: snps,dwmac: allow dwmac-3.70a to set pbl properties +- gpio: dwapb: Use generic request, free and set_config +- riscv: dts: thead: Enable Lichee Pi 4A PWM fan +- riscv: dts: thead: Add TH1520 PVT node +- riscv: dts: thead: Add TH1520 PWM node +- pwm: add T-HEAD PWM driver +- dt-bindings: pwm: Add T-HEAD PWM controller +- perf vendor events riscv: add T-HEAD C9xx JSON file +- riscv: dts: thead: th1520: Add PMU event node +- chore: dtb_install in /boot +- remove compression for riscv Image +- riscv: dts: thead: Enable LicheePi 4A eMMC and microSD +- riscv: dts: thead: Enable BeagleV Ahead eMMC and microSD +- riscv: dts: thead: Add TH1520 mmc controllers and sdhci clock +- riscv: defconfig: Enable mmc and dma drivers for T-Head TH1520 +- mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520 +- mmc: sdhci: add __sdhci_execute_tuning() to header +- dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support +- fix: remove linux/array_size.h for pinctrl-th1520 +- riscv: dtb: thead: Add BeagleV Ahead LEDs +- riscv: dts: thead: Add TH1520 pinctrl settings for UART0 +- riscv: dts: thead: Add Lichee Pi 4M GPIO line names +- riscv: dts: thead: Adjust TH1520 GPIO labels +- riscv: dts: thead: Add TH1520 GPIO ranges +- riscv: dts: thead: Add TH1520 pin control nodes +- pinctrl: Add driver for the T-Head TH1520 SoC +- dt-bindings: pinctrl: Add thead,th1520-pinctrl bindings +- riscv: Enable TEE driver +- sg2042: drivers: rtc: disable BMC RTC device +- sg2042: dts: add i2c-rtc ds1307 device node for single chip +- sg2042: riscv:dts:modify dw gpio clock name +- sg2042: drivers:pci:remove the err log of parsing pci +- sg2042: driver: ipmi: support KVM and IPMI SI for BMC +- sg2042: perf cpumap: Make counter as unsigned ints +- sg2042: kernel: schedule: Fix set_task_cpu() bug +- sg2042: mm: Modify __find_max_addr for memory hole +- sg2042: riscv: kernel: Optimize apply_relocate_add() +- sg2042: riscv: mm: Clear compilation warning about last_cpupid +- sg2042: kernel: tick: filter unnecessary printing +- sg2042: kernel: Adjust the log level of the tick_switch_to_oneshot function +- sg2042: drm/amd/display: Support DRM_AMD_DC_FP on RISC-V +- sg2042: riscv: Factor out riscv-march-y to a separate Makefile +- sg2042: riscv: Add support for kernel-mode FPU +- sg2042: mango pci hack:broadcast when no MSI source known +- sg2042: nvidia hda: force msi +- sg2042: radeon hack: force 64-bit msi to fit top intc +- sg2042: amdgpu: disable rebar +- sg2042: ttm: disallow cached mapping +- sg2042: driver: soc: Add sophgo sg2042 soc support +- sg2042: drivers: pcie: Create msi-x whitelist,turn on msi-x for top intr +- sg2042: driver: pcie: Add sophgo sg2042 soc support +- sg2042: driver: net: Add sophgo sg2042 soc support +- sg2042: driver: mtd: Add sophgo sg2042 soc support +- sg2042: driver: mmc: Add sophgo sg2042 soc support +- sg2042: driver: reset: Add sophgo sg2042 soc support +- sg2042: driver: pinctrl: Add sophgo sg2042 soc support +- sg2042: driver: clk: Add sophgo sg2042 soc support +- sg2042: riscv: spinlock: Fix deadlock issue +- sg2042: riscv: add smp_cond_load_acquire() +- sg2042: riscv: add ioremap_wc for gpu +- sg2042: riscv: changing T-Head PBMT attributes +- sg2042: riscv: errata: thead: Make cache clean to flush +- sg2042: riscv: use VA+PA variant of CMO macros for DMA page preparation +- sg2042: riscv: use VA+PA variant of CMO macros for DMA synchorization +- sg2042: riscv: errata: cmo: add CMO macro variant with both VA and PA +- sg2042: riscv: errata: Replace thead cache clean with flush +- sg2042: riscv: Kconfig: Set vector as default no +- sg2042: riscv: Add sophgo sg2042 soc support + +* Tue Aug 13 2024 ZhangPeng - 6.6.0-38.0.0.45 +- !10843 netfilter: nf_tables: prefer nft_chain_validate +- netfilter: nf_tables: prefer nft_chain_validate +- !10893 [openEuler-24.03-LTS][linux-6.6.y sync] Backport 6.6.45 LTS Patches +- selftests: mptcp: join: check backup support in signal endp +- selftests: mptcp: join: validate backup in MPJ +- selftests: mptcp: always close input's FD if opened +- mptcp: fix duplicate data handling +- mptcp: pm: only set request_bkup flag when sending MP_PRIO +- mptcp: fix bad RCVPRUNED mib accounting +- mptcp: mib: count MPJ with backup flag +- mptcp: fix NL PM announced address accounting +- mptcp: distinguish rcv vs sent backup flag in requests +- mptcp: fix user-space PM announced address accounting +- r8169: don't increment tx_dropped in case of NETDEV_TX_BUSY +- net: usb: sr9700: fix uninitialized variable use in sr_mdio_read +- drm/i915: Fix possible int overflow in skl_ddi_calculate_wrpll() +- drm/virtio: Fix type of dma-fence context variable +- drm/vmwgfx: Fix a deadlock in dma buf fence polling +- Revert "ALSA: firewire-lib: operate for period elapse event in process context" +- Revert "ALSA: firewire-lib: obsolete workqueue for period update" +- ALSA: seq: ump: Optimize conversions from SysEx to UMP +- ALSA: hda/realtek: Add quirk for Acer Aspire E5-574G +- ALSA: usb-audio: Correct surround channels in UAC1 channel map +- mptcp: sched: check both directions for backup +- protect the fetch of ->fd[fd] in do_dup2() from mispredictions +- btrfs: do not subtract delalloc from avail bytes +- btrfs: zoned: fix zone_unusable accounting on making block group read-write again +- HID: wacom: Modify pen IDs +- platform/chrome: cros_ec_proto: Lock device when updating MKBP version +- arm64: jump_label: Ensure patched jump_labels are visible to all CPUs +- riscv: Fix linear mapping checks for non-contiguous memory regions +- riscv/mm: Add handling for VM_FAULT_SIGSEGV in mm_fault_error() +- perf: riscv: Fix selecting counters in legacy mode +- riscv: remove unused functions in traps_misaligned.c +- ipv6: fix ndisc_is_useropt() handling for PIO +- igc: Fix double reset adapter triggered from a single taprio cmd +- net/mlx5e: Add a check for the return value from mlx5_port_set_eth_ptys +- net/mlx5e: Fix CT entry update leaks of modify header context +- net/mlx5e: Require mlx5 tc classifier action support for IPsec prio capability +- net/mlx5: Fix missing lock on sync reset reload +- net/mlx5: Lag, don't use the hardcoded value of the first port +- net/mlx5: Fix error handling in irq_pool_request_irq +- net/mlx5: Always drain health in shutdown callback +- netfilter: iptables: Fix potential null-ptr-deref in ip6table_nat_table_init(). +- netfilter: iptables: Fix null-ptr-deref in iptable_nat_table_init(). +- ALSA: hda: Conditionally use snooping for AMD HDMI +- net: phy: micrel: Fix the KSZ9131 MDI-X status issue +- net: mvpp2: Don't re-use loop iterator +- drm/i915/hdcp: Fix HDCP2_STREAM_STATUS macro +- net/iucv: fix use after free in iucv_sock_close() +- ice: add missing WRITE_ONCE when clearing ice_rx_ring::xdp_prog +- ice: replace synchronize_rcu with synchronize_net +- ice: don't busy wait for Rx queue disable in ice_qp_dis() +- ice: respect netif readiness in AF_XDP ZC related ndo's +- i915/perf: Remove code to update PWR_CLK_STATE for gen12 +- rtnetlink: Don't ignore IFLA_TARGET_NETNSID when ifname is specified in rtnl_dellink(). +- net: axienet: start napi before enabling Rx/Tx +- tcp: Adjust clamping window for applications specifying SO_RCVBUF +- tcp: annotate data-races around tp->window_clamp +- Bluetooth: hci_sync: Fix suspending with wrong filter policy +- Bluetooth: btintel: Fail setup on error +- ALSA: hda: conexant: Fix headset auto detect fail in the polling mode +- net: phy: realtek: add support for RTL8366S Gigabit PHY +- wifi: cfg80211: fix reporting failed MLO links status with cfg80211_connect_done +- sched: act_ct: take care of padding in struct zones_ht_key +- drm/vmwgfx: Trigger a modeset when the screen moves +- drm/vmwgfx: Fix overlay when using Screen Targets +- drm/nouveau: prime: fix refcount underflow +- perf tool: fix dereferencing NULL al->maps +- HID: amd_sfh: Move sensor discovery before HID device initialization +- ARM: 9406/1: Fix callchain_trace() return value +- MIPS: dts: loongson: Fix ls2k1000-rtc interrupt +- MIPS: dts: loongson: Fix liointc IRQ polarity +- MIPS: Loongson64: DTS: Fix PCIe port nodes for ls7a +- perf: imx_perf: fix counter start and config sequence +- dmaengine: fsl-edma: change the memory access from local into remote mode in i.MX 8QM +- dmaengine: fsl-edma: clean up unused "fsl,imx8qm-adma" compatible string +- dmaengine: fsl-edma: add i.MX8ULP edma support +- dmaengine: fsl-edma: add address for channel mux register in fsl_edma_chan +- f2fs: assign CURSEG_ALL_DATA_ATGC if blkaddr is valid +- f2fs: fix to avoid use SSR allocate when do defragment +- mm/page_alloc: fix pcp->count race between drain_pages_zone() vs __rmqueue_pcplist() +- fbdev: vesafb: Detect VGA compatibility from screen info's VESA attributes +- firmware/sysfb: Update screen_info for relocated EFI framebuffers +- video: Provide screen_info_get_pci_dev() to find screen_info's PCI device +- video: Add helpers for decoding screen_info +- fbdev/vesafb: Replace references to global screen_info by local pointer +- PCI: Add pci_get_base_class() helper +- KVM: nVMX: Check for pending posted interrupts when looking for nested events +- KVM: nVMX: Add a helper to get highest pending from Posted Interrupt vector +- KVM: VMX: Move posted interrupt descriptor out of VMX code +- KVM: VMX: Split off vmx_onhyperv.{ch} from hyperv.{ch} +- leds: triggers: Flush pending brightness before activating trigger +- leds: trigger: Call synchronize_rcu() before calling trig->activate() +- leds: trigger: Store brightness set by led_trigger_event() +- leds: trigger: Remove unused function led_trigger_rename_static() +- cpufreq: qcom-nvmem: fix memory leaks in probe error paths +- cpufreq: qcom-nvmem: Simplify driver data allocation +- sysctl: allow to change limits for posix messages queues +- sysctl: allow change system v ipc sysctls inside ipc namespace +- thermal/drivers/broadcom: Fix race between removal and clock disable +- thermal: bcm2835: Convert to platform remove callback returning void +- arm64: dts: qcom: sdm845: Disable SS instance in Parkmode for USB +- arm64: dts: qcom: sdm845: switch USB QMP PHY to new style of bindings +- arm64: dts: qcom: sdm845: switch USB+DP QMP PHY to new style of bindings +- arm64: dts: qcom: ipq8074: Disable SS instance in Parkmode for USB +- arm64: dts: qcom: msm8998: Disable SS instance in Parkmode for USB +- arm64: dts: qcom: msm8998: switch USB QMP PHY to new style of bindings +- arm64: dts: qcom: sc7280: Disable SuperSpeed instances in park mode +- arm64: dts: qcom: sc7280: switch USB+DP QMP PHY to new style of bindings +- arm64: dts: qcom: sc7180: Disable SuperSpeed instances in park mode +- arm64: dts: qcom: sc7180: switch USB+DP QMP PHY to new style of bindings +- !10823 mm/userfaultfd: reset ptes when close() for wr-protected ones +- mm/userfaultfd: reset ptes when close() for wr-protected ones +- !10824 dmaengine: idxd: Fix possible Use-After-Free in irq_process_work_list +- dmaengine: idxd: Fix possible Use-After-Free in irq_process_work_list +- !10855 CVE-2024-36971 +- net: fix kabi breakage in struct dst_ops +- net: fix __dst_negative_advice() race +- !10863 v2 ext4: flexibly control whether to enable dioread_nolock by default +- ext4: flexibly control whether to enable dioread_nolock by default +- !10796 Revert "ARM: spectre-v2: turn off the mitigation via boot cmdline param" +- Revert "ARM: spectre-v2: turn off the mitigation via boot cmdline param" +- !10795 Revert "security: restrict init parameters by configuration" +- Revert "security: restrict init parameters by configuration" +- !10794 revert kaslr arm32 support +- Revert "asm-generic: add .data.rel.ro sections to __ro_after_init" +- Revert "arm-soc: exynos: replace open coded VA->PA conversions" +- Revert "arm-soc: mvebu: replace open coded VA->PA conversion" +- Revert "arm-soc: various: replace open coded VA->PA calculation of pen_release" +- Revert "ARM: kernel: switch to relative exception tables" +- Revert "ARM: kernel: make vmlinux buildable as a PIE executable" +- Revert "ARM: kernel: use PC-relative symbol references in MMU switch code" +- Revert "ARM: kernel: use PC relative symbol references in suspend/resume code" +- Revert "ARM: mm: export default vmalloc base address" +- Revert "ARM: kernel: refer to swapper_pg_dir via its symbol" +- Revert "arm: vectors: use local symbol names for vector entry points" +- Revert "ARM: kernel: implement randomization of the kernel load address" +- Revert "ARM: decompressor: explicitly map decompressor binary cacheable" +- Revert "ARM: decompressor: add KASLR support" +- Revert "No idea why this broke ..." +- Revert "arm32: kaslr: When boot with vxboot, we must adjust dtb address before kaslr_early_init, and store dtb address after init." +- Revert "arm32: kaslr: pop visibility when compile decompress boot code as we need relocate BSS by GOT." +- Revert "arm32: kaslr: print kaslr offset when kernel panic" +- Revert "arm32: kaslr: Fix the bug of symbols relocation" +- Revert "arm32: kaslr: Fix clock_gettime and gettimeofday performance degradation when configure CONFIG_RANDOMIZE_BASE" +- !10615 USB: core: Fix duplicate endpoint bug by clearing reserved bits in the descriptor +- USB: core: Fix duplicate endpoint bug by clearing reserved bits in the descriptor +- !10834 v2 wifi: cfg80211: restrict NL80211_ATTR_TXQ_QUANTUM values +- wifi: cfg80211: restrict NL80211_ATTR_TXQ_QUANTUM values +- !10816 sched/cputime: Fix mul_u64_u64_div_u64() precision for cputime +- sched/cputime: Fix mul_u64_u64_div_u64() precision for cputime +- !10805 dummy_struct_ops selftest failed +- Revert "[Backport] selftests/bpf: adjust dummy_st_ops_success to detect additional error" +- Revert "[Backport] selftests/bpf: dummy_st_ops should reject 0 for non-nullable params" +- !10345 blk-wbt: don't throttle swap writes in direct reclaim +- blk-wbt: don't throttle swap writes in direct reclaim +- !10772 s390/pkey: Use kfree_sensitive() to fix Coccinelle warnings +- s390/pkey: Use kfree_sensitive() to fix Coccinelle warnings +- !10722 btrfs: zoned: fix use-after-free in do_zone_finish() +- btrfs: zoned: fix use-after-free in do_zone_finish() + +* Wed Aug 07 2024 ZhangPeng - 6.6.0-37.0.0.44 +- !10793 perf util: Add a function for replacing characters in a string +- perf util: Add a function for replacing characters in a string +- !10635 nvme: avoid double free special payload +- nvme: avoid double free special payload +- !10757 CVE-2024-41045 +- bpf: Defer work in bpf_timer_cancel_and_free +- bpf: replace bpf_timer_cancel_and_free with a generic helper +- bpf: replace bpf_timer_set_callback with a generic helper +- !10729 Backport vmalloc 2 bugfix +- mm: vmalloc: fix lockdep warning +- mm/vmalloc: eliminated the lock contention from twice to once +- !10746 irqchip/mbigen: Fix mbigen node address layout +- irqchip/mbigen: Fix mbigen node address layout +- !10533 backport mainline patchs +- cpufreq: Allow drivers to advertise boost enabled +- irqdomain: Fixed unbalanced fwnode get and put +- !10518 xfs: add bounds checking to xlog_recover_process_data +- xfs: add bounds checking to xlog_recover_process_data +- !10622 leds: mlxreg: Use devm_mutex_init() for mutex initialization +- leds: mlxreg: Use devm_mutex_init() for mutex initialization +- !10677 gve: Account for stopped queues when reading NIC stats +- gve: Account for stopped queues when reading NIC stats +- !10639 s390/mm: Fix VM_FAULT_HWPOISON handling in do_exception() +- s390/mm: Fix VM_FAULT_HWPOISON handling in do_exception() +- !10653 virtcca cvm feature patches +- gicv3: add lpi support for cvm guest +- config: modify arm64 defconfig for virtcca cvm feature +- mm: enable swiotlb alloc for cvm share mem +- pmu: enable pmu phys irq inject for cvm +- kvm: add virtcca cvm host feature +- !10658 CVE-2024-35860 +- bpf: Fix a potential use-after-free in bpf_link_free() +- Fix kabi breakage in struct bpf_link and bpf_link_ops +- bpf: support deferring bpf_link dealloc to after RCU grace period +- !10649 xfs: don't walk off the end of a directory data block +- xfs: don't walk off the end of a directory data block +- !10556 smart_grid: introducing rebuild_affinity_domain +- smart_grid: introducing rebuild_affinity_domain +- !10631 sched/deadline: Fix task_struct reference leak +- sched/deadline: Fix task_struct reference leak +- !10319 block: propagate partition scanning errors to the BLKRRPART ioctl +- block: propagate partition scanning errors to the BLKRRPART ioctl +- !10500 fix CVE-2024-42155 +- s390/pkey: Wipe copies of protected- and secure-keys +- !10657 [openEuler-24.03-LTS][linux-6.6.y sync] Backport 6.6.40-6.6.44 LTS Patches +- fs: don't allow non-init s_user_ns for filesystems without FS_USERNS_MOUNT +- nvme-pci: add missing condition check for existence of mapped data +- io_uring: fix io_match_task must_hold +- iommu: sprd: Avoid NULL deref in sprd_iommu_hw_en +- s390/cpum_cf: Fix endless loop in CF_DIAG event stop +- s390/pci: Allow allocation of more than 1 MSI interrupt +- s390/pci: Refactor arch_setup_msi_irqs() +- ceph: fix incorrect kmalloc size of pagevec mempool +- ASoC: Intel: use soc_intel_is_byt_cr() only when IOSF_MBI is reachable +- spi: spidev: add correct compatible for Rohm BH2228FV +- ASoC: sof: amd: fix for firmware reload failure in Vangogh platform +- nvme-pci: Fix the instructions for disabling power management +- spi: microchip-core: ensure TX and RX FIFOs are empty at start of a transfer +- spi: microchip-core: fix init function not setting the master and motorola modes +- spi: microchip-core: switch to use modern name +- spi: microchip-core: only disable SPI controller when register value change requires it +- spi: microchip-core: defer asserting chip select until just before write to TX FIFO +- spi: microchip-core: fix the issues in the isr +- ASoC: SOF: imx8m: Fix DSP control regmap retrieval +- auxdisplay: ht16k33: Drop reference after LED registration +- lirc: rc_dev_get_from_fd(): fix file leak +- powerpc: fix a file leak in kvm_vcpu_ioctl_enable_cap() +- apparmor: Fix null pointer deref when receiving skb during sock creation +- mISDN: Fix a use after free in hfcmulti_tx() +- bpf: Fix a segment issue when downgrading gso_size +- net: nexthop: Initialize all fields in dumped nexthops +- net: stmmac: Correct byte order of perfect_match +- tipc: Return non-zero value from tipc_udp_addr2str() on error +- netfilter: nft_set_pipapo_avx2: disable softinterrupts +- ice: Fix recipe read procedure +- net: bonding: correctly annotate RCU in bond_should_notify_peers() +- ipv4: Fix incorrect source address in Record Route option +- MIPS: SMP-CPS: Fix address for GCR_ACCESS register for CM3 and later +- tools/resolve_btfids: Fix comparison of distinct pointer types warning in resolve_btfids +- bpf, events: Use prog to emit ksymbol event for main program +- dma: fix call order in dmam_free_coherent +- af_unix: Disable MSG_OOB handling for sockets in sockmap/sockhash +- libbpf: Fix no-args func prototype BTF dumping syntax +- selftests/bpf: fexit_sleep: Fix stack allocation for arm64 +- kbuild: avoid build error when single DTB is turned into composite DTB +- f2fs: fix to update user block counts in block_operations() +- watchdog: rzg2l_wdt: Check return status of pm_runtime_put() +- watchdog: rzg2l_wdt: Use pm_runtime_resume_and_get() +- f2fs: fix start segno of large section +- um: time-travel: fix signal blocking race/hang +- um: time-travel: fix time-travel-start option +- phy: zynqmp: Enable reference clock correctly +- phy: cadence-torrent: Check return value on register read +- dmaengine: ti: k3-udma: Fix BCHAN count with UHC and HC channels +- jfs: Fix array-index-out-of-bounds in diFree +- kdb: Use the passed prompt in kdb_position_cursor() +- kdb: address -Wformat-security warnings +- f2fs: fix to truncate preallocated blocks in f2fs_file_open() +- s390/mm: Fix VM_FAULT_HWPOISON handling in do_exception() +- PCI/DPC: Fix use-after-free on concurrent DPC and hot-removal +- PCI: Introduce cleanup helpers for device reference counts and locks +- wifi: mac80211: track capability/opmode NSS separately +- mm/mglru: fix ineffective protection calculation +- nilfs2: handle inconsistent state in nilfs_btnode_create_block() +- minmax: scsi: fix mis-use of 'clamp()' in sr.c +- Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x13d3:0x3591 +- Bluetooth: btusb: Add RTL8852BE device 0489:e125 to device tables +- video: logo: Drop full path of the input filename in generated file +- lib/build_OID_registry: don't mention the full path of the script in output +- rbd: don't assume RBD_LOCK_STATE_LOCKED for exclusive mappings +- rbd: rename RBD_LOCK_STATE_RELEASING and releasing_wait +- drm/panfrost: Mark simple_ondemand governor as softdep +- drm/etnaviv: don't block scheduler when GPU is still active +- MIPS: Loongson64: Test register availability before use +- MIPS: Loongson64: reset: Prioritise firmware service +- MIPS: Loongson64: Remove memory node for builtin-dtb +- MIPS: Loongson64: env: Hook up Loongsson-2K +- MIPS: dts: loongson: Fix GMAC phy node +- MIPS: ip30: ip30-console: Add missing include +- MIPS: dts: loongson: Add ISA node +- remoteproc: imx_rproc: Fix refcount mistake in imx_rproc_addr_init +- remoteproc: imx_rproc: Skip over memory region when node value is NULL +- remoteproc: stm32_rproc: Fix mailbox interrupts queuing +- rbd: don't assume rbd_is_lock_owner() for exclusive mappings +- dm-verity: fix dm_is_verity_target() when dm-verity is builtin +- selftests/sigaltstack: Fix ppc64 GCC build +- RDMA/iwcm: Fix a use-after-free related to destroying CM IDs +- platform: mips: cpu_hwmon: Disable driver on unsupported hardware +- watchdog/perf: properly initialize the turbo mode timestamp and rearm counter +- rtc: abx80x: Fix return value of nvmem callback on read +- rtc: isl1208: Fix return value of nvmem callbacks +- drm/i915/dp: Don't switch the LTTPR mode on an active link +- drm/i915/dp: Reset intel_dp->link_trained before retraining the link +- drm/amd/amdgpu: Fix uninitialized variable warnings +- drm/amdgpu: reset vm state machine after gpu reset(vram lost) +- drm/dp_mst: Fix all mstb marked as not probed after suspend/resume +- drm/udl: Remove DRM_CONNECTOR_POLL_HPD +- drm/amdgpu/sdma5.2: Update wptr registers as well as doorbell +- drm/i915/gt: Do not consider preemption during execlists_dequeue for gen8 +- perf/x86/intel/pt: Fix a topa_entry base address calculation +- perf/x86/intel/pt: Fix topa_entry base length +- perf/x86/intel/ds: Fix non 0 retire latency on Raptorlake +- perf/x86/intel/uncore: Fix the bits of the CHA extended umask for SPR +- perf stat: Fix the hard-coded metrics calculation on the hybrid +- perf: Fix event leak upon exit +- scsi: qla2xxx: validate nvme_local_port correctly +- scsi: qla2xxx: Complete command early within lock +- scsi: qla2xxx: Fix flash read failure +- scsi: qla2xxx: Reduce fabric scan duplicate code +- scsi: qla2xxx: Use QP lock to search for bsg +- scsi: qla2xxx: Fix for possible memory corruption +- scsi: qla2xxx: Unable to act on RSCN for port online +- scsi: qla2xxx: During vport delete send async logout explicitly +- scsi: lpfc: Allow DEVICE_RECOVERY mode after RSCN receipt if in PRLI_ISSUE state +- rtc: cmos: Fix return value of nvmem callbacks +- mm/numa_balancing: teach mpol_to_str about the balancing mode +- irqchip/imx-irqsteer: Handle runtime power management correctly +- irqdomain: Fixed unbalanced fwnode get and put +- devres: Fix memory leakage caused by driver API devm_free_percpu() +- devres: Fix devm_krealloc() wasting memory +- ice: Add a per-VF limit on number of FDIR filters +- gve: Fix an edge case for TSO skb validity check +- kobject_uevent: Fix OOB access within zap_modalias_env() +- ASoC: amd: yc: Support mic on Lenovo Thinkpad E16 Gen 2 +- ASoC: SOF: ipc4-topology: Preserve the DMA Link ID for ChainDMA on unprepare +- kbuild: Fix '-S -c' in x86 stack protector scripts +- decompress_bunzip2: fix rare decompression failure +- mm: fix old/young bit handling in the faulting path +- block: fix deadlock between sd_remove & sd_release +- ubi: eba: properly rollback inside self_check_eba +- clk: davinci: da8xx-cfgchip: Initialize clk_init_data before use +- f2fs: use meta inode for GC of COW file +- f2fs: use meta inode for GC of atomic file +- f2fs: fix return value of f2fs_convert_inline_inode() +- f2fs: fix to don't dirty inode for readonly filesystem +- f2fs: fix to force buffered IO on inline_data inode +- ASoC: fsl: fsl_qmc_audio: Check devm_kasprintf() returned value +- scsi: qla2xxx: Return ENOBUFS if sg_cnt is more than one for ELS cmds +- fs/ntfs3: Update log->page_{mask,bits} if log->page_size changed +- efi/libstub: Zero initialize heap allocated struct screen_info +- hostfs: fix dev_t handling +- dev/parport: fix the array out-of-bounds risk +- binder: fix hang of unregistered readers +- PCI: rockchip: Use GPIOD_OUT_LOW flag while requesting ep_gpio +- PCI: dw-rockchip: Fix initial PERST# GPIO value +- PCI: hv: Return zero, not garbage, when reading PCI_INTERRUPT_PIN +- parisc: Fix warning at drivers/pci/msi/msi.h:121 +- hwrng: amd - Convert PCIBIOS_* return codes to errnos +- tools/memory-model: Fix bug in lock.cat +- ALSA: usb-audio: Add a quirk for Sonix HD USB Camera +- ALSA: usb-audio: Move HD Webcam quirk to the right place +- ALSA: usb-audio: Fix microphone sound on HD webcam. +- ALSA: ump: Force 1 Group for MIDI1 FBs +- ALSA: ump: Don't update FB name for static blocks +- KVM: nVMX: Request immediate exit iff pending nested event needs injection +- KVM: VMX: Split out the non-virtualization part of vmx_interrupt_blocked() +- media: ivsc: csi: don't count privacy on as error +- media: uvcvideo: Fix integer overflow calculating timestamp +- jbd2: avoid infinite transaction commit loop +- jbd2: precompute number of transaction descriptor blocks +- jbd2: make jbd2_journal_get_max_txn_bufs() internal +- media: imx-pxp: Fix ERR_PTR dereference in pxp_probe() +- media: ivsc: csi: add separate lock for v4l2 control handler +- leds: mt6360: Fix memory leak in mt6360_init_isnk_properties() +- md/md-bitmap: fix writing non bitmap pages +- leds: ss4200: Convert PCIBIOS_* return codes to errnos +- drivers: soc: xilinx: check return status of get_api_version() +- wifi: rtw88: usb: Fix disconnection after beacon loss +- wifi: mwifiex: Fix interface type change +- selftests/landlock: Add cred_transfer test +- trace/pid_list: Change gfp flags in pid_list_fill_irq() +- io_uring: tighten task exit cancellations +- ext4: make sure the first directory block is not a hole +- ext4: check dot and dotdot of dx_root before making dir indexed +- m68k: amiga: Turn off Warp1260 interrupts during boot +- udf: Avoid using corrupted block bitmap buffer +- task_work: Introduce task_work_cancel() again +- task_work: s/task_work_cancel()/task_work_cancel_func()/ +- cifs: mount with "unix" mount option for SMB1 incorrectly handled +- cifs: fix reconnect with SMB1 UNIX Extensions +- cifs: fix potential null pointer use in destroy_workqueue in init_cifs error path +- apparmor: use kvfree_sensitive to free data->data +- drm/amd/display: Check for NULL pointer +- scsi: qla2xxx: Fix optrom version displayed in FDMI +- drm/gma500: fix null pointer dereference in psb_intel_lvds_get_modes +- drm/gma500: fix null pointer dereference in cdv_intel_lvds_get_modes +- io_uring/io-wq: limit retrying worker initialisation +- ext2: Verify bitmap and itable block numbers before using them +- hfs: fix to initialize fields of hfs_inode_info after hfs_alloc_inode() +- ata: libata-scsi: Honor the D_SENSE bit for CK_COND=1 and no error +- ata: libata-scsi: Do not overwrite valid sense data when CK_COND=1 +- media: venus: fix use after free in vdec_close +- char: tpm: Fix possible memory leak in tpm_bios_measurements_open() +- ata: libata-scsi: Fix offsets for the fixed format sense data +- fuse: verify {g,u}id mount options correctly +- sched/fair: set_load_weight() must also call reweight_task() for SCHED_IDLE tasks +- NFSD: Support write delegations in LAYOUTGET +- ipv6: take care of scope when choosing the src addr +- ipv4: fix source address selection with route leak +- kernel: rerun task_work while freezing in get_signal() +- btrfs: fix extent map use-after-free when adding pages to compressed bio +- af_packet: Handle outgoing VLAN packets without hardware offloading +- net: netconsole: Disable target before netpoll cleanup +- tick/broadcast: Make takeover of broadcast hrtimer reliable +- dt-bindings: thermal: correct thermal zone node name limit +- exfat: fix potential deadlock on __exfat_get_dentry_set +- x86/efistub: Revert to heap allocated boot_params for PE entrypoint +- x86/efistub: Avoid returning EFI_SUCCESS on error +- mm/mglru: fix overshooting shrinker memory +- mm: mmap_lock: replace get_memcg_path_buf() with on-stack buffer +- mm/mglru: fix div-by-zero in vmpressure_calc_level() +- mm/hugetlb: fix possible recursive locking detected warning +- hugetlb: force allocating surplus hugepages on mempolicy allowed nodes +- landlock: Don't lose track of restrictions on cred_transfer +- LoongArch: Check TIF_LOAD_WATCH to enable user space watchpoint +- sbitmap: use READ_ONCE to access map->word +- s390/dasd: fix error checks in dasd_copy_pair_store() +- powerpc/8xx: fix size given to set_huge_pte_at() +- fs/ntfs3: Keep runs for $MFT::$ATTR_DATA and $MFT::$ATTR_BITMAP +- fs/ntfs3: Missed error return +- fs/ntfs3: Fix the format of the "nocase" mount option +- rtc: interface: Add RTC offset to alarm after fix-up +- nilfs2: avoid undefined behavior in nilfs_cnt32_ge macro +- fs/proc/task_mmu: properly detect PM_MMAP_EXCLUSIVE per page of PMD-mapped THPs +- fs/proc/task_mmu: don't indicate PM_MMAP_EXCLUSIVE without PM_PRESENT +- fs/proc/task_mmu.c: add_to_pagemap: remove useless parameter addr +- fs/proc/task_mmu: indicate PM_FILE for PMD-mapped file THP +- pinctrl: renesas: r8a779g0: Fix TPU suffixes +- pinctrl: renesas: r8a779g0: Fix TCLK suffixes +- pinctrl: renesas: r8a779g0: FIX PWM suffixes +- pinctrl: renesas: r8a779g0: Fix IRQ suffixes +- pinctrl: renesas: r8a779g0: Fix (H)SCIF3 suffixes +- pinctrl: renesas: r8a779g0: Fix (H)SCIF1 suffixes +- pinctrl: renesas: r8a779g0: Fix FXR_TXEN[AB] suffixes +- pinctrl: renesas: r8a779g0: Fix CANFD5 suffix +- fs/ntfs3: Fix field-spanning write in INDEX_HDR +- fs/ntfs3: Drop stray '' (backslash) in formatting string +- fs/ntfs3: Correct undo if ntfs_create_inode failed +- fs/ntfs3: Replace inode_trylock with inode_lock +- pinctrl: freescale: mxs: Fix refcount of child +- pinctrl: ti: ti-iodelay: fix possible memory leak when pinctrl_enable() fails +- pinctrl: ti: ti-iodelay: Drop if block with always false condition +- pinctrl: single: fix possible memory leak when pinctrl_enable() fails +- pinctrl: core: fix possible memory leak when pinctrl_enable() fails +- pinctrl: rockchip: update rk3308 iomux routes +- fs/ntfs3: Add missing .dirty_folio in address_space_operations +- fs/ntfs3: Fix getting file type +- fs/ntfs3: Missed NI_FLAG_UPDATE_PARENT setting +- fs/ntfs3: Deny getting attr data block in compressed frame +- fs/ntfs3: Fix transform resident to nonresident for compressed files +- fs/ntfs3: Merge synonym COMPRESSION_UNIT and NTFS_LZNT_CUNIT +- net: dsa: b53: Limit chip-wide jumbo frame config to CPU ports +- net: dsa: mv88e6xxx: Limit chip-wide frame size config to CPU ports +- ipv4: Fix incorrect TOS in fibmatch route get reply +- ipv4: Fix incorrect TOS in route get reply +- net: flow_dissector: use DEBUG_NET_WARN_ON_ONCE +- gve: Fix XDP TX completion handling when counters overflow +- ipvs: properly dereference pe in ip_vs_add_service +- netfilter: nf_set_pipapo: fix initial map fill +- netfilter: nft_set_pipapo: constify lookup fn args where possible +- netfilter: ctnetlink: use helper function to calculate expect ID +- bnxt_re: Fix imm_data endianness +- RDMA: Fix netdev tracker in ib_device_set_netdev +- RDMA/core: Remove NULL check before dev_{put, hold} +- iommu/vt-d: Fix identity map bounds in si_domain_init() +- macintosh/therm_windtunnel: fix module unload. +- powerpc/xmon: Fix disassembly CPU feature checks +- PCI: dwc: Fix index 0 incorrectly being interpreted as a free ATU slot +- PCI: qcom-ep: Disable resources unconditionally during PERST# assert +- MIPS: Octeron: remove source file executable bit +- clk: en7523: fix rate divider for slic and spi clocks +- clk: qcom: Park shared RCGs upon registration +- clk: qcom: kpss-xcc: Return of_clk_add_hw_provider to transfer the error +- crypto: qat - extend scope of lock in adf_cfg_add_key_value_param() +- nvmem: rockchip-otp: set add_legacy_fixed_of_cells config option +- net: missing check virtio +- vhost/vsock: always initialize seqpacket_allow +- PCI: endpoint: Fix error handling in epf_ntb_epc_cleanup() +- PCI: endpoint: Clean up error handling in vpci_scan_bus() +- ASoC: amd: Adjust error handling in case of absent codec device +- Input: elan_i2c - do not leave interrupt disabled on suspend failure +- RDMA/device: Return error earlier if port in not valid +- mtd: make mtd_test.c a separate module +- ASoC: max98088: Check for clk_prepare_enable() error +- powerpc/prom: Add CPU info to hardware description string later +- hwrng: core - Fix wrong quality calculation at hw rng registration +- scsi: lpfc: Fix a possible null pointer dereference +- ASoC: qcom: Adjust issues in case of DT error in asoc_qcom_lpass_cpu_platform_probe() +- RDMA/rxe: Don't set BTH_ACK_MASK for UC or UD QPs +- RDMA/mlx5: Use sq timestamp as QP timestamp when RoCE is disabled +- RDMA/mlx4: Fix truncated output warning in alias_GUID.c +- RDMA/mlx4: Fix truncated output warning in mad.c +- Input: qt1050 - handle CHIP_ID reading error +- interconnect: qcom: qcm2290: Fix mas_snoc_bimc RPM master ID +- clk: qcom: gpucc-sa8775p: Update wait_val fields for GPU GDSC's +- clk: qcom: gpucc-sa8775p: Park RCG's clk source at XO during disable +- clk: qcom: gpucc-sa8775p: Remove the CLK_IS_CRITICAL and ALWAYS_ON flags +- clk: qcom: gcc-sa8775p: Update the GDSC wait_val fields and flags +- clk: qcom: gpucc-sm8350: Park RCG's clk source at XO during disable +- RDMA/cache: Release GID table even if leak is detected +- usb: typec-mux: nb7vpq904m: unregister typec switch on probe error and remove +- ASoC: cs35l56: Accept values greater than 0 as IRQ numbers +- ASoc: tas2781: Enable RCA-based playback without DSP firmware download +- RDMA/mlx5: Set mkeys for dmabuf at PAGE_SIZE +- coresight: Fix ref leak when of_coresight_parse_endpoint() fails +- KVM: PPC: Book3S HV: Fix the get_one_reg of SDAR +- KVM: PPC: Book3S HV: Fix the set_one_reg for MMCR3 +- iio: frequency: adrf6780: rm clk provider include +- clk: qcom: camcc-sc7280: Add parent dependency to all camera GDSCs +- clk: qcom: gcc-sc7280: Update force mem core bit for UFS ICE clock +- scsi: ufs: mcq: Fix missing argument 'hba' in MCQ_OPR_OFFSET_n +- PCI: rcar: Demote WARN() to dev_warn_ratelimited() in rcar_pcie_wakeup() +- PCI: keystone: Fix NULL pointer dereference in case of DT error in ks_pcie_setup_rc_app_regs() +- PCI: keystone: Don't enable BAR 0 for AM654x +- PCI: keystone: Relocate ks_pcie_set/clear_dbi_mode() +- PCI: Fix resource double counting on remove & rescan +- iio: Fix the sorting functionality in iio_gts_build_avail_time_table +- SUNRPC: Fixup gss_status tracepoint error output +- sparc64: Fix incorrect function signature and add prototype for prom_cif_init +- leds: flash: leds-qcom-flash: Test the correct variable in init +- ext4: avoid writing unitialized memory to disk in EA inodes +- ext4: don't track ranges in fast_commit if inode has inlined data +- NFSv4.1 another fix for EXCHGID4_FLAG_USE_PNFS_DS for DS server +- SUNRPC: avoid soft lockup when transmitting UDP to reachable server. +- xprtrdma: Fix rpcrdma_reqs_reset() +- mfd: omap-usb-tll: Use struct_size to allocate tll +- mfd: rsmu: Split core code into separate module +- perf intel-pt: Fix exclude_guest setting +- perf intel-pt: Fix aux_watermark calculation for 64-bit size +- media: venus: flush all buffers in output plane streamoff +- drm/mediatek/dp: Fix spurious kfree() +- drm/mediatek/dp: switch to ->edid_read callback +- ext4: fix infinite loop when replaying fast_commit +- drm/mediatek: Remove less-than-zero comparison of an unsigned value +- Revert "leds: led-core: Fix refcount leak in of_led_get()" +- drm/qxl: Add check for drm_cvt_mode +- drm/etnaviv: fix DMA direction handling for cached RW buffers +- perf report: Fix condition in sort__sym_cmp() +- perf pmus: Fixes always false when compare duplicates aliases +- perf test: Make test_arm_callgraph_fp.sh more robust +- drm/msm/dpu: drop validity checks for clear_pending_flush() ctl op +- drm/msm/dsi: set VIDEO_COMPRESSION_MODE_CTRL_WC +- leds: trigger: Unregister sysfs attributes before calling deactivate() +- media: imx-jpeg: Drop initial source change event if capture has been setup +- drm/mediatek: Add OVL compatible name for MT8195 +- drm/mediatek: Turn off the layers with zero width or height +- drm/mediatek: Fix destination alpha error in OVL +- drm/mediatek: Fix XRGB setting error in Mixer +- drm/mediatek: Fix XRGB setting error in OVL +- drm/mediatek: Use 8-bit alpha in ETHDR +- drm/mediatek: Add missing plane settings when async update +- media: renesas: vsp1: Store RPF partition configuration per RPF instance +- media: renesas: vsp1: Fix _irqsave and _irq mix +- media: rcar-csi2: Cleanup subdevice in remove() +- media: rcar-csi2: Disable runtime_pm in probe error +- media: rcar-vin: Fix YUYV8_1X16 handling for CSI-2 +- drm: zynqmp_kms: Fix AUX bus not getting unregistered +- drm: zynqmp_dpsub: Fix an error handling path in zynqmp_dpsub_probe() +- media: uvcvideo: Override default flags +- media: uvcvideo: Add quirk for invalid dev_sof in Logitech C920 +- media: uvcvideo: Quirk for invalid dev_sof in Logitech C922 +- media: uvcvideo: Disable autosuspend for Insta360 Link +- media: i2c: imx219: fix msr access command sequence +- saa7134: Unchecked i2c_transfer function result fixed +- ipmi: ssif_bmc: prevent integer overflow on 32bit systems +- x86/shstk: Make return uprobe work with shadow stack +- media: mediatek: vcodec: Handle invalid decoder vsi +- s390/uv: Don't call folio_wait_writeback() without a folio reference +- s390/mm: Convert gmap_make_secure to use a folio +- s390/mm: Convert make_page_secure to use a folio +- media: v4l: async: Fix NULL pointer dereference in adding ancillary links +- media: i2c: Fix imx412 exposure control +- media: imon: Fix race getting ictx->lock +- media: pci: ivtv: Add check for DMA map result +- drm/bridge: it6505: fix hibernate to resume no display issue +- drm/bridge: Fixed a DP link training bug +- drm/panel: boe-tv101wum-nl6: Check for errors on the NOP in prepare() +- drm/panel: boe-tv101wum-nl6: If prepare fails, disable GPIO before regulators +- drm/panel: himax-hx8394: Handle errors from mipi_dsi_dcs_set_display_on() better +- drm/amdgpu: Remove GC HW IP 9.3.0 from noretry=1 +- drm/amdgpu: Check if NBIO funcs are NULL in amdgpu_device_baco_exit +- drm/amdgpu: Fix memory range calculation +- drm/amd/pm: Fix aldebaran pcie speed reporting +- drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_generic_write_seq() +- drm/mipi-dsi: Fix theoretical int overflow in mipi_dsi_dcs_write_seq() +- drm/amdkfd: Fix CU Masking for GFX 9.4.3 +- drm/arm/komeda: Fix komeda probe failing if there are no links in the secondary pipeline +- drm/rockchip: vop2: Fix the port mux of VP2 +- net: bridge: mst: Check vlan state for egress decision +- xdp: fix invalid wait context of page_pool_destroy() +- Bluetooth: btnxpuart: Add handling for boot-signature timeout errors +- Bluetooth: btintel: Refactor btintel_set_ppag() +- Bluetooth: hci_bcm4377: Use correct unit for timeouts +- selftests: forwarding: devlink_lib: Wait for udev events after reloading +- bpf: Eliminate remaining "make W=1" warnings in kernel/bpf/btf.o +- bna: adjust 'name' buf size of bna_tcb and bna_ccb structures +- bpf: annotate BTF show functions with __printf +- selftests/resctrl: Fix closing IMC fds on error and open-code R+W instead of loops +- selftests/resctrl: Convert perror() to ksft_perror() or ksft_print_msg() +- selftests/resctrl: Move run_benchmark() to a more fitting file +- selftests/bpf: Close obj in error path in xdp_adjust_tail +- selftests/bpf: Null checks for links in bpf_tcp_ca +- selftests/bpf: Close fd in error path in drop_on_reuseport +- locking/rwsem: Add __always_inline annotation to __down_write_common() and inlined callers +- wifi: virt_wifi: don't use strlen() in const context +- gss_krb5: Fix the error handling path for crypto_sync_skcipher_setkey +- wifi: virt_wifi: avoid reporting connection success with wrong SSID +- xfrm: call xfrm_dev_policy_delete when kill policy +- xfrm: fix netdev reference count imbalance +- wifi: rtw89: Fix array index mistake in rtw89_sta_info_get_iter() +- perf/x86/intel/cstate: Fix Alderlake/Raptorlake/Meteorlake +- perf: Fix default aux_watermark calculation +- perf: Prevent passing zero nr_pages to rb_alloc_aux() +- perf: Fix perf_aux_size() for greater-than 32-bit size +- perf/x86/intel/pt: Fix pt_topa_entry_for_page() address calculation +- bpftool: Mount bpffs when pinmaps path not under the bpffs +- wifi: rtl8xxxu: 8188f: Limit TX power index +- wifi: rtw89: 8852b: fix definition of KIP register number +- netfilter: nf_tables: rise cap on SELinux secmark context +- ipvs: Avoid unnecessary calls to skb_is_gso_sctp +- libbpf: Checking the btf_type kind when fixing variable offsets +- net: fec: Fix FEC_ECR_EN1588 being cleared on link-down +- net: fec: Refactor: #define magic constants +- udf: Fix bogus checksum computation in udf_rename() +- wifi: cfg80211: handle 2x996 RU allocation in cfg80211_calculate_bitrate_he() +- wifi: cfg80211: fix typo in cfg80211_calculate_bitrate_he() +- wifi: ath11k: fix wrong handling of CCMP256 and GCMP ciphers +- jump_label: Fix concurrency issues in static_key_slow_dec() +- perf/x86: Serialize set_attr_rdpmc() +- mlxsw: spectrum_acl: Fix ACL scale regression and firmware errors +- mlxsw: spectrum_acl_erp: Fix object nesting warning +- lib: objagg: Fix general protection fault +- udf: Fix lock ordering in udf_evict_inode() +- selftests/bpf: Check length of recv in test_sockmap +- net/smc: set rmb's SG_MAX_SINGLE_ALLOC limitation only when CONFIG_ARCH_NO_SG_CHAIN is defined +- tcp: fix races in tcp_v[46]_err() +- tcp: fix race in tcp_write_err() +- tcp: add tcp_done_with_error() helper +- wifi: ath12k: fix wrong definition of CE ring's base address +- wifi: ath11k: fix wrong definition of CE ring's base address +- wifi: ath11k: Update Qualcomm Innovation Center, Inc. copyrights +- wifi: ath12k: fix firmware crash during reo reinject +- wifi: ath12k: fix invalid memory access while processing fragmented packets +- wifi: ath12k: change DMA direction while mapping reinjected packets +- net: esp: cleanup esp_output_tail_tcp() in case of unsupported ESPINTCP +- selftests/bpf: Fix prog numbers in test_sockmap +- bpftool: Un-const bpf_func_info to fix it for llvm 17 and newer +- wifi: ath12k: Fix tx completion ring (WBM2SW) setup failure +- wifi: ath12k: Correct 6 GHz frequency value in rx status +- wifi: brcmsmac: LCN PHY code is used for BCM4313 2G-only device +- firmware: turris-mox-rwtm: Initialize completion before mailbox +- firmware: turris-mox-rwtm: Fix checking return value of wait_for_completion_timeout() +- firmware: turris-mox-rwtm: Do not complete if there are no waiters +- vmlinux.lds.h: catch .bss..L* sections into BSS") +- ARM: spitz: fix GPIO assignment for backlight +- m68k: cmpxchg: Fix return value for default case in __arch_xchg() +- cpufreq/amd-pstate: Fix the scaling_max_freq setting on shared memory CPPC systems +- arm64: dts: qcom: sm6350: Add missing qcom,non-secure-domain property +- arm64: dts: rockchip: fixes PHY reset for Lunzn Fastrhino R68S +- arm64: dts: rockchip: disable display subsystem for Lunzn Fastrhino R6xS +- arm64: dts: rockchip: remove unused usb2 nodes for Lunzn Fastrhino R6xS +- arm64: dts: rockchip: fix pmu_io supply for Lunzn Fastrhino R6xS +- arm64: dts: rockchip: fix usb regulator for Lunzn Fastrhino R6xS +- arm64: dts: rockchip: fix regulator name for Lunzn Fastrhino R6xS +- arm64: dts: rockchip: Add missing power-domains for rk356x vop_mmu +- x86/xen: Convert comma to semicolon +- arm64: dts: imx8mp: Fix pgc vpu locations +- arm64: dts: imx8mp: add HDMI power-domains +- arm64: dts: imx8mp: Fix pgc_mlmix location +- arm64: dts: imx8mp: Add NPU Node +- m68k: atari: Fix TT bootup freeze / unexpected (SCU) interrupt messages +- arm64: dts: renesas: r9a07g054: Add missing hypervisor virtual timer IRQ +- arm64: dts: renesas: r9a07g044: Add missing hypervisor virtual timer IRQ +- arm64: dts: renesas: r9a07g043u: Add missing hypervisor virtual timer IRQ +- arm64: dts: renesas: r8a779g0: Add missing hypervisor virtual timer IRQ +- arm64: dts: renesas: r8a779f0: Add missing hypervisor virtual timer IRQ +- arm64: dts: renesas: r8a779a0: Add missing hypervisor virtual timer IRQ +- arm64: dts: rockchip: Fix mic-in-differential usage on rk3568-evb1-v10 +- arm64: dts: rockchip: Fix mic-in-differential usage on rk3566-roc-pc +- arm64: dts: rockchip: Drop invalid mic-in-differential on rk3568-rock-3a +- arm64: dts: amlogic: setup hdmi system clock +- arm64: dts: amlogic: add power domain to hdmitx +- arm64: dts: amlogic: gx: correct hdmi clocks +- arm64: dts: mediatek: mt8183-kukui-jacuzzi: Add ports node for anx7625 +- arm64: dts: mediatek: mt8183-kukui: Fix the value of `dlg,jack-det-rate` mismatch +- arm64: dts: mediatek: mt7622: fix "emmc" pinctrl mux +- arm64: dts: mediatek: mt8192-asurada: Add off-on-delay-us for pp3300_mipibrdg +- arm64: dts: mediatek: mt8183-kukui: Drop bogus output-enable property +- arm64: dts: mediatek: mt8195: Fix GPU thermal zone name for SVS +- ARM: dts: imx6qdl-kontron-samx6i: fix PCIe reset polarity +- ARM: dts: imx6qdl-kontron-samx6i: fix SPI0 chip selects +- ARM: dts: imx6qdl-kontron-samx6i: fix board reset +- ARM: dts: imx6qdl-kontron-samx6i: fix PHY reset +- ARM: dts: imx6qdl-kontron-samx6i: fix phy-mode +- arm64: dts: amlogic: sm1: fix spdif compatibles +- arm64: dts: rockchip: Increase VOP clk rate on RK3328 +- soc: qcom: pdr: fix parsing of domains lists +- soc: qcom: pdr: protect locator_addr with the main mutex +- soc: qcom: icc-bwmon: Fix refcount imbalance seen during bwmon_remove +- arm64: dts: qcom: qdu1000: Add secure qfprom node +- arm64: dts: qcom: qdu1000-idp: drop unused LLCC multi-ch-bit-off +- arm64: dts: ti: k3-am62-verdin: Drop McASP AFIFOs +- arm64: dts: ti: k3-am625-beagleplay: Drop McASP AFIFOs +- arm64: dts: ti: k3-am62x: Drop McASP AFIFOs +- memory: fsl_ifc: Make FSL_IFC config visible and selectable +- OPP: ti: Fix ti_opp_supply_probe wrong return values +- cpufreq: ti-cpufreq: Handle deferred probe with dev_err_probe() +- arm64: dts: qcom: qrb4210-rb2: make L9A always-on +- ARM: dts: stm32: Add arm,no-tick-in-suspend to STM32MP15xx STGEN timer +- ARM: dts: sunxi: remove duplicated entries in makefile +- soc: xilinx: rename cpu_number1 to dummy_cpu_number +- arm64: dts: qcom: sa8775p: mark ethernet devices as DMA-coherent +- arm64: dts: qcom: msm8996: specify UFS core_clk frequencies +- arm64: dts: rockchip: Update WIFi/BT related nodes on rk3308-rock-pi-s +- arm64: dts: rockchip: Add mdio and ethernet-phy nodes to rk3308-rock-pi-s +- arm64: dts: rockchip: Add pinctrl for UART0 to rk3308-rock-pi-s +- arm64: dts: rockchip: Add sdmmc related properties on rk3308-rock-pi-s +- soc: qcom: rpmh-rsc: Ensure irqs aren't disabled by rpmh_rsc_send_data() callers +- soc: qcom: pmic_glink: Handle the return value of pmic_glink_init +- arm64: dts: qcom: msm8998: enable adreno_smmu by default +- arm64: dts: qcom: sdm850-lenovo-yoga-c630: fix IPA firmware path +- arm64: dts: qcom: msm8996-xiaomi-common: drop excton from the USB PHY +- arm64: dts: qcom: sm8450: add power-domain to UFS PHY +- arm64: dts: qcom: sm8350: add power-domain to UFS PHY +- arm64: dts: qcom: sm8250: add power-domain to UFS PHY +- arm64: dts: qcom: sm8250: switch UFS QMP PHY to new style of bindings +- arm64: dts: qcom: sm6350: add power-domain to UFS PHY +- arm64: dts: qcom: sm6115: add power-domain to UFS PHY +- arm64: dts: qcom: sdm845: add power-domain to UFS PHY +- arm64: dts: qcom: sc8180x: add power-domain to UFS PHY +- arm64: dts: qcom: sc8180x: switch UFS QMP PHY to new style of bindings +- arm64: dts: qcom: sc8180x: Correct PCIe slave ports +- hwmon: (max6697) Fix swapped temp{1,8} critical alarms +- hwmon: (max6697) Fix underflow when writing limit attributes +- pwm: atmel-tcb: Fix race condition and convert to guards +- drm/meson: fix canvas release in bind function +- nvmet-auth: fix nvmet_auth hash error handling +- pwm: stm32: Always do lazy disabling +- md: Don't wait for MD_RECOVERY_NEEDED for HOT_REMOVE_DISK ioctl +- block/mq-deadline: Fix the tag reservation code +- block: Call .limit_depth() after .hctx has been set +- hwmon: (adt7475) Fix default duty on fan is disabled +- x86/platform/iosf_mbi: Convert PCIBIOS_* return codes to errnos +- x86/pci/xen: Fix PCIBIOS_* return code handling +- x86/pci/intel_mid_pci: Fix PCIBIOS_* return code handling +- x86/of: Return consistent error type from x86_of_pci_irq_enable() +- hfsplus: fix to avoid false alarm of circular locking +- x86/kconfig: Add as-instr64 macro to properly evaluate AS_WRUSS +- block: initialize integrity buffer to zero before writing it to media +- ubd: untagle discard vs write zeroes not support handling +- ubd: refactor the interrupt handler +- platform/chrome: cros_ec_debugfs: fix wrong EC message version +- md: fix deadlock between mddev_suspend and flush bio +- rcu/tasks: Fix stale task snaphot for Tasks Trace +- EDAC, i10nm: make skx_common.o a separate module +- spi: atmel-quadspi: Add missing check for clk_prepare +- spi: spi-microchip-core: Fix the number of chip selects supported +- powerpc/configs: Update defconfig with now user-visible CONFIG_FSL_IFC +- ALSA: seq: ump: Skip useless ports for static blocks +- ALSA: pcm_dmaengine: Don't synchronize DMA channel when DMA is paused +- arm64: dts: qcom: sdm630: Disable SS instance in Parkmode for USB +- arm64: dts: qcom: ipq6018: Disable SS instance in Parkmode for USB +- arm64: dts: qcom: sm6350: Disable SS instance in Parkmode for USB +- arm64: dts: qcom: msm8996: Disable SS instance in Parkmode for USB +- arm64: dts: qcom: qrb4210-rb2: switch I2C2 to i2c-gpio +- ALSA: hda/realtek: Fix the speaker output on Samsung Galaxy Book Pro 360 +- ALSA: hda/realtek: Enable headset mic on Positivo SU C1400 +- usb: gadget: midi2: Fix incorrect default MIDI2 protocol setup +- jfs: don't walk off the end of ealist +- ocfs2: add bounds checking to ocfs2_check_dir_entry() +- cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie() +- cachefiles: fix slab-use-after-free in fscache_withdraw_volume() +- netfs, fscache: export fscache_put_volume() and add fscache_try_get_volume() +- wifi: iwlwifi: mvm: don't wake up rx_sync_waitq upon RFKILL +- wifi: mac80211: disable softirqs for queued frame handling +- wifi: cfg80211: wext: set ssids=NULL for passive scans +- of/irq: Disable "interrupt-map" parsing for PASEMI Nemo +- mm: page_ref: remove folio_try_get_rcu() +- ARM: 9324/1: fix get_user() broken with veneer +- cifs: fix noisy message on copy_file_range +- ALSA: hda: Use imply for suggesting CONFIG_SERIAL_MULTI_INSTANTIATE +- spi: mux: set ctlr->bits_per_word_mask +- selftests/bpf: Extend tcx tests to cover late tcx_entry release +- hfsplus: fix uninit-value in copy_name +- selftests/vDSO: fix clang build errors and warnings +- selftest/timerns: fix clang build failures for abs() calls +- ASoC: SOF: Intel: hda-pcm: Limit the maximum number of periods by MAX_BDL_ENTRIES +- ksmbd: return FILE_DEVICE_DISK instead of super magic +- spi: imx: Don't expect DMA for i.MX{25,35,50,51,53} cspi devices +- riscv: stacktrace: fix usage of ftrace_graph_ret_addr() +- drivers/perf: riscv: Reset the counter to hpmevent mapping while starting cpus +- wifi: iwlwifi: properly set WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK +- fs: better handle deep ancestor chains in is_subdir() +- drm/radeon: check bo_va->bo is non-NULL before using it +- drm/amd/display: Fix refresh rate range for some panel +- drm/amd/display: Account for cursor prefetch BW in DML1 mode support +- drm/amd/display: Add refresh rate range check +- erofs: ensure m_llen is reset to 0 if metadata is invalid +- Bluetooth: btnxpuart: Enable Power Save feature on startup +- tee: optee: ffa: Fix missing-field-initializers warning +- scsi: libsas: Fix exp-attached device scan after probe failure scanned in again after probe failed +- powerpc/pseries: Whitelist dtl slub object for copying to userspace +- net: mac802154: Fix racy device stats updates by DEV_STATS_INC() and DEV_STATS_ADD() +- net: usb: qmi_wwan: add Telit FN912 compositions +- ASoC: amd: yc: Fix non-functional mic on ASUS M5602RA +- ALSA: dmaengine_pcm: terminate dmaengine before synchronize +- ALSA: hda/relatek: Enable Mute LED on HP Laptop 15-gw0xxx +- ALSA: PCM: Allow resume only for suspended streams +- ibmvnic: Add tx check to prevent skb leak +- btrfs: qgroup: fix quota root leak after quota disable failure +- platform/x86: lg-laptop: Use ACPI device handle when evaluating WMAB/WMBB +- platform/x86: lg-laptop: Change ACPI device id +- platform/x86: lg-laptop: Remove LGEX0815 hotkey handling +- platform/x86: wireless-hotkey: Add support for LG Airplane Button +- platform/mellanox: nvsw-sn2201: Add check for platform_device_add_resources +- s390/sclp: Fix sclp_init() cleanup on failure +- octeontx2-pf: Fix coverity and klockwork issues in octeon PF driver +- gpio: pca953x: fix pca953x_irq_bus_sync_unlock race +- can: kvaser_usb: fix return value for hif_usb_send_regout +- Input: ads7846 - use spi_device_id table +- nvme: fix NVME_NS_DEAC may incorrectly identifying the disk as EXT_LBA. +- ASoC: rt722-sdca-sdw: add debounce time for type detection +- ASoC: SOF: sof-audio: Skip unprepare for in-use widgets on error rollback +- ASoC: ti: omap-hdmi: Fix too long driver name +- ASoC: ti: davinci-mcasp: Set min period size using FIFO config +- ALSA: dmaengine: Synchronize dma channel after drop() +- bytcr_rt5640 : inverse jack detect for Archos 101 cesium +- Input: xpad - add support for ASUS ROG RAIKIRI PRO +- ASoC: rt722-sdca-sdw: add silence detection register as volatile +- Input: i8042 - add Ayaneo Kun to i8042 quirk table +- Input: elantech - fix touchpad state on resume for Lenovo N24 +- mips: fix compat_sys_lseek syscall +- ALSA: hda: cs35l56: Select SERIAL_MULTI_INSTANTIATE +- drm/amdgpu: Indicate CU havest info to CP +- selftests: openvswitch: Set value to nla flags. +- cpumask: limit FORCE_NR_CPUS to just the UP case +- spi: Fix OCTAL mode support +- ALSA: hda/realtek: Add more codec ID to no shutup pins list +- drm/vmwgfx: Fix missing HYPERVISOR_GUEST dependency +- KVM: PPC: Book3S HV: Prevent UAF in kvm_spapr_tce_attach_iommu_group() +- ALSA: hda/realtek: Support Lenovo Thinkbook 16P Gen 5 +- ALSA: hda: cs35l56: Fix lifecycle of codec pointer +- nvmet: always initialize cqe.result +- nvme: avoid double free special payload +- drm/mediatek: Call drm_atomic_helper_shutdown() at shutdown time +- drm: panel-orientation-quirks: Add quirk for Aya Neo KUN +- drm/exynos: dp: drop driver owner initialization +- iomap: Fix iomap_adjust_read_range for plen calculation +- mei: demote client disconnect warning on suspend to debug +- fs/file: fix the check in find_next_fd() +- nfs: don't invalidate dentries on transient errors +- nfs: Avoid flushing many pages with NFS_FILE_SYNC +- nfs: propagate readlink errors in nfs_symlink_filler +- HID: Ignore battery for ELAN touchscreens 2F2C and 4116 +- input: Add support for "Do Not Disturb" +- input: Add event code for accessibility key +- kconfig: remove wrong expr_trans_bool() +- kconfig: gconf: give a proper initial state to the Save button +- ila: block BH in ila_output() +- net: ipv6: rpl_iptunnel: block BH in rpl_output() and rpl_input() +- Input: silead - Always support 10 fingers +- of/irq: Factor out parsing of interrupt-map parent phandle+args from of_irq_parse_raw() +- selftests/futex: pass _GNU_SOURCE without a value to the compiler +- selftests/openat2: Fix build warnings on ppc64 +- selftests: cachestat: Fix build warnings on ppc64 +- wifi: mac80211: fix UBSAN noise in ieee80211_prep_hw_scan() +- wifi: iwlwifi: mvm: Fix scan abort handling with HW rfkill +- wifi: iwlwifi: mvm: properly set 6 GHz channel direct probe option +- wifi: iwlwifi: mvm: handle BA session teardown in RF-kill +- wifi: iwlwifi: mvm: Handle BIGTK cipher in kek_kck cmd +- wifi: iwlwifi: mvm: remove stale STA link data during restart +- wifi: iwlwifi: mvm: d3: fix WoWLAN command version lookup +- wifi: cfg80211: fix 6 GHz scan request building +- wifi: mac80211: handle tasklet frames before stopping +- wifi: mac80211: apply mcast rate only if interface is up +- wifi: mac80211: mesh: init nonpeer_pm to active by default in mesh sdata +- tools/power/cpupower: Fix Pstate frequency reporting on AMD Family 1Ah CPUs +- ACPI: EC: Avoid returning AE_OK on errors in address space handler +- ACPI: EC: Abort address space access upon error +- efi/libstub: zboot.lds: Discard .discard sections +- scsi: qedf: Set qed_slowpath_params to zero before use +- scsi: qedf: Wait for stag work during unload +- scsi: qedf: Don't process stag work during unload and recovery +- scsi: sr: Fix unintentional arithmetic wraparound +- scsi: core: alua: I/O errors for ALUA state transitions +- filelock: Remove locks reliably when fcntl/close race is detected +- i2c: rcar: fix error code in probe() +- kbuild: Make ld-version.sh more robust against version string changes +- x86/bhi: Avoid warning in #DB handler due to BHI mitigation +- x86/entry/64: Remove obsolete comment on tracing vs. SYSRET +- x86/entry: Rename ignore_sysret() +- i2c: rcar: clear NO_RXDMA flag after resetting +- i2c: testunit: avoid re-issued work after read message +- i2c: rcar: ensure Gen3+ reset does not disturb local targets +- i2c: rcar: introduce Gen4 devices +- i2c: rcar: reset controller is mandatory for Gen3+ +- i2c: mark HostNotify target address as used +- i2c: rcar: bring hardware to known state when probing +- btrfs: tree-checker: add type and sequence check for inline backrefs +- ext4: avoid ptr null pointer dereference +- nilfs2: fix kernel bug on rename operation of broken directory +- selftests/net: fix gro.c compilation failure due to non-existent opt_ipproto_off +- mm/damon/core: merge regions aggressively when max_nr_regions is unmet +- mm/shmem: disable PMD-sized page cache if needed +- misc: fastrpc: Restrict untrusted app to attach to privileged PD +- misc: fastrpc: Fix ownership reassignment of remote heap +- misc: fastrpc: Fix memory leak in audio daemon attach operation +- misc: fastrpc: Copy the complete capability structure to user +- misc: fastrpc: Avoid updating PD type for capability request +- misc: fastrpc: Fix DSP capabilities request +- wireguard: send: annotate intentional data race in checking empty queue +- wireguard: queueing: annotate intentional data race in cpu round robin +- wireguard: allowedips: avoid unaligned 64-bit memory accesses +- wireguard: selftests: use acpi=off instead of -no-acpi for recent QEMU +- cpufreq: Allow drivers to advertise boost enabled +- cpufreq: ACPI: Mark boost policy as enabled when setting boost +- ACPI: processor_idle: Fix invalid comparison with insertion sort for latency +- libceph: fix race between delayed_work() and ceph_monc_stop() +- pmdomain: qcom: rpmhpd: Skip retention level for Power Domains +- Fix userfaultfd_api to return EINVAL as expected +- ALSA: hda/realtek: Limit mic boost on VAIO PRO PX +- ALSA: hda/realtek: Enable Mute LED on HP 250 G7 +- ALSA: hda/realtek: add quirk for Clevo V5[46]0TU +- tty: serial: ma35d1: Add a NULL check for of_node +- platform/x86: toshiba_acpi: Fix array out-of-bounds access +- nvmem: core: only change name to fram for current attribute +- nvmem: meson-efuse: Fix return value of nvmem callbacks +- nvmem: rmem: Fix return value of rmem_read() +- arm64: dts: qcom: sc8280xp-x13s: fix touchscreen power on +- arm64: dts: qcom: sa8775p: Correct IRQ number of EL2 non-secure physical timer +- iio: trigger: Fix condition for own trigger +- ksmbd: discard write access to the directory open +- mm/filemap: make MAX_PAGECACHE_ORDER acceptable to xarray +- mm/filemap: skip to create PMD-sized page cache if needed +- mm: vmalloc: check if a hash-index is in cpu_possible_mask +- s390/mm: Add NULL pointer check to crst_table_free() base_crst_free() +- xhci: always resume roothubs if xHC was reset during resume +- hpet: Support 32-bit userspace +- misc: microchip: pci1xxxx: Fix return value of nvmem callbacks +- USB: core: Fix duplicate endpoint bug by clearing reserved bits in the descriptor +- usb: gadget: configfs: Prevent OOB read/write in usb_string_copy() +- usb: dwc3: pci: add support for the Intel Panther Lake +- USB: Add USB_QUIRK_NO_SET_INTF quirk for START BP-850k +- USB: serial: mos7840: fix crash on resume +- USB: serial: option: add Rolling RW350-GL variants +- USB: serial: option: add Netprisma LCUK54 series modules +- USB: serial: option: add support for Foxconn T99W651 +- USB: serial: option: add Fibocom FM350-GL +- USB: serial: option: add Telit FN912 rmnet compositions +- USB: serial: option: add Telit generic core-dump composition +- net: ks8851: Fix potential TX stall after interface reopen +- net: ks8851: Fix deadlock with the SPI chip variant +- Revert "sched/fair: Make sure to try to detach at least one movable task" +- cifs: fix setting SecurityFlags to true +- octeontx2-af: fix issue with IPv4 match for RSS +- octeontx2-af: fix issue with IPv6 ext match for RSS +- octeontx2-af: fix detection of IP layer +- octeontx2-af: fix a issue with cpt_lf_alloc mailbox +- octeontx2-af: replace cpt slot with lf id on reg write +- i40e: fix: remove needless retries of NVM update +- ARM: davinci: Convert comma to semicolon +- ASoC: SOF: Intel: hda: fix null deref on system suspend entry +- firmware: cs_dsp: Prevent buffer overrun when processing V2 alg headers +- firmware: cs_dsp: Validate payload length before processing block +- firmware: cs_dsp: Return error if block header overflows file +- arm64: dts: qcom: sc8180x: Fix LLCC reg property again +- s390: Mark psw in __load_psw_mask() as __unitialized +- net, sunrpc: Remap EPERM in case of connection failure in xs_tcp_setup_socket +- ethtool: netlink: do not return SQI value if link is down +- net: ethernet: mtk-star-emac: set mac_managed_pm when probing +- bpf: Fail bpf_timer_cancel when callback is being cancelled +- bpf: replace bpf_timer_init with a generic helper +- bpf: make timer data struct more generic +- bpf: fix order of args in call to bpf_map_kvcalloc +- i40e: Fix XDP program unloading while removing the driver +- octeontx2-af: Fix incorrect value output on error path in rvu_check_rsrc_availability() +- net: phy: microchip: lan87xx: reinit PHY after cable test +- tcp: fix incorrect undo caused by DSACK of TLP retransmit +- net: bcmasp: Fix error code in probe() +- vfs: don't mod negative dentry count when on shrinker list +- fs/dcache: Re-use value stored to dentry->d_flags instead of re-reading +- dsa: lan9303: Fix mapping between DSA port number and PHY address +- cachefiles: add missing lock protection when polling +- cachefiles: cyclic allocation of msg_id to avoid reuse +- cachefiles: wait for ondemand_object_worker to finish when dropping object +- cachefiles: cancel all requests for the object that is being dropped +- cachefiles: stop sending new request when dropping object +- cachefiles: propagate errors from vfs_getxattr() to avoid infinite loop +- scsi: ufs: core: Fix ufshcd_abort_one racing issue +- scsi: ufs: core: Fix ufshcd_clear_cmd racing issue +- mm: prevent derefencing NULL ptr in pfn_section_valid() +- Compiler Attributes: Add __uninitialized macro +- !10610 wifi: cfg80211: wext: add extra SIOCSIWSCAN data check +- wifi: cfg80211: wext: add extra SIOCSIWSCAN data check +- !10599 ppp: reject claimed-as-LCP but actually malformed packets +- ppp: reject claimed-as-LCP but actually malformed packets +- !10539 tun: add missing verification for short frame +- tun: add missing verification for short frame +- !10538 tap: add missing verification for short frame +- tap: add missing verification for short frame +- !10555 skmsg: Skip zero length skb in sk_msg_recvmsg +- skmsg: Skip zero length skb in sk_msg_recvmsg +- !10596 net: ethernet: lantiq_etop: fix double free in detach +- net: ethernet: lantiq_etop: fix double free in detach +- !10517 mm/dynamic_pool: two bugfix about THP and migration +- mm/dynamic_pool: check page_from_dynamic_pool() on migration +- mm/dynamic_pool: replace task_in_dynamic_pool() with mm_in_dynamic_pool() +- !10579 Fix CVE-2024-41062 +- Bluetooth: Fix usage of __hci_cmd_sync_status +- Bluetooth: L2CAP: Fix deadlock +- bluetooth/l2cap: sync sock recv cb and release +- !10545 bpf: Take return from set_memory_ro() into account with bpf_prog_lock_ro() +- bpf: Take return from set_memory_ro() into account with bpf_prog_lock_ro() +- !10547 powerpc/eeh: avoid possible crash when edev->pdev changes +- powerpc/eeh: avoid possible crash when edev->pdev changes +- !10470 Make cpuset.cpus.exclusive independent of cpuset.cpus +- cgroup/cpuset: Make cpuset.cpus.exclusive independent of cpuset.cpus +- cgroup/cpuset: Delay setting of CS_CPU_EXCLUSIVE until valid partition +- cgroup/cpuset: Documentation update for partition +- !10443 v2 cxl/mem: Fix no cxl_nvd during pmem region auto-assembling +- cxl/mem: Fix no cxl_nvd during pmem region auto-assembling +- !10351 bpf: Fix null-pointer-deref in resolve_prog_type() +- selftests/bpf: Test for null-pointer-deref bugfix in resolve_prog_type() +- bpf: Fix null pointer dereference in resolve_prog_type() for BPF_PROG_TYPE_EXT +- !10401 firmware: cs_dsp: Use strnlen() on name fields in V1 wmfw files +- firmware: cs_dsp: Use strnlen() on name fields in V1 wmfw files +- !10512 powerpc: Avoid nmi_enter/nmi_exit in real mode interrupt. +- powerpc: Avoid nmi_enter/nmi_exit in real mode interrupt. +- !10524 Bluetooth: hci_core: cancel all works upon hci_unregister_dev() +- Bluetooth: hci_core: cancel all works upon hci_unregister_dev() +- !10486 fix CVE-2024-42086 +- iio: chemical: bme680: Fix overflows in compensate() functions +- !10466 null_blk: fix validation of block size +- null_blk: fix validation of block size +- !10480 ALSA: emux: improve patch ioctl data validation +- ALSA: emux: improve patch ioctl data validation +- !10385 firmware: cs_dsp: Fix overflow checking of wmfw header +- firmware: cs_dsp: Fix overflow checking of wmfw header +- !10403 Fix CVE-2024-41069 +- ASoC: topology: Fix route memory corruption +- ASoC: topology: Do not assign fields that are already set +- ASoC: topology: Fix references to freed memory +- !10474 jffs2: Fix potential illegal address access in jffs2_free_inode +- jffs2: Fix potential illegal address access in jffs2_free_inode +- !10463 io_uring: fix possible deadlock in io_register_iowq_max_workers() +- io_uring: fix possible deadlock in io_register_iowq_max_workers() +- !10456 NFSv4: Fix memory leak in nfs4_set_security_label +- NFSv4: Fix memory leak in nfs4_set_security_label +- !10450 fs/ntfs3: Validate ff offset +- fs/ntfs3: Validate ff offset +- !10394 filelock: Fix fcntl/close race recovery compat path +- filelock: Fix fcntl/close race recovery compat path +- !10496 PCI/MSI: Fix UAF in msi_capability_init +- PCI/MSI: Fix UAF in msi_capability_init +- !10380 filelock: fix potential use-after-free in posix_lock_inode +- filelock: fix potential use-after-free in posix_lock_inode +- !10378 fs/ntfs3: Add a check for attr_names and oatbl +- fs/ntfs3: Add a check for attr_names and oatbl +- !10491 Bluetooth: ISO: Check socket flag instead of hcon +- Bluetooth: ISO: Check socket flag instead of hcon +- !10495 drm/amdgpu: Using uninitialized value *size when calling amdgpu_vce_cs_reloc +- drm/amdgpu: Using uninitialized value *size when calling amdgpu_vce_cs_reloc +- !10442 net/sched: Fix UAF when resolving a clash +- net/sched: Fix UAF when resolving a clash +- !10457 udp: Set SOCK_RCU_FREE earlier in udp_lib_get_port(). +- udp: Set SOCK_RCU_FREE earlier in udp_lib_get_port(). +- !10371 iommu/arm-smmu-v3: Reducing the CMD_SYNC times +- iommu/arm-smmu-v3: Reducing the CMD_SYNC times +- !10228 PCI/ROM: Fix PCI ROM header check bug +- PCI/ROM: Fix PCI ROM header check bug +- !10416 [sync] PR-10408: iommu/arm-smmu-v3: Fix the compile warning +- iommu/arm-smmu-v3: Fix the compile warning +- !9824 fix CVE-2024-39486 +- drm/drm_file: Fix pid refcounting race +- !10388 ovl: simplify ovl_parse_param_lowerdir() +- ovl: ovl_parse_param_lowerdir: Add missed ' +- ovl: fix wrong lowerdir number check for parameter Opt_lowerdir +- ovl: pass string to ovl_parse_layer() +- !10507 Backport 6.6.35-40 LTS patches from upstream +- Revert "usb: xhci: prevent potential failure in handle_tx_event() for Transfer events without TRB" +- nilfs2: fix incorrect inode allocation from reserved inodes +- null_blk: Do not allow runt zone with zone capacity smaller then zone size +- drm/amdgpu: silence UBSAN warning +- ALSA: ump: Set default protocol when not given explicitly +- spi: cadence: Ensure data lines set to low during dummy-cycle period +- nfc/nci: Add the inconsistency check between the input data length and count +- kbuild: fix short log for AS in link-vmlinux.sh +- nvmet: fix a possible leak when destroy a ctrl during qp establishment +- platform/x86: touchscreen_dmi: Add info for the EZpad 6s Pro +- platform/x86: touchscreen_dmi: Add info for GlobalSpace SolT IVW 11.6" tablet +- regmap-i2c: Subtract reg size from max_write +- nvme: adjust multiples of NVME_CTRL_PAGE_SIZE in offset +- connector: Fix invalid conversion in cn_proc.h +- dma-mapping: benchmark: avoid needless copy_to_user if benchmark fails +- nvme-multipath: find NUMA path only for online numa-node +- vhost-scsi: Handle vhost_vq_work_queue failures for events +- ALSA: hda/realtek: Enable headset mic of JP-IK LEAP W502 with ALC897 +- fs/ntfs3: Mark volume as dirty if xattr is broken +- i2c: pnx: Fix potential deadlock warning from del_timer_sync() call in isr +- clk: mediatek: mt8183: Only enable runtime PM on mt8183-mfgcfg +- clk: qcom: clk-alpha-pll: set ALPHA_EN bit for Stromer Plus PLLs +- clk: qcom: gcc-sm6350: Fix gpll6* & gpll7 parents +- media: dw2102: fix a potential buffer overflow +- arm64: dts: rockchip: Fix the DCDC_REG2 minimum voltage on Quartz64 Model B +- bnx2x: Fix multiple UBSAN array-index-out-of-bounds +- net: stmmac: dwmac-qcom-ethqos: fix error array size +- mtd: rawnand: rockchip: ensure NVDDR timings are rejected +- mtd: rawnand: Bypass a couple of sanity checks during NAND identification +- mtd: rawnand: Fix the nand_read_data_op() early check +- mtd: rawnand: Ensure ECC configuration is propagated to upper layers +- powerpc/64s: Fix unnecessary copy to 0 when kernel is booted at address 0 +- powerpc/pseries: Fix scv instruction crash with kexec +- clk: sunxi-ng: common: Don't call hw_to_ccu_common on hw without common +- clk: qcom: gcc-ipq9574: Add BRANCH_HALT_VOTED flag +- drm: panel-orientation-quirks: Add quirk for Valve Galileo +- drm/amdgpu/atomfirmware: silence UBSAN warning +- drm/nouveau: fix null pointer dereference in nouveau_connector_get_modes +- Revert "mm/writeback: fix possible divide-by-zero in wb_dirty_limits(), again" +- fsnotify: Do not generate events for O_PATH file descriptors +- can: kvaser_usb: Explicitly initialize family in leafimx driver_info struct +- Bluetooth: qca: Fix BT enable failure again for QCA6390 after warm reboot +- Bluetooth: hci_bcm4377: Fix msgid release +- scsi: mpi3mr: Use proper format specifier in mpi3mr_sas_port_add() +- f2fs: Add inline to f2fs_build_fault_attr() stub +- btrfs: fix adding block group to a reclaim list and the unused list during reclaim +- mm: avoid overflows in dirty throttling logic +- mm: optimize the redundant loop of mm_update_owner_next() +- nilfs2: add missing check for inode numbers on directory entries +- nilfs2: fix inode number range checks +- Revert "igc: fix a log entry using uninitialized netdev" +- platform/x86: toshiba_acpi: Fix quickstart quirk handling +- cpu: Fix broken cmdline "nosmp" and "maxcpus=0" +- gpiolib: of: add polarity quirk for TSC2005 +- mlxsw: core_linecards: Fix double memory deallocation in case of invalid INI file +- inet_diag: Initialize pad field in struct inet_diag_req_v2 +- selftests: make order checking verbose in msg_zerocopy selftest +- selftests: fix OOM in msg_zerocopy selftest +- netfilter: nf_tables: unconditionally flush pending work before notifier +- riscv: kexec: Avoid deadlock in kexec crash path +- wifi: wilc1000: fix ies_len type in connect path +- gpio: mmio: do not calculate bgpio_bits via "ngpios" +- net: ntb_netdev: Move ntb_netdev_rx_handler() to call netif_rx() from __netif_rx() +- net: txgbe: initialize num_q_vectors for MSI/INTx interrupts +- gpiolib: of: fix lookup quirk for MIPS Lantiq +- e1000e: Fix S0ix residency on corporate systems +- KVM: s390: fix LPSWEY handling +- tcp_metrics: validate source addr length +- bluetooth/hci: disallow setting handle bigger than HCI_CONN_HANDLE_MAX +- Bluetooth: ISO: Check socket flag instead of hcon +- Bluetooth: Ignore too large handle values in BIG +- Bluetooth: hci_event: Fix setting of unicast qos interval +- net/mlx5e: Add mqprio_rl cleanup and free in mlx5e_priv_cleanup() +- net/mlx5: E-switch, Create ingress ACL when needed +- UPSTREAM: tcp: fix DSACK undo in fast recovery to call tcp_try_to_open() +- net: phy: phy_device: Fix PHY LED blinking code comment +- mac802154: fix time calculation in ieee802154_configure_durations() +- vhost_task: Handle SIGKILL by flushing work and exiting +- vhost: Release worker mutex during flushes +- vhost: Use virtqueue mutex for swapping worker +- tools/power turbostat: Remember global max_die_id +- cdrom: rearrange last_media_change check to avoid unintentional overflow +- btrfs: scrub: initialize ret in scrub_simple_mirror() to fix compilation warning +- s390/pkey: Wipe sensitive data on failure +- jffs2: Fix potential illegal address access in jffs2_free_inode +- serial: imx: Raise TX trigger level to 8 +- scsi: mpi3mr: Sanitise num_phys +- f2fs: check validation of fault attrs in f2fs_build_fault_attr() +- bpf: Avoid uninitialized value in BPF_CORE_READ_BITFIELD +- igc: fix a log entry using uninitialized netdev +- selftests/net: fix uninitialized variables +- powerpc/xmon: Check cpu id in commands "c#", "dp#" and "dx#" +- kunit: Fix timeout message +- orangefs: fix out-of-bounds fsid access +- powerpc/64: Set _IO_BASE to POISON_POINTER_DELTA not 0 for CONFIG_PCI=n +- i2c: i801: Annotate apanel_addr as __ro_after_init +- media: dvb-frontends: tda10048: Fix integer overflow +- media: s2255: Use refcount_t instead of atomic_t for num_channels +- media: dvb-frontends: tda18271c2dd: Remove casting during div +- net: dsa: mv88e6xxx: Correct check for empty list +- thermal/drivers/mediatek/lvts_thermal: Check NULL ptr on lvts_data +- wifi: mt76: mt7996: add sanity checks for background radar trigger +- wifi: mt76: replace skb_put with skb_put_zero +- usb: xhci: prevent potential failure in handle_tx_event() for Transfer events without TRB +- Input: ff-core - prefer struct_size over open coded arithmetic +- firmware: dmi: Stop decoding on broken entry +- sctp: prefer struct_size over open coded arithmetic +- riscv: Apply SiFive CIP-1200 workaround to single-ASID sfence.vma +- media: dw2102: Don't translate i2c read into write +- drm/amdgpu: fix the warning about the expression (int)size - len +- drm/amdgpu: fix uninitialized scalar variable warning +- drm/amd/display: Fix uninitialized variables in DM +- drm/amd/display: Skip finding free audio for unknown engine_id +- drm/amd/display: Check pipe offset before setting vblank +- drm/amd/display: Check index msg_id before read or write +- drm/amdgpu: Initialize timestamp for some legacy SOCs +- drm/amdgpu: Using uninitialized value *size when calling amdgpu_vce_cs_reloc +- drm/amdgpu: Fix uninitialized variable warnings +- media: mediatek: vcodec: Only free buffer VA that is not NULL +- crypto: aead,cipher - zeroize key buffer after use +- RISC-V: KVM: Fix the initial sample period value +- selftests/bpf: dummy_st_ops should reject 0 for non-nullable params +- selftests/bpf: do not pass NULL for non-nullable params in dummy_st_ops +- selftests/bpf: adjust dummy_st_ops_success to detect additional error +- scsi: qedf: Make qedf_execute_tmf() non-preemptible +- IB/core: Implement a limit on UMAD receive List +- media: dvb-usb: dib0700_devices: Add missing release_firmware() +- media: dvb: as102-fe: Fix as10x_register_addr packing +- powerpc: Avoid nmi_enter/nmi_exit in real mode interrupt. +- drm/lima: fix shared irq handling on driver remove +- leds: an30259a: Use devm_mutex_init() for mutex initialization +- locking/mutex: Introduce devm_mutex_init() +- Revert "powerpc/bpf: rename powerpc64_jit_data to powerpc_jit_data" +- Revert "powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free]" +- tracing/net_sched: NULL pointer dereference in perf_trace_qdisc_reset() +- serial: 8250_omap: Fix Errata i2310 with RX FIFO level check +- serial: imx: only set receiver level if it is zero +- cxl/region: Avoid null pointer dereference in region lookup +- cxl/region: Move cxl_dpa_to_region() work to the region driver +- arm64: dts: rockchip: Add sound-dai-cells for RK3368 +- arm64: dts: rockchip: fix PMIC interrupt pin on ROCK Pi E +- arm64: dts: rockchip: make poweroff(8) work on Radxa ROCK 5A +- ARM: dts: rockchip: rk3066a: add #sound-dai-cells to hdmi node +- arm64: dts: rockchip: Fix the value of `dlg,jack-det-rate` mismatch on rk3399-gru +- arm64: dts: rockchip: Rename LED related pinctrl nodes on rk3308-rock-pi-s +- arm64: dts: rockchip: Fix SD NAND and eMMC init on rk3308-rock-pi-s +- pwm: stm32: Refuse too small period requests +- syscalls: fix sys_fanotify_mark prototype +- syscalls: fix compat_sys_io_pgetevents_time64 usage +- ftruncate: pass a signed offset +- ata: libata-core: Fix double free on error +- ata: ahci: Clean up sysfs file on error +- can: mcp251xfd: fix infinite loop when xmit fails +- batman-adv: Don't accept TT entries for out-of-spec VIDs +- drm/amdgpu/atomfirmware: fix parsing of vram_info +- drm/amd/display: Send DP_TOTAL_LTTPR_CNT during detection if LTTPR is present +- drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_hd_modes +- drm/i915/gt: Fix potential UAF by revoke of fence registers +- drm/amdgpu: avoid using null object of framebuffer +- drm/fbdev-dma: Only set smem_start is enable per module option +- drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_ld_modes +- drm/drm_file: Fix pid refcounting race +- hexagon: fix fadvise64_64 calling conventions +- csky, hexagon: fix broken sys_sync_file_range +- btrfs: zoned: fix initial free space detection +- sh: rework sync_file_range ABI +- kbuild: Install dtb files as 0644 in Makefile.dtbinst +- cpu/hotplug: Fix dynstate assignment in __cpuhp_setup_state_cpuslocked() +- cpufreq: intel_pstate: Use HWP to initialize ITMT if CPPC is missing +- PCI/MSI: Fix UAF in msi_capability_init +- net: can: j1939: enhanced error handling for tightly received RTS messages in xtp_rx_rts_session_new +- net: can: j1939: recover socket queue on CAN bus error during BAM transmission +- net: can: j1939: Initialize unused data in j1939_send_one() +- tty: mcf: MCF54418 has 10 UARTS +- ALSA: hda/realtek: fix mute/micmute LEDs don't work for EliteBook 645/665 G11. +- serial: bcm63xx-uart: fix tx after conversion to uart_port_tx_limited() +- serial: core: introduce uart_port_tx_limited_flags() +- serial: imx: set receiver level before starting uart +- serial: 8250_omap: Implementation of Errata i2310 +- Revert "serial: core: only stop transmit when HW fifo is empty" +- usb: dwc3: core: Workaround for CSR read timeout +- usb: dwc3: core: Add DWC31 version 2.00a controller +- usb: ucsi: stm32: fix command completion handling +- usb: typec: ucsi: glink: fix child node release in probe function +- usb: gadget: aspeed_udc: fix device address configuration +- usb: dwc3: core: remove lock of otg mode during gadget suspend/resume to avoid deadlock +- usb: atm: cxacru: fix endpoint checking in cxacru_bind() +- usb: musb: da8xx: fix a resource leak in probe() +- usb: gadget: printer: fix races against disable +- usb: gadget: printer: SS+ support +- net: usb: ax88179_178a: improve link status logs +- iio: chemical: bme680: Fix sensor data read operation +- iio: chemical: bme680: Fix overflows in compensate() functions +- iio: chemical: bme680: Fix calibration data variable +- iio: chemical: bme680: Fix pressure value output +- iio: accel: fxls8962af: select IIO_BUFFER & IIO_KFIFO_BUF +- iio: adc: ad7266: Fix variable checking bug +- ata,scsi: libata-core: Do not leak memory for ata_port struct members +- ata: libata-core: Fix null pointer dereference on error +- i2c: testunit: discard write requests while old command is running +- i2c: testunit: don't erase registers after STOP +- kbuild: Fix build target deb-pkg: ln: failed to create hard link +- kbuild: doc: Update default INSTALL_MOD_DIR from extra to updates +- counter: ti-eqep: enable clock at probe +- iio: xilinx-ams: Don't include ams_ctrl_channels in scan_mask +- mmc: sdhci: Do not lock spinlock around mmc_gpio_get_ro() +- mmc: sdhci: Do not invert write-protect twice +- mmc: sdhci-pci: Convert PCIBIOS_* return codes to errnos +- mmc: sdhci-brcmstb: check R1_STATUS for erase/trim/discard +- mmc: sdhci-pci-o2micro: Convert PCIBIOS_* return codes to errnos +- mm: fix incorrect vbq reference in purge_fragmented_block +- nfs: drop the incorrect assertion in nfs_swap_rw() +- ocfs2: fix DIO failure due to insufficient transaction credits +- pinctrl: qcom: spmi-gpio: drop broken pm8008 support +- Revert "MIPS: pci: lantiq: restore reset gpio polarity" +- parisc: use generic sys_fanotify_mark implementation +- x86: stop playing stack games in profile_pc() +- randomize_kstack: Remove non-functional per-arch entropy filtering +- gpiolib: cdev: Disallow reconfiguration without direction (uAPI v1) +- riscv: stacktrace: convert arch_stack_walk() to noinstr +- drm/amdgpu: Fix pci state save during mode-1 reset +- RISC-V: fix vector insn load/store width mask +- gpio: davinci: Validate the obtained number of IRQs +- drm/panel: simple: Add missing display timing flags for KOE TX26D202VM0BWA +- nvme: fixup comment for nvme RDMA Provider Type +- drm/radeon/radeon_display: Decrease the size of allocated memory +- gfs2: Fix NULL pointer dereference in gfs2_log_flush +- soc: ti: wkup_m3_ipc: Send NULL dummy message instead of pointer message +- irqchip/loongson: Select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP for IRQ_LOONGARCH_CPU +- media: dvbdev: Initialize sbuf +- ALSA: emux: improve patch ioctl data validation +- crypto: ecdh - explicitly zeroize private_key +- net/dpaa2: Avoid explicit cpumask var allocation on stack +- net/iucv: Avoid explicit cpumask var allocation on stack +- RDMA/restrack: Fix potential invalid address access +- bpf: Mark bpf prog stack with kmsan_unposion_memory in interpreter mode +- wifi: ieee80211: check for NULL in ieee80211_mle_size_ok() +- mtd: partitions: redboot: Added conversion of operands to a larger type +- x86/fpu: Fix AMD X86_BUG_FXSAVE_LEAK fixup +- vduse: Temporarily fail if control queue feature requested +- vduse: validate block features only with block devices +- drm/panel: ilitek-ili9881c: Fix warning with GPIO controllers that sleep +- powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free] +- powerpc/bpf: rename powerpc64_jit_data to powerpc_jit_data +- net: mana: Fix possible double free in error handling path +- netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data registers +- ALSA: seq: Fix missing MSB in MIDI2 SPP conversion +- tcp: fix tcp_rcv_fastopen_synack() to enter TCP_CA_Loss for failed TFO +- powerpc: restore some missing spu syscalls +- parisc: use correct compat recv/recvfrom syscalls +- sparc: fix compat recv/recvfrom syscalls +- sparc: fix old compat_sys_select() +- net: dsa: microchip: fix wrong register write when masking interrupt +- ALSA: seq: Fix missing channel at encoding RPN/NRPN MIDI2 messages +- Fix race for duplicate reqsk on identical SYN +- btrfs: use NOFS context when getting inodes during logging and log replay +- xdp: Remove WARN() from __xdp_reg_mem_model() +- ice: Rebuild TC queues on VSI queue reconfiguration +- net: dsa: microchip: use collision based back pressure mode +- net: phy: micrel: add Microchip KSZ 9477 to the device table +- ibmvnic: Free any outstanding tx skbs during scrq reset +- mlxsw: spectrum_buffers: Fix memory corruptions on Spectrum-4 systems +- openvswitch: get related ct labels from its master if it is not confirmed +- net: dsa: microchip: fix initial port flush problem +- ASoC: fsl-asoc-card: set priv->pdev before using it +- ASoC: amd: acp: remove i2s configuration check in acp_i2s_probe() +- ASoC: amd: acp: add a null check for chip_pdev structure +- s390/pci: Add missing virt_to_phys() for directed DIBV +- bpf: Add missed var_off setting in coerce_subreg_to_size_sx() +- bpf: Add missed var_off setting in set_sext32_default_val() +- ASoC: q6apm-lpass-dai: close graph on prepare errors +- workqueue: Increase worker desc's length to 32 +- ASoC: atmel: atmel-classd: Re-add dai_link->platform to fix card init +- ASoC: atmel: convert not to use asoc_xxx() +- ASoC: mediatek: mt8183-da7219-max98357: Fix kcontrol name collision +- ASoC: rockchip: i2s-tdm: Fix trcm mode by setting clock on right mclk +- wifi: mac80211: Use flexible array in struct ieee80211_tim_ie +- selftests: mptcp: userspace_pm: fixed subtest names +- selftests: mptcp: print_test out of verify_listener_events +- MIPS: pci: lantiq: restore reset gpio polarity +- pinctrl: rockchip: fix pinmux reset in rockchip_pmx_set +- pinctrl: rockchip: use dedicated pinctrl type for RK3328 +- pinctrl: rockchip: fix pinmux bits for RK3328 GPIO3-B pins +- pinctrl: rockchip: fix pinmux bits for RK3328 GPIO2-B pins +- pinctrl: fix deadlock in create_pinctrl() when handling -EPROBE_DEFER +- Input: ili210x - fix ili251x_read_touch_data() return value +- usb: typec: ucsi: Ack also failed Get Error commands +- usb: typec: ucsi: Never send a lone connector change ack +- iio: pressure: bmp280: Fix BMP580 temperature reading +- iio: pressure: fix some word spelling errors +- Revert "mm: mmap: allow for the maximum number of bits for randomizing mmap_base by default" +- hid: asus: asus_report_fixup: fix potential read out of bounds +- kprobe/ftrace: fix build error due to bad function definition +- ASoC: Intel: sof-sdw: really remove FOUR_SPEAKER quirk +- drm/amd/display: revert Exit idle optimizations before HDCP execution +- LoongArch: Fix entry point in kernel image header +- efi/loongarch: Directly position the loaded image file +- vgacon: rework screen_info #ifdef checks +- riscv: force PAGE_SIZE linear mapping if debug_pagealloc is enabled +- riscv: Don't use PGD entries for the linear mapping +- x86/cpu: Fix x86_match_cpu() to match just X86_VENDOR_INTEL +- x86/cpu/vfm: Add new macros to work with (vendor/family/model) values +- tracing: Add MODULE_DESCRIPTION() to preemptirq_delay_test +- nbd: Fix signal handling +- nbd: Improve the documentation of the locking assumptions +- ocfs2: update inode fsync transaction id in ocfs2_unlink and ocfs2_link +- ocfs2: convert to new timestamp accessors +- wifi: rtl8xxxu: enable MFP support with security flag of RX descriptor +- perf script: Show also errors for --insn-trace option +- perf: script: add raw|disasm arguments to --insn-trace option +- spi: stm32: qspi: Clamp stm32_qspi_get_mode() output to CCR_BUSWIDTH_4 +- arm64: dts: imx8qm-mek: fix gpio number for reg_usdhc2_vmmc +- spi: stm32: qspi: Fix dual flash mode sanity test in stm32_qspi_setup() +- dt-bindings: i2c: google,cros-ec-i2c-tunnel: correct path to i2c-controller schema +- dt-bindings: i2c: atmel,at91sam: correct path to i2c-controller schema +- i2c: ocores: set IACK bit after core is enabled +- mm/page_table_check: fix crash on ZONE_DEVICE +- tcp: clear tp->retrans_stamp in tcp_rcv_fastopen_synack() +- mm: mmap: allow for the maximum number of bits for randomizing mmap_base by default +- efi/x86: Free EFI memory map only when installing a new one. +- kcov: don't lose track of remote references during softirqs +- gcov: add support for GCC 14 +- dt-bindings: dma: fsl-edma: fix dma-channels constraints +- drm/radeon: fix UBSAN warning in kv_dpm.c +- drm/i915/mso: using joiner is not possible with eDP MSO +- ALSA: hda/realtek: Add quirk for Lenovo Yoga Pro 7 14AHP9 +- ALSA: hda/realtek: Limit mic boost on N14AP7 +- ALSA: hda/realtek: fix mute/micmute LEDs don't work for ProBook 445/465 G11. +- ovl: fix encoding fid for lower only root +- RDMA/mlx5: Follow rb_key.ats when creating new mkeys +- RDMA/mlx5: Remove extra unlock on error path +- RDMA/rxe: Fix data copy for IB_SEND_INLINE +- KVM: x86: Always sync PIR to IRR prior to scanning I/O APIC routes +- KVM: arm64: Disassociate vcpus from redistributor region on teardown +- LoongArch: Fix multiple hardware watchpoint issues +- LoongArch: Trigger user-space watchpoints correctly +- LoongArch: Fix watchpoint setting error +- cifs: fix typo in module parameter enable_gcm_256 +- scsi: ufs: core: Free memory allocated for model before reinit +- btrfs: retry block group reclaim without infinite loop +- net: do not leave a dangling sk pointer, when socket creation fails +- net: usb: ax88179_178a: improve reset check +- net: stmmac: Assign configured channel value to EXTTS event +- locking/atomic: scripts: fix ${atomic}_sub_and_test() kerneldoc +- arm64: defconfig: enable the vf610 gpio driver +- ACPI: EC: Evaluate orphan _REG under EC device +- RDMA/mana_ib: Ignore optional access flags for MRs +- RDMA/mlx5: Fix unwind flow as part of mlx5_ib_stage_init_init +- firmware: psci: Fix return value from psci_system_suspend() +- io_uring/rsrc: fix incorrect assignment of iter->nr_segs in io_import_fixed +- spi: spi-imx: imx51: revert burst length calculation back to bits_per_word +- arm64: dts: freescale: imx8mm-verdin: enable hysteresis on slow input pin +- arm64: dts: imx93-11x11-evk: Remove the 'no-sdio' property +- arm64: dts: freescale: imx8mp-venice-gw73xx-2x: fix BT shutdown GPIO +- arm64: dts: imx8mp: Fix TC9595 input clock on DH i.MX8M Plus DHCOM SoM +- arm64: dts: imx8mp: Fix TC9595 reset GPIO on DH i.MX8M Plus DHCOM SoM +- thermal/drivers/mediatek/lvts_thermal: Return error in case of invalid efuse data +- regulator: bd71815: fix ramp values +- dmaengine: ioatdma: Fix missing kmem_cache_destroy() +- dmaengine: fsl-edma: avoid linking both modules +- dmaengine: ioatdma: Fix kmemleak in ioat_pci_probe() +- dmaengine: ioatdma: Fix error path in ioat3_dma_probe() +- dmaengine: ioatdma: Fix leaking on version mismatch +- regulator: core: Fix modpost error "regulator_get_regmap" undefined +- RDMA/rxe: Fix responder length checking for UD request packets +- spi: cs42l43: Correct SPI root clock speed +- RDMA/bnxt_re: Fix the max msix vectors macro +- net: usb: rtl8150 fix unintiatilzed variables in rtl8150_get_link_ksettings +- bnxt_en: Restore PTP tx_avail count in case of skb_pad() error +- ice: Fix VSI list rule with ICE_SW_LKUP_LAST type +- octeontx2-pf: Fix linking objects into multiple modules +- octeontx2-pf: Add error handling to VLAN unoffload handling +- virtio_net: fixing XDP for fully checksummed packets handling +- virtio_net: checksum offloading handling fix +- net: stmmac: No need to calculate speed divider when offload is disabled +- selftests: openvswitch: Use bash as interpreter +- ptp: fix integer overflow in max_vclocks_store +- sched: act_ct: add netns into the key of tcf_ct_flow_table +- net: phy: mxl-gpy: Remove interrupt mask clearing from config_init +- net: lan743x: Support WOL at both the PHY and MAC appropriately +- net: lan743x: disable WOL upon resume to restore full data path operation +- qca_spi: Make interrupt remembering atomic +- netns: Make get_net_ns() handle zero refcount net +- xfrm6: check ip6_dst_idev() return value in xfrm6_get_saddr() +- ipv6: prevent possible NULL deref in fib6_nh_init() +- bpf: Avoid splat in pskb_pull_reason +- ALSA: hda: tas2781: Component should be unbound before deconstruction +- ALSA: hda: cs35l56: Component should be unbound before deconstruction +- cipso: fix total option length computation +- net: mvpp2: use slab_build_skb for oversized frames +- ice: avoid IRQ collision to fix init failure on ACPI S3 resume +- ALSA/hda: intel-dsp-config: Document AVS as dsp_driver option +- ALSA: hda/realtek: Remove Framework Laptop 16 from quirks +- MIPS: Routerboard 532: Fix vendor retry check code +- ALSA: seq: ump: Fix missing System Reset message handling +- PCI: Do not wait for disconnected devices when resuming +- ACPI: EC: Install address space handler at the namespace root +- usb: gadget: function: Remove usage of the deprecated ida_simple_xx() API +- serial: exar: adding missing CTI and Exar PCI ids +- f2fs: don't set RO when shutting down f2fs +- PCI/PM: Avoid D3cold for HP Pavilion 17 PC/1972 PCIe Ports +- udf: udftime: prevent overflow in udf_disk_stamp_to_time() +- usb: typec: ucsi_glink: drop special handling for CCI_BUSY +- usb: dwc3: pci: Don't set "linux,phy_charger_detect" property on Lenovo Yoga Tab2 1380 +- Avoid hw_desc array overrun in dw-axi-dmac +- usb: misc: uss720: check for incompatible versions of the Belkin F5U002 +- usb: gadget: uvc: configfs: ensure guid to be valid before set +- kprobe/ftrace: bail out if ftrace was killed +- power: supply: cros_usbpd: provide ID table for avoiding fallback match +- platform/x86: p2sb: Don't init until unassigned resources have been assigned +- powerpc/io: Avoid clang null pointer arithmetic warnings +- media: mtk-vcodec: potential null pointer deference in SCP +- media: intel/ipu6: Fix build with !ACPI +- ALSA: hda/realtek: Add quirks for Lenovo 13X +- drm/lima: mask irqs in timeout path before hard reset +- drm/lima: add mask irq callback to gp and pp +- ASoC: Intel: sof_sdw: add quirk for Dell SKU 0C0F +- ASoC: Intel: sof_sdw: add JD2 quirk for HP Omen 14 +- platform/x86: toshiba_acpi: Add quirk for buttons on Z830 +- drm/amd/display: Exit idle optimizations before HDCP execution +- Bluetooth: ath3k: Fix multiple issues reported by checkpatch.pl +- ACPI: video: Add backlight=native quirk for Lenovo Slim 7 16ARH7 +- HID: asus: fix more n-key report descriptors if n-key quirked +- HID: Add quirk for Logitech Casa touchpad +- net: dsa: realtek: keep default LED state in rtl8366rb +- kselftest: arm64: Add a null pointer check +- net: sfp: add quirk for ATS SFP-GE-T 1000Base-TX module +- scsi: qedi: Fix crash while reading debugfs attribute +- ACPI: x86: Add PNP_UART1_SKIP quirk for Lenovo Blade2 tablets +- af_packet: avoid a false positive warning in packet_setsockopt() +- wifi: ath9k: work around memset overflow warning +- selftests/bpf: Fix flaky test btf_map_in_map/lookup_update +- selftests/bpf: Prevent client connect before server bind in test_tc_tunnel.sh +- block/ioctl: prefer different overflow check +- rcutorture: Fix invalid context warning when enable srcu barrier testing +- rcutorture: Make stall-tasks directly exit when rcutorture tests end +- rcutorture: Fix rcu_torture_one_read() pipe_count overflow comment +- io_uring/sqpoll: work around a potential audit memory leak +- padata: Disable BH when taking works lock on MT path +- zap_pid_ns_processes: clear TIF_NOTIFY_SIGNAL along with TIF_SIGPENDING +- i2c: designware: Fix the functionality flags of the slave-only interface +- i2c: at91: Fix the functionality flags of the slave-only interface +- misc: microchip: pci1xxxx: Fix a memory leak in the error handling of gp_aux_bus_probe() +- serial: core: Add UPIO_UNKNOWN constant for unknown port type +- device property: Implement device_is_big_endian() +- greybus: Fix use-after-free bug in gb_interface_release due to race condition. +- remoteproc: k3-r5: Jump to error handling labels in start/stop errors +- serial: 8250_pxa: Configure tx_loadsz to match FIFO IRQ level +- mm/huge_memory: don't unpoison huge_zero_folio +- tick/nohz_full: Don't abuse smp_call_function_single() in tick_setup_device() +- nilfs2: fix potential kernel bug due to lack of writeback flag waiting +- xfs: allow cross-linking special files without project quota +- xfs: allow sunit mount option to repair bad primary sb stripe values +- xfs: shrink failure needs to hold AGI buffer +- xfs: fix SEEK_HOLE/DATA for regions with active COW extents +- xfs: fix scrub stats file permissions +- xfs: fix imprecise logic in xchk_btree_check_block_owner +- pmdomain: ti-sci: Fix duplicate PD referrals +- intel_th: pci: Add Lunar Lake support +- intel_th: pci: Add Meteor Lake-S support +- intel_th: pci: Add Sapphire Rapids SOC support +- intel_th: pci: Add Granite Rapids SOC support +- intel_th: pci: Add Granite Rapids support +- drm/i915: Fix audio component initialization +- drm/i915/dpt: Make DPT object unshrinkable +- drm/shmem-helper: Fix BUG_ON() on mmap(PROT_WRITE, MAP_PRIVATE) +- drm/i915/gt: Disarm breadcrumbs if engines are already idle +- rtla/auto-analysis: Replace with spaces +- rtla/timerlat: Simplify "no value" printing on top +- iio: invensense: fix interrupt timestamp alignment +- iio: adc: axi-adc: make sure AXI clock is enabled +- remoteproc: k3-r5: Do not allow core1 to power up before core0 via sysfs +- remoteproc: k3-r5: Wait for core0 power-up before powering up core1 +- dmaengine: axi-dmac: fix possible race in remove() +- PCI: rockchip-ep: Remove wrong mask on subsys_vendor_id +- ocfs2: use coarse time for new created files +- fs/proc: fix softlockup in __read_vmcore +- knfsd: LOOKUP can return an illegal error value +- spmi: hisi-spmi-controller: Do not override device identifier +- dma-buf: handle testing kthreads creation failure +- null_blk: Print correct max open zones limit in null_init_zoned_dev() +- kheaders: explicitly define file modes for archived headers +- tracing/selftests: Fix kprobe event name test for .isra. functions +- riscv: fix overlap of allocated page and PTR_ERR +- perf auxtrace: Fix multiple use of --itrace option +- perf/core: Fix missing wakeup when waiting for context reference +- x86/amd_nb: Check for invalid SMN reads +- x86/kexec: Fix bug with call depth tracking +- irqchip/gic-v3-its: Fix potential race condition in its_vlpi_prop_update() +- mptcp: pm: update add_addr counters after connect +- mptcp: pm: inc RmAddr MIB counter once per RM_ADDR ID +- ACPI: x86: Force StorageD3Enable on more products +- drivers: core: synchronize really_probe() and dev_uevent() +- iio: imu: inv_icm42600: delete unneeded update watermark call +- iio: invensense: fix odr switching to same value +- iio: dac: ad5592r: fix temperature channel scaling value +- iio: adc: ad9467: fix scan type sign +- x86/boot: Don't add the EFI stub to targets, again +- ksmbd: fix missing use of get_write in in smb2_set_ea() +- bnxt_en: Adjust logging of firmware messages in case of released token in __hwrm_send() +- af_unix: Read with MSG_PEEK loops if the first unread byte is OOB +- net/ipv6: Fix the RT cache flush via sysctl using a previous delay +- nvmet-passthru: propagate status from id override functions +- block: fix request.queuelist usage in flush +- block: sed-opal: avoid possible wrong address reference in read_sed_opal_key() +- net: stmmac: replace priv->speed with the portTransmitRate from the tc-cbs parameters +- gve: ignore nonrelevant GSO type bits when processing TSO headers +- net: pse-pd: Use EOPNOTSUPP error code instead of ENOTSUPP +- scsi: ufs: core: Quiesce request queues before checking pending cmds +- x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking +- x86/asm: Use %c/%n instead of %P operand modifier in asm templates +- netfilter: nft_inner: validate mandatory meta and payload +- Bluetooth: L2CAP: Fix rejecting L2CAP_CONN_PARAM_UPDATE_REQ +- net/mlx5e: Fix features validation check for tunneled UDP (non-VXLAN) packets +- geneve: Fix incorrect inner network header offset when innerprotoinherit is set +- net dsa: qca8k: fix usages of device_get_named_child_node() +- tcp: fix race in tcp_v6_syn_recv_sock() +- drm/bridge/panel: Fix runtime warning on panel bridge release +- net: stmmac: dwmac-qcom-ethqos: Configure host DMA width +- net: sfp: Always call `sfp_sm_mod_remove()` on remove +- modpost: do not warn about missing MODULE_DESCRIPTION() for vmlinux.o +- af_unix: Annotate data-race of sk->sk_state in unix_accept(). +- drm/vmwgfx: Don't memcmp equivalent pointers +- drm/vmwgfx: Remove STDU logic from generic mode_valid function +- drm/vmwgfx: 3D disabled should not effect STDU memory limits +- drm/vmwgfx: Filter modes which exceed graphics memory +- drm/vmwgfx: Refactor drm connector probing for display modes +- io_uring/io-wq: avoid garbage value of 'match' in io_wq_enqueue() +- iommu: Return right value in iommu_sva_bind_device() +- iommu/amd: Fix sysfs leak in iommu init +- HID: core: remove unnecessary WARN_ON() in implement() +- gpio: tqmx86: fix broken IRQ_TYPE_EDGE_BOTH interrupt type +- gpio: tqmx86: store IRQ trigger type and unmask status separately +- gpio: tqmx86: introduce shadow register for GPIO output value +- gpio: tqmx86: fix typo in Kconfig label +- platform/x86: dell-smbios: Fix wrong token data in sysfs +- drm/panel: sitronix-st7789v: Add check for of_drm_get_panel_orientation +- nvme: fix nvme_pr_* status code parsing +- selftests/tracing: Fix event filter test to retry up to 10 times +- NFS: add barriers when testing for NFS_FSDATA_BLOCKED +- SUNRPC: return proper error from gss_wrap_req_priv +- NFSv4.1 enforce rootpath check in fs_location query +- clk: sifive: Do not register clkdevs for PRCI clocks +- selftests/ftrace: Fix to check required event file +- cxl/test: Add missing vmalloc.h for tools/testing/cxl/test/mem.c +- HID: nvidia-shield: Add missing check for input_ff_create_memless +- powerpc/uaccess: Fix build errors seen with GCC 13/14 +- gve: Clear napi->skb before dev_kfree_skb_any() +- scsi: sd: Use READ(16) when reading block zero on large capacity disks +- scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory +- scsi: mpi3mr: Fix ATA NCQ priority support +- scsi: core: Disable CDL by default +- thunderbolt: debugfs: Fix margin debugfs node creation condition +- xhci: Apply broken streams quirk to Etron EJ188 xHCI host +- xhci: Handle TD clearing for multiple streams case +- xhci: Apply reset resume quirk to Etron EJ188 xHCI host +- xhci: Set correct transferred length for cancelled bulk transfers +- jfs: xattr: fix buffer overflow for invalid xattr +- landlock: Fix d_parent walk +- serial: port: Don't block system suspend even if bytes are left to xmit +- tty: n_tty: Fix buffer offsets when lookahead is used +- mei: me: release irq in mei_me_pci_resume error path +- usb: typec: tcpm: Ignore received Hard Reset in TOGGLING state +- usb: typec: tcpm: fix use-after-free case in tcpm_register_source_caps +- USB: xen-hcd: Traverse host/ when CONFIG_USB_XEN_HCD is selected +- USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages +- bpf: fix multi-uprobe PID filtering logic +- eventfs: Update all the eventfs_inodes from the events descriptor +- irqchip/riscv-intc: Prevent memory leak when riscv_intc_init_common() fails +- irqchip/riscv-intc: Introduce Andes hart-level interrupt controller +- irqchip/riscv-intc: Allow large non-standard interrupt number +- selftests/mm: compaction_test: fix bogus test success on Aarch64 +- selftests/mm: log a consistent test name for check_compaction +- selftests/mm: conform test to TAP format output +- memory-failure: use a folio in me_huge_page() +- firmware: qcom_scm: disable clocks if qcom_scm_bw_enable() fails +- ksmbd: use rwsem instead of rwlock for lease break +- net: ethtool: fix the error condition in ethtool_get_phy_stats_ethtool() +- af_unix: Annotate data-race of sk->sk_shutdown in sk_diag_fill(). +- af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen(). +- af_unix: Use skb_queue_empty_lockless() in unix_release_sock(). +- af_unix: Use unix_recvq_full_lockless() in unix_stream_connect(). +- af_unix: Annotate data-race of net->unx.sysctl_max_dgram_qlen. +- af_unix: Annotate data-races around sk->sk_sndbuf. +- af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG. +- af_unix: Annotate data-race of sk->sk_state in unix_stream_read_skb(). +- af_unix: Annotate data-races around sk->sk_state in sendmsg() and recvmsg(). +- af_unix: Annotate data-race of sk->sk_state in unix_stream_connect(). +- af_unix: Annotate data-races around sk->sk_state in unix_write_space() and poll(). +- af_unix: Annotate data-race of sk->sk_state in unix_inq_len(). +- af_unix: Annodate data-races around sk->sk_state for writers. +- af_unix: Set sk->sk_state under unix_state_lock() for truly disconencted peer. +- net: wwan: iosm: Fix tainted pointer delete is case of region creation fail +- ice: add flag to distinguish reset from .ndo_bpf in XDP rings config +- ice: remove af_xdp_zc_qps bitmap +- ice: fix iteration of TLVs in Preserved Fields Area +- ptp: Fix error message on failed pin verification +- net/mlx5: Fix tainted pointer delete is case of flow rules creation fail +- net/mlx5: Stop waiting for PCI if pci channel is offline +- mptcp: count CLOSE-WAIT sockets for MPTCP_MIB_CURRESTAB +- tcp: count CLOSE-WAIT sockets for TCP_MIB_CURRESTAB +- vxlan: Fix regression when dropping packets due to invalid src addresses +- net: phy: Micrel KSZ8061: fix errata solution not taking effect problem +- net/smc: avoid overwriting when adjusting sock bufsizes +- octeontx2-af: Always allocate PF entries from low prioriy zone +- net: tls: fix marking packets as decrypted +- ipv6: sr: block BH in seg6_output_core() and seg6_input_core() +- ipv6: ioam: block BH from ioam6_output() +- bpf: Store ref_ctr_offsets values in bpf_uprobe array +- net: phy: micrel: fix KSZ9477 PHY issues after suspend/resume +- net/ncsi: Fix the multi thread manner of NCSI driver +- net/ncsi: Simplify Kconfig/dts control flow +- ax25: Replace kfree() in ax25_dev_free() with ax25_dev_put() +- ax25: Fix refcount imbalance on inbound connections +- RISC-V: KVM: Fix incorrect reg_subtype labels in kvm_riscv_vcpu_set_reg_isa_ext function +- RISC-V: KVM: No need to use mask when hart-index-bit is 0 +- scsi: ufs: mcq: Fix error output and clean up ufshcd_mcq_abort() +- wifi: mac80211: correctly parse Spatial Reuse Parameter Set element +- wifi: iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs ifdef +- wifi: iwlwifi: mvm: set properly mac header +- wifi: iwlwifi: mvm: revert gen2 TX A-MPDU size to 64 +- wifi: iwlwifi: mvm: don't initialize csa_work twice +- wifi: cfg80211: pmsr: use correct nla_get_uX functions +- wifi: cfg80211: Lock wiphy in cfg80211_get_station +- wifi: cfg80211: fully move wiphy work to unbound workqueue +- !10369 Backport 6.6.33-34 LTS patches from upstream +- openeuler_defconfig: add new config +- selftests: net: more strict check in net_helper +- powerpc/bpf: enforce full ordering for ATOMIC operations with BPF_FETCH +- ALSA: seq: Fix incorrect UMP type for system messages +- btrfs: fix leak of qgroup extent records after transaction abort +- tracefs: Clear EVENT_INODE flag in tracefs_drop_inode() +- eventfs: Keep the directories from having the same inode number as files +- NFS: Fix READ_PLUS when server doesn't support OP_READ_PLUS +- nfs: fix undefined behavior in nfs_block_bits() +- EDAC/igen6: Convert PCIBIOS_* return codes to errnos +- ALSA: ump: Don't accept an invalid UMP protocol number +- ALSA: ump: Don't clear bank selection after sending a program change +- i3c: master: svc: fix invalidate IBI type and miss call client IBI handler +- s390/cpacf: Make use of invalid opcode produce a link error +- s390/cpacf: Split and rework cpacf query functions +- parisc: Define sigset_t in parisc uapi header +- parisc: Define HAVE_ARCH_HUGETLB_UNMAPPED_AREA +- ARM: dts: samsung: exynos4412-origen: fix keypad no-autorepeat +- ARM: dts: samsung: smdk4412: fix keypad no-autorepeat +- ARM: dts: samsung: smdkv310: fix keypad no-autorepeat +- riscv: dts: starfive: Remove PMIC interrupt info for Visionfive 2 board +- drm/amdkfd: handle duplicate BOs in reserve_bo_and_cond_vms +- sparc: move struct termio to asm/termios.h +- kdb: Use format-specifiers rather than memset() for padding in kdb_read() +- kdb: Merge identical case statements in kdb_read() +- kdb: Fix console handling when editing and tab-completing commands +- kdb: Use format-strings rather than '0' injection in kdb_read() +- wifi: ath10k: fix QCOM_RPROC_COMMON dependency +- watchdog: rti_wdt: Set min_hw_heartbeat_ms to accommodate a safety margin +- selftests/mm: fix build warnings on ppc64 +- selftests/mm: compaction_test: fix incorrect write of zero to nr_hugepages +- mm/vmalloc: fix vmalloc which may return null if called with __GFP_NOFAIL +- mm: /proc/pid/smaps_rollup: avoid skipping vma after getting mmap_lock again +- mm/hugetlb: pass correct order_per_bit to cma_declare_contiguous_nid +- mm/cma: drop incorrect alignment check in cma_init_reserved_mem +- sparc64: Fix number of online CPUs +- rtla/timerlat: Fix histogram report when a cpu count is 0 +- intel_th: pci: Add Meteor Lake-S CPU support +- tpm_tis: Do *not* flush uninitialized work +- kmsan: do not wipe out origin when doing partial unpoisoning +- mm/ksm: fix ksm_pages_scanned accounting +- net/ipv6: Fix route deleting failure when metric equals 0 +- scsi: core: Handle devices which return an unusually large VPD page count +- HID: i2c-hid: elan: fix reset suspend current leakage +- filemap: add helper mapping_max_folio_size() +- kbuild: Remove support for Clang's ThinLTO caching +- crypto: ecrdsa - Fix module auto-load on add_key +- crypto: ecdsa - Fix module auto-load on add-key +- clk: qcom: clk-alpha-pll: fix rate setting for Stromer PLLs +- LoongArch: Override higher address bits in JUMP_VIRT_ADDR +- LoongArch: Add all CPUs enabled by fdt to NUMA node 0 +- KVM: arm64: AArch32: Fix spurious trapping of conditional instructions +- KVM: arm64: Allow AArch32 PSTATE.M to be restored as System mode +- KVM: arm64: Fix AArch32 register narrowing on userspace write +- Revert "drm/amdkfd: fix gfx_target_version for certain 11.0.3 devices" +- drm/amd: Fix shutdown (again) on some SMU v13.0.4/11 platforms +- drm/amdgpu/atomfirmware: add intergrated info v2.3 table +- drm/fbdev-generic: Do not set physical framebuffer address +- mmc: sdhci-acpi: Add quirk to enable pull-up on the card-detect GPIO on Asus T100TA +- mmc: sdhci-acpi: Disable write protect detection on Toshiba WT10-A +- mmc: sdhci-acpi: Fix Lenovo Yoga Tablet 2 Pro 1380 sdcard slot not working +- mmc: sdhci-acpi: Sort DMI quirks alphabetically +- mmc: sdhci: Add support for "Tuning Error" interrupts +- mmc: core: Add mmc_gpiod_set_cd_config() function +- media: v4l: async: Don't set notifier's V4L2 device if registering fails +- media: v4l2-core: hold videodev_lock until dev reg, finishes +- media: mxl5xx: Move xpt structures off stack +- media: mc: mark the media devnode as registered from the, start +- arm64: dts: ti: verdin-am62: Set memory size to 2gb +- arm64: dts: hi3798cv200: fix the size of GICR +- arm64: dts: qcom: sc8280xp: add missing PCIe minimum OPP +- wifi: rtlwifi: rtl8192de: Fix endianness issue in RX path +- wifi: rtlwifi: rtl8192de: Fix low speed with WPA3-SAE +- wifi: rtlwifi: rtl8192de: Fix 5 GHz TX power +- wifi: rtl8xxxu: Fix the TX power of RTL8192CU, RTL8723AU +- wifi: rtw89: pci: correct TX resource checking for PCI DMA channel of firmware command +- md/raid5: fix deadlock that raid5d() wait for itself to clear MD_SB_CHANGE_PENDING +- arm64: dts: qcom: qcs404: fix bluetooth device address +- arm64: tegra: Correct Tegra132 I2C alias +- ACPI: resource: Do IRQ override on TongFang GXxHRXx and GMxHGxx +- soc: qcom: rpmh-rsc: Enhance check for VRM in-flight request +- proc: Move fdinfo PTRACE_MODE_READ check into the inode .permission operation +- fsverity: use register_sysctl_init() to avoid kmemleak warning +- ata: pata_legacy: make legacy_exit() work again +- wifi: rtw89: correct aSIFSTime for 6GHz band +- bcache: fix variable length array abuse in btree_iter +- f2fs: fix to do sanity check on i_xattr_nid in sanity_check_inode() +- drm/sun4i: hdmi: Move mode_set into enable +- drm/sun4i: hdmi: Convert encoder to atomic +- selftests: net: List helper scripts in TEST_FILES Makefile variable +- selftests: net: included needed helper in the install targets +- selftests/net: synchronize udpgro tests' tx and rx connection +- vxlan: Fix regression when dropping packets due to invalid src addresses +- erofs: avoid allocating DEFLATE streams before mounting +- mptcp: fix full TCP keep-alive support +- mptcp: cleanup SOL_TCP handling +- mptcp: avoid some duplicate code in socket option handling +- net: sfp-bus: fix SFP mode detect from bitrate +- afs: Don't cross .backup mountpoint from backup volume +- mmc: core: Do not force a retune before RPMB switch +- riscv: stacktrace: fixed walk_stackframe() +- riscv: prevent pt_regs corruption for secondary idle threads +- SUNRPC: Fix loop termination condition in gss_free_in_token_pages() +- f2fs: use f2fs_{err,info}_ratelimited() for cleanup +- f2fs: write missing last sum blk of file pinning section +- perf sched timehist: Fix -g/--call-graph option failure +- media: vsp1: Remove unbalanced .s_stream(0) calls +- nouveau: report byte usage in VRAM usage. +- RDMA/bnxt_re: Fix the sparse warnings +- perf evlist: Add perf_evlist__go_system_wide() helper +- platform/x86/intel-uncore-freq: Don't present root domain on error +- platform/x86/intel/tpmi: Handle error from tpmi_process_info() +- KVM: x86: Don't advertise guest.MAXPHYADDR as host.MAXPHYADDR in CPUID +- x86/pci: Skip early E820 check for ECAM region +- x86/efistub: Omit physical KASLR when memory reservations exist +- ALSA: seq: ump: Fix swapped song position pointer data +- hwmon: (shtc1) Fix property misspelling +- hwmon: (intel-m10-bmc-hwmon) Fix multiplier for N6000 board power sensor +- drm/panel: sitronix-st7789v: fix display size for jt240mhqs_hwt_ek_e3 panel +- drm/panel: sitronix-st7789v: tweak timing for jt240mhqs_hwt_ek_e3 panel +- drm/panel: sitronix-st7789v: fix timing for jt240mhqs_hwt_ek_e3 panel +- powerpc/pseries/lparcfg: drop error message from guest name lookup +- ALSA: seq: Fix yet another spot for system message conversion +- ipvlan: Dont Use skb->sk in ipvlan_process_v{4,6}_outbound +- net: ena: Fix redundant device NUMA node override +- net: ena: Reduce lines with longer column width boundary +- net: dsa: microchip: fix RGMII error in KSZ DSA driver +- spi: stm32: Don't warn about spurious interrupts +- kheaders: use `command -v` to test for existence of `cpio` +- drm/i915/gt: Fix CCS id's calculation for CCS mode setting +- drm/i915/guc: avoid FIELD_PREP warning +- kconfig: fix comparison to constant symbols, 'm', 'n' +- net/sched: taprio: extend minimum interval restriction to entire cycle too +- net/sched: taprio: make q->picos_per_byte available to fill_sched_entry() +- netfilter: nft_fib: allow from forward/input without iif selector +- netfilter: tproxy: bail out if IP has been disabled on the device +- netfilter: nft_payload: skbuff vlan metadata mangle support +- net: ti: icssg-prueth: Fix start counter for ft1 filter +- ALSA: seq: Don't clear bank selection at event -> UMP MIDI2 conversion +- ALSA: seq: Fix missing bank setup between MIDI1/MIDI2 UMP conversion +- selftests: mptcp: join: mark 'fail' tests as flaky +- selftests: mptcp: add ms units for tc-netem delay +- selftests: mptcp: simult flows: mark 'unbalanced' tests as flaky +- ice: fix accounting if a VLAN already exists +- net: micrel: Fix lan8841_config_intr after getting out of sleep mode +- net:fec: Add fec_enet_deinit() +- ASoC: cs42l43: Only restrict 44.1kHz for the ASP +- net: usb: smsc95xx: fix changing LED_SEL bit value updated from EEPROM +- Octeontx2-pf: Free send queue buffers incase of leaf to inner +- af_unix: Read sk->sk_hash under bindlock during bind(). +- af_unix: Annotate data-race around unix_sk(sk)->addr. +- enic: Validate length of nl attributes in enic_set_vf_port +- ALSA: hda/realtek: Adjust G814JZR to use SPI init for amp +- ALSA: core: Remove debugfs at disconnection +- ALSA: jack: Use guard() for locking +- bpf: Fix potential integer overflow in resolve_btfids +- net/mlx5e: Fix UDP GSO for encapsulated packets +- net/mlx5e: Use rx_missed_errors instead of rx_dropped for reporting buffer exhaustion +- net/mlx5e: Fix IPsec tunnel mode offload feature check +- net/mlx5: Use mlx5_ipsec_rx_status_destroy to correctly delete status rules +- net/mlx5: Fix MTMP register capability offset in MCAM register +- net/mlx5: Lag, do bond only if slaves agree on roce state +- net: phy: micrel: set soft_reset callback to genphy_soft_reset for KSZ8061 +- drm/amd/display: Enable colorspace property for MST connectors +- nvmet: fix ns enable/disable possible hang +- nvme-multipath: fix io accounting on failover +- nvme-tcp: add definitions for TLS cipher suites +- dma-mapping: benchmark: handle NUMA_NO_NODE correctly +- dma-mapping: benchmark: fix node id validation +- dma-mapping: benchmark: fix up kthread-related error handling +- kthread: add kthread_stop_put +- netfilter: nft_payload: restore vlan q-in-q match support +- netfilter: nfnetlink_queue: acquire rcu_read_lock() in instance_destroy_rcu() +- kasan, fortify: properly rename memintrinsics +- ice: Interpret .set_channels() input differently +- drivers/xen: Improve the late XenStore init protocol +- nfc: nci: Fix handling of zero-length payload packets in nci_rx_work() +- net: relax socket state check at accept time. +- net: fec: avoid lock evasion when reading pps_enable +- Revert "ixgbe: Manual AN-37 for troublesome link partners for X550 SFI" +- i3c: master: svc: change ENXIO to EAGAIN when IBI occurs during start frame +- i3c: master: svc: return actual transfer data len +- i3c: master: svc: rename read_len as actual_len +- i3c: add actual_len in i3c_priv_xfer +- net: lan966x: Remove ptp traps in case the ptp is not enabled. +- rv: Update rv_en(dis)able_monitor doc to match kernel-doc +- openvswitch: Set the skbuff pkt_type for proper pmtud support. +- pNFS/filelayout: fixup pNfs allocation modes +- regulator: tps6594-regulator: Correct multi-phase configuration +- af_unix: Update unix_sk(sk)->oob_skb under sk_receive_queue lock. +- regulator: tps6287x: Force writing VSEL bit +- regulator: pickable ranges: don't always cache vsel +- rpcrdma: fix handling for RDMA_CM_EVENT_DEVICE_REMOVAL +- sunrpc: fix NFSACL RPC retry on soft mount +- nfs: keep server info for remounts +- NFSv4: Fixup smatch warning for ambiguous return +- ASoC: tas2552: Add TX path for capturing AUDIO-OUT data +- nfc: nci: Fix uninit-value in nci_rx_work +- selftests: net: kill smcrouted in the cleanup logic in amt.sh +- ipv6: sr: fix missing sk_buff release in seg6_input_core +- net: Always descend into dsa/ folder with CONFIG_NET_DSA enabled +- x86/kconfig: Select ARCH_WANT_FRAME_POINTERS again when UNWINDER_FRAME_POINTER=y +- perf/arm-dmc620: Fix lockdep assert in ->event_init() +- xen/x86: add extra pages to unpopulated-alloc if available +- regulator: bd71828: Don't overwrite runtime voltages +- blk-cgroup: Properly propagate the iostat update up the hierarchy +- blk-cgroup: fix list corruption from resetting io stat +- drm/nouveau: use tile_mode and pte_kind for VM_BIND bo allocations +- nouveau: add an ioctl to report vram usage +- nouveau: add an ioctl to return vram bar size. +- ASoC: mediatek: mt8192: fix register configuration for tdm +- ALSA: hda: cs35l56: Fix lifetime of cs_dsp instance +- ALSA: hda: cs35l56: Initialize all ASP1 registers +- ASoC: cs35l56: Fix to ensure ASP1 registers match cache +- null_blk: Fix the WARNING: modpost: missing MODULE_DESCRIPTION() +- ASoC: tas2781: Fix a warning reported by robot kernel test +- selftests/powerpc/dexcr: Add -no-pie to hashchk tests +- Revert "drm/bridge: ti-sn65dsi83: Fix enable error path" +- media: cec: core: avoid confusing "transmit timed out" message +- media: cec: core: avoid recursive cec_claim_log_addrs +- media: cec: cec-api: add locking in cec_release() +- media: cec: cec-adap: always cancel work in cec_transmit_msg_fh +- media: sunxi: a83-mips-csi2: also select GENERIC_PHY +- cxl/region: Fix cxlr_pmem leaks +- cxl/trace: Correct DPA field masks for general_media & dram events +- um: Fix the declaration of kasan_map_memory +- um: Fix the -Wmissing-prototypes warning for get_thread_reg +- um: Fix the -Wmissing-prototypes warning for __switch_mm +- powerpc/pseries: Add failure related checks for h_get_mpp and h_get_ppp +- media: flexcop-usb: fix sanity check of bNumEndpoints +- platform/x86: thinkpad_acpi: Take hotkey_mutex during hotkey_exit() +- tools/arch/x86/intel_sdsi: Fix meter_certificate decoding +- tools/arch/x86/intel_sdsi: Fix meter_show display +- tools/arch/x86/intel_sdsi: Fix maximum meter bundle length +- media: mediatek: vcodec: fix possible unbalanced PM counter +- media: mediatek: vcodec: add encoder power management helper functions +- drm/amdgpu: Fix buffer size in gfx_v9_4_3_init_ cp_compute_microcode() and rlc_microcode() +- drm/amdgpu: init microcode chip name from ip versions +- Input: cyapa - add missing input core locking to suspend/resume functions +- drm/bridge: tc358775: fix support for jeida-18 and jeida-24 +- um: vector: fix bpfflash parameter evaluation +- um: Add winch to winch_handlers before registering winch IRQ +- um: Fix return value in ubd_init() +- drm/meson: gate px_clk when setting rate +- drm/mediatek: dp: Fix mtk_dp_aux_transfer return value +- drm/msm/dpu: Always flush the slave INTF on the CTL +- drm/msm/dsi: Print dual-DSI-adjusted pclk instead of original mode pclk +- media: ov2680: Do not fail if data-lanes property is absent +- media: ov2680: Allow probing if link-frequencies is absent +- media: ov2680: Clear the 'ret' variable on success +- media: v4l: Don't turn on privacy LED if streamon fails +- media: v4l2-subdev: Document and enforce .s_stream() requirements +- Input: pm8xxx-vibrator - correct VIB_MAX_LEVELS calculation +- mmc: sdhci_am654: Fix ITAPDLY for HS400 timing +- mmc: sdhci_am654: Add ITAPDLYSEL in sdhci_j721e_4bit_set_clock +- mmc: sdhci_am654: Add OTAP/ITAP delay enable +- mmc: sdhci_am654: Drop lookup for deprecated ti,otap-del-sel +- mmc: sdhci_am654: Write ITAPDLY for DDR52 timing +- mmc: sdhci_am654: Add tuning algorithm for delay chain +- Input: ims-pcu - fix printf string overflow +- dt-bindings: adc: axi-adc: add clocks property +- dt-bindings: adc: axi-adc: update bindings for backend framework +- eventfs: Have "events" directory get permissions from its parent +- eventfs: Free all of the eventfs_inode after RCU +- eventfs/tracing: Add callback for release of an eventfs_inode +- eventfs: Create eventfs_root_inode to store dentry +- serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler +- serial: sc16is7xx: replace hardcoded divisor value with BIT() macro +- misc/pvpanic-pci: register attributes via pci_driver +- misc/pvpanic: deduplicate common code +- iio: accel: mxc4005: Reset chip on probe() and resume() +- iio: accel: mxc4005: allow module autoloading via OF compatible +- eventfs: Do not differentiate the toplevel events directory +- drm/amd/display: Revert Remove pixle rate limit for subvp +- drm/amd/display: Remove pixle rate limit for subvp +- dt-bindings: PCI: rockchip,rk3399-pcie: Add missing maxItems to ep-gpios +- s390/boot: Remove alt_stfle_fac_list from decompressor +- s390/ipl: Fix incorrect initialization of nvme dump block +- s390/ipl: Fix incorrect initialization of len fields in nvme reipl block +- s390/vdso: Use standard stack frame layout +- s390/vdso: Generate unwind information for C modules +- s390/vdso64: filter out munaligned-symbols flag for vdso +- LoongArch: Fix callchain parse error with kernel tracepoint events again +- perf tools: Add/use PMU reverse lookup from config to name +- perf tools: Use pmus to describe type from attribute +- perf pmu: "Compat" supports regular expression matching identifiers +- perf pmu: Move pmu__find_core_pmu() to pmus.c +- perf test: Add a test for strcmp_cpuid_str() expression +- perf stat: Don't display metric header for non-leader uncore events +- usb: fotg210: Add missing kernel doc description +- f2fs: fix to add missing iput() in gc_data_segment() +- perf daemon: Fix file leak in daemon_session__control +- libsubcmd: Fix parse-options memory leak +- serial: sh-sci: protect invalidating RXDMA on shutdown +- f2fs: fix to release node block count in error path of f2fs_new_node_page() +- f2fs: compress: fix to cover {reserve,release}_compress_blocks() w/ cp_rwsem lock +- f2fs: compress: fix error path of inc_valid_block_count() +- f2fs: introduce get_available_block_count() for cleanup +- f2fs: deprecate io_bits +- f2fs: compress: fix to update i_compr_blocks correctly +- perf symbols: Fix ownership of string in dso__load_vmlinux() +- perf maps: Move symbol maps functions to maps.c +- perf thread: Fixes to thread__new() related to initializing comm +- perf report: Avoid SEGV in report__setup_sample_type() +- perf ui browser: Avoid SEGV on title +- f2fs: fix block migration when section is not aligned to pow2 +- f2fs: support file pinning for zoned devices +- f2fs: kill heap-based allocation +- f2fs: separate f2fs_gc_range() to use GC for a range +- f2fs: use BLKS_PER_SEG, BLKS_PER_SEC, and SEGS_PER_SEC +- f2fs: support printk_ratelimited() in f2fs_printk() +- f2fs: Clean up errors in segment.h +- PCI/EDR: Align EDR_PORT_LOCATE_DSM with PCI Firmware r3.3 +- PCI/EDR: Align EDR_PORT_DPC_ENABLE_DSM with PCI Firmware r3.3 +- dt-bindings: spmi: hisilicon,hisi-spmi-controller: fix binding references +- extcon: max8997: select IRQ_DOMAIN instead of depending on it +- perf ui browser: Don't save pointer to stack memory +- perf bench internals inject-build-id: Fix trap divide when collecting just one DSO +- i2c: synquacer: Fix an error handling path in synquacer_i2c_probe() +- i2c: cadence: Avoid fifo clear after start +- ppdev: Add an error check in register_device +- ppdev: Remove usage of the deprecated ida_simple_xx() API +- stm class: Fix a double free in stm_register_device() +- usb: gadget: u_audio: Clear uac pointer when freed. +- dt-bindings: phy: qcom,usb-snps-femto-v2: use correct fallback for sc8180x +- dt-bindings: phy: qcom,sc8280xp-qmp-ufs-phy: fix msm899[68] power-domains +- watchdog: sa1100: Fix PTR_ERR_OR_ZERO() vs NULL check in sa1100dog_probe() +- watchdog: bd9576: Drop "always-running" property +- pinctrl: qcom: pinctrl-sm7150: Fix sdc1 and ufs special pins regs +- dt-bindings: pinctrl: mediatek: mt7622: fix array properties +- VMCI: Fix an error handling path in vmci_guest_probe_device() +- ovl: remove upper umask handling from ovl_create_upper() +- leds: pwm: Disable PWM when going to suspend +- pwm: Rename pwm_apply_state() to pwm_apply_might_sleep() +- perf intel-pt: Fix unassigned instruction op (discovered by MemorySanitizer) +- PCI: Wait for Link Training==0 before starting Link retrain +- microblaze: Remove early printk call from cpuinfo-static.c +- microblaze: Remove gcc flag for non existing early_printk.c file +- udf: Convert udf_expand_file_adinicb() to use a folio +- udf: Remove GFP_NOFS allocation in udf_expand_file_adinicb() +- i915: make inject_virtual_interrupt() void +- coresight: etm4x: Fix access to resource selector registers +- coresight: etm4x: Safe access for TRCQCLTR +- coresight: etm4x: Do not save/restore Data trace control registers +- coresight: etm4x: Do not hardcode IOMEM access for register restore +- iio: adc: adi-axi-adc: only error out in major version mismatch +- iio: adc: adi-axi-adc: move to backend framework +- iio: adc: ad9467: convert to backend framework +- iio: add the IIO backend framework +- iio: buffer-dmaengine: export buffer alloc and free functions +- iio: adc: adi-axi-adc: convert to regmap +- iio: adc: ad9467: use chip_info variables instead of array +- iio: adc: ad9467: use spi_get_device_match_data() +- iio: pressure: dps310: support negative temperature values +- perf test shell arm_coresight: Increase buffer size for Coresight basic tests +- perf docs: Document bpf event modifier +- coresight: etm4x: Fix unbalanced pm_runtime_enable() +- riscv: dts: starfive: visionfive 2: Remove non-existing TDM hardware +- iio: adc: stm32: Fixing err code to not indicate success +- f2fs: fix to check pinfile flag in f2fs_move_file_range() +- f2fs: fix to relocate check condition in f2fs_fallocate() +- f2fs: compress: fix to relocate check condition in f2fs_ioc_{,de}compress_file() +- f2fs: compress: fix to relocate check condition in f2fs_{release,reserve}_compress_blocks() +- perf bench uprobe: Remove lib64 from libc.so.6 binary path +- dt-bindings: PCI: rcar-pci-host: Add missing IOMMU properties +- dt-bindings: PCI: rcar-pci-host: Add optional regulators +- perf record: Fix debug message placement for test consumption +- perf record: Move setting tracking events before record__init_thread_masks() +- perf evlist: Add evlist__findnew_tracking_event() helper +- perf tests: Apply attributes to all events in object code reading test +- perf tests: Make "test data symbol" more robust on Neoverse N1 +- arm64: dts: meson: fix S4 power-controller node +- interconnect: qcom: qcm2290: Fix mas_snoc_bimc QoS port assignment +- module: don't ignore sysfs_create_link() failures +- serial: sc16is7xx: add proper sched.h include for sched_set_fifo() +- PCI: tegra194: Fix probe path for Endpoint mode +- greybus: arche-ctrl: move device table to its right location +- serial: max3100: Fix bitwise types +- serial: max3100: Update uart_driver_registered on driver removal +- perf annotate: Fix annotation_calc_lines() to pass correct address to get_srcline() +- perf annotate: Use global annotation_options +- perf top: Convert to the global annotation_options +- perf report: Convert to the global annotation_options +- perf annotate: Introduce global annotation_options +- perf annotate: Split branch stack cycles information out of 'struct annotation_line' +- perf machine thread: Remove exited threads by default +- perf record: Lazy load kernel symbols +- firmware: dmi-id: add a release callback function +- dmaengine: idma64: Add check for dma_set_max_seg_size +- soundwire: cadence: fix invalid PDI offset +- perf stat: Do not fail on metrics on s390 z/VM systems +- usb: typec: ucsi: simplify partner's PD caps registration +- usb: typec: ucsi: always register a link to USB PD device +- perf annotate: Get rid of duplicate --group option item +- counter: linux/counter.h: fix Excess kernel-doc description warning +- f2fs: fix to wait on page writeback in __clone_blkaddrs() +- phy: qcom: qmp-combo: fix duplicate return in qmp_v4_configure_dp_phy +- iio: core: Leave private pointer NULL when no private data supplied +- perf probe: Add missing libgen.h header needed for using basename() +- perf record: Delete session after stopping sideband thread +- sched/fair: Allow disabling sched_balance_newidle with sched_relax_domain_level +- af_packet: do not call packet_read_pending() from tpacket_destruct_skb() +- net: qrtr: ns: Fix module refcnt +- selftests: net: bridge: increase IGMP/MLD exclude timeout membership interval +- tracing/user_events: Fix non-spaced field matching +- tracing/user_events: Prepare find/delete for same name events +- tracing/user_events: Allow events to persist for perfmon_capable users +- RDMA/cma: Fix kmemleak in rdma_core observed during blktests nvme/rdma use siw +- RDMA/IPoIB: Fix format truncation compilation errors +- selftests/kcmp: remove unused open mode +- SUNRPC: Fix gss_free_in_token_pages() +- bnxt_re: avoid shift undefined behavior in bnxt_qplib_alloc_init_hwq +- RDMA/bnxt_re: Adds MSN table capability for Gen P7 adapters +- RDMA/bnxt_re: Update the HW interface definitions +- RDMA/bnxt_re: Remove roundup_pow_of_two depth for all hardware queue resources +- RDMA/bnxt_re: Refactor the queue index update +- ext4: remove the redundant folio_wait_stable() +- ext4: fix potential unnitialized variable +- sunrpc: removed redundant procp check +- ext4: avoid excessive credit estimate in ext4_tmpfile() +- x86/insn: Add VEX versions of VPDPBUSD, VPDPBUSDS, VPDPWSSD and VPDPWSSDS +- x86/insn: Fix PUSH instruction in x86 instruction decoder opcode map +- clk: qcom: mmcc-msm8998: fix venus clock issue +- clk: qcom: dispcc-sm8550: fix DisplayPort clocks +- clk: qcom: dispcc-sm6350: fix DisplayPort clocks +- clk: qcom: dispcc-sm8450: fix DisplayPort clocks +- lib/test_hmm.c: handle src_pfns and dst_pfns allocation failure +- clk: renesas: r9a07g043: Add clock and reset entry for PLIC +- clk: renesas: r8a779a0: Fix CANFD parent clock +- IB/mlx5: Use __iowrite64_copy() for write combining stores +- RDMA/rxe: Fix incorrect rxe_put in error path +- RDMA/rxe: Allow good work requests to be executed +- clk: qcom: clk-alpha-pll: remove invalid Stromer register offset +- clk: rs9: fix wrong default value for clock amplitude +- clk: mediatek: mt8365-mm: fix DPI0 parent +- clk: mediatek: pllfh: Don't log error for missing fhctl node +- RDMA/mlx5: Adding remote atomic access flag to updatable flags +- RDMA/mlx5: Uncacheable mkey has neither rb_key or cache_ent +- clk: samsung: exynosautov9: fix wrong pll clock id value +- media: cadence: csi2rx: configure DPHY before starting source stream +- drm/edid: Parse topology block for all DispID structure v1.x +- drm/rockchip: vop2: Do not divide height twice for YUV +- media: uvcvideo: Add quirk for Logitech Rally Bar +- drm/mipi-dsi: use correct return type for the DSC functions +- drm/panel: simple: Add missing Innolux G121X1-L03 format, flags, connector +- drm/bridge: anx7625: Update audio status while detecting +- drm/panel: novatek-nt35950: Don't log an error when DSI host can't be found +- drm/bridge: dpc3433: Don't log an error when DSI host can't be found +- drm/bridge: tc358775: Don't log an error when DSI host can't be found +- drm/bridge: lt9611uxc: Don't log an error when DSI host can't be found +- drm/bridge: lt9611: Don't log an error when DSI host can't be found +- drm/bridge: lt8912b: Don't log an error when DSI host can't be found +- drm/bridge: icn6211: Don't log an error when DSI host can't be found +- drm/bridge: anx7625: Don't log an error when DSI host can't be found +- ASoC: tracing: Export SND_SOC_DAPM_DIR_OUT to its value +- drm: vc4: Fix possible null pointer dereference +- media: atomisp: ssh_css: Fix a null-pointer dereference in load_video_binaries +- fbdev: sh7760fb: allow modular build +- media: v4l2-subdev: Fix stream handling for crop API +- media: i2c: et8ek8: Don't strip remove function when driver is builtin +- media: dt-bindings: ovti,ov2680: Fix the power supply names +- media: ipu3-cio2: Request IRQ earlier +- drm/msm/dp: Avoid a long timeout for AUX transfer if nothing connected +- drm/msm/dp: allow voltage swing / pre emphasis of 3 +- media: radio-shark2: Avoid led_names truncations +- media: rcar-vin: work around -Wenum-compare-conditional warning +- media: ngene: Add dvb_ca_en50221_init return value check +- ASoC: Intel: avs: Test result of avs_get_module_entry() +- ASoC: Intel: avs: Fix potential integer overflow +- ASoC: Intel: avs: Fix ASRC module initialization +- selftests: cgroup: skip test_cgcore_lesser_ns_open when cgroup2 mounted without nsdelegate +- fbdev: sisfb: hide unused variables +- ASoC: SOF: Intel: mtl: Implement firmware boot state check +- ASoC: SOF: Intel: mtl: Disable interrupts when firmware boot failed +- ASoC: SOF: Intel: mtl: call dsp dump when boot retry fails +- ASoC: SOF: Intel: lnl: Correct rom_status_reg +- ASoC: SOF: Intel: mtl: Correct rom_status_reg +- ASoC: SOF: Intel: pci-mtl: fix ARL-S definitions +- ASoC: SOF: Intel: pci-mtl: use ARL specific firmware definitions +- ASoC: Intel: common: add ACPI matching tables for Arrow Lake +- powerpc/fsl-soc: hide unused const variable +- drm/meson: vclk: fix calculation of 59.94 fractional rates +- ASoC: kirkwood: Fix potential NULL dereference +- fbdev: shmobile: fix snprintf truncation +- mtd: rawnand: hynix: fixed typo +- mtd: core: Report error if first mtd_otp_size() call fails in mtd_otp_nvmem_add() +- ASoC: Intel: avs: ssm4567: Do not ignore route checks +- ASoC: Intel: Disable route checks for Skylake boards +- drm/amd/display: Fix potential index out of bounds in color transformation function +- drm/panel: atna33xc20: Fix unbalanced regulator in the case HPD doesn't assert +- drm/dp: Don't attempt AUX transfers when eDP panels are not powered +- drm/lcdif: Do not disable clocks on already suspended hardware +- dev_printk: Add and use dev_no_printk() +- printk: Let no_printk() use _printk() +- drm/omapdrm: Fix console with deferred ops +- fbdev: Provide I/O-memory helpers as module +- drm/omapdrm: Fix console by implementing fb_dirty +- drm/ci: update device type for volteer devices +- drm/ci: add subset-1-gfx to LAVA_TAGS and adjust shards +- drm/ci: uprev mesa version: fix container build & crosvm +- drm/bridge: Fix improper bridge init order with pre_enable_prev_first +- Bluetooth: qca: Fix error code in qca_read_fw_build_info() +- Bluetooth: compute LE flow credits based on recvbuf space +- net: micrel: Fix receiving the timestamp in the frame for lan8841 +- mptcp: SO_KEEPALIVE: fix getsockopt support +- riscv, bpf: make some atomic operations fully ordered +- s390/bpf: Emit a barrier for BPF_FETCH instructions +- net/mlx5: Reload only IB representors upon lag disable/enable +- net/mlx5: Enable 4 ports multiport E-switch +- ipv6: sr: fix invalid unregister error path +- ipv6: sr: fix incorrect unregister order +- ipv6: sr: add missing seg6_local_exit +- net: usb: smsc95xx: stop lying about skb->truesize +- net: ethernet: cortina: Locking fixes +- selftests: net: move amt to socat for better compatibility +- selftests: net: add missing config for amt.sh +- selftests: net: add more missing kernel config +- net: ipv6: fix wrong start position when receive hop-by-hop fragment +- m68k: mac: Fix reboot hang on Mac IIci +- m68k: Fix spinlock race in kernel thread creation +- net: usb: sr9700: stop lying about skb->truesize +- usb: aqc111: stop lying about skb->truesize +- HID: amd_sfh: Handle "no sensors" in PM operations +- wifi: mwl8k: initialize cmd->addr[] properly +- scsi: qla2xxx: Fix debugfs output for fw_resource_count +- scsi: bfa: Ensure the copied buf is NUL terminated +- HID: intel-ish-hid: ipc: Add check for pci_alloc_irq_vectors +- selftests/bpf: Fix pointer arithmetic in test_xdp_do_redirect +- kunit: Fix kthread reference +- selftests: default to host arch for LLVM builds +- selftests/resctrl: fix clang build failure: use LOCAL_HDRS +- selftests/binderfs: use the Makefile's rules, not Make's implicit rules +- libbpf: Fix error message in attach_kprobe_multi +- wifi: mt76: mt7603: add wpdma tx eof flag for PSE client reset +- wifi: mt76: mt7603: fix tx queue of loopback packets +- Revert "sh: Handle calling csum_partial with misaligned data" +- sh: kprobes: Merge arch_copy_kprobe() into arch_prepare_kprobe() +- wifi: ar5523: enable proper endpoint verification +- net: give more chances to rcu in netdev_wait_allrefs_any() +- pwm: sti: Simplify probe function using devm functions +- pwm: sti: Prepare removing pwm_chip from driver data +- tcp: avoid premature drops in tcp_add_backlog() +- net: dsa: mv88e6xxx: Avoid EEPROM timeout without EEPROM on 88E6250-family switches +- net: dsa: mv88e6xxx: Add support for model-specific pre- and post-reset handlers +- wifi: ath10k: populate board data for WCN3990 +- cpufreq: brcmstb-avs-cpufreq: ISO C90 forbids mixed declarations +- scsi: ufs: core: mcq: Fix ufshcd_mcq_sqe_search() +- selftests/bpf: Fix a fd leak in error paths in open_netns +- gfs2: do_xmote fixes +- gfs2: finish_xmote cleanup +- gfs2: Rename gfs2_withdrawn to gfs2_withdrawing_or_withdrawn +- gfs2: Mark withdraws as unlikely +- gfs2: Rename gfs2_lookup_{ simple => meta } +- gfs2: Convert gfs2_internal_read to folios +- gfs2: Get rid of gfs2_alloc_blocks generation parameter +- wifi: ath10k: Fix an error code problem in ath10k_dbg_sta_write_peer_debug_trigger() +- dt-bindings: thermal: loongson,ls2k-thermal: Fix incorrect compatible definition +- dt-bindings: thermal: loongson,ls2k-thermal: Add Loongson-2K0500 compatible +- dt-bindings: thermal: loongson,ls2k-thermal: Fix binding check issues +- thermal/drivers/tsens: Fix null pointer dereference +- x86/purgatory: Switch to the position-independent small code model +- scsi: hpsa: Fix allocation size for Scsi_Host private data +- scsi: libsas: Fix the failure of adding phy with zero-address to port +- udp: Avoid call to compute_score on multiple sites +- x86/pat: Fix W^X violation false-positives when running as Xen PV guest +- x86/pat: Restructure _lookup_address_cpa() +- x86/pat: Introduce lookup_address_in_pgd_attr() +- cpufreq: exit() callback is optional +- tcp: increase the default TCP scaling ratio +- selftests/bpf: Fix umount cgroup2 error in test_sockmap +- x86/boot/64: Clear most of CR4 in startup_64(), except PAE, MCE and LA57 +- gfs2: Fix "ignore unlock failures after withdraw" +- gfs2: Don't forget to complete delayed withdraw +- ACPI: disable -Wstringop-truncation +- irqchip/loongson-pch-msi: Fix off-by-one on allocation error path +- irqchip/alpine-msi: Fix off-by-one in allocation error path +- locking/atomic/x86: Correct the definition of __arch_try_cmpxchg128() +- ACPI: LPSS: Advertise number of chip selects via property +- scsi: ufs: core: Perform read back after disabling UIC_COMMAND_COMPL +- scsi: ufs: core: Perform read back after disabling interrupts +- scsi: ufs: core: Perform read back after writing UTP_TASK_REQ_LIST_BASE_H +- scsi: ufs: cdns-pltfrm: Perform read back after writing HCLKDIV +- scsi: ufs: qcom: Perform read back after writing CGC enable +- scsi: ufs: qcom: Perform read back after writing unipro mode +- scsi: ufs: qcom: Perform read back after writing REG_UFS_SYS1CLK_1US +- scsi: ufs: qcom: Perform read back after writing reset bit +- bpf: prevent r10 register from being marked as precise +- bpf: Pack struct bpf_fib_lookup +- bpftool: Mount bpffs on provided dir instead of parent dir +- wifi: carl9170: re-fix fortified-memset warning +- dlm: fix user space lock decision to copy lvb +- bitops: add missing prototype check +- mlx5: stop warning for 64KB pages +- mlx5: avoid truncating error message +- qed: avoid truncating work queue length +- enetc: avoid truncating error message +- ACPI: Fix Generic Initiator Affinity _OSC bit +- sched/fair: Add EAS checks before updating root_domain::overutilized +- wifi: iwlwifi: mvm: fix check in iwl_mvm_sta_fw_id_mask +- wifi: iwlwifi: reconfigure TLC during HW restart +- wifi: iwlwifi: mvm: select STA mask only for active links +- wifi: iwlwifi: mvm: allocate STA links only for active links +- wifi: ieee80211: fix ieee80211_mle_basic_sta_prof_size_ok() +- x86/boot: Ignore relocations in .notes sections in walk_relocs() too +- wifi: mt76: mt7915: workaround too long expansion sparse warnings +- wifi: ath12k: use correct flag field for 320 MHz channels +- bpftool: Fix missing pids during link show +- wifi: ath11k: don't force enable power save on non-running vdevs +- wifi: brcmfmac: pcie: handle randbuf allocation failure +- wifi: ath10k: poll service ready message before failing +- block: fix and simplify blkdevparts= cmdline parsing +- lkdtm: Disable CFI checking for perms functions +- soc: qcom: pmic_glink: Make client-lock non-sleeping +- null_blk: Fix missing mutex_destroy() at module removal +- soc: mediatek: cmdq: Fix typo of CMDQ_JUMP_RELATIVE +- firmware: qcom: scm: Fix __scm and waitq completion variable initialization +- soc: qcom: pmic_glink: notify clients about the current state +- soc: qcom: pmic_glink: don't traverse clients list without a lock +- s390/mm: Re-enable the shared zeropage for !PV and !skeys KVM guests +- mm/userfaultfd: Do not place zeropages when zeropages are disallowed +- io-wq: write next_work before dropping acct_lock +- ARM: configs: sunxi: Enable DRM_DW_HDMI +- io_uring: use the right type for work_llist empty check +- s390/cio: fix tracepoint subchannel type field +- crypto: x86/sha512-avx2 - add missing vzeroupper +- crypto: x86/sha256-avx2 - add missing vzeroupper +- crypto: x86/nh-avx2 - add missing vzeroupper +- crypto: ccp - drop platform ifdef checks +- parisc: add missing export of __cmpxchg_u8() +- nilfs2: fix out-of-range warning +- firmware: raspberrypi: Use correct device for DMA mappings +- mm/slub, kunit: Use inverted data to corrupt kmem cache +- openpromfs: finish conversion to the new mount API +- nvmet: prevent sprintf() overflow in nvmet_subsys_nsid_exists() +- ksmbd: fix uninitialized symbol 'share' in smb2_tree_connect() +- epoll: be better about file lifetimes +- nvmet: fix nvme status code when namespace is disabled +- nvmet-tcp: fix possible memory leak when tearing down a controller +- nvme: cancel pending I/O if nvme controller is in terminal state +- nvmet-auth: replace pr_debug() with pr_err() to report an error. +- nvmet-auth: return the error code to the nvmet_auth_host_hash() callers +- nvme: find numa distance only if controller has valid numa id +- drm/amdkfd: Flush the process wq before creating a kfd_process +- drm/amd/display: Disable seamless boot on 128b/132b encoding +- drm/amd/display: Fix DC mode screen flickering on DCN321 +- drm/amd/display: Add VCO speed parameter for DCN31 FPU +- drm/amd/display: Allocate zero bw after bw alloc enable +- drm/amd/display: Add dtbclk access to dcn315 +- drm/amdgpu: Fix VRAM memory accounting +- ALSA: hda: intel-dsp-config: harden I2C/I2S codec detection +- ASoC: da7219-aad: fix usage of device_get_named_child_node() +- platform/x86: ISST: Add Grand Ridge to HPM CPU list +- softirq: Fix suspicious RCU usage in __do_softirq() +- ALSA: emu10k1: make E-MU FPGA writes potentially more reliable +- bpf, x86: Fix PROBE_MEM runtime load check +- fpga: dfl-pci: add PCI subdevice ID for Intel D5005 card +- Input: xpad - add support for ASUS ROG RAIKIRI +- KVM: selftests: Add test for uaccesses to non-existent vgic-v2 CPUIF +- ASoC: rt715-sdca: volume step modification +- ASoC: rt715: add vendor clear control register +- ASoC: cs35l41: Update DSP1RX5/6 Sources for DSP config +- regulator: vqmmc-ipq4019: fix module autoloading +- regulator: qcom-refgen: fix module autoloading +- ASoC: rt722-sdca: add headset microphone vrefo setting +- ASoC: rt722-sdca: modify channel number to support 4 channels +- ASoC: dt-bindings: rt5645: add cbj sleeve gpio property +- ASoC: rt5645: Fix the electric noise due to the CBJ contacts floating +- ASoC: acp: Support microphone from device Acer 315-24p +- ASoC: SOF: pcm: Restrict DSP D0i3 during S0ix to IPC3 +- ALSA: hda: cs35l56: Exit cache-only after cs35l56_wait_for_firmware_boot() +- regulator: irq_helpers: duplicate IRQ name +- ASoC: Intel: bytcr_rt5640: Apply Asus T100TA quirk to Asus T100TAM too +- sched/isolation: Fix boot crash when maxcpus < first housekeeping CPU +- selftests: sud_test: return correct emulated syscall value on RISC-V +- drm/etnaviv: fix tx clock gating on some GC7000 variants +- LoongArch: Lately init pmu after smp is online +- cpu: Ignore "mitigations" kernel parameter if CPU_MITIGATIONS=n +- drm/amdgpu: Fix the ring buffer size for queue VM flush +- drm/amdkfd: Add VRAM accounting for SVM migration +- drm/amd/pm: Restore config space after reset +- drm/amdgpu: Update BO eviction priorities +- drm/amd/display: Set color_mgmt_changed to true on unsuspend +- net: usb: qmi_wwan: add Telit FN920C04 compositions +- HID: mcp-2221: cancel delayed_work only when CONFIG_IIO is enabled +- dt-bindings: rockchip: grf: Add missing type to 'pcie-phy' node +- wifi: cfg80211: fix the order of arguments for trace events of the tx_rx_evt class +- wifi: mac80211: ensure beacon is non-S1G prior to extracting the beacon timestamp field +- wifi: mac80211: don't use rate mask for scanning +- KEYS: asymmetric: Add missing dependency on CRYPTO_SIG +- ALSA: hda/realtek: fix mute/micmute LEDs don't work for ProBook 440/460 G11. +- ksmbd: ignore trailing slashes in share paths +- ksmbd: avoid to send duplicate oplock break notifications +- fs/ntfs3: Break dir enumeration if directory contents error +- fs/ntfs3: Fix case when index is reused during tree transformation +- fs/ntfs3: Taking DOS names into account during link counting +- fs/ntfs3: Remove max link count info display during driver init +- net: smc91x: Fix m68k kernel compilation for ColdFire CPU +- net: lan966x: remove debugfs directory in probe() error path +- net: ti: icssg_prueth: Fix NULL pointer dereference in prueth_probe() +- tools/nolibc/stdlib: fix memory error in realloc() +- tools/latency-collector: Fix -Wformat-security compile warns +- net: mana: Fix the extra HZ in mana_hwc_send_request +- Revert "r8169: don't try to disable interrupts if NAPI is, scheduled already" +- io_uring: fail NOP if non-zero op flags is passed in +- Input: try trimming too long modalias strings +- serial: 8520_mtk: Set RTS on shutdown for Rx in-band wakeup +- serial: 8250_bcm7271: use default_mux_rate if possible +- tty: n_gsm: fix missing receive state reset after mode switch +- selftests/ftrace: Fix BTFARG testcase to check fprobe is enabled correctly +- x86/tsc: Trust initial offset in architectural TSC-adjust MSRs +- !10398 BMA: Fix DMA reset problem and change the version +- BMA/kbox_drv: Change the version number. +- BMA/veth_drv: Change the version number. +- BMA/cdev_drv: Change the version number. +- BMA/edma_drv: Fix DMA reset problem and change the version number. +- !10358 jbd2: stop waiting for space when jbd2_cleanup_journal_tail() returns error +- jbd2: stop waiting for space when jbd2_cleanup_journal_tail() returns error +- !10344 CVE-2024-39471 +- drm/amdgpu: Fix signedness bug in sdma_v4_0_process_trap_irq() +- drm/amdgpu: add error handle to avoid out-of-bounds +- !9904 ext4: improve buffered write with more than one blocks_per_folio +- ext4: improve sub-polio check in ext4_iomap_write_begin() +- iomap: add iomap_is_fully_dirty() +- iomap: correct the dirty length in page mkwrite +- iomap: advance the ifs allocation if we have more than one blocks per folio +- iomap: support invalidating partial folios +- iomap: correct the range of a partial dirty clear +- !9533 net/mlx5: Add a timeout to acquire the command queue semaphore +- net/mlx5: Add a timeout to acquire the command queue semaphore +- !10317 improve dump_page() robustness +- mm: improve dumping of mapcount and page_type +- mm: add __dump_folio() +- fs: improve dump_mapping() robustness +- !9361 macintosh/via-macii: Fix "BUG: sleeping function called from invalid context" +- macintosh/via-macii: Fix "BUG: sleeping function called from invalid context" +- !9892 support for SMC-D loopback_lo feature +- net/smc: enable the smc-lo on the x86 and arm64 platforms +- net/smc: implement DMB-merged operations of loopback-ism +- net/smc: adapt cursor update when sndbuf and peer DMB are merged +- net/smc: {at|de}tach sndbuf to peer DMB if supported +- net/smc: add operations to merge sndbuf with peer DMB +- net/smc: register loopback-ism into SMC-D device list +- net/smc: ignore loopback-ism when dumping SMC-D devices +- net/smc: mark optional smcd_ops and check for support when called +- net/smc: implement DMB-related operations of loopback-ism +- net/smc: implement ID-related operations of loopback-ism +- net/smc: introduce loopback-ism for SMC intra-OS shortcut +- net/smc: decouple ism_client from SMC-D DMB registration +- net/smc: change the term virtual ISM to Emulated-ISM +- net/smc: fix incorrect SMC-D link group matching logic +- net/smc: manage system EID in SMC stack instead of ISM driver +- net/smc: support extended GID in SMC-D lgr netlink attribute +- net/smc: compatible with 128-bits extended GID of virtual ISM device +- net/smc: define a reserved CHID range for virtual ISM devices +- net/smc: introduce virtual ISM device support feature +- net/smc: support SMCv2.x supplemental features negotiation +- net/smc: unify the structs of accept or confirm message for v1 and v2 +- net/smc: introduce sub-functions for smc_clc_send_confirm_accept() +- net/smc: rename some 'fce' to 'fce_v2x' for clarity +- !10171 netrom: Fix a memory leak in nr_heartbeat_expiry() +- netrom: Fix a memory leak in nr_heartbeat_expiry() +- !10312 bpf: Fix too early release of tcx_entry +- bpf: Fix too early release of tcx_entry +- !10170 x86: resctrl: Fix illegal access by the chips not having RDT +- x86: resctrl: Fix illegal access by the chips not having RDT +- !10311 wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects +- wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects +- !10254 fbdev: savage: Handle err return when savagefb_check_var failed +- fbdev: savage: Handle err return when savagefb_check_var failed +- !10078 bpf: Set run context for rawtp test_run callback +- bpf: Set run context for rawtp test_run callback +- !10261 batman-adv: bypass empty buckets in batadv_purge_orig_ref() +- batman-adv: bypass empty buckets in batadv_purge_orig_ref() +- !10066 serial: imx: Introduce timeout when waiting on transmitter empty +- serial: imx: Introduce timeout when waiting on transmitter empty +- !9971 KVM: Fix a data race on last_boosted_vcpu in kvm_vcpu_on_spin() +- KVM: Fix a data race on last_boosted_vcpu in kvm_vcpu_on_spin() + +' for pr_err +* Wed Jul 24 2024 ZhangPeng - 6.6.0-35.0.0.43 +- !9782 usb-storage: alauda: Check whether the media is initialized +- usb-storage: alauda: Check whether the media is initialized +- !10294 [OLK-6.6] drivers: Fix compile warning "argument used uninitialized" +- drivers: Fix compile warning "argument used uninitialized" +- !10257 media: dvb-usb: Fix unexpected infinite loop in dvb_usb_read_remote_control() +- media: dvb-usb: Fix unexpected infinite loop in dvb_usb_read_remote_control() +- !10287 CVE-2024-36979 +- net: bridge: mst: pass vlan group directly to br_mst_vlan_set_state +- net: bridge: mst: fix suspicious rcu usage in br_mst_set_state +- net: bridge: mst: fix vlan use-after-free +- !10018 ocfs2: fix NULL pointer dereference in ocfs2_journal_dirty() +- ocfs2: fix NULL pointer dereference in ocfs2_journal_dirty() +- !9985 btrfs: zoned: allocate dummy checksums for zoned NODATASUM writes +- btrfs: zoned: allocate dummy checksums for zoned NODATASUM writes +- !10260 [RoCE]从社区回合patch到openEuler(OLK-6.6) +- RDMA/hns: Fix mbx timing out before CMD execution is completed +- RDMA/hns: Fix insufficient extend DB for VFs. +- RDMA/hns: Fix undifined behavior caused by invalid max_sge +- RDMA/hns: Fix shift-out-bounds when max_inline_data is 0 +- RDMA/hns: Fix missing pagesize and alignment check in FRMR +- RDMA/hns: Fix unmatch exception handling when init eq table fails +- RDMA/hns: Check atomic wr length +- !10248 ssb: Fix potential NULL pointer dereference in ssb_device_uevent() +- ssb: Fix potential NULL pointer dereference in ssb_device_uevent() +- !9243 Bluetooth: RFCOMM: Fix not validating setsockopt user input +- Bluetooth: RFCOMM: Fix not validating setsockopt user input +- !10160 fix CVE-2024-40915 +- riscv: rewrite __kernel_map_pages() to fix sleeping in invalid context +- !10264 mm: filemap: optimize semantic when thp_exec_enabled is set to 3 +- mm: filemap: optimize semantic when thp_exec_enabled is set to 3 +- !5264 [OLK-6.6]HYGON: Support CSV Reuse ASID feature on Hygon CPUs +- KVM: SVM: Add support for different CSV guests to reuse the same ASID +- !10231 fix CVE-2024-41007 +- tcp: avoid too many retransmit packets +- tcp: use signed arithmetic in tcp_rtx_probe0_timed_out() +- !10233 fpga: bridge: add owner module and take its refcount +- fpga: bridge: add owner module and take its refcount +- !10237 ocfs2: fix NULL pointer dereference in ocfs2_abort_trigger() +- ocfs2: fix NULL pointer dereference in ocfs2_abort_trigger() +- !9915 powerpc/pseries: Enforce hcall result buffer validity and size +- powerpc/pseries: Enforce hcall result buffer validity and size +- !10148 fs/9p: fix uninitialized values during inode evict +- fs/9p: fix uninitialized values during inode evict +- !10056 io_uring/rsrc: don't lock while !TASK_RUNNING +- io_uring/rsrc: don't lock while !TASK_RUNNING +- !10226 cxl/region: Fix memregion leaks in devm_cxl_add_region() +- cxl/region: Fix memregion leaks in devm_cxl_add_region() +- !10177 ima: Fix use-after-free on a dentry's dname.name +- ima: Fix use-after-free on a dentry's dname.name +- !5262 [OLK-6.6]HYGON: Support Hygon DCU passthrough to VMs +- x86/config: Set CONFIG_HYDCU_FIXUP_HEADER=y by default +- drm/hygon: Add support to passthrough Hygon DCU to virtual machine +- !10220 bpf: Fix overrunning reservations in ringbuf +- bpf: Fix overrunning reservations in ringbuf +- !10219 CVE-2024-35931 +- drm/amdgpu: Skip do PCI error slot reset during RAS recovery +- drm/amdgpu : Add hive ras recovery check +- !10167 CVE-2024-36022 +- drm/amdgpu: Init zone device and drm client after mode-1 reset on reload +- drm/amdgpu: move the drm client creation behind drm device registration +- drm/amdkfd: init drm_client with funcs hook +- drm/amdkfd: Export DMABufs from KFD using GEM handles +- !9598 fpga: manager: add owner module and take its refcount +- fpga: manager: add owner module and take its refcount +- !10139 [sync] PR-10095: CVE-2024-40968 +- MIPS: Octeon: Add PCIe link status check +- !10044 btrfs: fix CVE-2024-39496 +- btrfs: zoned: fix use-after-free due to race with dev replace +- btrfs: zoned: factor out DUP bg handling from btrfs_load_block_group_zone_info +- btrfs: zoned: factor out single bg handling from btrfs_load_block_group_zone_info +- btrfs: zoned: factor out per-zone logic from btrfs_load_block_group_zone_info +- btrfs: zoned: introduce a zone_info struct in btrfs_load_block_group_zone_info +- !10114 v2 ecryptfs: Fix buffer size for tag 66 packet +- ecryptfs: Fix buffer size for tag 66 packet +- !10133 ALSA: timer: Set lower bound of start tick time +- ALSA: timer: Set lower bound of start tick time +- !10115 efi/unaccepted: touch soft lockup during memory accept +- efi/unaccepted: touch soft lockup during memory accept +- !10131 kunit/fortify: Fix mismatched kvalloc()/vfree() usage +- kunit/fortify: Fix mismatched kvalloc()/vfree() usage +- !10132 wifi: ath12k: fix out-of-bound access of qmi_invoke_handler() +- wifi: ath12k: fix out-of-bound access of qmi_invoke_handler() +- !10188 Part of "mm: mapcount for large folios + page_mapcount() cleanups" +- mm/rmap: add fast-path for small folios when adding/removing/duplicating +- mm/rmap: always inline anon/file rmap duplication of a single PTE +- mm: allow for detecting underflows with page_mapcount() again +- !10001 tty: n_gsm: fix possible out-of-bounds in gsm0_receive() +- tty: n_gsm: fix possible out-of-bounds in gsm0_receive() +- !10176 f2fs: compress: don't allow unaligned truncation on released compress inode +- f2fs: compress: don't allow unaligned truncation on released compress inode +- !10106 platform/x86: x86-android-tablets: Unregister devices in reverse order +- platform/x86: x86-android-tablets: Unregister devices in reverse order +- !10109 tracing: Build event generation tests only as modules +- tracing: Build event generation tests only as modules +- !10166 drop_monitor: replace spin_lock by raw_spin_lock +- drop_monitor: replace spin_lock by raw_spin_lock +- !10161 RDMA/mlx5: Add check for srq max_sge attribute +- RDMA/mlx5: Add check for srq max_sge attribute +- !10111 drm/exynos: hdmi: report safe 640x480 mode as a fallback when no EDID found +- drm/exynos: hdmi: report safe 640x480 mode as a fallback when no EDID found +- !10155 wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup() +- wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup() +- !10149 mips: bmips: BCM6358: make sure CBR is correctly set +- mips: bmips: BCM6358: make sure CBR is correctly set +- !10103 v2 fpga: region: add owner module and take its refcount +- fpga: region: add owner module and take its refcount +- !10097 [sync] PR-9741: scsi: qedf: Ensure the copied buf is NUL terminated +- scsi: qedf: Ensure the copied buf is NUL terminated +- !10021 drm/exynos/vidi: fix memory leak in .get_modes() +- drm/exynos/vidi: fix memory leak in .get_modes() +- !10127 wifi: iwlwifi: mvm: don't read past the mfuart notifcation +- wifi: iwlwifi: mvm: don't read past the mfuart notifcation +- !10117 wifi: iwlwifi: mvm: check n_ssids before accessing the ssids +- wifi: iwlwifi: mvm: check n_ssids before accessing the ssids +- !10116 wifi: mt76: mt7921s: fix potential hung tasks during chip recovery +- wifi: mt76: mt7921s: fix potential hung tasks during chip recovery +- !10017 liquidio: Adjust a NULL pointer handling path in lio_vf_rep_copy_packet +- liquidio: Adjust a NULL pointer handling path in lio_vf_rep_copy_packet +- !10051 tipc: force a dst refcount before doing decryption +- tipc: force a dst refcount before doing decryption +- !10102 vmxnet3: disable rx data ring on dma allocation failure +- vmxnet3: disable rx data ring on dma allocation failure +- !10093 drm/arm/malidp: fix a possible null pointer dereference +- drm/arm/malidp: fix a possible null pointer dereference +- !9989 io_uring/io-wq: Use set_bit() and test_bit() at worker->flags +- io_uring/io-wq: Use set_bit() and test_bit() at worker->flags +- !10083 CVE-2024-40955 +- ext4: clean up s_mb_rb_lock to fix build warnings with C=1 +- ext4: set the type of max_zeroout to unsigned int to avoid overflow +- ext4: set type of ac_groups_linear_remaining to __u32 to avoid overflow +- ext4: add positive int attr pointer to avoid sysfs variables overflow +- ext4: add new attr pointer attr_mb_order +- ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() +- ext4: refactor out ext4_generic_attr_show() +- ext4: refactor out ext4_generic_attr_store() +- ext4: avoid overflow when setting values via sysfs +- !10069 ALSA: Fix deadlocks with kctl removals at disconnection +- ALSA: Fix deadlocks with kctl removals at disconnection +- !10074 PCI: of_property: Return error for int_map allocation failure +- PCI: of_property: Return error for int_map allocation failure +- !10087 fix CVE-2024-40995 +- net/sched: act_api: fix possible infinite loop in tcf_idr_check_alloc() +- net/sched: act_api: rely on rcu in tcf_idr_check_alloc +- !10064 net/mlx5: Always stop health timer during driver removal +- net/mlx5: Always stop health timer during driver removal +- !9240 v2 cachefiles: introduce failover mechanism +- cachefiles: make on-demand read killable +- cachefiles: flush all requests after setting CACHEFILES_DEAD +- cachefiles: Set object to close if ondemand_id < 0 in copen +- cachefiles: defer exposing anon_fd until after copy_to_user() succeeds +- cachefiles: never get a new anonymous fd if ondemand_id is valid +- cachefiles: add spin_lock for cachefiles_ondemand_info +- cachefiles: add consistency check for copen/cread +- cachefiles: remove err_put_fd label in cachefiles_ondemand_daemon_read() +- cachefiles: fix slab-use-after-free in cachefiles_ondemand_daemon_read() +- cachefiles: fix slab-use-after-free in cachefiles_ondemand_get_fd() +- cachefiles: remove requests from xarray during flushing requests +- cachefiles: add output string to cachefiles_obj_[get|put]_ondemand_fd +- cachefiles, erofs: Fix NULL deref in when cachefiles is not doing ondemand-mode +- cachefiles: add restore command to recover inflight ondemand read requests +- cachefiles: narrow the scope of triggering EPOLLIN events in ondemand mode +- cachefiles: resend an open request if the read request's object is closed +- cachefiles: extract ondemand info field from cachefiles_object +- cachefiles: introduce object ondemand state +- !9933 nvdimm: Backport some bugfixs +- dax: alloc_dax() return ERR_PTR(-EOPNOTSUPP) for CONFIG_DAX=n +- nvdimm/pmem: fix leak on dax_add_host() failure +- !10038 media: v4l: async: Properly re-initialise notifier entry in unregister +- media: v4l: async: Properly re-initialise notifier entry in unregister +- !9970 CVE-2024-39503 +- netfilter: ipset: Fix suspicious rcu_dereference_protected() +- netfilter: ipset: Fix race between namespace cleanup and gc in the list:set type +- netfilter: ipset: Add list flush to cancel_gc +- !10011 xfs: fix mount hung while sb recover fail +- xfs: fix mount hung while sb recover fail +- !10050 vmci: prevent speculation leaks by sanitizing event in event_deliver() +- vmci: prevent speculation leaks by sanitizing event in event_deliver() +- !10006 drm/amdgpu: fix UBSAN warning in kv_dpm.c +- drm/amdgpu: fix UBSAN warning in kv_dpm.c +- !9959 parisc: Try to fix random segmentation faults in package builds +- parisc: Try to fix random segmentation faults in package builds +- !10028 ipv6: prevent possible NULL dereference in rt6_probe() +- ipv6: prevent possible NULL dereference in rt6_probe() +- !10005 seg6: fix parameter passing when calling NF_HOOK() in End.DX4 and End.DX6 behaviors +- seg6: fix parameter passing when calling NF_HOOK() in End.DX4 and End.DX6 behaviors + +* Wed Jul 17 2024 ZhangPeng - 6.6.0-34.0.0.42 +- Remove mlx5 related API from kabi whitelist + +* Wed Jul 17 2024 ZhangPeng - 6.6.0-34.0.0.41 +- !10059 nilfs2: fix use-after-free of timer for log writer thread +- nilfs2: fix use-after-free of timer for log writer thread +- !10025 9p: add missing locking around taking dentry fid list +- 9p: add missing locking around taking dentry fid list +- !9835 fix CVE-2024-39479 +- drm/i915/hwmon: Get rid of devm +- !9998 ALSA: hda/cs_dsp_ctl: Use private_free for control cleanup +- ALSA: hda/cs_dsp_ctl: Use private_free for control cleanup +- !9997 openrisc: traps: Don't send signals to kernel mode threads +- openrisc: traps: Don't send signals to kernel mode threads +- !9956 drm/komeda: check for error-valued pointer +- drm/komeda: check for error-valued pointer +- !9914 arm64: asm-bug: Add .align 2 to the end of __BUG_ENTRY +- arm64: asm-bug: Add .align 2 to the end of __BUG_ENTRY +- !9944 f2fs: remove clear SB_INLINECRYPT flag in default_options +- f2fs: remove clear SB_INLINECRYPT flag in default_options +- !9909 sock_map: avoid race between sock_map_close and sk_psock_put +- sock_map: avoid race between sock_map_close and sk_psock_put +- !10045 misc: microchip: pci1xxxx: fix double free in the error handling of gp_aux_bus_probe() +- misc: microchip: pci1xxxx: fix double free in the error handling of gp_aux_bus_probe() +- !10055 media: v4l: async: Fix notifier list entry init +- media: v4l: async: Fix notifier list entry init +- !9900 ipv6: fix possible race in __fib6_drop_pcpu_from() +- ipv6: fix possible race in __fib6_drop_pcpu_from() +- !9979 CVE-2024-40972 +- ext4: do not create EA inode under buffer lock +- ext4: fold quota accounting into ext4_xattr_inode_lookup_create() +- !9988 netpoll: Fix race condition in netpoll_owner_active +- netpoll: Fix race condition in netpoll_owner_active +- !9945 ACPICA: Revert "ACPICA: avoid Info: mapping multiple BARs. Your kernel is fine." +- ACPICA: Revert "ACPICA: avoid Info: mapping multiple BARs. Your kernel is fine." +- !9935 ALSA: hda: cs35l41: Possible null pointer dereference in cs35l41_hda_unbind() +- ALSA: hda: cs35l41: Possible null pointer dereference in cs35l41_hda_unbind() +- !9962 iommu/arm-smmu-v3: Change the style to identify the the hisi_platform +- iommu/arm-smmu-v3: Change the style to identify the the hisi_platform +- !9896 bonding: Fix out-of-bounds read in bond_option_arp_ip_targets_set() +- bonding: Fix out-of-bounds read in bond_option_arp_ip_targets_set() +- !9928 ocfs2: fix races between hole punching and AIO+DIO +- ocfs2: fix races between hole punching and AIO+DIO +- !9938 fix CVE-2024-40934 +- HID: logitech-dj: Fix memory leak in logi_dj_recv_switch_to_dj_mode() +- !9899 ionic: fix use after netif_napi_del() +- ionic: fix use after netif_napi_del() +- !9898 cpufreq: amd-pstate: fix memory leak on CPU EPP exit +- cpufreq: amd-pstate: fix memory leak on CPU EPP exit +- !9903 mptcp: ensure snd_una is properly initialized on connect +- mptcp: ensure snd_una is properly initialized on connect +- !9878 CVE-2024-39478 +- crypto: starfive - Do not free stack buffer +- !9888 ipv6: sr: fix memleak in seg6_hmac_init_algo +- ipv6: sr: fix memleak in seg6_hmac_init_algo +- !5261 [OLK-6.6]Hygon: Some enhancement and bugfixes for HYGON CSV/CSV2 +- KVM: SVM: Unmap ghcb pages if they're still mapped when destroy guest +- KVM: x86: Fix KVM_GET_MSRS stack info leak +- KVM: SEV: Do not intercept accesses to MSR_IA32_XSS for SEV-ES guests +- x86/head/64: Flush caches for .bss..decrypted section after CR3 switches to early_top_pgt +- KVM: x86: Calls is_64_bit_hypercall() instead of is_64_bit_mode() in complete_hypercall_exit() +- x86/csv2: Keep in atomic context when holding ghcb page if the #VC comes from userspace +- KVM: SVM: Fix the available ASID range for CSV2 guest +- !9861 MPTCP Upstream part 13 +- selftests: mptcp: lib: catch duplicated subtest entries +- selftests: mptcp: explicitly trigger the listener diag code-path +- bpf, btf: Add check_btf_kconfigs helper +- bpf, btf: Fix return value of register_btf_id_dtor_kfuncs +- !9876 v3 Fix xfs file creation issue +- xfs: Avoid races with cnt_btree lastrec updates +- Revert "xfs: Fix file creation failure" +- !9877 gfs2: Fix potential glock use-after-free on unmount +- gfs2: Fix potential glock use-after-free on unmount +- !9862 ipvlan: Modify the value of ipvlan modes +- ipvlan: Modify the value of ipvlan modes +- !5260 [OLK-6.6] Support live migration for CSV/CSV2 guest, and support rebooting CSV/CSV2 guest +- KVM: SVM: Force flush caches before reboot CSV guest +- KVM: SVM: Add support for rebooting CSV2 guest +- KVM: x86: Introduce control_{pre,post}_system_reset ioctl interfaces +- KVM: SVM: Export MSR_AMD64_SEV_ES_GHCB to userspace for CSV2 guest +- KVM: x86: Restore control registers in __set_sregs() to support CSV2 guest live migration +- KVM: SVM: Add KVM_SEV_RECEIVE_UPDATE_VMSA command +- KVM: SVM: Add KVM_SEV_SEND_UPDATE_VMSA command +- crypto: ccp: Fix definition of struct sev_data_send_update_vmsa +- KVM: SVM: Add RECEIVE_UPDATE_DATA command helper to support KVM_CSV_COMMAND_BATCH +- KVM: SVM: Add SEND_UPDATE_DATA command helper to support KVM_CSV_COMMAND_BATCH +- KVM: SVM: Prepare memory pool to allocate buffers for KVM_CSV_COMMAND_BATCH +- KVM: SVM: Add KVM_CSV_COMMAND_BATCH command for applying CSV RING_BUFFER mode +- crypto: ccp: Add support for issue commands in CSV RING_BUFFER mode +- crypto: ccp: Add support to switch to CSV RING_BUFFER mode +- crypto: ccp: Add support for dequeue status in CSV RING_BUFFER mode +- crypto: ccp: Add support for enqueue command pointers in CSV RING_BUFFER mode +- crypto: ccp: Introduce init and free helpers to manage CSV RING_BUFFER queues +- !9294 Compiler: Add clang's PGO support for kernel. +- Compiler: Add clang's PGO support for kernel. +- !9610 rcu: Fix buffer overflow in print_cpu_stall_info() +- rcu: Fix buffer overflow in print_cpu_stall_info() +- !9845 xfs: fix log recovery buffer allocation for the legacy h_size fixup +- xfs: fix log recovery buffer allocation for the legacy h_size fixup +- !9859 block: enable BLK_IO_HUNG_TASK_CHECK by default +- block: enable BLK_IO_HUNG_TASK_CHECK by default +- !9857 drm/amdgpu/mes: fix use-after-free issue +- drm/amdgpu/mes: fix use-after-free issue +- !9829 fix CVE-2024-38620 +- Bluetooth: fix connection setup in l2cap_connect +- Bluetooth: HCI: Remove HCI_AMP support +- Bluetooth: hci_event: Remove code to removed CONFIG_BT_HS +- Bluetooth: Remove usage of the deprecated ida_simple_xx() API +- Bluetooth: ISO: Fix BIS cleanup +- !9838 cgroup: Fix AA deadlock caused by cgroup_bpf_release +- cgroup: Fix AA deadlock caused by cgroup_bpf_release +- !9841 ASoC: SOF: ipc4-topology: Fix input format query of process modules without base extension +- ASoC: SOF: ipc4-topology: Fix input format query of process modules without base extension +- !9834 mmc: davinci: Don't strip remove function when driver is builtin +- mmc: davinci: Don't strip remove function when driver is builtin + +* Wed Jul 10 2024 ZhangPeng - 6.6.0-33.0.0.40 +- !9779 CVE-2024-39461 +- clk: bcm: rpi: Assign ->num before accessing ->hws +- !9801 loongarch平台config配置对kdump的支持 +- loongarch: configs: Configure degbuginfo +- Fix the kdump second kernel boot failure +- loongarch: Cleanup loongson3_defconfig with make savedefconfig +- !9811 fix CVE-2024-39481 +- media: mc: Fix graph walk in media_pipeline_start +- !9810 KVM: SVM: WARN on vNMI + NMI window iff NMIs are outright masked +- KVM: SVM: WARN on vNMI + NMI window iff NMIs are outright masked +- !9821 kdb: Fix buffer overflow during tab-complete +- kdb: Fix buffer overflow during tab-complete +- !9788 net: fix wrong return value in bpf_sock_ops_get_uid_gid +- net: fix wrong return value in bpf_sock_ops_get_uid_gid +- !9816 mm: mem_reliable: Make counting reliable task usage compatible with folio +- mm: mem_reliable: Make counting reliable task usage compatible with folio +- !9807 drm: zynqmp_dpsub: Always register bridge +- drm: zynqmp_dpsub: Always register bridge +- !9804 CVE-2024-36478 +- null_blk: Fix return value of nullb_device_power_store() +- null_blk: fix null-ptr-dereference while configuring 'power' and 'submit_queues' +- !9805 md: fix resync softlockup when bitmap size is less than array size +- md: fix resync softlockup when bitmap size is less than array size +- !9802 ax25: Fix reference count leak issue of net_device +- ax25: Fix reference count leak issue of net_device +- !9770 Add a switch to enable hungtask check for io +- block: disable BLK_IO_HUNG_TASK_CHECK by default +- block: add a switch to enable hungtask check for io +- !9793 drm: bridge: cdns-mhdp8546: Fix possible null pointer dereference +- drm: bridge: cdns-mhdp8546: Fix possible null pointer dereference +- !9649 f2fs: fix to do sanity check on i_xattr_nid in sanity_check_inode() +- f2fs: fix to do sanity check on i_xattr_nid in sanity_check_inode() +- !9732 CVE-2024-39469 +- nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors +- nilfs2: return the mapped address from nilfs_get_page() +- !9775 mm/slub: Reduce memory consumption in extreme scenarios +- mm/slub: Reduce memory consumption in extreme scenarios +- !9614 v2 wifi: carl9170: add a proper sanity check for endpoints +- wifi: carl9170: add a proper sanity check for endpoints +- !9709 cgroup: fix uaf when proc_cpuset_show +- cgroup: fix uaf when proc_cpuset_show +- !9748 cxl/pci: Skip to handle RAS errors if CXL.mem device is detached +- cxl/pci: Skip to handle RAS errors if CXL.mem device is detached +- !8877 drm/vmwgfx: Fix invalid reads in fence signaled events +- drm/vmwgfx: Fix invalid reads in fence signaled events +- !9730 efi: libstub: only free priv.runtime_map when allocated +- efi: libstub: only free priv.runtime_map when allocated +- !9679 cgroup/cpuset: Make cpuset hotplug processing synchronous +- cgroup/cpuset: Make cpuset hotplug processing synchronous +- !9757 net: openvswitch: fix overwriting ct original tuple for ICMPv6 +- net: openvswitch: fix overwriting ct original tuple for ICMPv6 +- !9665 CVE-2024-38622 +- drm/msm/dpu: make error messages at dpu_core_irq_register_callback() more sensible +- drm/msm/dpu: Add callback function pointer check before its call +- drm/msm/dpu: stop using raw IRQ indices in the kernel output +- drm/msm/dpu: make the irq table size static +- drm/msm/dpu: add helper to get IRQ-related data +- drm/msm/dpu: extract dpu_core_irq_is_valid() helper +- drm/msm/dpu: remove irq_idx argument from IRQ callbacks +- !9668 wifi: nl80211: Avoid address calculations via out of bounds array indexing +- wifi: nl80211: Avoid address calculations via out of bounds array indexing +- !9715 CVE-2024-38602 +- ax25: Fix reference count leak issues of ax25_dev +- ax25: Use kernel universal linked list to implement ax25_dev_list +- !9746 v2 Revert "ACPI: processor: Add support for processors described as container packages" +- Revert "ACPI: processor: Add support for processors described as container packages" +- !9736 net/9p: fix uninit-value in p9_client_rpc() +- net/9p: fix uninit-value in p9_client_rpc() +- !9596 iomap: fix warning in iomap_write_delalloc_release() +- iomap: fix warning in iomap_write_delalloc_release() +- !9703 dma-buf/sw-sync: don't enable IRQ from sync_print_obj() +- dma-buf/sw-sync: don't enable IRQ from sync_print_obj() +- !9642 CVE-2024-38582 +- nilfs2: fix potential hang in nilfs_detach_log_writer() +- nilfs2: fix unexpected freezing of nilfs_segctor_sync() +- !9687 greybus: lights: check return of get_channel_from_mode +- greybus: lights: check return of get_channel_from_mode +- !9678 crypto: bcm - Fix pointer arithmetic +- crypto: bcm - Fix pointer arithmetic +- !7918 [OLK-6.6]drivers: support Yunsilicon's metaScale/metaVisor series NICs +- drivers: support Yunsilicon's MS and MV series NICs +- !9619 r8169: Fix possible ring buffer corruption on fragmented Tx packets. +- r8169: Fix possible ring buffer corruption on fragmented Tx packets. +- !9664 tls: fix missing memory barrier in tls_init +- tls: fix missing memory barrier in tls_init +- !9161 xfs: don't use current->journal_info +- xfs: don't use current->journal_info +- !9624 CVE-2024-38597 +- net: fec: remove .ndo_poll_controller to avoid deadlocks +- eth: sungem: remove .ndo_poll_controller to avoid deadlocks +- !9631 ACPI: APEI: Skip initialization of GHES_ASSIST structures for Machine Check Architecture +- ACPI: APEI: Skip initialization of GHES_ASSIST structures for Machine Check Architecture +- !9632 drm/msm/a6xx: Avoid a nullptr dereference when speedbin setting fails +- drm/msm/a6xx: Avoid a nullptr dereference when speedbin setting fails +- !9399 fix CVE-2024-38544 and CVE-2024-37356 +- tcp: Fix shift-out-of-bounds in dctcp_update_alpha(). +- RDMA/rxe: Fix seg fault in rxe_comp_queue_pkt +- !9341 serial: max3100: Lock port->lock when calling uart_handle_cts_change() +- serial: max3100: Lock port->lock when calling uart_handle_cts_change() +- !9562 CVE-2024-38385 +- genirq/irqdesc: Prevent use-after-free in irq_find_at_or_after() +- !9582 v2 eventfs: Fix a possible null pointer dereference in eventfs_find_events() +- eventfs: Fix a possible null pointer dereference in eventfs_find_events() +- !9588 s390/ap: Fix crash in AP internal function modify_bitmap() +- s390/ap: Fix crash in AP internal function modify_bitmap() +- !9513 RDMA/rxe: Fix seg fault in rxe_comp_queue_pkt +- RDMA/rxe: Fix seg fault in rxe_comp_queue_pkt +- !9561 v2 virtio: delete vq in vp_find_vqs_msix() when request_irq() fails +- virtio: delete vq in vp_find_vqs_msix() when request_irq() fails +- !9578 net/mlx5: Discard command completions in internal error +- net/mlx5: Discard command completions in internal error +- !9549 btrfs: fix crash on racing fsync and size-extending write into prealloc +- btrfs: fix crash on racing fsync and size-extending write into prealloc +- !9479 xfs: fix unlink vs cluster buffer instantiation race +- xfs: fix unlink vs cluster buffer instantiation race +- !9519 MPTCP Upstream part 12 +- mptcp: annotate lockless accesses around read-mostly fields +- mptcp: annotate lockless access for token +- mptcp: annotate lockless access for RX path fields +- mptcp: annotate lockless access for the tx path +- mptcp: annotate access for msk keys +- !9557 i2c: acpi: Unbind mux adapters before delete +- i2c: acpi: Unbind mux adapters before delete +- !9555 smb: client: fix deadlock in smb2_find_smb_tcon() +- smb: client: fix deadlock in smb2_find_smb_tcon() +- !9489 fs/ntfs3: Check 'folio' pointer for NULL +- fs/ntfs3: Check 'folio' pointer for NULL +- !9482 fs/ntfs3: Use 64 bit variable to avoid 32 bit overflow +- fs/ntfs3: Use 64 bit variable to avoid 32 bit overflow +- !9506 usb: gadget: u_audio: Fix race condition use of controls after free during gadget unbind. +- usb: gadget: u_audio: Fix race condition use of controls after free during gadget unbind. +- !9528 media: lgdt3306a: Add a check against null-pointer-def +- media: lgdt3306a: Add a check against null-pointer-def +- !9551 ext4: fix mb_cache_entry's e_refcnt leak in ext4_xattr_block_cache_find() +- ext4: fix mb_cache_entry's e_refcnt leak in ext4_xattr_block_cache_find() +- !9478 watchdog: cpu5wdt.c: Fix use-after-free bug caused by cpu5wdt_trigger +- watchdog: cpu5wdt.c: Fix use-after-free bug caused by cpu5wdt_trigger +- !9536 clk: bcm: dvp: Assign ->num before accessing ->hws +- clk: bcm: dvp: Assign ->num before accessing ->hws +- !9463 fix CVE-2024-38621 +- media: stk1160: fix bounds checking in stk1160_copy_video() +- !9457 bpf: Add BPF_PROG_TYPE_CGROUP_SKB attach type enforcement in BPF_LINK_CREATE +- bpf: Add BPF_PROG_TYPE_CGROUP_SKB attach type enforcement in BPF_LINK_CREATE +- !9459 bpf: Fix verifier assumptions about socket->sk +- bpf: Fix verifier assumptions about socket->sk +- !9522 bonding: fix oops during rmmod +- bonding: fix oops during rmmod +- !9502 netrom: fix possible dead-lock in nr_rt_ioctl() +- netrom: fix possible dead-lock in nr_rt_ioctl() +- !9402 fs/ntfs3: Use variable length array instead of fixed size +- fs/ntfs3: Use variable length array instead of fixed size +- !9320 drm/amd/display: Fix potential index out of bounds in color transformation function +- drm/amd/display: Fix potential index out of bounds in color transformation function +- !9493 thermal/drivers/qcom/lmh: Check for SCM availability at probe +- thermal/drivers/qcom/lmh: Check for SCM availability at probe +- !9398 tracing/probes: fix error check in parse_btf_field() +- tracing/probes: fix error check in parse_btf_field() +- !9510 ftrace: Fix possible use-after-free issue in ftrace_location() +- ftrace: Fix possible use-after-free issue in ftrace_location() +- !9509 cifs: fix pagecache leak when do writepages +- cifs: fix pagecache leak when do writepages +- !9436 v2 ASoC: mediatek: Assign dummy when codec not specified for a DAI link +- ASoC: mediatek: Assign dummy when codec not specified for a DAI link +- !9486 [OLK-6.6] Fix os crash while enable sriov for rnp +- RNPVF: NET: Fix os crash while enable sriov for rnp +- !9371 MPTCP Upstream part 11 +- selftests: net: ip_local_port_range: define IPPROTO_MPTCP +- selftests: mptcp: join: check CURRESTAB counters +- selftests/net: add MPTCP coverage for IP_LOCAL_PORT_RANGE +- mptcp: sockopt: support IP_LOCAL_PORT_RANGE and IP_BIND_ADDRESS_NO_PORT +- mptcp: rename mptcp_setsockopt_sol_ip_set_transparent() +- !5258 [OLK-6.6] Support request attestation report from CSV guest +- driver/virt/coco: Add HYGON CSV Guest dirver. +- KVM: x86: Support VM_ATTESTATION hypercall +- !9485 v2 CVE-2024-38610 +- drivers/virt/acrn: fix PFNMAP PTE checks in acrn_vm_ram_map() +- virt: acrn: stop using follow_pfn +- !9380 psi: using cpuacct_cgrp_id under CONFIG_CGROUP_CPUACCT +- psi: using cpuacct_cgrp_id under CONFIG_CGROUP_CPUACCT +- !8899 block: fix module reference leakage from bdev_open_by_dev error path +- block: fix module reference leakage from bdev_open_by_dev error path +- !9445 blk-cgroup: fix list corruption from reorder of WRITE ->lqueued +- blk-cgroup: fix list corruption from reorder of WRITE ->lqueued +- !9466 io_uring: check for non-NULL file pointer in io_file_can_poll() +- io_uring: check for non-NULL file pointer in io_file_can_poll() +- !9389 block: refine the EOF check in blkdev_iomap_begin +- block: refine the EOF check in blkdev_iomap_begin +- !9414 vfio/pci: fix potential memory leak in vfio_intx_enable() +- vfio/pci: fix potential memory leak in vfio_intx_enable() +- !9455 jffs2: prevent xattr node from overflowing the eraseblock +- jffs2: prevent xattr node from overflowing the eraseblock +- !9465 CVE-2024-38662 +- Revert "bpf, sockmap: Prevent lock inversion deadlock in map delete elem" +- bpf: Allow delete from sockmap/sockhash only if update is allowed +- !9410 Fix CVE-2024-31076 +- genirq/cpuhotplug, x86/vector: Prevent vector leak during CPU offline +- !9449 rcu-tasks: Fix show_rcu_tasks_trace_gp_kthread buffer overflow +- rcu-tasks: Fix show_rcu_tasks_trace_gp_kthread buffer overflow + +* Wed Jun 26 2024 ZhangPeng - 6.6.0-31.0.0.39 +- !9438 【OLK-6.6】RDMA/hns: Fix some mutex UAF +- RDMA/hns: Fix some mutex UAF +- !9394 CVE-2024-38587 +- speakup: Fix sizeof() vs ARRAY_SIZE() bug +- !9405 drm/mediatek: Add 0 size check to mtk_drm_gem_obj +- drm/mediatek: Add 0 size check to mtk_drm_gem_obj +- !9415 mm: drop the 'anon_' prefix for swap-out mTHP counters +- mm: drop the 'anon_' prefix for swap-out mTHP counters +- !9376 ALSA: core: Fix NULL module pointer assignment at card init +- ALSA: core: Fix NULL module pointer assignment at card init +- !9295 Port patches from OLK-5.10 +- livepatch: Enable CONFIG_LIVEPATCH_ISOLATE_KPROBE in openeuler_defconfig +- livepatch: Avoid patching conflicts with kprobes +- !9356 tpm_tis_spi: Account for SPI header when allocating TPM SPI xfer buffer +- tpm_tis_spi: Account for SPI header when allocating TPM SPI xfer buffer +- !9332 net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP +- net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP +- !9355 f2fs: multidev: fix to recognize valid zero block address +- f2fs: multidev: fix to recognize valid zero block address +- !9329 af_unix: Fix data races in unix_release_sock/unix_stream_sendmsg +- af_unix: Fix data races in unix_release_sock/unix_stream_sendmsg +- !9352 MPTCP Upstream part 10 +- MAINTAINERS: add Geliang as reviewer for MPTCP +- mailmap: add entries for Geliang Tang +- mptcp: fill in missing MODULE_DESCRIPTION() +- netlink: fill in missing MODULE_DESCRIPTION() +- netlink: specs: mptcp: rename the MPTCP path management spec +- !9304 MPTCP Upstream part 9 +- selftests: mptcp: add mptcp_lib_wait_local_port_listen +- selftests: mptcp: add mptcp_lib_check_transfer +- selftests: mptcp: add mptcp_lib_make_file +- selftests: mptcp: add missing oflag=append +- !9307 of: module: add buffer overflow check in of_modalias() +- of: module: add buffer overflow check in of_modalias() +- !9331 Some folio bugfix +- mm/memory: don't require head page for do_set_pmd() +- mm/migrate: fix kernel BUG at mm/compaction.c:2761! +- mm: huge_memory: fix misused mapping_large_folio_support() for anon folios +- mm: shmem: fix getting incorrect lruvec when replacing a shmem folio +- mm: fix possible OOB in numa_rebuild_large_mapping() +- mm: support multi-size THP numa balancing +- mm/rmap: do not add fully unmapped large folio to deferred split list +- !9302 ring-buffer: Fix a race between readers and resize checks +- ring-buffer: Fix a race between readers and resize checks +- !9345 net: sched: sch_multiq: fix possible OOB write in multiq_tune() +- net: sched: sch_multiq: fix possible OOB write in multiq_tune() +- !9346 net: bridge: xmit: make sure we have at least eth header len bytes +- net: bridge: xmit: make sure we have at least eth header len bytes +- !9301 MPTCP Upstream part 8 +- selftests: mptcp: userspace pm send RM_ADDR for ID 0 +- selftests: mptcp: userspace pm remove initial subflow +- mptcp: userspace pm rename remove_err to out +- selftests: mptcp: userspace pm create id 0 subflow +- mptcp: add mptcpi_subflows_total counter +- !9266 MPTCP Upstream part 7 +- net: fill in MODULE_DESCRIPTION()s for SOCK_DIAG modules +- selftests: mptcp: sockopt: drop mptcp_connect var +- mptcp: define more local variables sk +- mptcp: move sk assignment statement ahead +- !9262 MPTCP Upstream part 6 +- mptcp: use mptcp_get_ext helper +- mptcp: use mptcp_check_fallback helper +- mptcp: drop useless ssk in pm_subflow_check_next +- mptcp: ignore notsent_lowat setting at the subflow level +- mptcp: consolidate sockopt synchronization +- !5257 [OLK-6.6] Support DOWNLOAD_FIRMWARE feature for hygon CSV +- crypto: ccp: Implement CSV_DOWNLOAD_FIRMWARE ioctl command +- crypto: ccp: Implement CSV_PLATFORM_SHUTDOWN ioctl command +- crypto: ccp: Implement CSV_PLATFORM_INIT ioctl command +- crypto: ccp: Support DOWNLOAD_FIRMWARE when detect CSV +- !8058 Intel: Backport QuickAssist Technology(QAT) live migration support for in-tree driver +- Enable QAT_VFIO_PCI as kernel module to support Intel QAT live migration +- crypto: qat - Fix ADF_DEV_RESET_SYNC memory leak +- crypto: qat - specify firmware files for 402xx +- crypto: qat - validate slices count returned by FW +- crypto: qat - improve error logging to be consistent across features +- crypto: qat - improve error message in adf_get_arbiter_mapping() +- crypto: qat - implement dh fallback for primes > 4K +- crypto: qat - Fix spelling mistake "Invalide" -> "Invalid" +- crypto: qat - Avoid -Wflex-array-member-not-at-end warnings +- vfio/qat: Add vfio_pci driver for Intel QAT SR-IOV VF devices +- crypto: qat - implement interface for live migration +- crypto: qat - add interface for live migration +- crypto: qat - add bank save and restore flows +- crypto: qat - expand CSR operations for QAT GEN4 devices +- crypto: qat - rename get_sla_arr_of_type() +- crypto: qat - relocate CSR access code +- crypto: qat - move PFVF compat checker to a function +- crypto: qat - relocate and rename 4xxx PF2VM definitions +- crypto: qat - adf_get_etr_base() helper +- !8304 [OLK-6.6] Backport TPMI based RAPL PMU support for next Intel Xeon Granite Rapids (GNR) +- powercap: intel_rapl_tpmi: Enable PMU support +- powercap: intel_rapl: Introduce APIs for PMU support +- powercap: intel_rapl: Sort header files +- !9245 MPTCP Upstream part 5 +- mptcp: prevent BPF accessing lowat from a subflow socket. +- mptcp: use copy_from_iter helpers on transmit +- mptcp: give rcvlowat some love +- tcp: define initial scaling factor value as a macro +- mptcp: use plain bool instead of custom binary enum +- mptcp: add a new sysctl for make after break timeout +- !8422 [OLK-6.6] Intel IAA Compression Accelerator Crypto Driver (iaa_crypto) +- openeuler_defconfig: Add kernel config for Intel IAA crypto driver +- dmaengine: idxd: Avoid unnecessary destruction of file_ida +- dmaengine: idxd: Check for driver name match before sva user feature +- crypto: iaa - Use cpumask_weight() when rebalancing +- crypto: iaa - Fix some errors in IAA documentation +- crypto: iaa - Change iaa statistics to atomic64_t +- crypto: iaa - Add global_stats file and remove individual stat files +- crypto: iaa - Remove comp/decomp delay statistics +- crypto: iaa - fix decomp_bytes_in stats +- crypto: iaa - Fix nr_cpus < nr_iaa case +- crypto: iaa - fix the missing CRYPTO_ALG_ASYNC in cra_flags +- crypto: iaa - Fix comp/decomp delay statistics +- crypto: iaa - Fix async_disable descriptor leak +- crypto: iaa - Remove unnecessary debugfs_create_dir() error check in iaa_crypto_debugfs_init() +- crypto: iaa - Remove header table code +- dmaengine: idxd: constify the struct device_type usage +- dmaengine: idxd: make dsa_bus_type const +- dmaengine: idxd: Remove usage of the deprecated ida_simple_xx() API +- crypto: iaa - Account for cpu-less numa nodes +- crypto: iaa - remove unneeded semicolon +- crypto: iaa - Remove unneeded newline in update_max_adecomp_delay_ns() +- crypto: iaa - Change desc->priv to 0 +- dmaengine: idxd: Add support for device/wq defaults +- crypto: iaa - Add IAA Compression Accelerator stats +- crypto: iaa - Add irq support for the crypto async interface +- crypto: iaa - Add support for deflate-iaa compression algorithm +- crypto: iaa - Add compression mode management along with fixed mode +- crypto: iaa - Add per-cpu workqueue table with rebalancing +- crypto: iaa - Add Intel IAA Compression Accelerator crypto driver core +- crypto: iaa - Add IAA Compression Accelerator Documentation +- dmaengine: idxd: add callback support for iaa crypto +- dmaengine: idxd: Add wq private data accessors +- dmaengine: idxd: Export wq resource management functions +- dmaengine: idxd: Export descriptor management functions +- dmaengine: idxd: Rename drv_enable/disable_wq to idxd_drv_enable/disable_wq, and export +- dmaengine: idxd: add external module driver support for dsa_bus_type +- dmaengine: idxd: Fix incorrect descriptions for GRPCFG register +- dmaengine: idxd: add wq driver name support for accel-config user tool +- dmaengine: idxd: rate limit printk in misc interrupt thread +- !9230 MPTCP Upstream part 4 +- net: mptcp: use policy generated by YAML spec +- net: mptcp: rename netlink handlers to mptcp_pm_nl__{doit,dumpit} +- uapi: mptcp: use header file generated from YAML spec +- Documentation: netlink: add a YAML spec for mptcp +- net: mptcp: convert netlink from small_ops to ops +- !9229 v2 sched: smart_grid: fix potential NULL pointer dereference +- sched: smart_grid: fix potential NULL pointer dereference +- !9226 MPTCP Upstream part 3 +- tools: ynl-gen: add support for exact-len validation +- tools: ynl: add uns-admin-perm to genetlink legacy +- tools: ynl-gen: support limit names +- tools: ynl-gen: support full range of min/max checks for integer values +- tools: ynl-gen: track attribute use +- !9217 memcg: attach memcg async reclaim worker to curcpu +- memcg: attach memcg async reclaim worker to curcpu +- !9173 MPTCP Upstream part 2 +- inet: implement lockless getsockopt(IP_MULTICAST_IF) +- inet: lockless IP_PKTOPTIONS implementation +- inet: implement lockless getsockopt(IP_UNICAST_IF) +- inet: lockless getsockopt(IP_MTU) +- inet: lockless getsockopt(IP_OPTIONS) + +* Wed Jun 19 2024 ZhangPeng - 6.6.0-30.0.0.38 +- !8809 MPTCP Upstream part 1 +- net: bpf: Use sockopt_lock_sock() in ip_sock_set_tos() +- inet: lock the socket in ip_sock_set_tos() +- inet: implement lockless IP_TOS +- inet: implement lockless IP_MTU_DISCOVER +- inet: implement lockless IP_MULTICAST_TTL +- !9141 Fix allmodconfig build frame size error +- net/ethernet/huawei/hiroce3: Fix allmodconfig build frame size error +- !9101 ext4: Skip moving extents if page writeback failed +- ext4: Skip moving extents if page writeback failed +- !9126 arm64: armv8_deprecated: Fix warning in isndep cpuhp starting process +- arm64: armv8_deprecated: Fix warning in isndep cpuhp starting process +- !9010 Backport 6.6.31&6.6.32 LTS patches from upstream +- block: add a partscan sysfs attribute for disks +- block: add a disk_has_partscan helper +- Docs/admin-guide/mm/damon/usage: fix wrong example of DAMOS filter matching sysfs file +- docs: kernel_include.py: Cope with docutils 0.21 +- admin-guide/hw-vuln/core-scheduling: fix return type of PR_SCHED_CORE_GET +- KEYS: trusted: Do not use WARN when encode fails +- remoteproc: mediatek: Make sure IPI buffer fits in L2TCM +- serial: kgdboc: Fix NMI-safety problems from keyboard reset code +- usb: typec: tipd: fix event checking for tps6598x +- usb: typec: ucsi: displayport: Fix potential deadlock +- net: usb: ax88179_178a: fix link status when link is set to down/up +- usb: dwc3: Wait unconditionally after issuing EndXfer command +- binder: fix max_thread type inconsistency +- drm/amdgpu: Fix possible NULL dereference in amdgpu_ras_query_error_status_helper() +- erofs: reliably distinguish block based and fscache mode +- erofs: get rid of erofs_fs_context +- kselftest: Add a ksft_perror() helper +- mmc: core: Add HS400 tuning in HS400es initialization +- KEYS: trusted: Fix memory leak in tpm2_key_encode() +- Bluetooth: L2CAP: Fix div-by-zero in l2cap_le_flowctl_init() +- Bluetooth: L2CAP: Fix slab-use-after-free in l2cap_connect() +- ice: remove unnecessary duplicate checks for VF VSI ID +- ice: pass VSI pointer into ice_vc_isvalid_q_id +- net: ks8851: Fix another TX stall caused by wrong ISR flag handling +- drm/amd/display: Fix division by zero in setup_dsc_config +- smb: smb2pdu.h: Avoid -Wflex-array-member-not-at-end warnings +- ksmbd: add continuous availability share parameter +- cifs: Add tracing for the cifs_tcon struct refcounting +- smb: client: instantiate when creating SFU files +- smb: client: fix NULL ptr deref in cifs_mark_open_handles_for_deleted_file() +- smb3: add trace event for mknod +- smb311: additional compression flag defined in updated protocol spec +- smb311: correct incorrect offset field in compression header +- cifs: Move some extern decls from .c files to .h +- ksmbd: Fix spelling mistake "connction" -> "connection" +- ksmbd: fix possible null-deref in smb_lazy_parent_lease_break_close +- cifs: remove redundant variable assignment +- cifs: fixes for get_inode_info +- cifs: defer close file handles having RH lease +- ksmbd: add support for durable handles v1/v2 +- ksmbd: mark SMB2_SESSION_EXPIRED to session when destroying previous session +- smb: common: simplify compression headers +- smb: common: fix fields sizes in compression_pattern_payload_v1 +- smb: client: negotiate compression algorithms +- smb3: add dynamic trace point for ioctls +- smb: client: return reparse type in /proc/mounts +- smb: client: set correct d_type for reparse DFS/DFSR and mount point +- smb: client: parse uid, gid, mode and dev from WSL reparse points +- smb: client: introduce SMB2_OP_QUERY_WSL_EA +- smb: client: Fix a NULL vs IS_ERR() check in wsl_set_xattrs() +- smb: client: add support for WSL reparse points +- smb: client: reduce number of parameters in smb2_compound_op() +- smb: client: fix potential broken compound request +- smb: client: move most of reparse point handling code to common file +- smb: client: introduce reparse mount option +- smb: client: retry compound request without reusing lease +- smb: client: do not defer close open handles to deleted files +- smb: client: reuse file lease key in compound operations +- smb: client: get rid of smb311_posix_query_path_info() +- smb: client: parse owner/group when creating reparse points +- smb3: update allocation size more accurately on write completion +- smb: client: handle path separator of created SMB symlinks +- cifs: update the same create_guid on replay +- ksmbd: Add kernel-doc for ksmbd_extract_sharename() function +- cifs: set replay flag for retries of write command +- cifs: commands that are retried should have replay flag set +- smb: client: delete "true", "false" defines +- smb: Fix some kernel-doc comments +- cifs: new mount option called retrans +- smb: client: don't clobber ->i_rdev from cached reparse points +- cifs: new nt status codes from MS-SMB2 +- cifs: pick channel for tcon and tdis +- cifs: minor comment cleanup +- cifs: remove redundant variable tcon_exist +- ksmbd: vfs: fix all kernel-doc warnings +- ksmbd: auth: fix most kernel-doc warnings +- cifs: remove unneeded return statement +- cifs: get rid of dup length check in parse_reparse_point() +- cifs: Pass unbyteswapped eof value into SMB2_set_eof() +- smb3: Improve exception handling in allocate_mr_list() +- cifs: fix in logging in cifs_chan_update_iface +- smb: client: handle special files and symlinks in SMB3 POSIX +- smb: client: cleanup smb2_query_reparse_point() +- smb: client: allow creating symlinks via reparse points +- smb: client: optimise reparse point querying +- smb: client: allow creating special files via reparse points +- smb: client: extend smb2_compound_op() to accept more commands +- smb: client: Fix minor whitespace errors and warnings +- smb: client: introduce cifs_sfu_make_node() +- cifs: fix use after free for iface while disabling secondary channels +- Missing field not being returned in ioctl CIFS_IOC_GET_MNT_INFO +- smb3: minor cleanup of session handling code +- smb3: more minor cleanups for session handling routines +- smb3: minor RDMA cleanup +- cifs: print server capabilities in DebugData +- smb: use crypto_shash_digest() in symlink_hash() +- Add definition for new smb3.1.1 command type +- SMB3: clarify some of the unused CreateOption flags +- cifs: Add client version details to NTLM authenticate message +- md: fix kmemleak of rdev->serial +- Revert "selftests/bpf: Add netkit to tc_redirect selftest" +- btrfs: do not wait for short bulk allocation +- keys: Fix overwrite of key expiration on instantiation +- dmaengine: idxd: add a write() method for applications to submit work +- dmaengine: idxd: add a new security check to deal with a hardware erratum +- VFIO: Add the SPR_DSA and SPR_IAX devices to the denylist +- Bluetooth: qca: fix firmware check error path +- Bluetooth: qca: fix info leak when fetching fw build id +- Bluetooth: qca: fix info leak when fetching board id +- Bluetooth: qca: generalise device address check +- Bluetooth: qca: fix NVM configuration parsing +- Bluetooth: qca: add missing firmware sanity checks +- Bluetooth: qca: fix wcn3991 device address check +- Bluetooth: qca: fix invalid device address check +- eventfs: Do not treat events directory different than other directories +- tracefs: Still use mount point as default permissions for instances +- tracefs: Reset permissions on remount if permissions are options +- ksmbd: do not grant v2 lease if parent lease key and epoch are not set +- ksmbd: avoid to send duplicate lease break notifications +- ksmbd: off ipv6only for both ipv4/ipv6 binding +- spi: microchip-core-qspi: fix setting spi bus clock rate +- regulator: core: fix debugfs creation regression +- nvme-pci: Add quirk for broken MSIs +- selftests/mm: fix powerpc ARCH check +- x86/apic: Don't access the APIC when disabling x2APIC +- hwmon: (pmbus/ucd9000) Increase delay from 250 to 500us +- net: fix out-of-bounds access in ops_init +- arm64: dts: qcom: sa8155p-adp: fix SDHC2 CD pin configuration +- drm/amd/display: Fix incorrect DSC instance for MST +- drm/amd/display: Handle Y carry-over in VCP X.Y calculation +- drm/i915/bios: Fix parsing backlight BDB data +- drm/i915/gt: Automate CCS Mode setting during engine resets +- drm/i915/audio: Fix audio time stamp programming for DP +- drm/vmwgfx: Fix invalid reads in fence signaled events +- drm/vmwgfx: Fix Legacy Display Unit +- drm/ttm: Print the memory decryption status just once +- drm/amdkfd: don't allow mapping the MMIO HDP page with large pages +- Revert "drm/nouveau/firmware: Fix SG_DEBUG error with nvkm_firmware_ctor()" +- drm/nouveau/firmware: Fix SG_DEBUG error with nvkm_firmware_ctor() +- mei: me: add lunar lake point M DID +- clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI +- clk: sunxi-ng: common: Support minimum and maximum rate +- slimbus: qcom-ngd-ctrl: Add timeout for wait operation +- dyndbg: fix old BUG_ON in >control parser +- ASoC: ti: davinci-mcasp: Fix race condition during probe +- ASoC: tegra: Fix DSPK 16-bit playback +- net: bcmgenet: synchronize UMAC_CMD access +- net: bcmgenet: synchronize use of bcmgenet_set_rx_mode() +- net: bcmgenet: synchronize EXT_RGMII_OOB_CTRL access +- xtensa: fix MAKE_PC_FROM_RA second argument +- tipc: fix UAF in error path +- e1000e: change usleep_range to udelay in PHY mdic access +- kmsan: compiler_types: declare __no_sanitize_or_inline +- iio: accel: mxc4005: Interrupt handling fixes +- iio: pressure: Fixes BME280 SPI driver data +- iio:imu: adis16475: Fix sync mode setting +- dt-bindings: iio: health: maxim,max30102: fix compatible check +- workqueue: Fix selection of wake_cpu in kick_pool() +- mptcp: only allow set existing scheduler for net.mptcp.scheduler +- mptcp: ensure snd_nxt is properly initialized on connect +- mm/slab: make __free(kfree) accept error pointers +- maple_tree: fix mas_empty_area_rev() null pointer dereference +- btrfs: set correct ram_bytes when splitting ordered extent +- btrfs: add missing mutex_unlock in btrfs_relocate_sys_chunks() +- firewire: ohci: fulfill timestamp for some local asynchronous transaction +- ALSA: hda/realtek: Fix mute led of HP Laptop 15-da3001TU +- usb: typec: tcpm: Check for port partner validity before consuming it +- usb: typec: tcpm: unregister existing source caps before re-registration +- usb: typec: tcpm: clear pd_event queue in PORT_RESET +- usb: dwc3: core: Prevent phy suspend during init +- usb: xhci-plat: Don't include xhci.h +- usb: gadget: f_fs: Fix a race condition when processing setup packets. +- usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete +- usb: gadget: uvc: use correct buffer size when parsing configfs lists +- usb: gadget: composite: fix OS descriptors w_value logic +- USB: core: Fix access violation during port device removal +- usb: ohci: Prevent missed ohci interrupts +- usb: Fix regression caused by invalid ep0 maxpacket in virtual SuperSpeed device +- usb: typec: ucsi: Fix connector check on init +- usb: typec: ucsi: Check for notifications after init +- Reapply "drm/qxl: simplify qxl_fence_wait" +- firewire: nosy: ensure user_length is taken into account when fetching packet contents +- btrfs: fix kvcalloc() arguments order in btrfs_ioctl_send() +- drm/amdgpu: once more fix the call oder in amdgpu_ttm_move() v2 +- drm/amdgpu: Fix comparison in amdgpu_res_cpu_visible +- drm/amd/display: Atom Integrated System Info v2_2 for DCN35 +- gpiolib: cdev: fix uninitialised kfifo +- gpiolib: cdev: relocate debounce_period_us from struct gpio_desc +- gpiolib: cdev: Fix use after free in lineinfo_changed_notify +- dm/amd/pm: Fix problems with reboot/shutdown for some SMU 13.0.4/13.0.11 users +- drm/connector: Add +- drm/meson: dw-hdmi: add bandgap setting for g12 +- drm/meson: dw-hdmi: power up phy on device init +- net: dsa: mv88e6xxx: add phylink_get_caps for the mv88e6320/21 family +- net/smc: fix neighbour and rtable leak in smc_ib_find_route() +- ipv6: prevent NULL dereference in ip6_output() +- ipv6: annotate data-races around cnf.disable_ipv6 +- hsr: Simplify code for announcing HSR nodes timer setup +- net-sysfs: convert dev->operstate reads to lockless ones +- ipv6: fib6_rules: avoid possible NULL dereference in fib6_rule_action() +- dt-bindings: net: mediatek: remove wrongly added clocks and SerDes +- rxrpc: Only transmit one ACK per jumbo packet received +- rxrpc: Fix congestion control algorithm +- rxrpc: Fix the names of the fields in the ACK trailer struct +- selftests: test_bridge_neigh_suppress.sh: Fix failures due to duplicate MAC +- selftests/net: convert test_bridge_neigh_suppress.sh to run it in unique namespace +- ipv6: Fix potential uninit-value access in __ip6_make_skb() +- net: bridge: fix corrupted ethernet header on multicast-to-unicast +- nfc: nci: Fix kcov check in nci_rx_work() +- phonet: fix rtm_phonet_notify() skb allocation +- hwmon: (corsair-cpro) Protect ccp->wait_input_report with a spinlock +- hwmon: (corsair-cpro) Use complete_all() instead of complete() in ccp_raw_event() +- hwmon: (corsair-cpro) Use a separate buffer for sending commands +- rtnetlink: Correct nested IFLA_VF_VLAN_LIST attribute validation +- net: ks8851: Queue RX packets in IRQ handler instead of disabling BHs +- Bluetooth: l2cap: fix null-ptr-deref in l2cap_chan_timeout +- Bluetooth: HCI: Fix potential null-ptr-deref +- Bluetooth: msft: fix slab-use-after-free in msft_do_close() +- Bluetooth: Fix use-after-free bugs caused by sco_sock_timeout +- tcp: Use refcount_inc_not_zero() in tcp_twsk_unique(). +- tcp: defer shutdown(SEND_SHUTDOWN) for TCP_SYN_RECV sockets +- ARM: 9381/1: kasan: clear stale stack poison +- qibfs: fix dentry leak +- SUNRPC: add a missing rpc_stat for TCP TLS +- blk-iocost: do not WARN if iocg was already offlined +- net:usb:qmi_wwan: support Rolling modules +- drm/radeon: silence UBSAN warning (v3) +- platform/x86: ISST: Add Granite Rapids-D to HPM CPU list +- drm/nouveau/dp: Don't probe eDP ports twice harder +- gpio: lpc32xx: fix module autoloading +- fs/9p: drop inodes immediately on non-.L too +- clk: Don't hold prepare_lock when calling kref_put() +- gpio: crystalcove: Use -ENOTSUPP consistently +- gpio: wcove: Use -ENOTSUPP consistently +- powerpc/crypto/chacha-p10: Fix failure on non Power10 +- 9p: explicitly deny setlease attempts +- fs/9p: fix the cache always being enabled on files with qid flags +- fs/9p: translate O_TRUNC into OTRUNC +- fs/9p: only translate RWX permissions for plain 9P2000 +- iommu: mtk: fix module autoloading +- smb3: fix broken reconnect when password changing on the server by allowing password rotation +- Drivers: hv: vmbus: Don't free ring buffers that couldn't be re-encrypted +- uio_hv_generic: Don't free decrypted memory +- hv_netvsc: Don't free decrypted memory +- Drivers: hv: vmbus: Track decrypted status in vmbus_gpadl +- Drivers: hv: vmbus: Leak pages if set_memory_encrypted() fails +- selftests: timers: Fix valid-adjtimex signed left-shift undefined behavior +- amd/amdkfd: sync all devices to wait all processes being evicted +- drm/amdgpu: Fix VCN allocation in CPX partition +- drm/amd/display: Skip on writeback when it's not applicable +- drm/amdgpu: implement IRQ_STATE_ENABLE for SDMA v4.4.2 +- drm/amdgpu: Refine IB schedule error logging +- tools/power/turbostat: Fix uncore frequency file string +- MIPS: scall: Save thread_info.syscall unconditionally on entry +- gpu: host1x: Do not setup DMA for virtual devices +- blk-iocost: avoid out of bounds shift +- scsi: target: Fix SELinux error when systemd-modules loads the target module +- memblock tests: fix undefined reference to `BIT' +- memblock tests: fix undefined reference to `panic' +- memblock tests: fix undefined reference to `early_pfn_to_nid' +- btrfs: always clear PERTRANS metadata during commit +- btrfs: make btrfs_clear_delalloc_extent() free delalloc reserve +- tools/power turbostat: Fix warning upon failed /dev/cpu_dma_latency read +- tools/power turbostat: Print ucode revision only if valid +- tools/power turbostat: Fix Bzy_MHz documentation typo +- tools/power turbostat: Increase the limit for fd opened +- tools/power turbostat: Fix added raw MSR output +- firewire: ohci: mask bus reset interrupts between ISR and bottom half +- ata: sata_gemini: Check clk_enable() result +- vboxsf: explicitly deny setlease attempts +- net: bcmgenet: Reset RBUF on first open +- ALSA: line6: Zero-initialize message buffers +- scsi: ufs: core: Fix MCQ mode dev command timeout +- scsi: ufs: core: WLUN suspend dev/link state error recovery +- regulator: tps65132: Add of_match table +- ASoC: SOF: Intel: hda-dsp: Skip IMR boot on ACE platforms in case of S3 suspend +- kbuild: Disable KCSAN for autogenerated *.mod.c intermediaries +- selftests/ftrace: Fix event filter target_func selection +- bpf: Check bloom filter map value size +- drm/amdkfd: range check cp bad op exception interrupts +- drm/amdkfd: Check cgroup when returning DMABuf info +- btrfs: return accurate error code on open failure in open_fs_devices() +- scsi: bnx2fc: Remove spin_lock_bh while releasing resources after upload +- scsi: mpi3mr: Avoid memcpy field-spanning write WARNING +- net: mark racy access on sk->sk_rcvbuf +- wifi: iwlwifi: mvm: guard against invalid STA ID on removal +- wifi: iwlwifi: read txq->read_ptr under lock +- wifi: mac80211: fix prep_connection error path +- wifi: cfg80211: fix rdev_dump_mpp() arguments order +- wifi: mac80211: fix ieee80211_bss_*_flags kernel-doc +- gfs2: Fix invalid metadata access in punch_hole +- scsi: lpfc: Use a dedicated lock for ras_fwlog state +- scsi: lpfc: Release hbalock before calling lpfc_worker_wake_up() +- scsi: lpfc: Replace hbalock with ndlp lock in lpfc_nvme_unregister_port() +- scsi: lpfc: Update lpfc_ramp_down_queue_handler() logic +- scsi: lpfc: Remove IRQF_ONESHOT flag from threaded IRQ handling +- scsi: lpfc: Move NPIV's transport unregistration to after resource clean up +- scsi: ufs: core: Fix MCQ MAC configuration +- KVM: arm64: vgic-v2: Check for non-NULL vCPU in vgic_v2_parse_attr() +- KVM: arm64: vgic-v2: Use cpuid from userspace as vcpu_id +- swiotlb: initialise restricted pool list_head when SWIOTLB_DYNAMIC=y +- powerpc/pseries/iommu: LPAR panics during boot up with a frozen PE +- powerpc/pseries: make max polling consistent for longer H_CALLs +- clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change +- clk: qcom: smd-rpm: Restore msm8976 num_clk +- net: gro: add flush check in udp_gro_receive_segment +- net: gro: fix udp bad offset in socket lookup by adding {inner_}network_offset to napi_gro_cb +- net: gro: parse ipv6 ext headers without frag0 invalidation +- ipv4: Fix uninit-value access in __ip_make_skb() +- drm/panel: ili9341: Use predefined error codes +- drm/panel: ili9341: Respect deferred probe +- drm/panel: ili9341: Correct use of device property APIs +- s390/qeth: Fix kernel panic after setting hsuid +- vxlan: Pull inner IP header in vxlan_rcv(). +- tipc: fix a possible memleak in tipc_buf_append +- rxrpc: Clients must accept conn from any address +- net: core: reject skb_copy(_expand) for fraglist GSO skbs +- net: bridge: fix multicast-to-unicast with fraglist GSO +- spi: fix null pointer dereference within spi_sync +- drm/amdgpu: fix doorbell regression +- net: dsa: mv88e6xxx: Fix number of databases for 88E6141 / 88E6341 +- cxgb4: Properly lock TX queue for the selftest. +- s390/cio: Ensure the copied buf is NUL terminated +- ALSA: hda: intel-sdw-acpi: fix usage of device_get_named_child_node() +- ASoC: meson: cards: select SND_DYNAMIC_MINORS +- ASoC: meson: axg-tdm-interface: manage formatters in trigger +- ASoC: meson: axg-card: make links nonatomic +- ASoC: meson: axg-fifo: use threaded irq to check periods +- ASoC: meson: axg-fifo: use FIELD helpers +- vxlan: Add missing VNI filter counter update in arp_reduce(). +- vxlan: Fix racy device stats updates. +- net: qede: use return from qede_parse_actions() +- net: qede: use return from qede_parse_flow_attr() for flow_spec +- net: qede: use return from qede_parse_flow_attr() for flower +- net: qede: sanitize 'rc' in qede_add_tc_flower_fltr() +- ALSA: emu10k1: fix E-MU dock initialization +- ALSA: emu10k1: move the whole GPIO event handling to the workqueue +- ALSA: emu10k1: factor out snd_emu1010_load_dock_firmware() +- ALSA: emu10k1: fix E-MU card dock presence monitoring +- Fix a potential infinite loop in extract_user_to_sg() +- s390/vdso: Add CFI for RA register to asm macro vdso_func +- net l2tp: drop flow hash on forward +- nsh: Restore skb->{protocol,data,mac_header} for outer header in nsh_gso_segment(). +- octeontx2-af: avoid off-by-one read from userspace +- bna: ensure the copied buf is NUL terminated +- xdp: use flags field to disambiguate broadcast redirect +- s390/mm: Fix clearing storage keys for huge pages +- s390/mm: Fix storage key clearing for guest huge pages +- ASoC: codecs: wsa881x: set clk_stop_mode1 flag +- ASoC: Intel: avs: Set name of control as in topology +- riscv, bpf: Fix incorrect runtime stats +- bpf, arm64: Fix incorrect runtime stats +- spi: axi-spi-engine: fix version format string +- spi: axi-spi-engine: use common AXI macros +- spi: axi-spi-engine: move msg state to new struct +- spi: axi-spi-engine: use devm_spi_alloc_host() +- spi: axi-spi-engine: simplify driver data allocation +- spi: spi-axi-spi-engine: Use helper function devm_clk_get_enabled() +- bpf: Fix a verifier verbose message +- nvme: fix warn output about shared namespaces without CONFIG_NVME_MULTIPATH +- ASoC: SOF: Intel: add default firmware library path for LNL +- ASoC: SOF: Introduce generic names for IPC types +- regmap: Add regmap_read_bypassed() +- bpf, skmsg: Fix NULL pointer dereference in sk_psock_skb_ingress_enqueue +- bpf, kconfig: Fix DEBUG_INFO_BTF_MODULES Kconfig definition +- regulator: change devm_regulator_get_enable_optional() stub to return Ok +- regulator: change stubbed devm_regulator_get_enable to return Ok +- regulator: mt6360: De-capitalize devicetree regulator subnodes +- pinctrl: devicetree: fix refcount leak in pinctrl_dt_to_map() +- power: supply: mt6360_charger: Fix of_match for usb-otg-vbus regulator +- power: rt9455: hide unused rt9455_boost_voltage_values +- pinctrl: baytrail: Fix selecting gpio pinctrl state +- nfs: Handle error of rpc_proc_register() in nfs_net_init(). +- nfs: make the rpc_stat per net namespace +- nfs: expose /proc/net/sunrpc/nfs in net namespaces +- sunrpc: add a struct rpc_stats arg to rpc_create_args +- pinctrl: mediatek: paris: Rework support for PIN_CONFIG_{INPUT,OUTPUT}_ENABLE +- pinctrl: mediatek: paris: Fix PIN_CONFIG_INPUT_SCHMITT_ENABLE readback +- pinctrl: core: delete incorrect free in pinctrl_enable() +- pinctrl/meson: fix typo in PDM's pin name +- pinctrl: pinctrl-aspeed-g6: Fix register offset for pinconf of GPIOR-T +- Bluetooth: qca: add support for QCA2066 +- eeprom: at24: fix memory corruption race condition +- eeprom: at24: Probe for DDR3 thermal sensor in the SPD case +- rust: kernel: require `Send` for `Module` implementations +- wifi: nl80211: don't free NULL coalescing rule +- rust: macros: fix soundness issue in `module!` macro +- rust: module: place generated init_module() function in .init.text +- mtd: limit OTP NVMEM cell parse to non-NAND devices +- nvmem: add explicit config option to read old syntax fixed OF cells +- dmaengine: Revert "dmaengine: pl330: issue_pending waits until WFP state" +- dmaengine: pl330: issue_pending waits until WFP state +- !9104 [OLK-6.6] drm/phytium: Fix make allmodconfig build fail +- DRM: Fix Phytium DRM build fail +- !9085 [OLK-6.6] openeuler_defconfig: fix checkdefconfig fail +- openeuler_defconfig: fix checkdefconfig fail +- !8750 ubifs: Check @c->dirty_[n|p +- ubifs: Check @c->dirty_[n|p]n_cnt and @c->nroot state under @c->lp_mutex +- !8703 v2 IMA: Introduce a config to bypass i_version detection for Overlayfs issue +- IMA: Introduce a config to bypass i_version detection for Overlayfs issue +- !8621 LoongArch: fix HT RX INT TRANS register not initialized +- LoongArch: fix HT RX INT TRANS register not initialized +- !8440 arm64: cpufeature: Both the major and the minor version numbers need to be checked +- arm64/mpam: skip mpam initialize under kdump kernel +- arm64: cpufeature: Both the major and the minor version numbers need to be checked +- !8107 [OLK 6.6]net: hns3: fix kernel crash when devlink reload during pf/vf initialization +- {topost} net: hns3: fix kernel crash when devlink reload during vf initialization +- {topost} net: hns3: fix kernel crash when devlink reload during pf initialization +- !8481 Fix vf init and common user permissions issue +- net/ethernet/huawei/hiroce3: Fix vf init and common user permissions issue +- !8576 【OLK-6.6】backport PCC patches to support shared interrupt for multiple subspaces and platform notification handling +- soc: hisilicon: kunpeng_hccs: replace MAILBOX dependency with PCC +- soc: hisilicon: kunpeng_hccs: Add the check for obtaining complete port attribute +- mailbox: pcc: Support shared interrupt for multiple subspaces +- mailbox: pcc: Add support for platform notification handling +- !8471 ext4: Fixes len calculation in mpage_journal_page_buffers +- ext4: Fixes len calculation in mpage_journal_page_buffers +- !8496 mm/mlock: return EINVAL for illegal user memory range in mlock +- mm/mlock: return EINVAL for illegal user memory range in mlock +- !8435 LoongArch: add GMAC&GNET support +- net: stmmac: dwmac-loongson: Add loongson module author +- net: stmmac: dwmac-loongson: Move disable_force flag to _gnet_date +- net: stmmac: dwmac-loongson: Add Loongson GNET support +- net: stmmac: dwmac-loongson: Fixed failure to set network speed to 1000. +- net: stmmac: dwmac-loongson: Add loongson_dwmac_config_legacy +- net: stmmac: dwmac-loongson: Add full PCI support +- net: stmmac: dwmac-loongson: Add phy_interface for Loongson GMAC +- net: stmmac: dwmac-loongson: Add phy mask for Loongson GMAC +- net: stmmac: dwmac-loongson: Add ref and ptp clocks for Loongson +- net: stmmac: dwmac-loongson: Split up the platform data initialization +- net: stmmac: dwmac-loongson: Use PCI_DEVICE_DATA() macro for device identification +- net: stmmac: dwmac-loongson: Drop useless platform data +- net: stmmac: Export dwmac1000_dma_ops +- net: stmmac: Add multi-channel support +- net: stmmac: Move the atds flag to the stmmac_dma_cfg structure +- !7896 backport upstream stmmac related patches. +- net: stmmac: Move MAC caps init to phylink MAC caps getter +- net: stmmac: Rename phylink_get_caps() callback to update_caps() +- net: phylink: provide mac_get_caps() method +- !8450 sched/core: Fix incorrect initialization of the 'burst' parameter in cpu_max_write() +- sched/core: Fix incorrect initialization of the 'burst' parameter in cpu_max_write() +- !7482 v2 perf parse-events: Make legacy events lower priority than sysfs/JSON +- perf x86 test: Update hybrid expectations +- perf parse-events: Make legacy events lower priority than sysfs/JSON +- !8309 xfs: Fix file creation failure +- xfs: Fix file creation failure +- !8183 perf pmu: Count sys and cpuid JSON events separately +- perf pmu: Count sys and cpuid JSON events separately +- !7077 v4 block: dicard bugfix +- block: check io size before submit discard +- block: fix overflow in blk_ioctl_discard() +- !8353 mm/dynamic_pool: clear PG_hugetlb when promote hugepages +- mm/dynamic_pool: clear PG_hugetlb when promote hugepages +- !8151 LoongArch: Fix secondary bridge routing errors +- LoongArch: Fix secondary bridge routing errors +- !7948 【OLK-6.6】Fix BUILD REGRESSION warnings in bzwx N5/N6 series NIC drivers +- drivers: Fix BUILD REGRESSION warnings in bzwx N5/N6 series NIC drivers +- !8228 ubifs: ubifs_link: Fix wrong name len calculating when UBIFS is encrypted +- ubifs: ubifs_link: Fix wrong name len calculating when UBIFS is encrypted +- !6283 fix deadlock in cgroup1_writeback V2 +- cgroup_writeback: fix deadlock in cgroup1_writeback +- cgroup_writeback: Revert "fix deadlock in cgroup1_writeback" +- !8036 fix CVE-2024-27010 +- net/sched: fix kabi change in struct Qdisc +- net/sched: Fix mirred deadlock on device recursion + + to message about demoting connector force-probes +* Thu Jun 13 2024 ZhangPeng - 6.6.0-28.0.0.37 +- Enable kabi check for src and change the check-kabi format to Python3 + +* Thu Jun 6 2024 Mingzheng Xing - 6.6.0-28.0.0.36 +- riscv-kernel patch update to 6.6.0-29.0.0 +- Fix QEMU UEFI boot panic +- Deal with riscv SoC dtb search path + +* Thu Jun 6 2024 ZhangPeng - 6.6.0-28.0.0.35 +- Add kabi_whitelist_aarch64/x86 and update Module.kabi_aarch64/x86 + +* Sun May 26 2024 Mingzheng Xing - 6.6.0-28.0.0.34 +- riscv-kernel patch update to 6.6.0-28.0.0 +- fixed a merge conflict from the commit f1e873348141 + +* Sun May 26 2024 ZhangPeng - 6.6.0-28.0.0.33 +- !8010 mm/mempolicy.c: fix the out-of-bounds access issue in mpol_parse_str +- mm/mempolicy.c: fix the out-of-bounds access issue in mpol_parse_str +- !7997 mm: some misc bugfix +- mm: vmalloc: bail out early in find_vmap_area() if vmap is not init +- Revert "mm: support multi-size THP numa balancing" +- mm: simplify thp_vma_allowable_order +- mm: huge_memory: add the missing folio_test_pmd_mappable() for THP split statistics +- mm/huge_memory: skip invalid debugfs new_order input for folio split +- mm: prohibit the last subpage from reusing the entire large folio +- mm/memory.c: do_numa_page(): remove a redundant page table read +- mm: memory: fix shift-out-of-bounds in fault_around_bytes_set +- !7966 [OLK-6.6] openeuler_defconfig: Modify openeuler-defconfig +- openeuler_defconfig: Modify openeuler-defconfig +- !7909 Scheduler load balance fixes +- config: Disable COBFIG_ARCH_CUSTOM_NUMA_DISTANCE for arm64 +- sched/numa: Fix numa imbalance in load_balance() +- !7917 sched: QOS_SCHED_DYNAMIC_AFFINITY depend on FAIR_GROUP_SCHED +- sched: QOS_SCHED_DYNAMIC_AFFINITY depend on FAIR_GROUP_SCHED +- Revert "sched: QOS_SCHED_DYNAMIC_AFFINITY depend on FAIR_CGROUP_SCHED" +- !7902 v3 Revert "ACPI: Rename ACPI_HOTPLUG_CPU to include 'present'" +- Revert "ACPI: Rename ACPI_HOTPLUG_CPU to include 'present'" +- !7888 v3 mm: add thp anon pmd size mapping align control +- mm: add thp anon pmd size mapping align control +- !7730 v2 sched: QOS_SCHED_DYNAMIC_AFFINITY depend on FAIR_CGROUP_SCHED +- sched: QOS_SCHED_DYNAMIC_AFFINITY depend on FAIR_CGROUP_SCHED +- !7808 Bluetooth: L2CAP: Fix not validating setsockopt user input +- Bluetooth: L2CAP: Fix not validating setsockopt user input +- !7822 LoongArch: limit min pci msi-x/msi vector number when request more than 32 vectors +- LoongArch: limit min pci msi-x/msi vector number when request more than 32 vectors +- !7823 LoongArch: fix kdump not work when legacy mode disabled +- LoongArch: fix efi map page table error +- Revert "LoongArch: kdump: Add memory reservation for old kernel" +- Revert "LoongArch: Fix kdump failure on v40 interface specification" +- Revert "LoongArch: kdump: Add high memory reservation" +- !7764 v2 mm: Some bugfix and optimization +- mm/dynamic_pool: clear PG_hugetlb when demote hugepages +- mm: optimise vmf_anon_prepare() for VMAs without an anon_vma +- mm: delay the check for a NULL anon_vma +- mm: assert the mmap_lock is held in __anon_vma_prepare() +- mm/memory: change vmf_anon_prepare() to be non-static +- mm: always initialise folio->_deferred_list +- mm: page_alloc: control latency caused by zone PCP draining +- mm/hugetlb: fix DEBUG_LOCKS_WARN_ON(1) when dissolve_free_hugetlb_folio() +- hugetlb: check for hugetlb folio before vmemmap_restore +- hugetlb: set hugetlb page flag before optimizing vmemmap +- mm: add alloc_contig_migrate_range allocation statistics +- mm: convert free_zone_device_page to free_zone_device_folio +- mm: combine __folio_put_small, __folio_put_large and __folio_put +- mm: inline destroy_large_folio() into __folio_put_large() +- mm: combine free_the_page() and free_unref_page() +- mm: free non-hugetlb large folios in a batch +- mm: increase folio batch size +- mm: fix list corruption in put_pages_list +- mm: remove folio from deferred split list before uncharging it +- mm: convert free_swap_cache() to take a folio +- mm: use a folio in __collapse_huge_page_copy_succeeded() +- mm: convert free_pages_and_swap_cache() to use folios_put() +- mm: remove lru_to_page() +- mm: remove free_unref_page_list() +- memcg: remove mem_cgroup_uncharge_list() +- mm: free folios directly in move_folios_to_lru() +- mm: free folios in a batch in shrink_folio_list() +- mm: allow non-hugetlb large folios to be batch processed +- mm: handle large folios in free_unref_folios() +- mm: use __page_cache_release() in folios_put() +- mm: use free_unref_folios() in put_pages_list() +- mm: remove use of folio list from folios_put() +- memcg: add mem_cgroup_uncharge_folios() +- mm: use folios_put() in __folio_batch_release() +- mm: add free_unref_folios() +- mm: convert free_unref_page_list() to use folios +- mm: make folios_put() the basis of release_pages() +- !7812 [OLK-6.6] drm/phytium: Replace default efi fb0 with dc fb +- drm/phytium: Replace default efi fb0 with dc fb +- !7767 irqchip/loongson-eiointc: fix gsi register error +- irqchip/loongson-eiointc: fix gsi register error +- !7771 ext4: default enable iomap for buffered IO and large folio +- ext4: default enable iomap for buffered IO and large folio +- !7721 【OLK-6.6】bugfix from upstream v6.9 for AMD EPYC +- x86/CPU/AMD: Add models 0x10-0x1f to the Zen5 range +- x86/CPU/AMD: Do the common init on future Zens too +- !7572 Fix pseudo nmi identifier undeclaration complilation error +- arm64/cpufeature: Fix pseudo nmi identifier undeclaration complilation error +- !7537 [OLK-6.6] irqchip/gic-v3: Fix one race condition due to NMI withdraw +- irqchip/gic-v3: Fix one race condition due to NMI withdraw +- !7164 [sync] PR-7143: media: usbtv: Remove useless locks in usbtv_video_free() +- media: usbtv: Remove useless locks in usbtv_video_free() +- !6386 [OLK-6.6] Fix warnings for RNPVF driver with loongarch-allmodconfig +- RNPVF: NET: Fix "'%d' directive output may be truncated" warnings +- !5243 [OLK-6.6] Support PSP identification for Hygon 4th CPU and print secure features when running on Hygon CPUs +- x86/config: Set CONFIG_HYGON_CSV by default +- x86/cpu/hygon: Clear SME feature flag when not in use +- x86/cpufeatures: Add CSV3 CPU feature +- x86/cpufeatures: Add CPUID_8C86_0000_EDX CPUID leaf +- x86/cpu: Detect memory encryption features on Hygon CPUs +- KVM: SVM: Print Hygon CSV support info if support is detected +- crypto: ccp: Print Hygon CSV API version when CSV support is detected +- x86/mm: Print CSV info into the kernel log +- x86/mm: Provide a Kconfig entry to build the HYGON memory encryption support into the kernel +- Documentation/arch/x86: Add HYGON secure virtualization description +- crypto: ccp: Add support to detect CCP devices on Hygon 4th CPUs +- !7180 【3snic】 use same string “sssnic" for "Kernel driver in use" and "Kernel modules" +- 3snic: use sssnic as kernel driver name +- !7607 Fix allmodconfig build error +- net/ethernet/huawei/hiroce3: Fix allmodconfig build error +- !7583 [OLK-6.6] Fixed display error for ps23xx when using ast and pe2201 bmc card +- drm/ast: Fixed display error for ps23xx when using ast bmc card +- drm/phytium: Bugfix Xorg startup for ps23xx when using pe2201 bmc card +- !7593 memcg_swap_qos: Backport two bugfix +- mm/swapfile: fix infinite loop in get_swap_pages after set memory.swapfile +- memcg: fix incorrect value of sysctl_memcg_swap_qos_stat +- !7595 jbd2: speed up jbd2_transaction_committed() +- jbd2: speed up jbd2_transaction_committed() +- !5480 [OLK-6.6] Fix DMA RW sequence disorder issue +- Add kh40000_iommu_dma_ops for KH-40000 platform +- Add kh40000_direct_dma_ops for KH-40000 platform +- !3133 [OLK-6.6] iommu/vt-d:Add support for detecting ACPI device in RMRR +- iommu/vt-d: Add support for detecting ACPI namespace device in RMRR + +* Fri May 24 2024 Mingzheng Xing - 6.6.0-27.0.0.32 +- Update the riscv-kernel patch for sg2042, rebase 6.6.0-27.0.0 and add features: + - SPI Flash driver + - kexec file raw image + - HIGHMEM +- This patch only applies to the RISC-V architecture, the related commit list: +- +- sg2042: Update sg2042 openeuler_defconfig +- th1520: riscv: config: Enable th1520 support +- riscv: thead: Use the wback_inv instead of wback_only +- riscv: errata: thead: use pa based instructions for CMO +- riscv: errata: thead: use riscv_nonstd_cache_ops for CMO +- Revert "riscv: use VA+PA variant of CMO macros for DMA page preparation" +- Revert "riscv: use VA+PA variant of CMO macros for DMA synchorization" +- Revert "riscv: errata: cmo: add CMO macro variant with both VA and PA" +- Revert "riscv: errata: Replace thead cache clean with flush" +- Revert "riscv: errata: thead: use riscv_nonstd_cache_ops for CMO" +- Revert "riscv: errata: thead: use pa based instructions for CMO" +- riscv: mm: fix NOCACHE_THEAD does not set bit[61] correctly +- riscv: mm: update T-Head memory type definitions +- Revert "sg2042: riscv: changing T-Head PBMT attributes" +- riscv: remove compression for riscv Image +- th1520: cpufreq: correct typo in config name +- th1520: riscv: dts: thead: Add Milk-V Meles board +- th1520: cpufreq: light-mpw-cpufreq: fix -Wunused-variable in panic_cpufreq_notifier_call +- th1520: cpufreq: light-mpw-cpufreq: fix cpu_pll1 already disabled warning +- riscv: Add th1520-lichee-cluster-4a dts support (8G/16G) +- riscv: dts: th1520-beaglev-ahead: add alias for emmc & sd +- riscv: dts: th1520-lichee-pi-4a: add alias for emmc & sd +- riscv: dts: lpi4a 16g support +- th1520: perf vendor events riscv: add T-HEAD C9xx JSON file +- th1520: riscv: dts: thead: Add PMU event node +- riscv: pinctrl: th1520: fix build +- riscv: dts: th1520: lpi4a: add rpmsg node +- riscv: dts: th1520: add mbox client node +- riscv: rpmsg: mailbox-client: sync thead sdk 1.4.2 +- riscv: panic: add thead sdk quirks +- riscv: dts: add watchdog node +- th1520: riscv: dts: Add th1520 reset device tree +- th1520: reset: Add th1520 reset driver support +- th1520: dt-bindings: reset: Document th1520 reset control +- riscv: light_wdt: update sdk 1.4.2 +- th1520_light_event: update sdk 1.4.2 +- th1520_aon: update sdk 1.4.2 +- th1520: fix compile th1520-beaglev-ahead error +- th1520: add TH1520 cpu frequency driver +- th1520: riscv: errata: thead: use pa based instructions for CMO +- th1520: riscv: errata: thead: use riscv_nonstd_cache_ops for CMO +- riscv: dts: thead: Add TH1520 CPU reset node +- th1520: riscv: dts: thead: Enable Lichee Pi 4A USB +- th1520: riscv: dts: thead: Add Lichee Pi 4A IO expansions +- th1520: riscv: dts: thead: Add TH1520 USB nodes +- th1520: riscv: dts: thead: Add TH1520 I2C nodes +- th1520: usb: dwc3: add T-HEAD TH1520 usb driver +- th1520: dt-bindings: usb: Add T-HEAD TH1520 USB controller +- th1520: riscv: dts: thead: Add BeagleV Ahead SDIO0 pins +- th1520: riscv: dts: thead: Add Lichee Pi 4A SDIO0 pins +- th1520: riscv: dts: thead: Add TH1520 ethernet nodes +- th1520: net: stmmac: add glue layer for T-HEAD TH1520 SoC +- th1520: dt-bindings: net: add T-HEAD dwmac support +- th1520: dt-bindings: net: snps,dwmac: allow dwmac-3.70a to set pbl properties +- th1520: riscv: dts: thead: Enable Lichee Pi 4A PWM fan +- th1520: riscv: dts: thead: Add TH1520 PVT node +- th1520: riscv: dts: thead: Add TH1520 PWM node +- th1520: pwm: add T-HEAD PWM driver +- th1520: dt-bindings: pwm: Add T-HEAD PWM controller +- th1520: gpio: dwapb: Use generic request, free and set_config +- riscv: dts: thead: Enable LicheePi 4A eMMC and microSD +- riscv: dts: thead: Enable BeagleV Ahead eMMC and microSD +- riscv: dts: thead: Add TH1520 mmc controllers and sdhci clock +- riscv: defconfig: Enable mmc and dma drivers for T-Head TH1520 +- mmc: sdhci-of-dwcmshc: Add support for T-Head TH1520 +- mmc: sdhci: add __sdhci_execute_tuning() to header +- dt-bindings: mmc: sdhci-of-dwcmhsc: Add T-Head TH1520 support +- th1520: riscv: dtb: thead: Add BeagleV Ahead LEDs +- th1520: riscv: dts: thead: Add TH1520 pinctrl settings for UART0 +- th1520: riscv: dts: thead: Adjust TH1520 GPIO labels +- th1520: riscv: dts: thead: Add TH1520 GPIO ranges +- th1520: riscv: dts: thead: Add TH1520 pin control nodes +- th1520: pinctrl: Add driver for the T-Head TH1520 SoC +- th1520: dt-bindings: pinctrl: Add thead,th1520-pinctrl bindings +- th1520: dt-bindings: gpio: dwapb: allow gpio-ranges +- sg2042: riscv: config: Enable sg2042 support +- sg2042: drivers: rtc: disable BMC RTC device +- sg2042: dts: add i2c-rtc ds1307 device node for single chip +- sg2042: riscv:dts:modify dw gpio clock name +- sg2042: drivers:pci:remove the err log of parsing pci +- sg2042: driver: ipmi: support KVM and IPMI SI for BMC +- sg2042: perf cpumap: Make counter as unsigned ints +- sg2042: driver: radeon: deinit device during kexec +- sg2042: kernel: schedule: Fix set_task_cpu() bug +- sg2042: mm: Modify __find_max_addr for memory hole +- sg2042: riscv: kernel: Optimize apply_relocate_add() +- sg2042: riscv: mm: Clear compilation warning about last_cpupid +- sg2042: kernel: tick: filter unnecessary printing +- sg2042: kernel: Adjust the log level of the tick_switch_to_oneshot function +- sg2042: driver: clk: Modify the timer clock is turned off defaultly +- sg2042: drivers: clock: Add sophgo sg2042 multi-chip clock synchronous support +- Revert "riscv: Fix set_memory_XX() and set_direct_map_XX() by splitting huge linear mappings" +- Revert "riscv: Fix set_direct_map_default_noflush() to reset _PAGE_EXEC" +- Revert "riscv: Fix wrong usage of lm_alias() when splitting a huge linear mapping" +- sg2042: riscv: mm: Add high memory on riscv64 using sv39 +- sg2042: riscv/kexec: handle R_RISCV_ADD16 and R_RISCV_SUB16 relocation types +- sg2042: riscv: kexec: Add image loader for kexec file +- sg2042: drm/amd/display: Support DRM_AMD_DC_FP on RISC-V +- sg2042: riscv: Factor out riscv-march-y to a separate Makefile +- sg2042: riscv: Add support for kernel-mode FPU +- sg2042: mango pci hack:broadcast when no MSI source known +- sg2042: nvidia hda: force msi +- sg2042: radeon hack: force 64-bit msi to fit top intc +- sg2042: amdgpu: disable rebar +- sg2042: ttm: disallow cached mapping +- sg2042: driver: soc: Add sophgo sg2042 soc support +- sg2042: drivers: pcie: Create msi-x whitelist,turn on msi-x for top intr +- sg2042: driver: pcie: Add sophgo sg2042 soc support +- sg2042: driver: net: Add sophgo sg2042 soc support +- sg2042: driver: mtd: Add sophgo sg2042 soc support +- sg2042: driver: mmc: Add sophgo sg2042 soc support +- sg2042: driver: reset: Add sophgo sg2042 soc support +- sg2042: driver: pinctrl: Add sophgo sg2042 soc support +- sg2042: driver: clk: Add sophgo sg2042 soc support +- sg2042: riscv: spinlock: Fix deadlock issue +- sg2042: riscv: add smp_cond_load_acquire() +- sg2042: riscv: add ioremap_wc for gpu +- sg2042: riscv: changing T-Head PBMT attributes +- sg2042: riscv: errata: thead: Make cache clean to flush +- sg2042: riscv: use VA+PA variant of CMO macros for DMA page preparation +- sg2042: riscv: use VA+PA variant of CMO macros for DMA synchorization +- sg2042: riscv: errata: cmo: add CMO macro variant with both VA and PA +- sg2042: riscv: errata: Replace thead cache clean with flush +- sg2042: riscv: Kconfig: Set vector as default no +- sg2042: riscv: Add sophgo sg2042 soc support + * Sat May 18 2024 ZhangPeng - 6.6.0-27.0.0.31 - !7527 ext4 iomap performance optimize - ext4: fallback to generic_perform_write once iov_iter_count <= PAGE_SIZE