From 332445f4406b06791705c1a9427f39aaa1c30e24 Mon Sep 17 00:00:00 2001 From: liuzh Date: Tue, 26 Mar 2024 15:11:14 +0800 Subject: [PATCH] add HAOC patch and spec for openEuler 24.03 LTS --- 0005-haoc-kernel.patch | 13895 +++++++++++++++++++++++++++++++++++++++ haoc-kernel.spec | 5003 ++++++++++++++ 2 files changed, 18898 insertions(+) create mode 100644 0005-haoc-kernel.patch create mode 100644 haoc-kernel.spec diff --git a/0005-haoc-kernel.patch b/0005-haoc-kernel.patch new file mode 100644 index 0000000..ceb1a93 --- /dev/null +++ b/0005-haoc-kernel.patch @@ -0,0 +1,13895 @@ +From 5e3439b082bd2c50d5d99776cc09875b58c6986f Mon Sep 17 00:00:00 2001 +From: liuzh +Date: Wed, 20 Mar 2024 10:54:11 +0800 +Subject: [PATCH] Squashed commit of the following: + +commit ec1ca7489f99f8ae78f59846bbde576ba8c1d17d +Author: liuzh +Date: Mon Mar 18 15:32:43 2024 +0800 + + modify slub.c set_track_prepare() + +commit b0a92d4bdf6e5b70566d40a9eaca212c25a861be +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 70bd0cd14fadd8de90c24f7d068ce0c178926978 +Author: zhangsy +Date: Mon Mar 18 10:40:42 2024 +0800 + + Fix bugs on qemu when opening CONFIG_IEE and CONFIG_PTP. + +commit c2354a983b6815d92fe9186c4633029701a0c961 +Author: zhangsy +Date: Thu Mar 14 16:34:53 2024 +0800 + + Fix compiling bugs of CONFIG_PTP. + +commit 0705cba2c67808b11fe921683bdf03035059cb71 +Author: zhangsy +Date: Thu Mar 14 11:10:00 2024 +0800 + + Fix bugs on qemu when opening CONFIG_IEE and CONFIG_INTERRUPTABLE. + +commit 51cb50831e41ed95736a62a29dfc3c0a4a6fa912 +Author: zhangsy +Date: Wed Mar 13 17:31:39 2024 +0800 + + Fix bugs on qemu when opening CONFIG_IEE. + +commit 911534e59d6d1aa89255021f6740cd68b3284149 +Author: liuzh +Date: Tue Mar 12 15:32:29 2024 +0800 + + fix the map of IEE_SI_TEXT. + +commit 5ec57031b813c9283059dc3236295ad45db97ad6 +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 8d808438b6335c47da6d60d2903125eeb4b4cb41 +Author: liuzh +Date: Thu Mar 7 14:27:45 2024 +0800 + + fix some conflicts + +commit e0349b6ad5963f985b36a726ba63ff91ac68874d +Author: liuzh +Date: Wed Mar 6 12:31:11 2024 +0800 + + rebase to 6.6.0-12.0.0 for update. +--- + .gitignore | 4 + + 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 | 145 ++ + arch/arm64/include/asm/iee-def.h | 73 + + arch/arm64/include/asm/iee-si.h | 69 + + 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 | 12 + + arch/arm64/include/asm/pgalloc.h | 4 + + arch/arm64/include/asm/pgtable-hwdef.h | 4 + + arch/arm64/include/asm/pgtable.h | 313 +++- + arch/arm64/include/asm/sysreg.h | 56 + + 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 | 18 + + arch/arm64/kernel/debug-monitors.c | 4 + + arch/arm64/kernel/entry-common.c | 4 + + arch/arm64/kernel/entry.S | 656 +++++++ + arch/arm64/kernel/head.S | 52 + + arch/arm64/kernel/hibernate.c | 8 + + arch/arm64/kernel/hw_breakpoint.c | 99 + + arch/arm64/kernel/iee/Makefile | 1 + + arch/arm64/kernel/iee/iee-func.c | 189 ++ + arch/arm64/kernel/iee/iee-gate.S | 231 +++ + arch/arm64/kernel/iee/iee.c | 1359 ++++++++++++++ + arch/arm64/kernel/koi/Makefile | 1 + + arch/arm64/kernel/koi/koi.c | 1327 ++++++++++++++ + arch/arm64/kernel/mte.c | 5 + + arch/arm64/kernel/process.c | 13 + + arch/arm64/kernel/proton-pack.c | 8 + + arch/arm64/kernel/setup.c | 35 + + arch/arm64/kernel/traps.c | 25 + + arch/arm64/kernel/vmlinux.lds.S | 70 + + arch/arm64/mm/context.c | 92 +- + arch/arm64/mm/fault.c | 4 + + arch/arm64/mm/fixmap.c | 74 +- + arch/arm64/mm/init.c | 34 + + arch/arm64/mm/mmu.c | 2224 ++++++++++++++++++++--- + arch/arm64/mm/pgd.c | 39 + + arch/arm64/mm/proc.S | 23 + + 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 | 24 + + 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 + + include/linux/stacktrace.h | 5 + + init/main.c | 158 ++ + kernel/cred.c | 170 ++ + kernel/exit.c | 8 + + kernel/fork.c | 316 ++-- + kernel/groups.c | 7 + + kernel/kthread.c | 13 + + kernel/smpboot.c | 9 + + kernel/stacktrace.c | 38 + + 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/mm_init.c | 6 + + mm/slub.c | 220 ++- + mm/sparse-vmemmap.c | 21 + + mm/swap.c | 13 + + mm/vmalloc.c | 2 +- + net/dns_resolver/dns_key.c | 9 + + security/commoncap.c | 153 ++ + security/keys/keyctl.c | 23 + + security/keys/process_keys.c | 52 + + security/security.c | 15 + + 110 files changed, 9485 insertions(+), 447 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 0bbae167bf93..77b3024b92d5 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -51,6 +51,7 @@ + *.tar + *.xz + *.zst ++*.log + Module.symvers + modules.order + +@@ -170,3 +171,6 @@ sphinx_*/ + + # Rust analyzer configuration + /rust-project.json ++ ++#command ++command.txt +diff --git a/Makefile b/Makefile +index e458c8265d75..1c2293c9204d 100644 +--- a/Makefile ++++ b/Makefile +@@ -554,7 +554,7 @@ LINUXINCLUDE := \ + -I$(objtree)/include \ + $(USERINCLUDE) + +-KBUILD_AFLAGS := -D__ASSEMBLY__ -fno-PIE ++KBUILD_AFLAGS := -D__ASSEMBLY__ -fno-PIE -march=armv8.1-a + + KBUILD_CFLAGS := + KBUILD_CFLAGS += -std=gnu11 +@@ -563,6 +563,7 @@ KBUILD_CFLAGS += -funsigned-char + KBUILD_CFLAGS += -fno-common + KBUILD_CFLAGS += -fno-PIE + KBUILD_CFLAGS += -fno-strict-aliasing ++KBUILD_CFLAGS += -march=armv8.1-a + + KBUILD_CPPFLAGS := -D__KERNEL__ + KBUILD_RUSTFLAGS := $(rust_common_flags) \ +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index b6088df74edd..47325c81abd2 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -1653,6 +1653,24 @@ config UNMAP_KERNEL_AT_EL0 + + If unsure, say Y. + ++# Config for iee ++config IEE ++ depends on ARM64 ++ depends on ARM64_PAN ++ depends on ARM64_VA_BITS_48 ++ depends on ARM64_4K_PAGES ++ def_bool y ++ ++# Config for support of interruption of iee ++config IEE_INTERRUPTABLE ++ depends on IEE ++ def_bool n ++ ++# Config for credentials isolation ++config CREDP ++ depends on IEE ++ def_bool n ++ + config MITIGATE_SPECTRE_BRANCH_HISTORY + bool "Mitigate Spectre style attacks against branch history" if EXPERT + default y +diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h +index 7712c532ce1e..358df7be2570 100644 +--- a/arch/arm64/include/asm/assembler.h ++++ b/arch/arm64/include/asm/assembler.h +@@ -26,6 +26,41 @@ + #include + #include + ++#ifdef CONFIG_IEE ++ .macro iee_si_restore_daif, flags:req ++ msr daifclr, #0xf ++ tbnz \flags, #6, 114221f ++ tbnz \flags, #7, 114210f ++ tbnz \flags, #8, 114100f ++ msr daifset, #0b000 ++ b 114514f ++114221: ++ tbnz \flags, #7, 114211f ++ tbnz \flags, #8, 114101f ++ msr daifset, #0b001 ++ b 114514f ++114211: ++ tbnz \flags, #8, 114111f ++ msr daifset, #0b011 ++ b 114514f ++114210: ++ tbnz \flags, #8, 114110f ++ msr daifset, #0b010 ++ b 114514f ++114100: ++ msr daifset, #0b100 ++ b 114514f ++114101: ++ msr daifset, #0b101 ++ b 114514f ++114110: ++ msr daifset, #0b110 ++ b 114514f ++114111: ++ msr daifset, #0b111 ++114514: ++ .endm ++#endif + /* + * Provide a wxN alias for each wN register so what we can paste a xN + * reference after a 'w' to obtain the 32-bit version. +@@ -52,7 +87,11 @@ alternative_else_nop_endif + + .macro disable_daif + disable_allint ++#ifdef CONFIG_IEE ++ msr daifset, #0x7 ++#else + msr daifset, #0xf ++#endif + .endm + + .macro enable_daif +@@ -69,7 +108,11 @@ alternative_else_nop_endif + .endm + + .macro restore_irq, flags ++#ifdef CONFIG_IEE ++ iee_si_restore_daif \flags ++#else + msr daif, \flags ++#endif + .endm + + .macro enable_dbg +@@ -77,20 +120,44 @@ alternative_else_nop_endif + .endm + + .macro disable_step_tsk, flgs, tmp ++// #ifdef CONFIG_IEE ++// 1145: ++// tbz \flgs, #TIF_SINGLESTEP, 9990f ++// mrs \tmp, mdscr_el1 ++// bic \tmp, \tmp, #DBG_MDSCR_SS ++// orr \tmp, \tmp, #DBG_MDSCR_MDE ++// msr mdscr_el1, \tmp ++// isb // Synchronise with enable_dbg ++// mrs \tmp, mdscr_el1 ++// tbz \tmp, #15, 1145b ++// #else + tbz \flgs, #TIF_SINGLESTEP, 9990f + mrs \tmp, mdscr_el1 + bic \tmp, \tmp, #DBG_MDSCR_SS + msr mdscr_el1, \tmp + isb // Synchronise with enable_dbg ++// #endif + 9990: + .endm + + /* call with daif masked */ + .macro enable_step_tsk, flgs, tmp ++// #ifdef CONFIG_IEE ++// 1146: ++// tbz \flgs, #TIF_SINGLESTEP, 9990f ++// mrs \tmp, mdscr_el1 ++// orr \tmp, \tmp, #DBG_MDSCR_SS ++// orr \tmp, \tmp, #DBG_MDSCR_MDE ++// msr mdscr_el1, \tmp ++// isb // Synchronise with enable_dbg ++// mrs \tmp, mdscr_el1 ++// tbz \tmp, #15, 1146b ++// #else + tbz \flgs, #TIF_SINGLESTEP, 9990f + mrs \tmp, mdscr_el1 + orr \tmp, \tmp, #DBG_MDSCR_SS + msr mdscr_el1, \tmp ++// #endif + 9990: + .endm + +diff --git a/arch/arm64/include/asm/daifflags.h b/arch/arm64/include/asm/daifflags.h +index 2417cc6b1631..4e2a812fc898 100644 +--- a/arch/arm64/include/asm/daifflags.h ++++ b/arch/arm64/include/asm/daifflags.h +@@ -26,11 +26,19 @@ static inline void local_daif_mask(void) + (read_sysreg_s(SYS_ICC_PMR_EL1) == (GIC_PRIO_IRQOFF | + GIC_PRIO_PSR_I_SET))); + ++#ifdef CONFIG_IEE ++ asm volatile( ++ "msr daifset, #0x7 // local_daif_mask\n" ++ : ++ : ++ : "memory"); ++#else + asm volatile( + "msr daifset, #0xf // local_daif_mask\n" + : + : + : "memory"); ++#endif + + /* Don't really care for a dsb here, we don't intend to enable IRQs */ + if (system_uses_irq_prio_masking()) +@@ -118,7 +126,11 @@ static inline void local_daif_restore(unsigned long flags) + gic_write_pmr(pmr); + } + ++#ifdef CONFIG_IEE ++ iee_si_write_daif(flags); ++#else + write_sysreg(flags, daif); ++#endif + + /* If we can take asynchronous errors we can take NMIs */ + if (system_uses_nmi()) { +@@ -151,7 +163,11 @@ static inline void local_daif_inherit(struct pt_regs *regs) + * system_has_prio_mask_debugging() won't restore the I bit if it can + * use the pmr instead. + */ ++#ifdef CONFIG_IEE ++ iee_si_write_daif(flags); ++#else + write_sysreg(flags, daif); ++#endif + + /* The ALLINT field is at the same position in pstate and ALLINT */ + if (system_uses_nmi()) { +diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h +index bcd5622aa096..c13059f17f04 100644 +--- a/arch/arm64/include/asm/efi.h ++++ b/arch/arm64/include/asm/efi.h +@@ -58,7 +58,11 @@ void arch_efi_call_virt_teardown(void); + #define arch_efi_save_flags(state_flags) \ + ((void)((state_flags) = read_sysreg(daif))) + ++#ifdef CONFIG_IEE ++#define arch_efi_restore_flags(state_flags) iee_si_write_daif(state_flags) ++#else + #define arch_efi_restore_flags(state_flags) write_sysreg(state_flags, daif) ++#endif + + + /* arch specific definitions used by the stub code */ +diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h +index 58c294a96676..095a0731dce3 100644 +--- a/arch/arm64/include/asm/fixmap.h ++++ b/arch/arm64/include/asm/fixmap.h +@@ -108,6 +108,9 @@ void __init fixmap_copy(pgd_t *pgdir); + #define __late_clear_fixmap(idx) __set_fixmap((idx), 0, FIXMAP_PAGE_CLEAR) + + extern void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot); ++#ifdef CONFIG_PTP ++extern void __iee_set_fixmap_pre_init(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot); ++#endif + + #include + +diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h +index 84055329cd8b..f72d89bb9a32 100644 +--- a/arch/arm64/include/asm/hw_breakpoint.h ++++ b/arch/arm64/include/asm/hw_breakpoint.h +@@ -104,6 +104,18 @@ static inline void decode_ctrl_reg(u32 reg, + write_sysreg(VAL, dbg##REG##N##_el1);\ + } while (0) + ++#ifdef CONFIG_IEE ++#define IEE_SI_AARCH64_DBG_READ(N, REG, VAL) do{\ ++ VAL = this_cpu_read(iee_si_user_##REG##N);\ ++} while (0) ++ ++#define IEE_SI_AARCH64_DBG_WRITE(N, REG, VAL) do{\ ++ u64 __val = (u64)(VAL); \ ++ this_cpu_write(iee_si_user_##REG##N, __val);\ ++ iee_rwx_gate_entry(IEE_WRITE_AFSR0);\ ++} while (0) ++#endif ++ + struct task_struct; + struct notifier_block; + 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 +--- /dev/null ++++ b/arch/arm64/include/asm/iee-access.h +@@ -0,0 +1,36 @@ ++#ifndef _LINUX_IEE_ACCESS_H ++#define _LINUX_IEE_ACCESS_H ++ ++#include ++#include ++ ++extern unsigned long long iee_rw_gate(int flag, ...); ++ ++#ifdef CONFIG_IEE ++void iee_write_in_byte(void *ptr, u64 data, int length) ++{ ++ iee_rw_gate(IEE_WRITE_IN_BYTE, ptr, data, length); ++} ++ ++void iee_memset(void *ptr, int data, size_t n) ++{ ++ iee_rw_gate(IEE_MEMSET, ptr, data, n); ++} ++ ++void iee_set_track(struct track *ptr, struct track *data) ++{ ++ iee_rw_gate(IEE_OP_SET_TRACK, ptr, data); ++} ++ ++void iee_set_freeptr(freeptr_t *pptr, freeptr_t ptr) ++{ ++ iee_rw_gate(IEE_OP_SET_FREEPTR, pptr, ptr); ++} ++ ++void iee_write_entry_task(struct task_struct *tsk) ++{ ++ iee_rw_gate(IEE_WRITE_ENTRY_TASK, tsk); ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/arch/arm64/include/asm/iee-cred.h b/arch/arm64/include/asm/iee-cred.h +new file mode 100644 +index 000000000000..d98e3645d8a3 +--- /dev/null ++++ b/arch/arm64/include/asm/iee-cred.h +@@ -0,0 +1,145 @@ ++#ifndef _LINUX_IEE_CRED_H ++#define _LINUX_IEE_CRED_H ++ ++#include ++#include ++ ++extern unsigned long long iee_rw_gate(int flag, ...); ++ ++#ifdef CONFIG_CREDP ++static void __maybe_unused iee_copy_cred(const struct cred *old, struct cred *new) ++{ ++ iee_rw_gate(IEE_OP_COPY_CRED,old,new); ++} ++ ++static void __maybe_unused iee_set_cred_uid(struct cred *cred, kuid_t uid) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_UID,cred,uid); ++} ++ ++static void __maybe_unused iee_set_cred_gid(struct cred *cred, kgid_t gid) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_GID,cred,gid); ++} ++ ++static void __maybe_unused iee_set_cred_suid(struct cred *cred, kuid_t suid) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_SUID,cred,suid); ++} ++ ++static void __maybe_unused iee_set_cred_sgid(struct cred *cred, kgid_t sgid) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_SGID,cred,sgid); ++} ++ ++static void __maybe_unused iee_set_cred_euid(struct cred *cred, kuid_t euid) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_EUID,cred,euid); ++} ++ ++static void __maybe_unused iee_set_cred_egid(struct cred *cred, kgid_t egid) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_EGID,cred,egid); ++} ++ ++static void __maybe_unused iee_set_cred_fsuid(struct cred *cred, kuid_t fsuid) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_FSUID,cred,fsuid); ++} ++ ++static void __maybe_unused iee_set_cred_fsgid(struct cred *cred, kgid_t fsgid) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_FSGID,cred,fsgid); ++} ++ ++static void __maybe_unused iee_set_cred_user(struct cred *cred, struct user_struct *user) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_USER,cred,user); ++} ++ ++static void __maybe_unused iee_set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_USER_NS,cred,user_ns); ++} ++ ++static void __maybe_unused iee_set_cred_group_info(struct cred *cred, struct group_info *group_info) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_GROUP_INFO,cred,group_info); ++} ++ ++static void __maybe_unused iee_set_cred_securebits(struct cred *cred, unsigned securebits) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_SECUREBITS,cred,securebits); ++} ++ ++static void __maybe_unused iee_set_cred_cap_inheritable(struct cred *cred, kernel_cap_t cap_inheritable) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_CAP_INHER,cred,cap_inheritable); ++} ++ ++static void __maybe_unused iee_set_cred_cap_permitted(struct cred *cred, kernel_cap_t cap_permitted) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_CAP_PERM,cred,cap_permitted); ++} ++ ++static void __maybe_unused iee_set_cred_cap_effective(struct cred *cred, kernel_cap_t cap_effective) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_CAP_EFFECT,cred,cap_effective); ++} ++ ++static void __maybe_unused iee_set_cred_cap_bset(struct cred *cred, kernel_cap_t cap_bset) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_CAP_BSET,cred,cap_bset); ++} ++ ++static void __maybe_unused iee_set_cred_cap_ambient(struct cred *cred, kernel_cap_t cap_ambient) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_CAP_AMBIENT,cred,cap_ambient); ++} ++ ++#ifdef CONFIG_KEYS ++static void __maybe_unused iee_set_cred_jit_keyring(struct cred *cred, unsigned char jit_keyring) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_JIT_KEYRING,cred,jit_keyring); ++} ++ ++static void __maybe_unused iee_set_cred_session_keyring(struct cred *cred, struct key *session_keyring) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_SESS_KEYRING,cred,session_keyring); ++} ++ ++static void __maybe_unused iee_set_cred_process_keyring(struct cred *cred, struct key *process_keyring) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_PROC_KEYRING,cred,process_keyring); ++} ++ ++static void __maybe_unused iee_set_cred_thread_keyring(struct cred *cred, struct key *thread_keyring) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_THREAD_KEYRING,cred,thread_keyring); ++} ++ ++static void __maybe_unused iee_set_cred_request_key_auth(struct cred *cred, struct key *request_key_auth) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_REQ_KEYRING,cred,request_key_auth); ++} ++#endif ++ ++static void __maybe_unused iee_set_cred_atomic_set_usage(struct cred *cred, int i) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_ATSET_USAGE,cred,i); ++} ++ ++#ifdef CONFIG_SECURITY ++static void __maybe_unused iee_set_cred_security(struct cred *cred, void *security) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_SECURITY,cred,security); ++} ++#endif ++ ++static void __maybe_unused iee_set_cred_rcu(struct cred *cred, struct rcu_head *rcu) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_RCU,cred,rcu); ++} ++#endif ++ ++#endif +\ 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..ff37f352f823 +--- /dev/null ++++ b/arch/arm64/include/asm/iee-def.h +@@ -0,0 +1,73 @@ ++// 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 ++#ifdef CONFIG_KOI ++#define IEE_READ_KOI_STACK 49 // Parameters: struct task_struct *tsk ++#define IEE_WRITE_KOI_STACK 50 // Parameters: struct task_struct *tsk, unsigned long koi_stack ++#define IEE_READ_TOKEN_TTBR1 51 // Parameters: struct task_struct *tsk ++#define IEE_WRITE_TOKEN_TTBR1 52 // Parameters: struct task_struct *tsk, unsigned long current_ttbr1 ++#define IEE_READ_KOI_KERNEL_STACK 53 // Parameters: struct task_struct *tsk ++#define IEE_WRITE_KOI_KERNEL_STACK 54 // Parameters: struct task_struct *tsk, unsigned long kernel_stack ++#define IEE_READ_KOI_STACK_BASE 55 // Parameters: struct task_struct *tsk ++#define IEE_WRITE_KOI_STACK_BASE 56 // Parameters: struct task_struct *tsk, unsigned long koi_stack_base ++#endif ++ ++/* Add new IEE ops here */ ++ ++#define AT_INC 1 ++#define AT_INC_NOT_ZERO 2 ++#define AT_DEC_AND_TEST 3 ++/* Atomic ops for atomic_t */ ++ ++#ifdef CONFIG_KOI ++#define IEE_SWITCH_TO_KERNEL 7 ++#define IEE_SWITCH_TO_KOI 8 ++#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..064975632cd1 +--- /dev/null ++++ b/arch/arm64/include/asm/iee-si.h +@@ -0,0 +1,69 @@ ++#ifndef _LINUX_IEE_SI_H ++#define _LINUX_IEE_SI_H ++ ++#include ++#define __iee_si_code __section(".iee.si_text") ++#define __iee_si_base __section(".iee.si_base") ++#define __iee_si_data __section(".iee.si_data") ++ ++/* Used for copying globals that iee rwx gate needs. */ ++// extern unsigned long iee_base_kimage_voffset; ++// extern unsigned long iee_base_memstart_addr; ++extern unsigned long iee_base_iee_pg_dir; ++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; ++extern pgd_t iee_pg_dir[PTRS_PER_PGD]; ++extern bool iee_init_done; ++ ++DECLARE_PER_CPU(unsigned long, iee_si_user_bvr0); ++DECLARE_PER_CPU(unsigned long, iee_si_user_bcr0); ++ ++/* The following are __init functions used for iee si initialization. */ ++extern void iee_si_set_base_swapper_cnp(void); ++extern void isolate_iee_si(void); ++ ++// Handler function for sensitive inst ++u64 iee_si_handler(int flag, ...); ++/* ++ * TODO: scan a page to check whether it contains sensitive instructions ++ * return 1 when finding sensitive inst, 0 on safe page. ++ */ ++extern int iee_si_scan_page(unsigned long addr); ++ ++ ++#define DBG_MDSCR_SS (1 << 0) ++#define DBG_MDSCR_MDE (1 << 15) ++ ++#define IEE_SI_TEST 0 ++#define IEE_WRITE_SCTLR 1 ++#define IEE_WRITE_TTBR0 2 ++#define IEE_WRITE_VBAR 3 ++#define IEE_WRITE_TCR 4 ++#define IEE_WRITE_MDSCR 5 ++#define IEE_CONTEXT_SWITCH 6 ++#define IEE_WRITE_AFSR0 10 ++/* Provide ttbr1 switch gate for KOI */ ++#ifdef CONFIG_KOI ++#define IEE_SWITCH_TO_KERNEL 7 ++#define IEE_SWITCH_TO_KOI 8 ++#endif ++/* MASK modify-permitted bits on IEE protected sys registers */ ++#define IEE_SCTLR_MASK (SCTLR_EL1_CP15BEN | SCTLR_EL1_SED | SCTLR_EL1_UCT | SCTLR_EL1_UCI |\ ++ SCTLR_EL1_BT0 | SCTLR_EL1_BT1 | SCTLR_EL1_TCF0_MASK | SCTLR_ELx_DSSBS) ++#define IEE_TTBR0_MASK ~0 ++#define IEE_TTBR1_MASK ~0 ++#define IEE_TCR_MASK (TCR_HD | TCR_T0SZ_MASK) ++#define IEE_MDSCR_MASK (DBG_MDSCR_SS | DBG_MDSCR_MDE) ++ ++#define IEE_DBGBCR_BT 0b0000 << 20 ++#define IEE_DBGBCR_SSC 0b00 << 14 ++#define IEE_DBGBCR_HMC 0b1 << 13 ++#define IEE_DBGBCR_BAS 0b1111 << 5 ++#define IEE_DBGBCR_PMC 0b11 << 1 ++#define IEE_DBGBCR_E 0b1 ++#define IEE_DBGBCR IEE_DBGBCR_BT | IEE_DBGBCR_SSC | IEE_DBGBCR_HMC | IEE_DBGBCR_BAS \ ++ | IEE_DBGBCR_PMC | IEE_DBGBCR_E ++ ++#endif +\ No newline at end of file +diff --git a/arch/arm64/include/asm/iee-slab.h b/arch/arm64/include/asm/iee-slab.h +new file mode 100644 +index 000000000000..4f3c17c7da00 +--- /dev/null ++++ b/arch/arm64/include/asm/iee-slab.h +@@ -0,0 +1,23 @@ ++#ifndef _LINUX_IEE_SLAB_H ++#define _LINUX_IEE_SLAB_H ++/* ++ * Tracking user of a slab. ++ */ ++#include ++ ++#define TRACK_ADDRS_COUNT 16 ++struct track { ++ unsigned long addr; /* Called from address */ ++#ifdef CONFIG_STACKDEPOT ++ depot_stack_handle_t handle; ++#endif ++ int cpu; /* Was running on cpu */ ++ int pid; /* Pid context */ ++ unsigned long when; /* When did the operation occur */ ++}; ++ ++enum track_item { TRACK_ALLOC, TRACK_FREE }; ++ ++typedef struct { unsigned long v; } freeptr_t; ++ ++#endif +\ 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 +--- /dev/null ++++ b/arch/arm64/include/asm/iee-token.h +@@ -0,0 +1,40 @@ ++#ifndef _LINUX_IEE_TOKEN_H ++#define _LINUX_IEE_TOKEN_H ++ ++#include ++ ++extern unsigned long long iee_rw_gate(int flag, ...); ++struct task_token; ++struct task_struct; ++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) ++{ ++ iee_rw_gate(IEE_INIT_TOKEN, tsk, kernel_stack, iee_stack); ++} ++ ++void iee_free_token(struct task_struct *tsk) ++{ ++ iee_rw_gate(IEE_FREE_TOKEN, tsk); ++} ++ ++unsigned long iee_read_token_stack(struct task_struct *tsk) ++{ ++ unsigned long ret; ++ ret = iee_rw_gate(IEE_READ_TOKEN_STACK, tsk); ++ return ret; ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/arch/arm64/include/asm/iee.h b/arch/arm64/include/asm/iee.h +new file mode 100644 +index 000000000000..598f6d0b2626 +--- /dev/null ++++ b/arch/arm64/include/asm/iee.h +@@ -0,0 +1,10 @@ ++#ifndef _LINUX_IEE_H ++#define _LINUX_IEE_H ++#define __iee_code __section(".iee.text") ++#define __iee_header __section(".iee.text.header") ++ ++u64 iee_dispatch(int flag, ...); ++ ++#include ++ ++#endif +diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h +index 85d26143faa5..e7a3081ce285 100644 +--- a/arch/arm64/include/asm/kernel-pgtable.h ++++ b/arch/arm64/include/asm/kernel-pgtable.h +@@ -118,4 +118,25 @@ + #define SWAPPER_RX_MMUFLAGS (SWAPPER_RW_MMUFLAGS | PTE_RDONLY) + #endif + ++#ifdef CONFIG_IEE ++ ++#ifdef CONFIG_ARM64_4K_PAGES // zgcXXX: it has been deleted in 6.6. ++#define ARM64_SWAPPER_USES_SECTION_MAPS 1 ++#else ++#define ARM64_SWAPPER_USES_SECTION_MAPS 0 ++#endif ++ ++#define SWAPPER_MM_MMUFLAGS (PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS) // zgcXXX: warning: 6.6 delete this macro. should delete this line later. ++ ++#define SWAPPER_PTE_FLAGS_IDMAP (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED | PTE_RDONLY) ++#define SWAPPER_PMD_FLAGS_IDMAP (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S | PMD_SECT_RDONLY) ++ ++#if ARM64_SWAPPER_USES_SECTION_MAPS ++#define SWAPPER_MM_MMUFLAGS_IDMAP (PMD_ATTRINDX(MT_NORMAL) | SWAPPER_PMD_FLAGS_IDMAP) ++#else ++#define SWAPPER_MM_MMUFLAGS_IDMAP (PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS_IDMAP) ++#endif ++ ++#endif ++ + #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 +--- /dev/null ++++ b/arch/arm64/include/asm/koi.h +@@ -0,0 +1,335 @@ ++#include "linux/mm.h" ++#include "asm/current.h" ++#include "asm/pgtable-hwdef.h" ++#include "asm/pgtable-types.h" ++#include "asm/pgtable.h" ++#include "linux/mm_types.h" ++#include "linux/pgtable.h" ++#include "linux/printk.h" ++#include "linux/slab.h" ++#include "linux/string.h" ++#include ++#include "linux/hashtable.h" ++#include "linux/module.h" ++#include "linux/vmalloc.h" ++#include "stacktrace.h" ++#include "asm/mmu.h" ++#ifdef CONFIG_IEE ++#include "asm/iee-si.h" ++#include "asm/iee-def.h" ++#endif ++ ++#define HASH_TABLE_BIT 10 ++#define HASH_TABLE_LEN (1 << HASH_TABLE_BIT) ++#define HASH_KEY_MASK ((1 << HASH_TABLE_BIT) - 1) ++ ++#define MAX_VAR_NAME 64 ++#define DRIVER_ISOLATION_VAR_ARRAY_SIZE 32 ++#define DRIVER_ISOLATION_MAX_VAL 256 ++ ++extern struct hlist_head koi_mem_htbl[1024]; ++extern spinlock_t koi_mem_htbl_spin_lock; ++extern unsigned long koi_swapper_ttbr1; ++extern s64 koi_offset; ++ ++#ifdef CONFIG_IEE ++extern unsigned long long iee_rw_gate(int flag, ...); ++#endif ++ ++DECLARE_PER_CPU(unsigned long[PAGE_SIZE / sizeof(unsigned long)], ++ koi_irq_current_ttbr1); ++ ++/** ++* struct koi_mem_hash_node - ++*@mod:pointer to driver module ++*@mem_list_head:free memory list head ++*@ko_mm: mm_struct in each driver ++*@pgdp:entry to Page Global Directory :pgd ++*@node:hash linked list node ++*@addr_htbl[1 << (HASH_TABLE_BIT)]: ++*@rcu: ++*/ ++struct koi_mem_hash_node { ++ struct module *mod; ++ struct list_head mem_list_head; ++ struct mm_struct *ko_mm; ++ pgd_t *pgdp; ++ unsigned long ko_ttbr1; ++ struct hlist_node node; ++ struct hlist_head addr_htbl[1 << (HASH_TABLE_BIT)]; ++ struct rcu_head rcu; ++ // used to protect free mem list ++ spinlock_t spin_lock; ++ // used to protect addr hashtable ++ spinlock_t addr_htbl_spin_lock; ++}; ++//describe the global shared var ++struct shared_variable_descriptor { ++ unsigned int id; ++ unsigned int type; ++ char name[MAX_VAR_NAME]; ++ unsigned long offset; ++ unsigned int size; ++ unsigned int self_ptr_ids[DRIVER_ISOLATION_VAR_ARRAY_SIZE]; ++}; ++ ++int koi_do_switch_to_kernel_pgtbl(void); ++ ++int koi_copy_pagetable(struct mm_struct *ko_mm, pgd_t *koi_pg_dir, ++ unsigned long addr, unsigned long end); ++ ++void koi_create_pagetable(struct module *mod); ++ ++void koi_map_kostack(struct module *mod); ++unsigned long koi_mem_alloc(struct module *mod, unsigned long orig_addr, ++ unsigned long size); ++void koi_mem_free(struct module *mod, unsigned long addr, unsigned long size, ++ bool is_const, int count, ...); ++void *koi_mem_lookup(struct module *mod, unsigned long addr); ++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_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); ++ ++#define switch_pgtable(ttbr1) \ ++ do { \ ++ write_sysreg(ttbr1, ttbr1_el1); \ ++ isb(); \ ++ asm volatile(ALTERNATIVE("nop; nop; nop", \ ++ "ic iallu; dsb nsh; isb", \ ++ ARM64_WORKAROUND_CAVIUM_27456)); \ ++ } while (0); ++ ++#ifndef CONFIG_IEE ++#define koi_switch_to_ko() \ ++ do { \ ++ unsigned long flags, ko_ttbr1, cur_sp; \ ++ unsigned long *ptr; \ ++ struct task_token *token; \ ++ asm volatile("mrs %0, daif\n" \ ++ "msr daifset, #2\n" \ ++ "isb\n" \ ++ "mov %1, sp\n" \ ++ : "=r"(flags), "=r"(cur_sp) \ ++ :); \ ++ if (!on_irq_stack(cur_sp, NULL)) { \ ++ koi_do_switch_to_ko_stack(); \ ++ ko_ttbr1 = koi_ttbr_ctor(THIS_MODULE); \ ++ token = (struct task_token *)((unsigned long)current + \ ++ koi_offset); \ ++ token->current_ttbr1 = ko_ttbr1 & (~TTBR_ASID_MASK); \ ++ } else { \ ++ ko_ttbr1 = koi_ttbr_ctor(THIS_MODULE); \ ++ ptr = SHIFT_PERCPU_PTR(koi_irq_current_ttbr1, \ ++ __kern_my_cpu_offset()); \ ++ *ptr = ko_ttbr1 & ~(TTBR_ASID_MASK); \ ++ } \ ++ switch_pgtable(ko_ttbr1); \ ++ asm volatile("msr daif, %0\n" \ ++ "isb\n" \ ++ : \ ++ : "r"(flags)); \ ++ } while (0); ++ ++#define koi_switch_to_kernel() \ ++ do { \ ++ unsigned long cur_sp, flags, asid; \ ++ unsigned long *ptr; \ ++ struct task_token *token; \ ++ asm volatile("mrs %0, daif\n" \ ++ "msr daifset, #2\n" \ ++ "isb\n" \ ++ "mov %1, sp\n" \ ++ "mov %2, ttbr0_el1\n" \ ++ : "=r"(flags), "=r"(cur_sp), "=r"(asid) \ ++ :); \ ++ asid &= ~USER_ASID_FLAG; \ ++ asid &= TTBR_ASID_MASK; \ ++ switch_pgtable(koi_swapper_ttbr1); \ ++ if (!on_irq_stack(cur_sp, NULL)) { \ ++ token = (struct task_token *)((unsigned long)current + \ ++ 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()); \ ++ *ptr = koi_swapper_ttbr1; \ ++ } \ ++ asm volatile("msr daif, %0\n" \ ++ "isb\n" \ ++ : \ ++ : "r"(flags)); \ ++ } while (0); ++#else ++#define koi_switch_to_ko() \ ++ do { \ ++ unsigned long cur_sp, flags, ko_ttbr1; \ ++ unsigned long *ptr; \ ++ asm volatile("mrs %0, daif\n" \ ++ "msr daifset, #2\n" \ ++ "isb\n" \ ++ "mov %1, sp\n" \ ++ : "=r"(flags), "=r"(cur_sp) \ ++ :); \ ++ if (!on_irq_stack(cur_sp, NULL)) { \ ++ koi_do_switch_to_ko_stack(); \ ++ ko_ttbr1 = koi_ttbr_ctor(THIS_MODULE); \ ++ iee_rw_gate(IEE_WRITE_TOKEN_TTBR1, current, \ ++ ko_ttbr1 &(~TTBR_ASID_MASK)); \ ++ } else { \ ++ ko_ttbr1 = koi_ttbr_ctor(THIS_MODULE); \ ++ ptr = SHIFT_PERCPU_PTR(koi_irq_current_ttbr1, \ ++ __kern_my_cpu_offset()); \ ++ *ptr = ko_ttbr1 & (~TTBR_ASID_MASK); \ ++ } \ ++ iee_rwx_gate_entry(IEE_SWITCH_TO_KOI, ko_ttbr1); \ ++ asm volatile("msr daif, %0\n" \ ++ "isb\n" \ ++ : \ ++ : "r"(flags)); \ ++ } while (0); ++ ++#define koi_switch_to_kernel() \ ++ do { \ ++ unsigned long flags, cur_sp; \ ++ unsigned long *ptr; \ ++ asm volatile("mrs %0, daif\n" \ ++ "msr daifset, #2\n" \ ++ "isb\n" \ ++ "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_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()); \ ++ *ptr = koi_swapper_ttbr1; \ ++ } \ ++ asm volatile("msr daif, %0\n" \ ++ "isb\n" \ ++ : \ ++ : "r"(flags)); \ ++ } while (0); ++#endif ++//kzalloc function in driver space ++static __maybe_unused noinline void * ++koi_kzalloc_wrapper(struct module *mod, size_t size, gfp_t flags) ++{ ++ int cnt = (size + PAGE_SIZE - 1) / PAGE_SIZE; ++ void *addr; ++ 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("mem node for module: %s not found\n", mod->name); ++ return NULL; ++ } ++ ++ addr = kzalloc(size, flags); ++ koi_copy_pagetable(target->ko_mm, target->pgdp, (unsigned long)addr, ++ (unsigned long)addr + PAGE_SIZE * cnt); ++ koi_switch_to_ko(); ++ return addr; ++} ++//kmalloc function in driver space ++static __maybe_unused __always_inline void * ++koi_kmalloc_wrapper(struct module *mod, size_t size, gfp_t flags) ++{ ++ int cnt = (size + PAGE_SIZE - 1) / PAGE_SIZE; ++ void *addr; ++ 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("mem node for module: %s not found\n", mod->name); ++ return 0; ++ } ++ ++ 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(); ++ return (void *)addr; ++} ++//vmalloc function in driver space ++static __maybe_unused void *koi_vmalloc_wrapper(struct module *mod, ++ unsigned long size) ++{ ++ int cnt = (size + PAGE_SIZE - 1) / PAGE_SIZE; ++ void *addr; ++ 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("mem node for module: %s not found\n", mod->name); ++ koi_switch_to_ko(); ++ return 0; ++ } ++ addr = vmalloc(cnt * PAGE_SIZE); ++ koi_copy_pagetable(target->ko_mm, target->pgdp, (unsigned long)addr, ++ (unsigned long)addr + PAGE_SIZE * cnt); ++ koi_switch_to_ko(); ++ return addr; ++} ++//kmalloc_array function in driver space ++static __maybe_unused void *koi_kmalloc_array_wrapper(struct module *mod, ++ size_t n, size_t size, ++ gfp_t flags) ++{ ++ int kpage; ++ void *addr; ++ 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("mem node for module: %s not found\n", mod->name); ++ koi_switch_to_ko(); ++ return 0; ++ } ++ kpage = (n * size + PAGE_SIZE - 1) / PAGE_SIZE; ++ 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); ++ koi_switch_to_ko(); ++ return addr; ++} +\ No newline at end of file +diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h +index fde4186cc387..c9047b1eba01 100644 +--- a/arch/arm64/include/asm/memory.h ++++ b/arch/arm64/include/asm/memory.h +@@ -190,6 +190,13 @@ extern u64 vabits_actual; + #endif + + extern s64 memstart_addr; ++ ++#if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++extern s64 memstart_addr_init; ++extern s64 iee_offset; ++#define LOGICAL_RANDOM (long long int)((long unsigned int)__va(memstart_addr_init) & (~PAGE_OFFSET)) ++#endif ++ + /* 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); + #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)0x4 << 44) ++#endif ++ ++#ifdef CONFIG_IEE ++#ifdef CONFIG_IEE_OFFSET ++#define IEE_OFFSET ((CONFIG_IEE_OFFSET) - LOGICAL_RANDOM) ++#else ++#define IEE_OFFSET (((unsigned long)0x4 << 44) - LOGICAL_RANDOM) ++#endif ++#define __phys_to_iee(x) (__phys_to_virt(x) + IEE_OFFSET) ++#define SET_UPAGE(x) __pgprot(pgprot_val(x) | PTE_USER) ++#define SET_PPAGE(x) __pgprot(pgprot_val(x) & (~PTE_USER)) ++#define SET_INVALID(x) __pgprot(pgprot_val(x) & (~PTE_VALID)) ++#define SET_NG(x) __pgprot(pgprot_val(x) | PTE_NG) ++#endif ++ + /* + * Convert a page to/from a physical address + */ +diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h +index a6fb325424e7..273f39919e31 100644 +--- a/arch/arm64/include/asm/mmu_context.h ++++ b/arch/arm64/include/asm/mmu_context.h +@@ -43,7 +43,11 @@ static inline void cpu_set_reserved_ttbr0_nosync(void) + { + unsigned long ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir)); + ++#ifdef CONFIG_IEE ++ iee_rwx_gate_entry(IEE_WRITE_ttbr0_el1, ttbr); ++#else + write_sysreg(ttbr, ttbr0_el1); ++#endif + } + + static inline void cpu_set_reserved_ttbr0(void) +@@ -79,7 +83,11 @@ static inline void __cpu_set_tcr_t0sz(unsigned long t0sz) + + tcr &= ~TCR_T0SZ_MASK; + tcr |= t0sz << TCR_T0SZ_OFFSET; ++#ifdef CONFIG_IEE ++ iee_rwx_gate_entry(IEE_WRITE_tcr_el1, tcr); ++#else + write_sysreg(tcr, tcr_el1); ++#endif + isb(); + } + +@@ -174,6 +182,10 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap) + ttbr1 |= TTBR_CNP_BIT; + } + ++ #ifdef CONFIG_IEE ++ ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, ASID(current->active_mm)); ++ #endif ++ + replace_phys = (void *)__pa_symbol(idmap_cpu_replace_ttbr1); + + __cpu_install_idmap(idmap); +diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h +index 237224484d0f..4e3304da8421 100644 +--- a/arch/arm64/include/asm/pgalloc.h ++++ b/arch/arm64/include/asm/pgalloc.h +@@ -63,6 +63,10 @@ static inline void __p4d_populate(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot) + extern pgd_t *pgd_alloc(struct mm_struct *mm); + extern void pgd_free(struct mm_struct *mm, pgd_t *pgdp); + ++#ifdef CONFIG_KOI ++pgd_t *koi_pgd_alloc(void); ++#endif ++ + static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t ptep, + pmdval_t prot) + { +diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h +index e4944d517c99..3442d1f910de 100644 +--- a/arch/arm64/include/asm/pgtable-hwdef.h ++++ b/arch/arm64/include/asm/pgtable-hwdef.h +@@ -84,6 +84,10 @@ + #define CONT_PMD_SIZE (CONT_PMDS * PMD_SIZE) + #define CONT_PMD_MASK (~(CONT_PMD_SIZE - 1)) + ++#define PGD_APT (_AT(pudval_t, 1) << 61) ++#define PGD_PXN (_AT(pudval_t, 1) << 59) ++#define PGD_UXN (_AT(pudval_t, 1) << 60) ++ + /* + * Hardware page table definitions. + * +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index 7f7d9b1df4e5..dee52c1838dc 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -34,6 +34,9 @@ + #include + #include + #include ++#ifdef CONFIG_PTP ++#include ++#endif + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + #define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE +@@ -157,6 +160,30 @@ 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 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; ++} ++#endif ++ + static inline pte_t clear_pte_bit(pte_t pte, pgprot_t prot) + { + pte_val(pte) &= ~pgprot_val(prot); +@@ -261,8 +288,40 @@ static inline pte_t pte_mkdevmap(pte_t pte) + return set_pte_bit(pte, __pgprot(PTE_DEVMAP | PTE_SPECIAL)); + } + +-static inline void set_pte(pte_t *ptep, pte_t pte) ++#ifdef CONFIG_PTP ++static 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); ++ 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); + + /* +@@ -274,6 +333,57 @@ static inline void set_pte(pte_t *ptep, pte_t pte) + isb(); + } + } ++#endif ++ ++static inline void set_pte(pte_t *ptep, pte_t pte) ++{ ++#ifdef CONFIG_KOI ++ if (!pte_none(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 ++} ++ ++#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(); ++ } ++} ++#endif + + extern void __sync_icache_dcache(pte_t pteval); + bool pgattr_change_is_safe(u64 old, u64 new); +@@ -531,6 +641,65 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd) + #define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT) + #define pfn_pud(pfn,prot) __pud(__phys_to_pud_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) + ++#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) ++{ ++ 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)); ++ ++ __check_safe_pte_update(mm, (pte_t *)pmdp, pmd_pte(pmd)); ++ ++ set_pmd(pmdp, pmd); ++} ++ ++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)); ++ ++ __check_safe_pte_update(mm, (pte_t *)pudp, pud_pte(pud)); ++ ++ set_pud(pudp, pud); ++} ++ ++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); ++} ++#else + static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp, pmd_t pmd) + { +@@ -544,7 +713,7 @@ static inline void set_pud_at(struct mm_struct *mm, unsigned long addr, + page_table_check_pud_set(mm, pudp, pud); + return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud)); + } +- ++#endif + #define __p4d_to_phys(p4d) __pte_to_phys(p4d_pte(p4d)) + #define __phys_to_p4d_val(phys) __phys_to_pte_val(phys) + +@@ -611,6 +780,7 @@ static inline bool pud_table(pud_t pud) { return true; } + extern pgd_t init_pg_dir[PTRS_PER_PGD]; + extern pgd_t init_pg_end[]; + extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; ++extern pgd_t iee_pg_dir[PTRS_PER_PGD]; + extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; + extern pgd_t tramp_pg_dir[PTRS_PER_PGD]; + extern pgd_t reserved_pg_dir[PTRS_PER_PGD]; +@@ -623,7 +793,22 @@ 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_IEE ++static inline bool in_iee_pgdir(void *addr) ++{ ++ return ((unsigned long)addr & PAGE_MASK) == ++ ((unsigned long)iee_pg_dir & PAGE_MASK); ++} ++#endif ++ ++#ifdef CONFIG_PTP ++static inline bool in_tramp_pgdir(void *addr) ++{ ++ return ((unsigned long)addr & PAGE_MASK) == ++ ((unsigned long)tramp_pg_dir & PAGE_MASK); ++} ++ ++static inline void iee_set_fixmap_pmd_pre_init(pmd_t *pmdp, pmd_t pmd) + { + #ifdef __PAGETABLE_PMD_FOLDED + if (in_swapper_pgdir(pmdp)) { +@@ -631,7 +816,6 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) + return; + } + #endif /* __PAGETABLE_PMD_FOLDED */ +- + WRITE_ONCE(*pmdp, pmd); + + if (pmd_valid(pmd)) { +@@ -639,6 +823,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); ++#endif ++ if (pmd_valid(pmd)) { ++ dsb(ishst); ++ isb(); ++ } ++} + + static inline void pmd_clear(pmd_t *pmdp) + { +@@ -658,6 +868,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)) + ++#ifdef CONFIG_PTP ++#define pte_set_fixmap_init(addr) ((pte_t *)iee_set_fixmap_offset_pre_init(FIX_PTE, addr)) ++#define pte_set_fixmap_offset_init(pmd, addr) pte_set_fixmap_init(pte_offset_phys(pmd, addr)) ++#define pte_clear_fixmap_init() clear_fixmap_init(FIX_PTE) ++#endif ++ + #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) +@@ -686,7 +902,9 @@ 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) + { + #ifdef __PAGETABLE_PUD_FOLDED + if (in_swapper_pgdir(pudp)) { +@@ -694,7 +912,6 @@ static inline void set_pud(pud_t *pudp, pud_t pud) + return; + } + #endif /* __PAGETABLE_PUD_FOLDED */ +- + WRITE_ONCE(*pudp, pud); + + if (pud_valid(pud)) { +@@ -702,6 +919,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)) { ++ // 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(); ++ } ++} + + static inline void pud_clear(pud_t *pudp) + { +@@ -721,6 +965,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)) + ++#ifdef CONFIG_PTP ++#define pmd_set_fixmap_init(addr) ((pmd_t *)iee_set_fixmap_offset_pre_init(FIX_PMD, addr)) ++#define pmd_set_fixmap_offset_init(pud, addr) pmd_set_fixmap_init(pmd_offset_phys(pud, addr)) ++#define pmd_clear_fixmap_init() clear_fixmap_init(FIX_PMD) ++#endif ++ + #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) +@@ -752,15 +1002,30 @@ 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)) + + static inline void set_p4d(p4d_t *p4dp, p4d_t p4d) + { +- if (in_swapper_pgdir(p4dp)) { ++ #ifdef CONFIG_IEE ++ if (in_swapper_pgdir(p4dp) | in_iee_pgdir(p4dp)) ++ #else ++ if (in_swapper_pgdir(p4dp)) ++ #endif ++ { + 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 + dsb(ishst); + isb(); + } +@@ -783,6 +1048,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)) + ++#ifdef CONFIG_PTP ++#define pud_set_fixmap_init(addr) ((pud_t *)iee_set_fixmap_offset_pre_init(FIX_PUD, addr)) ++#define pud_set_fixmap_offset_init(p4d, addr) pud_set_fixmap_init(pud_offset_phys(p4d, addr)) ++#define pud_clear_fixmap_init() clear_fixmap_init(FIX_PUD) ++#endif ++ + #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) +@@ -809,6 +1080,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)) + ++#ifdef CONFIG_PTP ++#define pgd_set_fixmap_init(addr) ((pgd_t *)iee_set_fixmap_offset_pre_init(FIX_PGD, addr)) ++#define pgd_clear_fixmap_init() clear_fixmap_init(FIX_PGD) ++#endif + #define pgd_set_fixmap(addr) ((pgd_t *)set_fixmap_offset(FIX_PGD, addr)) + #define pgd_clear_fixmap() clear_fixmap(FIX_PGD) + +@@ -888,8 +1163,13 @@ static inline int __ptep_test_and_clear_young(pte_t *ptep) + do { + old_pte = pte; + pte = pte_mkold(pte); ++ #ifdef CONFIG_PTP ++ pte_val(pte) = iee_set_cmpxchg_relaxed(ptep, ++ pte_val(old_pte), pte_val(pte)); ++ #else + pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep), + pte_val(old_pte), pte_val(pte)); ++ #endif + } while (pte_val(pte) != pte_val(old_pte)); + + return pte_young(pte); +@@ -937,8 +1217,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) + { ++ #ifdef CONFIG_PTP ++ pteval_t pteval= iee_set_xchg_relaxed((pte_t *)&pte_val(*ptep), (pteval_t)0); ++ pte_t pte = __pte(pteval); ++ #else + pte_t pte = __pte(xchg_relaxed(&pte_val(*ptep), 0)); +- ++ #endif + page_table_check_pte_clear(mm, pte); + + return pte; +@@ -949,7 +1233,12 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, + static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, + unsigned long address, pmd_t *pmdp) + { ++ #ifdef CONFIG_PTP ++ pteval_t pteval= iee_set_xchg_relaxed((pte_t *)&pmd_val(*pmdp), (pteval_t)0); ++ pmd_t pmd = __pmd(pteval); ++ #else + pmd_t pmd = __pmd(xchg_relaxed(&pmd_val(*pmdp), 0)); ++ #endif + + page_table_check_pmd_clear(mm, pmd); + +@@ -970,8 +1259,12 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres + do { + old_pte = pte; + pte = pte_wrprotect(pte); ++ #ifdef CONFIG_PTP ++ pte_val(pte) = iee_set_cmpxchg_relaxed(ptep,pte_val(old_pte), pte_val(pte)); ++ #else + pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep), + pte_val(old_pte), pte_val(pte)); ++ #endif + } while (pte_val(pte) != pte_val(old_pte)); + } + +@@ -988,7 +1281,11 @@ 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_PTP ++ return __pmd((pmdval_t)iee_set_xchg_relaxed((pte_t *)&pmd_val(*pmdp), (pmdval_t)pmd_val(pmd))); ++ #else + return __pmd(xchg_relaxed(&pmd_val(*pmdp), pmd_val(pmd))); ++ #endif + } + #endif + +diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h +index 0086a617dfa1..3f0def06add5 100644 +--- a/arch/arm64/include/asm/sysreg.h ++++ b/arch/arm64/include/asm/sysreg.h +@@ -1113,6 +1113,62 @@ + write_sysreg_s(__scs_new, sysreg); \ + } while (0) + ++ ++#ifdef CONFIG_IEE ++ ++extern void iee_rwx_gate_entry(int flag, ...); ++#define IEE_SI_TEST 0 ++#define IEE_WRITE_sctlr_el1 1 ++#define IEE_WRITE_ttbr0_el1 2 ++#define IEE_WRITE_vbar_el1 3 ++#define IEE_WRITE_tcr_el1 4 ++#define IEE_WRITE_mdscr_el1 5 ++#define IEE_WRITE_AFSR0 10 ++ ++#define sysreg_clear_set_iee_si(sysreg, clear, set) do { \ ++ u64 __scs_val = read_sysreg(sysreg); \ ++ u64 __scs_new = (__scs_val & ~(u64)(clear)) | (set); \ ++ if (__scs_new != __scs_val) \ ++ iee_rwx_gate_entry(IEE_WRITE_##sysreg, __scs_new); \ ++} while (0) ++ ++#define IEE_SI_WRITE_DAIF_SEL "msr daifclr, #0xf\n\t" \ ++ "tbnz %x0, #6, 114221f\n\t" \ ++ "tbnz %x0, #7, 114210f\n\t" \ ++ "tbnz %x0, #8, 114100f\n\t" \ ++ "msr daifset, #0b000\n\t" \ ++ "b 114514f\n\t" \ ++"114221:\n\t" \ ++ "tbnz %x0, #7, 114211f\n\t" \ ++ "tbnz %x0, #8, 114101f\n\t" \ ++ "msr daifset, #0b001\n\t" \ ++ "b 114514f\n\t" \ ++"114211:\n\t" \ ++ "tbnz %x0, #8, 114111f\n\t" \ ++ "msr daifset, #0b011\n\t" \ ++ "b 114514f\n\t" \ ++"114210:\n\t" \ ++ "tbnz %x0, #8, 114110f\n\t" \ ++ "msr daifset, #0b010\n\t" \ ++ "b 114514f\n\t" \ ++"114100:\n\t" \ ++ "msr daifset, #0b100\n\t" \ ++ "b 114514f\n\t" \ ++"114101:\n\t" \ ++ "msr daifset, #0b101\n\t" \ ++ "b 114514f\n\t" \ ++"114110:\n\t" \ ++ "msr daifset, #0b110\n\t" \ ++ "b 114514f\n\t" \ ++"114111:\n\t" \ ++ "msr daifset, #0b111\n\t" \ ++"114514:\n\t" ++ ++#define iee_si_write_daif(v) do { \ ++ u64 __val = (u64)(v); \ ++ asm volatile(IEE_SI_WRITE_DAIF_SEL: : "rZ" (__val));} while (0) ++#endif ++ + #define read_sysreg_par() ({ \ + 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..108f6e01776b 100644 +--- a/arch/arm64/include/asm/tlb.h ++++ b/arch/arm64/include/asm/tlb.h +@@ -11,8 +11,17 @@ + #include + #include + ++#ifdef CONFIG_PTP ++#include ++#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)_table); ++#endif + free_page_and_swap_cache((struct page *)_table); + } + +diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h +index b149cf9f91bc..ab07d1bcb040 100644 +--- a/arch/arm64/include/asm/tlbflush.h ++++ b/arch/arm64/include/asm/tlbflush.h +@@ -49,6 +49,7 @@ + + #define __tlbi(op, ...) __TLBI_N(op, ##__VA_ARGS__, 1, 0) + ++ + #define __tlbi_user(op, arg) do { \ + if (arm64_kernel_unmapped_at_el0()) \ + __tlbi(op, (arg) | USER_ASID_FLAG); \ +@@ -252,6 +253,10 @@ static inline void flush_tlb_mm(struct mm_struct *mm) + asid = __TLBI_VADDR(0, ASID(mm)); + __tlbi(aside1is, asid); + __tlbi_user(aside1is, asid); ++ #if defined(CONFIG_IEE) || defined (CONFIG_KOI) ++ if (!arm64_kernel_unmapped_at_el0()) ++ __tlbi(aside1is, asid | USER_ASID_FLAG); ++ #endif + dsb(ish); + mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL); + } +@@ -267,6 +272,10 @@ static inline void __flush_tlb_page_nosync(struct mm_struct *mm, + __tlbi_user(vale1is, addr); + mmu_notifier_arch_invalidate_secondary_tlbs(mm, uaddr & PAGE_MASK, + (uaddr & PAGE_MASK) + PAGE_SIZE); ++ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++ if (!arm64_kernel_unmapped_at_el0()) ++ __tlbi(vale1is, addr | USER_ASID_FLAG); ++ #endif + } + + static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, +@@ -364,6 +373,7 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) + * scale or num = 0 and scale + 1. The loop below favours the latter + * since num is limited to 30 by the __TLBI_RANGE_NUM() macro. + */ ++#if defined(CONFIG_IEE) || defined(CONFIG_KOI) + #define __flush_tlb_range_op(op, start, pages, stride, \ + asid, tlb_level, tlbi_user) \ + do { \ +@@ -376,6 +386,8 @@ do { \ + 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; \ +@@ -388,6 +400,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; \ +@@ -397,6 +411,42 @@ do { \ + } \ + } while (0) + ++#else ++#define __flush_tlb_range_op(op, start, pages, stride, \ ++ asid, tlb_level, tlbi_user) \ ++do { \ ++ int num = 0; \ ++ int scale = 0; \ ++ unsigned long addr; \ ++ \ ++ while (pages > 0) { \ ++ if (!system_supports_tlb_range() || \ ++ pages % 2 == 1) { \ ++ addr = __TLBI_VADDR(start, asid); \ ++ __tlbi_level(op, addr, tlb_level); \ ++ if (tlbi_user) \ ++ __tlbi_user_level(op, addr, tlb_level); \ ++ start += stride; \ ++ pages -= stride >> PAGE_SHIFT; \ ++ continue; \ ++ } \ ++ \ ++ num = __TLBI_RANGE_NUM(pages, scale); \ ++ if (num >= 0) { \ ++ addr = __TLBI_VADDR_RANGE(start, asid, scale, \ ++ num, tlb_level); \ ++ __tlbi(r##op, addr); \ ++ if (tlbi_user) \ ++ __tlbi_user(r##op, addr); \ ++ start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \ ++ pages -= __TLBI_RANGE_PAGES(num, scale); \ ++ } \ ++ scale++; \ ++ } \ ++} while (0) ++ ++#endif //if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++ + #define __flush_s2_tlb_range_op(op, start, pages, stride, tlb_level) \ + __flush_tlb_range_op(op, start, pages, stride, 0, tlb_level, false) + +@@ -456,7 +506,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end + return; + } + +- start = __TLBI_VADDR(start, 0); ++ start = __TLBI_VADDR(start, 0); + end = __TLBI_VADDR(end, 0); + + dsb(ishst); +@@ -472,9 +522,9 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end + */ + static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr) + { +- unsigned long addr = __TLBI_VADDR(kaddr, 0); +- +- dsb(ishst); ++ unsigned long addr = __TLBI_VADDR(kaddr, 0); ++ ++ dsb(ishst); + __tlbi(vaae1is, addr); + dsb(ish); + isb(); +diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile +index 21ef9c21a400..44eb76cc54d7 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 \ + syscall.o proton-pack.o idreg-override.o idle.o \ + patching.o + ++obj-y += iee/ ++obj-$(CONFIG_KOI) += koi/ + obj-$(CONFIG_AARCH32_EL0) += binfmt_elf32.o sys32.o signal32.o \ + 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 +--- 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) + + static int cp15_barrier_set_hw_mode(bool enable) + { ++#ifdef CONFIG_IEE ++ if (enable) ++ sysreg_clear_set_iee_si(sctlr_el1, 0, SCTLR_EL1_CP15BEN); ++ else ++ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_EL1_CP15BEN, 0); ++ return 0; ++#else + if (enable) + sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_CP15BEN); + else + sysreg_clear_set(sctlr_el1, SCTLR_EL1_CP15BEN, 0); + return 0; ++#endif + } + + static bool try_emulate_cp15_barrier(struct pt_regs *regs, u32 insn) +@@ -341,11 +349,19 @@ static int setend_set_hw_mode(bool enable) + if (!cpu_supports_mixed_endian_el0()) + return -EINVAL; + ++#ifdef CONFIG_IEE ++ if (enable) ++ sysreg_clear_set_iee_si(sctlr_el1, 0, SCTLR_EL1_CP15BEN); ++ else ++ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_EL1_CP15BEN, 0); ++ return 0; ++#else + if (enable) + sysreg_clear_set(sctlr_el1, SCTLR_EL1_SED, 0); + else + sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_SED); + return 0; ++#endif + } + + 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 +--- 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 + DEFINE(FREGS_SIZE, sizeof(struct ftrace_regs)); ++#ifdef CONFIG_IEE ++ DEFINE(iee_from_token_offset, offsetof(struct task_token, iee_stack)); ++ 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)); ++#endif + BLANK(); + #endif + #ifdef CONFIG_AARCH32_EL0 +diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c +index a686a96d966a..7b8bd91262e2 100644 +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -80,7 +80,11 @@ hisilicon_1980005_enable(const struct arm64_cpu_capabilities *__unused) + __set_bit(ARM64_HAS_CACHE_IDC, system_cpucaps); + arm64_ftr_reg_ctrel0.sys_val |= BIT(CTR_EL0_IDC_SHIFT); + arm64_ftr_reg_ctrel0.strict_mask &= ~BIT(CTR_EL0_IDC_SHIFT); ++#ifdef CONFIG_IEE ++ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_EL1_UCT, 0); ++#else + sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0); ++#endif + } + #endif + +@@ -132,7 +136,11 @@ cpu_enable_trap_ctr_access(const struct arm64_cpu_capabilities *cap) + enable_uct_trap = true; + + if (enable_uct_trap) ++#ifdef CONFIG_IEE ++ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_EL1_UCT, 0); ++#else + sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0); ++#endif + } + + #ifdef CONFIG_ARM64_ERRATUM_1463225 +@@ -147,7 +155,11 @@ has_cortex_a76_erratum_1463225(const struct arm64_cpu_capabilities *entry, + static void __maybe_unused + cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused) + { ++#ifdef CONFIG_IEE ++ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_EL1_UCI, 0); ++#else + sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCI, 0); ++#endif + } + + #ifdef CONFIG_HISILICON_ERRATUM_HIP08_RU_PREFETCH +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index 316c57b19c93..ed2d72575420 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -1622,7 +1622,11 @@ static void cpu_emulate_effective_ctr(const struct arm64_cpu_capabilities *__unu + * value. + */ + if (!(read_cpuid_cachetype() & BIT(CTR_EL0_IDC_SHIFT))) ++#ifdef CONFIG_IEE ++ sysreg_clear_set_iee_si(sctlr_el1, SCTLR_EL1_UCT, 0); ++#else + sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0); ++#endif + } + + static bool has_cache_dic(const struct arm64_cpu_capabilities *entry, +@@ -1883,7 +1887,11 @@ static inline void __cpu_enable_hw_dbm(void) + { + u64 tcr = read_sysreg(tcr_el1) | TCR_HD; + ++#ifdef CONFIG_IEE ++ iee_rwx_gate_entry(IEE_WRITE_tcr_el1, tcr); ++#else + write_sysreg(tcr, tcr_el1); ++#endif + isb(); + local_flush_tlb_all(); + } +@@ -2066,7 +2074,9 @@ static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused) + */ + WARN_ON_ONCE(in_interrupt()); + ++ #ifndef CONFIG_IEE + sysreg_clear_set(sctlr_el1, SCTLR_EL1_SPAN, 0); ++ #endif + set_pstate_pan(1); + } + #endif /* CONFIG_ARM64_PAN */ +@@ -2131,7 +2141,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)) ++#ifdef CONFIG_IEE ++ sysreg_clear_set_iee_si(tcr_el1, 0, TCR_E0PD1); ++#else + sysreg_clear_set(tcr_el1, 0, TCR_E0PD1); ++#endif + } + #endif /* CONFIG_ARM64_E0PD */ + +@@ -2234,7 +2248,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: + */ ++#ifdef CONFIG_IEE ++ sysreg_clear_set_iee_si(sctlr_el1, 0, SCTLR_EL1_BT0 | SCTLR_EL1_BT1); ++#else + sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_BT0 | SCTLR_EL1_BT1); ++#endif + isb(); + } + #endif /* CONFIG_ARM64_BTI */ +diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c +index 745aefddd9a3..265417e0ad81 100644 +--- a/arch/arm64/kernel/debug-monitors.c ++++ b/arch/arm64/kernel/debug-monitors.c +@@ -36,10 +36,14 @@ u8 debug_monitors_arch(void) + */ + static void mdscr_write(u32 mdscr) + { ++// #ifdef CONFIG_IEE ++// iee_rwx_gate_entry(IEE_WRITE_mdscr_el1, mdscr); ++// #else + unsigned long flags; + flags = local_daif_save(); + write_sysreg(mdscr, mdscr_el1); + local_daif_restore(flags); ++// #endif + } + NOKPROBE_SYMBOL(mdscr_write); + +diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c +index 08274e4317b2..0d259e355c90 100644 +--- a/arch/arm64/kernel/entry-common.c ++++ b/arch/arm64/kernel/entry-common.c +@@ -156,7 +156,11 @@ asmlinkage void noinstr asm_exit_to_user_mode(struct pt_regs *regs) + * mode. Before this function is called it is not safe to call regular kernel + * code, instrumentable code, or any code which may trigger an exception. + */ ++#ifdef CONFIG_IEE ++void noinstr arm64_enter_nmi(struct pt_regs *regs) ++#else + static void noinstr arm64_enter_nmi(struct pt_regs *regs) ++#endif + { + regs->lockdep_hardirqs = lockdep_hardirqs_enabled(); + +diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S +index a6030913cd58..4f8dd74aceeb 100644 +--- a/arch/arm64/kernel/entry.S ++++ b/arch/arm64/kernel/entry.S +@@ -29,12 +29,390 @@ + #include + #include + ++#ifdef CONFIG_IEE ++#include ++ ++#define BAD_SP_EL0 0 ++#define BAD_ELR_EL1 1 ++#define BAD_TCR_EL1 2 ++#endif ++ + .macro clear_gp_regs + .irp n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29 + mov x\n, xzr + .endr + .endm + ++#ifdef CONFIG_KOI ++#ifdef CONFIG_IEE ++/* ++ * This function is used to switch to ko stack in glue code ++ */ ++SYM_FUNC_START(koi_do_switch_to_ko_stack) ++ sub sp, sp, #48 ++ stp x29, x30, [sp] ++ str x2, [sp, #16] ++ stp x0, x1, [sp, #32] ++ ++ // iee_rw_gate(IEE_WRITE_KERNEL_STACK, current, sp) ++ mov x0, #IEE_WRITE_KOI_KERNEL_STACK ++ mrs x1, sp_el0 ++ add x2, sp, #48 ++ ++ bl iee_rw_gate ++ ++ // iee_rw_gate(IEE_READ_KOI_STACK, current) ++ mov x0, #IEE_READ_KOI_STACK ++ mrs x1, sp_el0 ++ bl iee_rw_gate ++ ++ ldp x29, x30, [sp] ++ ldr x2, [sp, #16] ++ add x1, sp, #32 ++ mov sp, x0 ++ ldp x0, x1, [x1] ++ ++ isb ++ ret ++SYM_FUNC_END(koi_do_switch_to_ko_stack) ++ ++/* ++ * This fucntion is used to switch to kernel stack in glue code ++ */ ++SYM_FUNC_START(koi_do_switch_to_kernel_stack) ++ sub sp, sp, #48 ++ stp x29, x30, [sp] ++ str x2, [sp, #16] ++ stp x0, x1, [sp, #32] ++ // iee_rw_gate(IEE_WRITE_KOI_STACK, current, sp) ++ mov x0, #IEE_WRITE_KOI_STACK ++ mrs x1, sp_el0 ++ add x2, sp, #48 ++ bl iee_rw_gate ++ ++ // iee_rw_gate(IEE_READ_KOI_KERNEL_STACK, current) ++ mov x0, #IEE_READ_KOI_KERNEL_STACK ++ mrs x1, sp_el0 ++ bl iee_rw_gate ++ ++ ldp x29, x30, [sp] ++ ldr x2, [sp, #16] ++ add x1, sp, #32 ++ mov sp, x0 ++ ldp x0, x1, [x1] ++ isb ++ ret ++SYM_FUNC_END(koi_do_switch_to_kernel_stack) ++ ++/* ++ * Before switch to ko's pgtable, we must switch current stack to ko's stack. ++ * We have stored registers to kernel stack, and we need to restore them from ko's stack after switching, ++ * so we need to copy from kernel stack to ko stack ++ * the memory region to copy is [sp, stack_top) ++ * void koi_switch_to_ko_stack(void); ++ */ ++SYM_FUNC_START(koi_switch_to_ko_stack) ++ mrs x17, pan ++ msr pan, 0x0 ++ ++ sub sp, sp, #32 ++ str x17, [sp, #16] ++ stp x30, x29, [sp] ++ ++ // current sp stores in x1 ++ add x1, x1, #176 ++ // current sp_el0 stores in x0 ++ bl _iee_write_koi_kernel_stack ++ ++ mrs x0, sp_el0 ++ bl _iee_read_koi_stack ++ ++ ldr x17, [sp, #16] ++ ldp x30, x29, [sp] ++ add sp, sp, #32 ++ ++ msr pan, x17 ++ ++ sub x0, x0, #176 ++ mov x1, sp ++ mov x2, #176 ++ ++ // memcpy(current->driver_stack, current->kernel_stack, 176) ++ mov x16, lr ++ bl memcpy ++ mov lr, x16 ++ ++ mov sp, x0 ++ isb ++ ret ++SYM_FUNC_END(koi_switch_to_ko_stack) ++ ++SYM_FUNC_START(koi_switch_to_kernel_stack) ++ /* ++ * current sp belongs to driver stack, and the bottom 160 bytes saves registers when exception occurred, ++ * so we should add 160 to current sp, and store it in task_struct ++ * also, fetch kernel sp from task_struct, copy the bottom 160 bytes from driver stack to kernel stack ++ */ ++ mrs x17, pan ++ msr pan, 0x0 ++ ++ sub sp, sp, #32 ++ stp x30, x29, [sp] ++ str x17, [sp, #16] ++ ++ mrs x0, sp_el0 ++ add x1, sp, #192 ++ bl _iee_write_koi_stack ++ ++ mrs x0, sp_el0 ++ bl _iee_read_koi_kernel_stack ++ ++ ldr x17, [sp, #16] ++ ldp x30, x29, [sp] ++ add sp, sp, #32 ++ ++ msr pan, x17 ++ ++ // x0 = kernel_stack ++ sub x0, x0, #160 ++ mov x1, sp ++ // x2 = 160 ++ mov x2, #160 ++ ++ mov x16, lr ++ bl memcpy ++ mov lr, x16 ++ ++ mov sp, x0 ++ isb ++ ret ++SYM_FUNC_END(koi_switch_to_kernel_stack) ++#else ++/* ++ * This function is used to switch to ko stack in glue code ++ */ ++SYM_FUNC_START(koi_do_switch_to_ko_stack) ++ sub sp, sp, #16 ++ stp x16, x17, [sp] ++ mrs x17, sp_el0 ++ adrp x16, koi_offset ++ ldr x16, [x16, #:lo12:koi_offset] ++ add x17, x17, x16 ++ add x16, sp, #16 ++ str x16, [x17, #koi_kernel_from_token_offset] ++ ldr x16, [x17, #koi_from_token_offset] ++ mov x17, sp ++ mov sp, x16 ++ ldp x16, x17, [x17] ++ isb ++ ret ++SYM_FUNC_END(koi_do_switch_to_ko_stack) ++ ++/* ++ * This fucntion is used to switch to kernel stack in glue code ++ */ ++SYM_FUNC_START(koi_do_switch_to_kernel_stack) ++ sub sp, sp, #16 ++ stp x16, x17, [sp] ++ mrs x17, sp_el0 ++ adrp x16, koi_offset ++ ldr x16, [x16, #:lo12:koi_offset] ++ add x17, x17, x16 ++ add x16, sp, #16 ++ str x16, [x17, #koi_from_token_offset] ++ ldr x16, [x17, #koi_kernel_from_token_offset] ++ mov x17, sp ++ mov sp, x16 ++ ldp x16, x17, [x17] ++ isb ++ ret ++SYM_FUNC_END(koi_do_switch_to_kernel_stack) ++ ++/* ++ * Before switch to ko's pgtable, we must switch current stack to ko's stack. ++ * We have stored registers to kernel stack, and we need to restore them from ko's stack after switching, ++ * so we need to copy from kernel stack to ko stack ++ * the memory region to copy is [sp, stack_top) ++ * void koi_switch_to_ko_stack(unsigned long stack_top); ++ */ ++SYM_FUNC_START(koi_switch_to_ko_stack) ++ // current sp stores in x1 ++ add x3, x1, #176 ++ adrp x4, koi_offset ++ ldr x4, [x4, #:lo12:koi_offset] ++ add x4, x0, x4 ++ // current sp_el0 stores in x0 ++ str x3, [x4, #koi_kernel_from_token_offset] ++ ldr x0, [x4, #koi_from_token_offset] ++ sub x0, x0, #176 ++ mov x2, #176 ++ ++ // memcpy(current->driver_stack, current->kernel_stack, 176) ++ mov x16, lr ++ bl memcpy ++ mov lr, x16 ++ ++ mov sp, x0 ++ isb ++ ret ++SYM_FUNC_END(koi_switch_to_ko_stack) ++ ++SYM_FUNC_START(koi_switch_to_kernel_stack) ++ /* ++ * current sp belongs to driver stack, and the bottom 176 bytes saves registers when exception occurred, ++ * so we should add 176 to current sp, and store it in task_struct ++ * also, fetch kernel sp from task_struct, copy the bottom 176 bytes from driver stack to kernel stack ++ */ ++ mov x1, sp ++ add x3, sp, #160 ++ ++ mrs x16, sp_el0 ++ adrp x2, koi_offset ++ ldr x2, [x2, #:lo12:koi_offset] ++ add x16, x16, x2 ++ str x3, [x16, #koi_from_token_offset] ++ // sp points to kernel_stack ++ ldr x0, [x16, #koi_kernel_from_token_offset] ++ ++ // x0 = kernel_stack ++ sub x0, x0, #160 ++ // x2 = 160 ++ mov x2, #160 ++ mov x16, lr ++ // memcpy(kernel_stack, driver_stack, 160) ++ bl memcpy ++ mov lr, x16 ++ mov sp, x0 ++ isb ++ ret ++SYM_FUNC_END(koi_switch_to_kernel_stack) ++#endif ++ ++SYM_FUNC_START(koi_switch_to_ko_pgtbl) ++ stp x0, x1, [sp, #16 * 1] ++ stp x2, x3, [sp, #16 * 2] ++ stp x4, x5, [sp, #16 * 3] ++ stp x6, x7, [sp, #16 * 4] ++ stp x8, x9, [sp, #16 * 5] ++ stp x10, x11, [sp, #16 * 6] ++ stp x12, x13, [sp, #16 * 7] ++ stp x14, x15, [sp, #16 * 8] ++ stp x16, x17, [sp, #16 * 9] ++ stp x18, x30, [sp, #16 * 10] ++ ++ adrp x0, koi_swapper_ttbr1 ++ ldr x0, [x0, #:lo12:koi_swapper_ttbr1] ++ cbz x0, 0f ++ bl koi_do_switch_to_ko_pgtbl ++ // if x0 == 0, don't need to switch pgtable and stack, jump to 0 ++ cbz x0, 0f ++ mov x19, x0 ++ // if current on task's kernel stack, switch to ko stack ++ mrs x0, sp_el0 ++ mov x1, sp ++ ldr x2, [x0, TSK_STACK] ++ eor x2, x2, x1 ++ and x2, x2, #~(THREAD_SIZE - 1) ++ cbnz x2, 1f ++ ++ bl koi_switch_to_ko_stack ++1: ++#ifndef CONFIG_IEE ++ msr ttbr1_el1, x19 ++ isb ++ nop ++ nop ++ nop ++#else ++ mov x0, #IEE_SWITCH_TO_KOI ++ mov x1, x19 ++ bl iee_rwx_gate_entry ++#endif ++0: ++ ++ ldp x0, x1, [sp, #16 * 1] ++ ldp x2, x3, [sp, #16 * 2] ++ ldp x4, x5, [sp, #16 * 3] ++ ldp x6, x7, [sp, #16 * 4] ++ ldp x8, x9, [sp, #16 * 5] ++ ldp x10, x11, [sp, #16 * 6] ++ ldp x12, x13, [sp, #16 * 7] ++ ldp x14, x15, [sp, #16 * 8] ++ ldp x16, x17, [sp, #16 * 9] ++ ldp x18, x30, [sp, #16 * 10] ++ 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] ++ stp x2, x3, [sp, #16 * 1] ++ stp x4, x5, [sp, #16 * 2] ++ stp x6, x7, [sp, #16 * 3] ++ stp x8, x9, [sp, #16 * 4] ++ stp x10, x11, [sp, #16 * 5] ++ ++ stp x12, x13, [sp, #16 * 6] ++ stp x14, x15, [sp, #16 * 7] ++ stp x16, x17, [sp, #16 * 8] ++ stp x18, x30, [sp, #16 * 9] ++ // check whether paging init finished ++ adrp x0, koi_swapper_ttbr1 ++ ldr x0, [x0, #:lo12:koi_swapper_ttbr1] ++ cbz x0, 0f ++ ++ bl koi_do_switch_to_kernel_pgtbl ++ /* ++ * koi_do_switch_to_kernel_pgtbl return 0 indicates ++ * that when exception occurred, the isolated ko is executing under koi pgtbl, ++ * so we need to switch stack to kernel stack after switch pgtbl back to koi_swapper_ttbr1. ++ */ ++ cbz x0, 0f ++#ifndef CONFIG_IEE ++ mrs x0, sp_el0 ++ adrp x1, koi_offset ++ ldr x1, [x1, #:lo12:koi_offset] ++ add x0, x0, x1 ++ mov x16, sp ++ ldr x17, [x0, koi_stack_base_from_token_offset] ++ eor x17, x17, x16 ++ and x17, x17, #~(THREAD_SIZE - 1) ++ cbnz x17, 0f ++#else ++ // save current pan ++ mrs x17, pan ++ // disable pan ++ msr pan, 0x0 ++ mrs x0, sp_el0 ++ bl _iee_read_koi_stack_base ++ // restore pan ++ msr pan, x17 ++ ++ mov x16, sp ++ eor x0, x0, x16 ++ and x0, x0, #~(THREAD_SIZE - 1) ++ cbnz x0, 0f ++#endif ++ bl koi_switch_to_kernel_stack ++0: ++ ++ ldp x0, x1, [sp, #16 * 0] ++ ldp x2, x3, [sp, #16 * 1] ++ ldp x4, x5, [sp, #16 * 2] ++ ldp x6, x7, [sp, #16 * 3] ++ ldp x8, x9, [sp, #16 * 4] ++ ldp x10, x11, [sp, #16 * 5] ++ ldp x12, x13, [sp, #16 * 6] ++ ldp x14, x15, [sp, #16 * 7] ++ ldp x16, x17, [sp, #16 * 8] ++ ldp x18, x30, [sp, #16 * 9] ++ add sp, sp, #160 ++ ret ++SYM_FUNC_END(koi_switch_to_kernel_pgtbl) ++.popsection ++#endif ++ + .macro kernel_ventry, el:req, ht:req, regsize:req, label:req + .align 7 + .Lventry_start\@: +@@ -151,6 +529,17 @@ alternative_else_nop_endif + #endif + .endm + ++#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) ++#endif ++ + /* Clear the MTE asynchronous tag check faults */ + .macro clear_mte_async_tcf thread_sctlr + #ifdef CONFIG_ARM64_MTE +@@ -224,6 +613,14 @@ alternative_cb_end + ldr_this_cpu tsk, __entry_task, x20 + msr sp_el0, tsk + ++#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 ++ + /* + * Ensure MDSCR_EL1.SS is clear, since we can unmask debug exceptions + * when scheduling. +@@ -276,6 +673,13 @@ alternative_else_nop_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 +737,11 @@ alternative_else_nop_endif + .endm + + .macro kernel_exit, el ++ #ifndef CONFIG_IEE + .if \el != 0 + disable_daif + .endif ++ #endif + + #ifdef CONFIG_ARM64_PSEUDO_NMI + alternative_if_not ARM64_HAS_GIC_PRIO_MASKING +@@ -411,6 +817,50 @@ alternative_else_nop_endif + + msr elr_el1, x21 // set up the return data + msr spsr_el1, x22 ++ ++#ifdef CONFIG_IEE ++ ++ .if \el == 0 ++ ++ #ifndef CONFIG_UNMAP_KERNEL_AT_EL0 ++ // SET hpd1 = 0 start ++ mrs x0, tcr_el1 ++ and x0, x0, #0xFFFFFBFFFFFFFFFF ++ and x0, x0, #0xFFFFFFFFFFBFFFFF ++ msr tcr_el1, x0 ++ // SET hpd1 = 0 end ++ ++ disable_daif ++ ++ // Check ELR_EL1 ++ mrs x0, elr_el1 ++ lsr x0, x0, #48 ++ tst x0, #0xffff ++ b.ne 5f ++ #endif ++ ++ // write dbg ctrl registers for breakpoint 0 to serve user ptrace. ++ //mrs x5, afsr0_el1 ++ //cbz x5, 1145f // skip if not used by user ++ //ldr_this_cpu x1, iee_si_user_bvr0, x2 ++ //ldr_this_cpu x3, iee_si_user_bcr0, x4 ++ //msr dbgbvr0_el1, x1 ++ //msr dbgbcr0_el1, x3 ++1145: ++ ++ .endif ++ ++#else ++#ifdef CONFIG_KOI ++ .if \el==0 ++ mrs x0, tcr_el1 ++ and x0, x0, #0xFFFFFFFFFFBFFFFF ++ msr tcr_el1,x0 ++ .endif ++#endif ++ ++#endif ++ + ldp x0, x1, [sp, #16 * 0] + ldp x2, x3, [sp, #16 * 1] + ldp x4, x5, [sp, #16 * 2] +@@ -447,6 +897,17 @@ alternative_else_nop_endif + add sp, sp, #PT_REGS_SIZE // restore sp + br x29 + #endif ++ ++#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 +@@ -565,12 +1026,193 @@ SYM_CODE_START_LOCAL(__bad_stack) + SYM_CODE_END(__bad_stack) + #endif /* CONFIG_VMAP_STACK */ + ++/* ++ * iee exception entry ++ */ ++ .macro iee_exception_entry, el ++ ++ /* skip setting breakpoint 0 if user hasn't change it. */ ++ //.if \el == 0 ++ //mrs x0, afsr0_el1 ++ //cbz x0, 1148f ++ //.endif ++ ++ //b 1147f ++ /* enable breakpoint 0 to proctect iee rwx gate */ ++ //adrp x1, iee_rwx_gate_entry ++ //add x1, x1, #:lo12:iee_rwx_gate_entry ++#ifdef CONFIG_KOI ++ //add x1, x1, #120 ++#else ++ //add x1, x1, #36 ++#endif ++1145: ++ //msr dbgbvr0_el1, x1 ++ //mov x2, 0x21e7 ++1146: ++ //msr dbgbcr0_el1, x2 ++ //isb ++ ++1147: ++ /* check val of dbg ctrl registers */ ++ //mrs x3, dbgbvr0_el1 ++ //adrp x1, iee_rwx_gate_entry ++ //add x1, x1, #:lo12:iee_rwx_gate_entry ++#ifdef CONFIG_KOI ++ //add x1, x1, #120 ++#else ++ //add x1, x1, #36 ++#endif ++ //cmp x1, x3 ++ //bne 1145b ++ //mov x2, 0x21e7 ++ //mrs x0, dbgbcr0_el1 ++ //cmp x2, x0 ++ //bne 1146b ++ //enable_dbg ++1148: ++ ++ /* el0 set hpds */ ++ .if \el == 0 ++ ++ #ifndef CONFIG_UNMAP_KERNEL_AT_EL0 ++ /* SET hpd1 = 1 start */ ++ mrs x0, tcr_el1 ++ orr x0, x0, #0x0000040000000000 ++ orr x0, x0, #0x0000000000400000 ++ msr tcr_el1, x0 ++ /* SET hpd1 = 1 end */ ++ ++ disable_daif ++ ++ /* Check TCR_EL1 */ ++ mrs x0, tcr_el1 ++ tst x0, #0x0000040000000000 ++ b.eq 5f ++ tst x0, #0x0000000000400000 ++ b.ne 6f ++ ++5: ++ /* TCR_EL1 check fail */ ++ mov x0, sp ++ mov x1, #BAD_TCR_EL1 ++ mrs x2, esr_el1 ++ bl iee_bad_mode ++ ASM_BUG() ++ ++6: ++ nop ++ #endif ++ ++ .else ++#ifdef CONFIG_IEE_INTERRUPTABLE ++ /* el1 save elr_el1 and set pan */ ++ /* Check ELR_EL1 */ ++ ldr x1, =__iee_code_start ++ cmp x1, x22 ++ b.hi 7f ++ ldr x1, =__iee_code_end ++ cmp x1, x22 ++ b.lo 7f ++ /* Exception from iee code */ ++ /* Switch to kernel stack */ ++ mrs x0, sp_el0 /* x0 -> task_struct(VA) */ ++ adrp x2, iee_offset ++ ldr x2, [x2, #:lo12:iee_offset] ++ add x1, x0, x2 /* x1 -> task_token(IEE) */ ++ // store iee stack ++ mov x3, sp ++ str x3, [x1, #iee_from_token_offset] ++ // load kernel stack ++ ldr x3, [x1, #kernel_from_token_offset] ++ mov sp, x3 ++ sub sp, sp, #PT_REGS_SIZE ++ /* Enable PAN */ ++ msr pan, #0x1 ++ ++7: ++ /* Exception from kernel code */ ++ mov x0, #0x0 ++ mov x1, #0x0 ++ mov x2, #0x0 ++ mov x3, #0x0 ++#endif ++ .endif ++ .endm ++ ++/* ++ * iee exception exit ++ */ ++ .macro iee_exception_exit, el ++ // Disable daif ++ disable_daif ++ ++ .if \el == 1 ++#ifdef CONFIG_IEE_INTERRUPTABLE ++ /* el1 pop elr_el1 and set pan */ ++ /* Check ELR_EL1 */ ++ ldr x1, =__iee_code_start ++ cmp x1, x22 ++ b.hi 9f ++ ldr x1, =__iee_code_end ++ cmp x1, x22 ++ b.lo 9f ++ /* Eret iee code */ ++ /* Disable PAN */ ++ msr pan, #0x0 ++ /* Switch to iee stack */ ++ add sp, sp, #PT_REGS_SIZE ++ mrs x0, sp_el0 /* x0 -> task_struct */ ++ adrp x2, iee_offset ++ ldr x2, [x2, #:lo12:iee_offset] ++ add x1, x0, x2 /* x1 -> task_token(IEE) */ ++ // store kernel stack ++ mov x3, sp ++ str x3, [x1, #kernel_from_token_offset] ++ // load iee stack ++ ldr x2, [x1, #iee_from_token_offset] ++ mov sp, x2 ++ /* Load ELR_EL1 from iee stack */ ++ ldr x21, [sp, #S_PC] ++ /* Check the modify of ELR_EL1 */ ++ cmp x21, x22 ++ b.ne 8f ++ /* ELR_EL1 not modified */ ++ b 9f ++ ++8: ++ // ELR_EL1 modified ++ mov x0, sp ++ mov x1, #BAD_ELR_EL1 ++ mrs x2, esr_el1 ++ bl iee_bad_mode ++ ASM_BUG() ++ ++9: ++ // Eret kernel code ++ mov x0, #0x0 ++ mov x1, #0x0 ++ mov x2, #0x0 ++ mov x3, #0x0 ++#endif ++ .endif ++ .endm + + .macro entry_handler el:req, ht:req, regsize:req, label:req + SYM_CODE_START_LOCAL(el\el\ht\()_\regsize\()_\label) + kernel_entry \el, \regsize ++ ++ #ifdef CONFIG_IEE ++ iee_exception_entry \el ++ #endif ++ + mov x0, sp + bl el\el\ht\()_\regsize\()_\label\()_handler ++ ++ #ifdef CONFIG_IEE ++ iee_exception_exit \el ++ #endif ++ + .if \el == 0 + b ret_to_user + .else +@@ -840,6 +1482,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 +@@ -1029,6 +1678,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 ++#endif + + /* If we interrupted the kernel point to the previous stack/frame. */ + and x0, x3, #0xc +diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S +index 7b236994f0e1..b1ecb594c968 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. + * +@@ -656,6 +692,18 @@ 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 +@@ -672,7 +720,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 +diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c +index 02870beb271e..02cdb79f8af7 100644 +--- a/arch/arm64/kernel/hibernate.c ++++ b/arch/arm64/kernel/hibernate.c +@@ -34,6 +34,10 @@ + #include + #include + ++#ifdef CONFIG_PTP ++#include ++#endif ++ + /* + * 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,6 +201,9 @@ 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; +@@ -207,6 +214,7 @@ static int create_safe_exec_page(void *src_start, size_t length, + if (rc) + return rc; + ++ // zgcXXX: lack a lot of things. + cpu_install_ttbr0(trans_ttbr0, t0sz); + *phys_dst_addr = virt_to_phys(page); + +diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c +index d39a8787edf2..b5ac4b7670bc 100644 +--- a/arch/arm64/kernel/hw_breakpoint.c ++++ b/arch/arm64/kernel/hw_breakpoint.c +@@ -26,6 +26,10 @@ + #include + #include + ++#ifdef CONFIG_IEE ++#include ++#endif ++ + /* Breakpoint currently in use for each BRP. */ + static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); + +@@ -102,13 +106,68 @@ int hw_breakpoint_slots(int type) + WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 15, REG, VAL) + ++#ifdef CONFIG_IEE ++ ++#define IEE_SI_READ_WB_REG_CASE(OFF, N, REG, VAL) \ ++ case (OFF + N): \ ++ IEE_SI_AARCH64_DBG_READ(N, REG, VAL); \ ++ break ++ ++#define IEE_SI_WRITE_WB_REG_CASE(OFF, N, REG, VAL) \ ++ case (OFF + N): \ ++ IEE_SI_AARCH64_DBG_WRITE(N, REG, VAL); \ ++ break ++ ++#define IEE_SI_GEN_READ_REG_CASES(OFF, REG, VAL) \ ++ IEE_SI_READ_WB_REG_CASE(OFF, 0, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 1, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 2, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 3, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 4, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 5, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 6, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 7, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 8, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 9, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 10, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 11, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 12, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 13, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 15, REG, VAL) ++ ++#define IEE_SI_GEN_WRITE_REG_CASES(OFF, REG, VAL) \ ++ IEE_SI_WRITE_WB_REG_CASE(OFF, 0, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 1, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 2, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 3, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 4, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 5, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 6, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 7, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 8, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 9, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 10, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 11, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 12, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 13, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ ++ WRITE_WB_REG_CASE(OFF, 15, REG, VAL) ++ ++#endif ++ + static u64 read_wb_reg(int reg, int n) + { + u64 val = 0; + + switch (reg + n) { ++// #ifdef CONFIG_IEE ++// IEE_SI_GEN_READ_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); ++// IEE_SI_GEN_READ_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); ++// #else + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); ++// #endif + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); + default: +@@ -122,8 +181,13 @@ NOKPROBE_SYMBOL(read_wb_reg); + static void write_wb_reg(int reg, int n, u64 val) + { + switch (reg + n) { ++// #ifdef CONFIG_IEE ++// IEE_SI_GEN_WRITE_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); ++// IEE_SI_GEN_WRITE_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); ++// #else + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); ++// #endif + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); + default: +@@ -171,6 +235,10 @@ static int is_a32_compat_bp(struct perf_event *bp) + return tsk && is_a32_compat_thread(task_thread_info(tsk)); + } + ++#ifdef CONFIG_IEE ++int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw); ++#endif ++ + /** + * hw_breakpoint_slot_setup - Find and setup a perf slot according to + * operations +@@ -191,6 +259,37 @@ static int hw_breakpoint_slot_setup(struct perf_event **slots, int max_slots, + { + int i; + struct perf_event **slot; ++// reserve hw breakpoint 0 for iee rwx gate in kernel sapce. ++// #ifdef CONFIG_IEE ++// struct arch_hw_breakpoint *info = counter_arch_bp(bp); ++// if (arch_check_bp_in_kernelspace(info)){ ++// for (i = 1; i < max_slots; ++i) { // search from hw breakpoint 1 ++// slot = &slots[i]; ++// switch (ops) { ++// case HW_BREAKPOINT_INSTALL: ++// if (!*slot) { ++// *slot = bp; ++// return i; ++// } ++// break; ++// case HW_BREAKPOINT_UNINSTALL: ++// if (*slot == bp) { ++// *slot = NULL; ++// return i; ++// } ++// break; ++// case HW_BREAKPOINT_RESTORE: ++// if (*slot == bp) ++// return i; ++// break; ++// default: ++// pr_warn_once("Unhandled hw breakpoint ops %d\n", ops); ++// return -EINVAL; ++// } ++// } ++// return -ENOSPC; ++// } ++// #endif + + for (i = 0; i < max_slots; ++i) { + slot = &slots[i]; +diff --git a/arch/arm64/kernel/iee/Makefile b/arch/arm64/kernel/iee/Makefile +new file mode 100644 +index 000000000000..123c68c5cc4e +--- /dev/null ++++ b/arch/arm64/kernel/iee/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_IEE) += iee.o iee-gate.o iee-func.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..8ef0b769af73 +--- /dev/null ++++ b/arch/arm64/kernel/iee/iee-func.c +@@ -0,0 +1,189 @@ ++#include "asm/pgtable.h" ++#include ++#include ++#include ++#include ++#include ++ ++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 < (((unsigned long)0xffff << 48) + IEE_OFFSET)) | (addr > (((unsigned long)0xffff8 << 44)))) ++ return; ++ ++ pte = __pte(pte_val(pte) | 0x1); ++ set_pte(ptep, pte); ++ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); ++ isb(); ++} ++ ++void set_iee_page_invalid(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 < (((unsigned long)0xffff << 48) + IEE_OFFSET)) | (addr > (((unsigned long)0xffff8 << 44)))) ++ return; ++ ++ pte = __pte(pte_val(pte) & ~0x1); ++ set_pte(ptep, pte); ++ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); ++ isb(); ++} ++ ++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 = pmd_offset(pudp, addr); ++ ++ pte_t *ptep = pte_offset_kernel(pmdp, addr); ++ pte_t pte = READ_ONCE(*ptep); ++ ++ if(addr < ((unsigned long)0xffff << 48)) ++ 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_logical_mem_rw(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 < ((unsigned long)0xffff << 48)) | (addr > ((unsigned long)0xffff4 << 44))) ++ return; ++ ++ pte = __pte(pte_val(pte) | PTE_DBM); ++ set_pte(ptep, pte); ++ flush_tlb_kernel_range(addr, addr+PAGE_SIZE); ++ isb(); ++} ++ ++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); ++ ++ p4d_t *p4dp = p4d_offset(pgdp, (unsigned long)token); ++ ++ pud_t *pudp = pud_offset(p4dp, (unsigned long)token); ++ ++ 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))); ++ set_pte(ptep, pte); ++ flush_tlb_kernel_range((unsigned long)token, (unsigned long)(token+PAGE_SIZE)); ++ isb(); ++} ++ ++void iee_set_token_page_invalid(void *token) ++{ ++ 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); ++ ++ 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)); ++ isb(); ++} ++ ++void iee_set_kernel_ppage(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); ++ ++ 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_ppage(ptep, pte); ++ ptep++; ++ } ++ flush_tlb_kernel_range(addr, addr+4*PAGE_SIZE); ++ isb(); ++} ++ ++void iee_set_kernel_upage(unsigned long 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; ++ ++ __p4d_populate(p4dp, __p4d_to_phys(p4d), PGD_APT | PUD_TYPE_TABLE); ++ for(i = 0; i < 4; i++) ++ { ++ pte_t pte = READ_ONCE(*ptep); ++ pte = __pte(pte_val(pte) | PTE_USER | PTE_NG); ++ iee_set_pte_upage(ptep, pte); ++ ptep++; ++ } ++ flush_tlb_kernel_range(addr, addr+4*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..b2e847995ff1 +--- /dev/null ++++ b/arch/arm64/kernel/iee/iee-gate.S +@@ -0,0 +1,231 @@ ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_IEE ++ ++SYM_FUNC_START(iee_rw_gate) ++ /* save daif, close irq */ ++ mrs x13, daif ++ msr daifset, #0x2 ++ isb ++ /* save lr */ ++ sub sp, sp, #16 ++ stp x29, x30, [sp] ++ bl iee_protected_rw_gate ++ /* restore lr */ ++ ldp x29, x30, [sp] ++ add sp, sp, #16 ++ /* restore daif */ ++ msr daif, x13 ++ ret ++SYM_FUNC_END(iee_rw_gate) ++#if defined(CONFIG_CREDP) || defined(CONFIG_KOI) ++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) */ ++ // store kernel stack ++ mov x10, sp ++ str x10, [x11, #kernel_from_token_offset] ++ // load iee stack ++ ldr x10, [x11, #iee_from_token_offset] ++ mov sp, x10 ++#ifdef CONFIG_IEE_INTERRUPTABLE ++ isb ++ /* restore daif */ ++ msr daif, x13 ++ sub sp, sp, #16 ++ stp x29, x30, [sp] ++#else ++ sub sp, sp, #16 ++ stp x13, x30, [sp] ++#endif ++ /* call iee func */ ++ bl iee_dispatch ++#ifdef CONFIG_IEE_INTERRUPTABLE ++ ldp x29, x30, [sp] ++ add sp, sp, #16 ++ /* store and disable daif */ ++ mrs x13, daif ++ msr daifset, #0x2 ++ isb ++#else ++ ldp x13, x30, [sp] ++ add sp, sp, #16 ++#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 ++ /* enable PAN */ ++ msr pan, #0x1 ++ ret ++SYM_FUNC_END(iee_protected_rw_gate) ++ ++ .popsection ++ ++#include ++#define BAD_IEE 3 ++ ++ .pushsection ".iee.exec_entry", "ax" ++ ++SYM_FUNC_START(iee_rwx_gate_entry) ++ /* Disable irq first. */ ++ mrs x15, daif // use x15 to restore daif ++ msr DAIFSet, #0x2 ++ ++ msr dbgbvr0_el1, xzr // clear breakpoint 0 ++ isb ++ ++ msr pan, #0 ++#ifdef CONFIG_KOI ++ cmp x0, #7 ++ b.lo 3f ++ ++ /* Use x13 to mark KOI switch branches. */ ++ mov x13, #1 ++ ++ /* Get ASID from ttbr0 to calculate ASID of TTBR1. */ ++ mrs x10, ttbr0_el1 ++ ubfx x12, x10, #48, #16 ++ /* ASID of ttbr0 must be odd number except 1 when KOI switch. */ ++ tbz x12, #0, error ++ cmp x12, #1 ++ b.eq error ++ bic x12, x12, #1 ++ ++ cmp x0, #7 ++ b.eq 2f ++ /* Branch of switching to KOI pgd. */ ++ /* TODO: verify the incomming pdg addr val. */ ++ mov x9, x1 ++ bfi x9, x12, #48, #16 ++ b 1f ++2: /* Branch of switching back to kernel. */ ++ adrp x9, iee_base_swapper_pg_dir ++ ldr x9, [x9, #:lo12:iee_base_swapper_pg_dir] ++ bfi x9, x12, #48, #16 ++ b 1f ++3: /* Branch of switching to IEE pgd. */ ++ mov x13, #0 ++#endif ++// trans va of iee_pg_dir to pa to switch ttbr1 ++ mrs x14, ttbr1_el1 // use x14 to restore ttbr1 ++ adrp x9, iee_base_iee_pg_dir ++ ldr x9, [x9, #:lo12:iee_base_iee_pg_dir] ++ movk x9, #1, lsl 48 ++1: ++ msr ttbr1_el1, x9 ++ isb ++ /* Reset dbgbvr0_el1 and check its value to prevent reuse attack */ ++4: ++ adr x9, 1b ++ msr dbgbvr0_el1, x9 // protect msr ttbr1 inst ++ isb ++ mrs x10, dbgbvr0_el1 ++ adr x11, 1b ++ cmp x10, x11 ++ b.ne 4b ++#ifdef CONFIG_KOI ++ cbz x13, 5f ++ /* Restore PAN and DAIF to end KOI switch */ ++ msr pan, #1 ++ msr daif, x15 ++ ret ++5: ++#endif ++ /* jump to iee si codes which are only visible to iee pgd. */ ++ b iee_rwx_gate_tramp ++error: ++/* ++ mov x0, sp ++ mov x1, #BAD_TTBR0_ASID ++ mrs x2, esr_el1 ++ bl iee_bad_mode ++*/ ++ ASM_BUG() ++SYM_FUNC_END(iee_rwx_gate_entry) ++EXPORT_SYMBOL(iee_rwx_gate_entry) ++ ++ .popsection ++ ++ .pushsection ".iee.si_text", "ax" ++ ++SYM_FUNC_START(iee_rwx_gate_tramp) ++ /* use x13 to store current stack */ ++ mov x13, sp ++ ++ /* If iee hasn't initialized, skip stack switch. */ ++ ldr x11, =iee_init_done; ++ ldr x10, [x11] ++ cbz x10, 1f ++ ++ /* 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) ++ // load iee stack ++ ldr x10, [x11, #iee_from_token_offset] ++ mov sp, x10 ++1: ++ str x13, [sp, #-16]! // Switch stack end ++ ++ /* In context switch, change x14 here to modify ASID of TTBR1 when iee exits */ ++ cmp w0, #6 // for IEE_CONTEXT_SWITCH ++ b.ne 2f ++ ubfx x10, x1, #48, #16 // get ASID field of incomming TTBR0 value. ++ bic x10, x10, #1 ++ bfi x14, x10, #48, #16 // insert new ASID to x14 ++ ++ /* x15 stores daif and x14 stores previous ttbr1 */ ++2: ++ stp x15, x14, [sp, #-32]! ++ stp x29, x30, [sp, #16] ++ bl iee_si_handler // enter actual handler ++ ldp x29, x30, [sp, #16] ++ ++ b iee_rwx_gate_exit // jump to iee exit ++SYM_FUNC_END(iee_rwx_gate_tramp) ++ ++ .popsection ++ ++ .pushsection ".iee.exec_exit", "ax" ++ ++SYM_FUNC_START(iee_rwx_gate_exit) ++ ldp x15, x14, [sp], #32 ++// switch to kernel stack ++ ldr x13, [sp], #16 ++ mov sp, x13 ++// switch end ++ msr pan, #1 ++ /* Switch back to kernel PGD. ASID maybe changed by iee_rwx_gate_tramp. */ ++ msr ttbr1_el1, x14 ++ isb ++ msr daif, x15 ++ isb ++ ret ++SYM_FUNC_END(iee_rwx_gate_exit) ++ ++ .popsection ++ ++#endif +diff --git a/arch/arm64/kernel/iee/iee.c b/arch/arm64/kernel/iee/iee.c +new file mode 100644 +index 000000000000..d73be9f005d3 +--- /dev/null ++++ b/arch/arm64/kernel/iee/iee.c +@@ -0,0 +1,1359 @@ ++#include "linux/sched.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_IEE ++extern struct cred init_cred; ++extern s64 memstart_addr; ++ ++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_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); ++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); ++#endif ++ ++/* 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); ++} ++ ++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_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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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; ++} ++ ++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; ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++ return (u64)_iee_set_cred_atomic_op_usage(cred, flag); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++void __iee_code iee_wrapper_free_token(va_list args) { ++ struct task_struct *tsk = va_arg(args, struct task_struct *); ++ _iee_free_token(tsk); ++} ++ ++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); ++} ++ ++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); ++} ++ ++#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); ++} ++ ++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); ++} ++ ++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); ++} ++ ++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, ++#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 ++#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; ++ } ++#endif ++ default: ++ { ++ #ifndef CONFIG_KOI ++ if((flag < IEE_WRITE_IN_BYTE) | (flag > IEE_WRITE_ENTRY_TASK)) ++ 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_KOI ++unsigned long __iee_code _iee_read_koi_stack(struct task_struct *tsk) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ return (unsigned long)token->koi_stack; ++} ++ ++void __iee_code _iee_write_koi_stack(struct task_struct *tsk, unsigned long koi_stack) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ token->koi_stack = koi_stack; ++} ++ ++unsigned long __iee_code _iee_read_token_ttbr1(struct task_struct *tsk) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ return token->current_ttbr1; ++} ++ ++void __iee_code _iee_write_token_ttbr1(struct task_struct *tsk, unsigned long current_ttbr1) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ token->current_ttbr1 = current_ttbr1; ++} ++ ++unsigned long __iee_code _iee_read_koi_kernel_stack(struct task_struct *tsk) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ return token->koi_kernel_stack; ++} ++ ++void __iee_code _iee_write_koi_kernel_stack(struct task_struct *tsk, unsigned long kernel_stack) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ token->koi_kernel_stack = kernel_stack; ++} ++ ++unsigned long __iee_code _iee_read_koi_stack_base(struct task_struct *tsk) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ return (unsigned long)token->koi_stack_base; ++} ++ ++void __iee_code _iee_write_koi_stack_base(struct task_struct *tsk, unsigned long koi_stack_base) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ 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) ++{ ++ // 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; ++} ++ ++unsigned long __iee_code _iee_read_token_stack(struct task_struct *tsk) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ return (unsigned long)token->iee_stack; ++} ++ ++void __iee_code _iee_free_token(struct task_struct *tsk) ++{ ++ _iee_memset(tsk, 0, sizeof(struct task_token)); ++} ++ ++#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) ++{ ++ 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 ++} ++ ++void __iee_code _iee_set_token_mm(struct task_struct *tsk, struct mm_struct *mm) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ token->mm = mm; ++} ++ ++void __iee_code _iee_set_token_pgd(struct task_struct *tsk, pgd_t *pgd) ++{ ++ struct task_token *token = (struct task_token *)__phys_to_iee(__pa(tsk)); ++ token->pgd = pgd; ++} ++ ++void __iee_code _iee_set_freeptr(freeptr_t *pptr, freeptr_t ptr) ++{ ++ pptr = (freeptr_t *)__phys_to_iee(__pa(pptr)); ++ *pptr = ptr; ++} ++ ++#pragma GCC push_options ++#pragma GCC optimize("O0") ++void __iee_code _iee_memset(void *ptr, int data, size_t n) ++{ ++ char *_ptr = (char *)__phys_to_iee(__pa(ptr)); ++ ++ while (n--) ++ *_ptr++ = data; ++} ++ ++void __iee_code _iee_memcpy(void *dst, void *src, size_t n) ++{ ++ char *_dst = (char *)__phys_to_iee(__pa(dst)); ++ char *_src = (char *)src; ++ ++ while(n--) ++ *_dst++ = *_src++; ++} ++#pragma GCC pop_options ++ ++void __iee_code _iee_set_track(struct track *ptr, struct track *data) ++{ ++ _iee_memcpy(ptr, data, sizeof(struct track)); ++} ++ ++void __iee_code _iee_set_cred_rcu(struct cred *cred, struct rcu_head *rcu) ++{ ++ 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 ++} ++ ++void __iee_code _iee_set_cred_security(struct cred *cred, void *security) ++{ ++ 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; ++} ++ ++bool __iee_code _iee_set_cred_atomic_op_usage(struct cred *cred, int flag) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ switch (flag) ++ { ++ case AT_INC: { ++ atomic_long_inc(&cred->usage); ++ return 0; ++ } ++ case AT_INC_NOT_ZERO: { ++ return atomic_long_inc_not_zero(&cred->usage); ++ } ++ case AT_DEC_AND_TEST: { ++ return atomic_long_dec_and_test(&cred->usage); ++ } ++ } ++ return 0; ++} ++ ++void __iee_code _iee_set_cred_atomic_set_usage(struct cred *cred, int i) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ atomic_long_set(&cred->usage,i); ++} ++ ++void __iee_code _iee_set_cred_non_rcu(struct cred *cred, int non_rcu) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->non_rcu = non_rcu; ++} ++ ++void __iee_code _iee_set_cred_session_keyring(struct cred *cred, struct key *session_keyring) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->session_keyring = session_keyring; ++} ++ ++void __iee_code _iee_set_cred_process_keyring(struct cred *cred, struct key *process_keyring) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->process_keyring = process_keyring; ++} ++ ++void __iee_code _iee_set_cred_thread_keyring(struct cred *cred, struct key *thread_keyring) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->thread_keyring = thread_keyring; ++} ++ ++void __iee_code _iee_set_cred_request_key_auth(struct cred *cred, struct key *request_key_auth) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->request_key_auth = request_key_auth; ++} ++ ++void __iee_code _iee_set_cred_jit_keyring(struct cred *cred, unsigned char jit_keyring) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->jit_keyring = jit_keyring; ++} ++ ++void __iee_code _iee_set_cred_cap_inheritable(struct cred *cred, kernel_cap_t cap_inheritable) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->cap_inheritable = cap_inheritable; ++} ++ ++void __iee_code _iee_set_cred_cap_permitted(struct cred *cred, kernel_cap_t cap_permitted) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->cap_permitted = cap_permitted; ++} ++ ++void __iee_code _iee_set_cred_cap_effective(struct cred *cred, kernel_cap_t cap_effective) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->cap_effective = cap_effective; ++} ++ ++void __iee_code _iee_set_cred_cap_bset(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_cred_cap_ambient(struct cred *cred, kernel_cap_t cap_ambient) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->cap_ambient = cap_ambient; ++} ++ ++void __iee_code _iee_set_cred_securebits(struct cred *cred, unsigned securebits) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->securebits = securebits; ++} ++ ++void __iee_code _iee_set_cred_group_info(struct cred *cred, struct group_info *group_info) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->group_info = group_info; ++} ++ ++void __iee_code _iee_set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->user_ns = user_ns; ++} ++ ++void __iee_code _iee_set_cred_user(struct cred *cred, struct user_struct *user) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->user = user; ++} ++ ++void __iee_code _iee_set_cred_fsgid(struct cred *cred, kgid_t fsgid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->fsgid = fsgid; ++} ++ ++void __iee_code _iee_set_cred_fsuid(struct cred *cred, kuid_t fsuid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->fsuid = fsuid; ++} ++ ++void __iee_code _iee_set_cred_egid(struct cred *cred, kgid_t egid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->egid = egid; ++} ++ ++void __iee_code _iee_set_cred_euid(struct cred *cred, kuid_t euid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->euid = euid; ++} ++ ++void __iee_code _iee_set_cred_sgid(struct cred *cred, kgid_t sgid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->sgid = sgid; ++} ++ ++void __iee_code _iee_set_cred_suid(struct cred *cred, kuid_t suid) ++{ ++ cred = (struct cred *)__phys_to_iee(__pa(cred)); ++ cred->suid = suid; ++} ++ ++void __iee_code _iee_copy_cred(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(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; ++} ++ ++void __iee_code _iee_write_in_byte(void *ptr, __u64 data, int length) ++{ ++ ptr = (void *)__phys_to_iee(__pa(ptr)); ++ 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; ++ } ++ } ++} ++ ++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) ++{ ++ WRITE_ONCE(*((pgd_t *)(__phys_to_iee(__pa_symbol(pgdp)))), pgd); ++} ++ ++void __iee_code _iee_set_swapper_pgd(pgd_t *pgdp, pgd_t pgd) ++{ ++ if(!(pgd_val(pgd) & PMD_SECT_VALID)) ++ { ++ WRITE_ONCE(*((pgd_t *)(__phys_to_iee(__pa_symbol(pgdp)))), pgd); ++ return; ++ } ++ ++ 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, (unsigned long)0xffff4 << 44)) && (pgdp < pgd_offset_pgd((pgd_t *)swapper_pg_dir, (unsigned long)0xffff8 << 44)) && !(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)) ++ { ++ WRITE_ONCE(*((p4d_t *)(__phys_to_iee(__pa(p4dp)))), p4d); ++ return; ++ } ++ ++ 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) ++{ ++ if(!(pud_val(pud) & PMD_SECT_VALID)) ++ { ++ WRITE_ONCE(*((pud_t *)(__phys_to_iee(__pa(pudp)))), pud); ++ return; ++ } ++ ++ 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) ++ { ++ 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)); ++ } ++ } ++ 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) ++{ ++ 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 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++) ++ { ++ if(check_addr_in_iee_valid(addr + PAGE_SIZE * i)) ++ return true; ++ } ++ 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)) ++ { ++ WRITE_ONCE(*((pmd_t *)(__phys_to_iee(__pa(pmdp)))), pmd); ++ return; ++ } ++ ++ // 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) ++{ ++ return false; ++} ++ ++// 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; ++ ++ if((pte_val(*ptep) & PTE_VALID)) ++ { ++ if((pte_val(*ptep) & PTE_USER) != (pte_val(pte) & PTE_USER)) ++ panic("Incorrectly change privilage.\n"); ++ } ++ else ++ { ++ if((pte_val(pte) & PTE_USER) && is_kernel_pte_table(ptep, pte)) ++ panic("Add new U page in kernel space.\n"); ++ } ++ 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) ++{ ++ return true; ++} ++ ++// Return true if it is only changing prot of a pte. ++static inline bool is_changing_pte_prot(pte_t *ptep, pte_t pte) ++{ ++ if(((pte_val(*ptep) ^ pte_val(pte)) & PTE_ADDR_MASK) == 0) ++ return true; ++ else ++ return false; ++} ++ ++// Return true if the modify does not break DEP. ++static inline bool check_pte_dep(char *addr, pte_t pte) ++{ ++ // 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; ++} ++ ++void __iee_code _iee_set_pte(pte_t *ptep, pte_t pte) ++{ ++ char * addr = (char *)__phys_to_kimg(__pte_to_phys(pte)); ++ ++ if(!(pte_val(pte) & PTE_VALID)) ++ { ++ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa(ptep)))), pte); ++ return; ++ } ++ ++ // 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 *)(__phys_to_iee(__pa(ptep)))), pte); ++} ++ ++// Return true if it only sets U page and modify NG. ++static inline bool is_setting_upage(pte_t *ptep, pte_t pte) ++{ ++ 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; ++} ++ ++void __iee_code _iee_set_pte_upage(pte_t *ptep, pte_t pte) ++{ ++ // Check if it only change the prot. ++ if(!is_setting_upage(ptep,pte)) ++ panic("Incorrectly setting U page.\n"); ++ ++ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa(ptep)))), pte); ++} ++ ++// Return true if it only sets P page and modify NG. ++static inline bool is_setting_ppage(pte_t *ptep, pte_t pte) ++{ ++ 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; ++} ++ ++void __iee_code _iee_set_pte_ppage(pte_t *ptep, pte_t pte) ++{ ++ // Check if it only change the prot. ++ if(!is_setting_ppage(ptep,pte)) ++ panic("Incorrectly setting P page.\n"); ++ ++ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa(ptep)))), pte); ++} ++ ++void __iee_code _iee_set_bm_pte(pte_t *ptep, pte_t pte) ++{ ++ WRITE_ONCE(*((pte_t *)(__phys_to_iee(__pa_symbol(ptep)))), pte); ++} ++ ++/* 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_base; ++unsigned long iee_base_iee_pg_dir __iee_si_base; ++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; ++ ++DEFINE_PER_CPU(unsigned long, iee_si_user_bvr0); ++DEFINE_PER_CPU(unsigned long, iee_si_user_bcr0); ++EXPORT_SYMBOL(iee_si_user_bvr0); ++EXPORT_SYMBOL(iee_si_user_bcr0); ++ ++// unsigned long iee_base_kimage_voffset __iee_si_base; ++// unsigned long iee_base_memstart_addr __iee_si_data; ++// /* replace __pa macro inside IEE rwx gate. */ ++// #define __iee_si_is_lm_address(addr) (((u64)(addr) ^ PAGE_OFFSET) < (PAGE_END - PAGE_OFFSET)) ++// #define __iee_si_lm_to_phys(addr) (((addr) & ~PAGE_OFFSET) + iee_base_memstart_addr) ++// #define __iee_si_kimg_to_phys(addr) ((addr) - iee_base_kimage_voffset) ++ ++// #define __iee_si_virt_to_phys(x) ({ ++// __iee_si_is_lm_address(x) ? __iee_si_lm_to_phys(x) : __iee_si_kimg_to_phys(x); ++// }) ++// #define __iee_si_pa(x) __iee_si_virt_to_phys((unsigned long)(x)) ++ ++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; ++ ++ // 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; ++ ++ // Check ASID first ++ if (new_asid!=0 && (new_asid == 1 || new_asid % 2 ==0)) ++ panic("IEE SI warning: TTBR0 ASID invalid: %llx:%llx", new_asid, new_val); ++ // TO DO: operations to protect idmap_pg_dir ++ if (new_phys == iee_base_idmap_pg_dir) ++ { ++ printk("IEE SI: switch to idmap_pg_dir."); ++ } ++ ++ /* 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); ++ 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; ++ } ++ /* To protect IEE rwx gate by DBG Breakpoint 0 */ ++ case IEE_WRITE_AFSR0: { ++ u64 user_bcr0; ++ /* iee_si_user_bcr0 = 0 means user proc doesn't use breakpoint 0 */ ++ user_bcr0 = this_cpu_read(iee_si_user_bcr0); ++ if (user_bcr0 == 0) ++ write_sysreg(1, afsr0_el1); ++ else ++ write_sysreg(0, afsr0_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/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") ++ ++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 ++ ++__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 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; ++}; ++ ++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_ko_stack); ++EXPORT_SYMBOL(koi_do_switch_to_kernel_stack); ++ ++extern unsigned long long iee_rw_gate(int flag, ...); ++ ++/** ++* 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_rcu (koi_mem_htbl, bkt, ko, node) { ++ if (ko->mod == mod) { ++ ko_mm = ko->ko_mm; ++ 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) ++{ ++ 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); ++} ++ ++#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; ++ 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; ++ } ++ } ++ rcu_read_unlock(); ++ return 0; ++} ++/** ++* koi_do_switch_to_kernel_pgtbl - switch to kernel pagetable ++*/ ++__koi_code noinline int koi_do_switch_to_kernel_pgtbl(void) ++{ ++ 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; ++ 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; ++ } ++ } ++ rcu_read_unlock(); ++ return 0; ++} ++ ++__koi_code noinline int koi_do_switch_to_kernel_pgtbl(void) ++{ ++ 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; ++ } ++ 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; ++} ++/** ++*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 NULL; ++ } ++ ++check_pfn: ++ return pfn_to_page(pfn); ++} ++ ++/** ++ * 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) ++{ ++ pte_t pte = *src_pte; ++ struct page *page; ++ ++ page = koi_normal_page(pte); ++ if (!page) { ++ printk(KERN_ERR "pte_page unavailable. Impossible.....\n"); ++ return -1; ++ } ++ ++ 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; ++ ++ src_ptl = pmd_lockptr(&init_mm, src_pmd); ++ spin_lock_bh(src_ptl); ++ ++ ret = -EAGAIN; ++ pmd = *src_pmd; ++ ++ set_pte((pte_t *)dst_pmd, pmd_pte(pmd)); ++ ret = 0; ++ spin_unlock_bh(src_ptl); ++ return ret; ++} ++ ++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; ++ ++ /* ++ * 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 ? */ ++ #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; ++ } ++ spin_unlock_bh(ptl); ++ if (new) ++ pte_free(mm, new); ++ return 0; ++} ++ ++#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_map(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) ++{ ++ 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(); ++ ++ 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; ++ ++ smp_wmb(); /* See comment in __pte_alloc */ ++ ++ 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; ++} ++ ++static inline pmd_t *koi_pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) ++{ ++ 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) ++{ ++ 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; ++ } ++ 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; ++} ++ ++int __koi_pud_alloc(struct mm_struct *mm, p4d_t *p4d, unsigned long address) ++{ ++ 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; ++} ++ ++static inline pud_t *koi_pud_alloc(struct mm_struct *mm, p4d_t *p4d, ++ unsigned long address) ++{ ++ return (unlikely(p4d_none(*p4d)) && __koi_pud_alloc(mm, p4d, address)) ? ++ NULL : pud_offset(p4d, address); ++} ++ ++/** ++*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) ++{ ++ 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 */ ++ } ++ 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; ++} ++ ++/** ++* 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) ++{ ++ 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; ++} ++ ++/** ++*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; ++ ++ pgd_t *src_pgd, *dst_pgd; ++ ++ 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); ++ ++ return ret; ++} ++ ++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; ++ } ++ ++ p4dp = p4d_offset(pgdp, addr); ++ if (p4d_none(*p4dp) || p4d_bad(*p4dp)) { ++ return; ++ } ++ ++ 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; ++ } ++ ++ ptep = pte_offset_kernel(pmdp, addr); ++ if (pte_none(*ptep)) { ++ printk(KERN_ERR "ptep 0x%llx not available\n", ptep); ++ return; ++ } ++ 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) ++{ ++ 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); ++#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); ++ ++ // 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); ++ ++ // 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); ++ ++ 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); ++ } ++ ++ 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); ++ } ++ ++#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); ++#endif ++ ++ // 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); ++ ++ 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; ++ ++ 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(&new_node->spin_lock); ++ list_add_rcu(&new_mem_node->list, &new_node->mem_list_head); ++ spin_unlock(&new_node->spin_lock); ++ ++ 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); ++} ++/** ++* 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) ++{ ++ 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); ++ } ++ ++ 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; ++} ++EXPORT_SYMBOL(koi_mem_alloc); ++// find the parameter pointer corresponding to the copy ++noinline void *koi_mem_lookup(struct module *mod, unsigned long addr) ++{ ++ 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; ++ } ++ ++ 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; ++ } ++} ++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, ...) ++{ ++ 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; ++ } ++ ++ 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); ++ ++ 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); ++} ++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 *)) ++{ ++ 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; ++ } ++ ++ 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); ++ } ++ ++ 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); ++ ++void koi_map_mem(struct module *mod, unsigned long addr, unsigned long size) ++{ ++ 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(); ++ ++ 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); ++} ++EXPORT_SYMBOL(koi_map_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) ++{ ++ 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; ++ } ++ ++ 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; ++ } ++ ++ 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); ++} ++EXPORT_SYMBOL(koi_mem_free_to_user); ++// map the driver stack to kernel ++void koi_map_kostack(struct module *mod) ++{ ++ 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; ++ } ++#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; ++ } ++ } ++ 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); ++} ++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 4edecaac8f91..6c25c1e7895d 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..82240fc6c421 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 + } + + /* +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..11ff7d3f4392 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,32 @@ 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_pgd_early(void) ++{ ++ /* prepare data used for iee rwx gate. */ ++ iee_base_swapper_pg_dir = phys_to_ttbr(__pa_symbol(swapper_pg_dir)); ++ iee_base_iee_pg_dir = phys_to_ttbr(__pa_symbol(iee_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)); ++ iee_base__bp_harden_el1_vectors = (unsigned long)__bp_harden_el1_vectors; ++ // copy init_pg_dir totoally to simplify ttbr1 switch in iee rwx gate. ++ memcpy(iee_pg_dir, init_pg_dir, PAGE_SIZE); ++} ++#endif ++ + 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()) | 0x2); ++ #endif ++ + *cmdline_p = boot_command_line; + + kaslr_init(); +@@ -371,6 +398,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_pgd_early(); ++#endif ++ + /* + * 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..cad7b0a5dd09 100644 +--- a/arch/arm64/kernel/traps.c ++++ b/arch/arm64/kernel/traps.c +@@ -902,6 +902,31 @@ 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" ++}; ++ ++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..58785cd99a4b 100644 +--- a/arch/arm64/kernel/vmlinux.lds.S ++++ b/arch/arm64/kernel/vmlinux.lds.S +@@ -134,6 +134,56 @@ 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_base_start = .; \ ++ *(.iee.si_base) \ ++ . = ALIGN(PAGE_SIZE); \ ++ __iee_exec_entry_start = .; \ ++ *(.iee.exec_entry) \ ++ . = ALIGN(PAGE_SIZE); \ ++ __iee_exec_entry_end = .; \ ++ __iee_si_text_start = .; \ ++ *(.iee.si_text) \ ++ . = ALIGN(PAGE_SIZE); \ ++ __iee_si_data_start = .; \ ++ *(.iee.si_data) \ ++ . = ALIGN(PAGE_SIZE); \ ++ __iee_si_data_end = .; \ ++ . += PAGE_SIZE - (20); \ ++ __iee_exec_exit = .; \ ++ __iee_exec_exit_pg = . + (20); \ ++ *(.iee.exec_exit) \ ++ . = ALIGN(PAGE_SIZE); \ ++ __iee_exec_exit_end = .; ++#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 +226,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) + } + +@@ -223,6 +276,11 @@ SECTIONS + swapper_pg_dir = .; + . += PAGE_SIZE; + ++#ifdef CONFIG_IEE ++ iee_pg_dir = .; ++ . += PAGE_SIZE; ++#endif ++ + . = ALIGN(SEGMENT_ALIGN); + __init_begin = .; + __inittext_begin = .; +@@ -318,6 +376,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 = .; ++ ++ . = 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..a72a3382b045 100644 +--- a/arch/arm64/mm/context.c ++++ b/arch/arm64/mm/context.c +@@ -17,6 +17,10 @@ + #include + #include + ++#ifdef CONFIG_IEE ++#include ++#endif ++ + 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; ++ ++ 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; ++ } ++ ++ 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 +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,31 @@ 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); ++ // ttbr1 &= ~TTBR_ASID_MASK; ++ // ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); ++ iee_rwx_gate_entry(IEE_CONTEXT_SWITCH, ttbr0); ++ // TODO : IEE-SI ++ // 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(); + } + +@@ -375,11 +434,20 @@ 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); ++ } ++ #else ++ if (arm64_kernel_unmapped_at_el0()) { ++ num_available_asids /= 2; ++ if (pinned_asid_map) ++ set_kpti_asid_bits(pinned_asid_map); ++ } ++ #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 +468,10 @@ arch_initcall(asids_update_limit); + + static int asids_init(void) + { ++ #if defined(CONFIG_IEE) || defined(CONFIG_KOI) ++ unsigned int len; ++ #endif ++ + asid_bits = get_cpu_asid_bits(); + atomic64_set(&asid_generation, ASID_FIRST_VERSION); + asid_map = bitmap_zalloc(NUM_USER_ASIDS, GFP_KERNEL); +@@ -410,6 +482,10 @@ 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); ++ #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 +493,8 @@ static int asids_init(void) + */ + if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) + set_kpti_asid_bits(asid_map); ++ #endif ++ + return 0; + } + early_initcall(asids_init); +diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c +index c376e58e8cf0..d5b4f48cd616 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 */ +diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c +index c0a3301203bd..cccb9a7716ba 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 ++ ++#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); ++ ++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 ++ + 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 ++ } + + 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; ++ ++ BUG_ON(idx <= FIX_HOLE || idx >= __end_of_fixed_addresses); ++ ++ ptep = fixmap_pte(addr); ++ ++ 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 ++ + /* + * 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..729df5277d1d 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 ++#ifdef CONFIG_IEE ++s64 iee_offset __ro_after_init = -1; ++#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) > 1ULL << 46) ++ panic("Image on too high phys mem.\n"); ++ else ++ memblock_remove(1ULL << 46, 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)0x4 << 44); ++ #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 58d228de4808..33abc832b2ab 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 ++#ifdef CONFIG_IEE ++#include ++#include ++#include ++#endif + + #define NO_BLOCK_MAPPINGS BIT(0) + #define NO_CONT_MAPPINGS BIT(1) +@@ -76,8 +82,286 @@ 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_base_start[]; ++extern unsigned long __iee_exec_entry_start[]; ++extern unsigned long __iee_si_data_start[]; ++extern unsigned long __iee_si_data_end[]; ++extern unsigned long __iee_exec_exit_pg[]; ++extern unsigned long __iee_exec_exit_end[]; ++ ++extern void *bm_pte_addr; ++extern void *bm_pmd_addr; ++extern void *bm_pud_addr; ++ ++#ifdef CONFIG_PTP ++ ++/* 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(&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); ++} ++ ++void iee_set_p4d_pre_init(p4d_t *p4dp, p4d_t p4d) ++{ ++ 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(); ++} ++ ++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; ++ } ++#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(); ++ } ++} ++ ++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; ++ } ++#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(); ++ } ++} ++ ++ ++void __iee_p4d_populate_pre_init(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot) ++{ ++ iee_set_p4d_pre_init(p4dp, __p4d(__phys_to_p4d_val(pudp) | prot)); ++} ++ ++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 __iee_pmd_populate_pre_init(pmd_t *pmdp, phys_addr_t ptep, ++ pmdval_t prot) ++{ ++ iee_set_pmd_pre_init(pmdp, __pmd(__phys_to_pmd_val(ptep) | prot)); ++} ++ ++#define set_pgd_init(pgdptr, pgdval) iee_set_p4d_pre_init((p4d_t *)(pgdptr), (p4d_t) { pgdval }) ++ ++/* 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)); ++ ++ /* 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_fixmap_pud_pre_init(pudp, new_pud); ++ return 1; ++} ++ ++static int iee_pmd_set_huge_fixmap(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) ++{ ++ pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), mk_pmd_sect_prot(prot)); ++ ++ /* Only allow permission changes for now */ ++ if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)), ++ pmd_val(new_pmd))) ++ return 0; ++ ++ VM_BUG_ON(phys & ~PMD_MASK); ++ iee_set_fixmap_pmd_pre_init(pmdp, new_pmd); ++ return 1; ++} ++ ++static inline void __iee_pmd_populate_fixmap(pmd_t *pmdp, phys_addr_t ptep, ++ pmdval_t prot) ++{ ++ iee_set_fixmap_pmd_pre_init(pmdp, __pmd(__phys_to_pmd_val(ptep) | prot)); ++} ++ ++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)); ++} ++#endif /* END CONFIG_PTP*/ ++ ++void iee_set_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); ++ ++ /* ++ * 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 void __init iee_set_token_page_valid_pre_init(void *token, void *new) ++{ ++ 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); ++ ++ 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))); ++ iee_set_pte_pre_init(ptep, pte); ++ flush_tlb_kernel_range((unsigned long)token, (unsigned long)(token+PAGE_SIZE)); ++ isb(); ++} ++#endif /* END CONFIG_IEE*/ ++ ++#if defined(CONFIG_KOI) && !defined(CONFIG_IEE) ++int koi_add_page_mapping(unsigned long dst, unsigned long src) ++{ ++ 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; ++} ++ ++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; ++ ++ 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(); ++} ++#endif ++ + 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); +@@ -90,6 +374,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, +@@ -118,7 +403,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); + +@@ -126,11 +415,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 + */ ++ #ifdef CONFIG_PTP ++ pte_clear_fixmap_init(); ++ #else + pte_clear_fixmap(); ++ #endif + + return phys; + } + ++ + bool pgattr_change_is_safe(u64 old, u64 new) + { + /* +@@ -178,7 +472,11 @@ static void init_pte(pmd_t *pmdp, unsigned long addr, unsigned long end, + do { + pte_t old_pte = READ_ONCE(*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 +@@ -211,7 +509,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 +550,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 + + /* + * After the PMD entry has been populated once, we +@@ -289,7 +595,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 +655,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 + + /* + * After the PUD entry has been populated once, we +@@ -393,7 +707,6 @@ static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys, + 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, +@@ -413,194 +726,1419 @@ 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)); +- +- /* +- * 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); + +- __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)); + +-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)))); + +- __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, +- NO_CONT_MAPPINGS); ++ phys += PAGE_SIZE; ++ } while (ptep++, addr += PAGE_SIZE, addr != end); + +- /* flush the TLBs after updating live kernel mappings */ +- flush_tlb_kernel_range(virt, virt + size); ++ pte_clear_fixmap_init(); + } + +-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) + { +- __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); + +-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; + +-#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); ++ } ++ BUG_ON(pmd_bad(pmd)); + +-bool __ro_after_init kfence_early_init = !!CONFIG_KFENCE_SAMPLE_INTERVAL; ++ do { ++ pgprot_t __prot = prot; + +-/* 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); + +- 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); + } +-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) + { +- 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); ++ ++ 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 ++ */ ++ if (pud_sect_supported() && ++ ((addr | next | phys) & ~PUD_MASK) == 0 && ++ (flags & NO_BLOCK_MAPPINGS) == 0) { ++ iee_pud_set_huge_pre_init(pudp, phys, prot); ++ ++ /* ++ * 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); ++ ++ 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); ++ ++ /* ++ * 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); ++ 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 ++ 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 ++ ++ /* 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) ++{ ++ /* ++ * 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); ++} ++ ++#ifdef CONFIG_KFENCE ++ ++bool __ro_after_init kfence_early_init = !!CONFIG_KFENCE_SAMPLE_INTERVAL; ++ ++/* early_param() will be parsed before map_mem() below. */ ++static int __init parse_kfence_early_init(char *arg) ++{ ++ int val; ++ ++ if (get_option(&arg, &val)) ++ kfence_early_init = !!val; ++ ++#if IS_ENABLED(CONFIG_KFENCE_MUST_EARLY_INIT) ++ kfence_must_early_init = (val == -1) ? true : false; ++#endif ++ ++ return 0; ++} ++early_param("kfence.sample_interval", parse_kfence_early_init); ++ ++static phys_addr_t __init arm64_kfence_alloc_pool(void) ++{ ++ phys_addr_t kfence_pool; ++ ++ if (!kfence_early_init) ++ return 0; ++ ++ 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; ++ } ++ ++ /* Temporarily mark as NOMAP. */ ++ memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE); ++ ++ return kfence_pool; ++} ++ ++static void __init arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) ++{ ++ 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); ++} ++#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 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; ++ ++ /* ++ * 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(); ++ ++ if (can_set_direct_map()) ++ flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; ++ ++ #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 ++ */ ++ 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(pgdp, start, end, pgprot_tagged(PAGE_KERNEL), ++ flags); ++ } ++ ++ /* ++ * 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); ++ #else ++ __map_memblock(pgdp, kernel_start, kernel_end, ++ PAGE_KERNEL, NO_CONT_MAPPINGS); ++ #endif ++ memblock_clear_nomap(kernel_start, kernel_end - kernel_start); ++ arm64_kfence_map_pool(early_kfence_pool, pgdp); ++} ++ ++void mark_rodata_ro(void) ++{ ++ unsigned long section_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); ++ ++ 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) ++{ ++ 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); ++} ++ ++/* ++ * 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_text_idmap, vmlinux_iee_base, vmlinux_iee_code, ++ vmlinux_iee_data, 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_base_start, text_prot, &vmlinux_text, ++ 0, VM_NO_GUARD); ++ /* ++ * Cancel contiguous mappings of idmap and iee si sections to ++ * simplify modifications later. ++ */ ++ // map_kernel_segment(pgdp, __idmap_text_start, __iee_si_base_start, text_prot, &vmlinux_text_idmap, ++ // NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); ++ /* ++ * Map iee_si_base and iee_si_data as RW page, iee codes as NG page. ++ */ ++ map_kernel_segment(pgdp, __iee_si_base_start, __iee_exec_entry_start, SET_NG(PAGE_KERNEL), &vmlinux_iee_base, ++ NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); ++ map_kernel_segment(pgdp, __iee_exec_entry_start, __iee_si_data_start, SET_NG(text_prot), &vmlinux_iee_code, ++ NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); ++ map_kernel_segment(pgdp, __iee_si_data_start, __iee_si_data_end, SET_NG(PAGE_KERNEL), &vmlinux_iee_data, ++ NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD); ++ map_kernel_segment(pgdp, __iee_si_data_end, _etext, SET_NG(text_prot), &vmlinux_text_end, ++ NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, 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 __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; + +- 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; ++ 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); + } + +- /* Temporarily mark as NOMAP. */ +- memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE); ++ /* ++ * 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 int __init iee_si_set_page_attr(unsigned long addr, pteval_t attr) ++{ ++ 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); ++ pr_info("IEE: page access permission changed on address 0x%lx, curr pte val: 0x%lx", ++ addr, (unsigned long)pte_val(pte)); ++ if(attr & PTE_RDONLY) ++ pte = __pte((pte_val(pte) | PTE_RDONLY) & ~PTE_DBM); ++ pte = __pte(pte_val(pte) | attr); ++ if((pte_val(pte) & PTE_USER) && !(pte_val(*ptep) & PTE_USER)) ++ { ++ iee_set_pte_upage(ptep, __pte(pte_val(*ptep) | PTE_USER)); ++ set_pte(ptep, pte); ++ } ++ else ++ set_pte(ptep, pte); ++ pr_info("IEE: modified pte val: 0x%lx", (unsigned long)pte_val(pte)); ++ return 1; ++} ++ ++/* ++ * Copy one pte. Returns 0 if succeeded. ++ */ ++static inline int iee_si_copy_present_pte(pte_t *dst_pte, pte_t *src_pte, ++ unsigned long addr) ++{ ++ pte_t pte = *src_pte; ++ ++ // if ((pte_val(pte) & PTE_NG) == 0) { ++ // printk(KERN_ERR "global pte found: 0x%16llx\n", pte); ++ // } else { ++ // printk(KERN_ERR "non global pte found: 0x%16llx\n", pte); ++ // } ++ set_pte(dst_pte, pte); ++ /* Clear src pte after copy to hide this page from kernel. */ ++ printk("IEE: Copy src pte %lx to %lx done. Hiding it new...", (unsigned long)src_pte, (unsigned long)dst_pte); ++ set_pte(src_pte, __pte(0)); ++ return 0; ++} ++ ++/* ++ * copy huge pmd entry from kernel to iee. ++ */ ++static int __init iee_si_copy_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, ++ pmd_t *src_pmd, unsigned long addr) ++{ ++ pmd_t pmd; ++ int ret = -ENOMEM; ++ ++ ret = -EAGAIN; ++ pmd = *src_pmd; ++ mm_inc_nr_ptes(mm); ++ ++ set_pte((pte_t *)dst_pmd, pmd_pte(pmd)); ++ ret = 0; ++ return ret; ++} ++/* ++ * Allocate page table directory for IEE SI codes. ++ * Would do pmd_populate anyway and overwrite pmd entry. ++ */ ++static int __init __iee_si_pte_alloc_kernel(pmd_t *pmd) ++{ ++ unsigned long iee_addr; ++ pte_t *new = pte_alloc_one_kernel(&init_mm); ++ if (!new) ++ return -ENOMEM; ++ ++ smp_wmb(); /* See comment in __pte_alloc */ ++ ++ spin_lock(&init_mm.page_table_lock); ++ pmd_populate_kernel(&init_mm, pmd, new); ++ spin_unlock(&init_mm.page_table_lock); ++ return 0; ++} ++ ++#define iee_si_pte_alloc_kernel(pmd, address) \ ++ ((__iee_si_pte_alloc_kernel(pmd))? \ ++ NULL: pte_offset_kernel(pmd, address)) ++ ++/* ++ * Copy pte table from kernel mappings to iee mappings ++ */ ++static int __init iee_si_copy_pte_range(struct mm_struct *mm, pmd_t *dst_pmd, ++ pmd_t *src_pmd, unsigned long addr, unsigned long end) ++{ ++ pte_t *src_pte, *dst_pte; ++ unsigned long src_pte_t_pg, dst_pte_t_pg; ++ int ret = 0; ++again: ++ dst_pte = iee_si_pte_alloc_kernel(dst_pmd, addr); ++ if (!dst_pte) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ src_pte = pte_offset_kernel(src_pmd, addr); ++ ++ #ifdef CONFIG_PTP ++ // Get va of new and old pte table page. ++ dst_pte_t_pg = (unsigned long)__phys_to_iee(pmd_page_paddr(*dst_pmd)); ++ src_pte_t_pg = (unsigned long)__phys_to_iee(pmd_page_paddr(*src_pmd)); ++ // printk("IEE: src_pte_t:%lx, dst_pte_t:%lx", src_pte_t_pg, dst_pte_t_pg); ++ // Copy all content from source pte table. Disable pan to manipulate inside iee. ++ asm volatile("msr pan, #0"); ++ memcpy((void *)dst_pte_t_pg, (void *)src_pte_t_pg, PAGE_SIZE); ++ asm volatile("msr pan, #1"); ++ #else ++ // Get va of new and old pte table page. ++ dst_pte_t_pg = (unsigned long)__va(pmd_page_paddr(*dst_pmd)); ++ src_pte_t_pg = (unsigned long)__va(pmd_page_paddr(*src_pmd)); ++ // printk("IEE: src_pte_t:%lx, dst_pte_t:%lx", src_pte_t_pg, dst_pte_t_pg); ++ // Copy all content from source pte table. Disable pan to manipulate inside iee. ++ memcpy(dst_pte_t_pg, src_pte_t_pg, PAGE_SIZE); ++ #endif ++ ++ arch_enter_lazy_mmu_mode(); ++ do { ++ if (pte_none(*src_pte)) ++ continue; ++ if (unlikely(!pte_present(*src_pte))) { ++ continue; ++ } ++ ret = iee_si_copy_present_pte(dst_pte, src_pte, addr); ++ if (unlikely(ret == -EAGAIN)) ++ break; ++ } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end); ++ arch_leave_lazy_mmu_mode(); ++ ++ if (ret) { ++ WARN_ON_ONCE(ret != -EAGAIN); ++ ret = 0; ++ } ++ if (addr != end) ++ goto again; ++out: ++ return ret; ++} ++ ++#if defined(__PAGETABLE_PMD_FOLDED) || !defined(CONFIG_MMU) ++static inline int __iee_si_pmd_alloc(struct mm_struct *mm, pud_t *pud, ++ unsigned long address) ++{ ++ return 0; ++} ++#endif ++ ++#ifndef __PAGETABLE_PMD_FOLDED ++/* ++ * Allocate page middle directory for IEE SI codes. ++ * Would do pud_populate anyway and overwrite pud entry. ++ */ ++static int __init __iee_si_pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) ++{ ++ unsigned long iee_addr; ++ spinlock_t *ptl; ++ pmd_t *new = pmd_alloc_one(mm, address); ++ if (!new) ++ return -ENOMEM; ++ ++ smp_wmb(); /* See comment in __pte_alloc */ ++ ++ ptl = pud_lock(mm, pud); ++ #ifdef CONFIG_PTP ++ /* Valid iee mapping of the allocated page. */ ++ 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); ++ spin_unlock(ptl); ++ return 0; ++} ++#endif /* __PAGETABLE_PMD_FOLDED */ ++ ++static inline pmd_t *iee_si_pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) ++{ ++ return (__iee_si_pmd_alloc(mm, pud, address))? ++ NULL: pmd_offset(pud, address); ++} ++ ++/* ++ * Copy pmd table from kernel mappings to iee mappings ++ */ ++static inline int iee_si_copy_pmd_range(struct mm_struct *mm, pud_t *dst_pud, ++ pud_t *src_pud, unsigned long addr, ++ unsigned long end) ++{ ++ pmd_t *src_pmd, *dst_pmd; ++ unsigned long next, src_pmd_t_pg, dst_pmd_t_pg; ++ int err; ++ ++ dst_pmd = iee_si_pmd_alloc(mm, dst_pud, addr); ++ if (!dst_pmd) { ++ return -ENOMEM; ++ } ++ src_pmd = pmd_offset(src_pud, addr); ++ #ifdef CONFIG_PTP ++ // Get va of new and old pmd table page. ++ dst_pmd_t_pg = (unsigned long)__phys_to_iee(pud_page_paddr(*dst_pud)); ++ src_pmd_t_pg = (unsigned long)__phys_to_iee(pud_page_paddr(*src_pud)); ++ // printk("IEE: src_pmd_t:%lx, dst_pmd_t:%lx", src_pmd_t_pg, dst_pmd_t_pg); ++ // Copy all content from source pmd table. Disable pan to manipulate inside iee. ++ asm volatile("msr pan, #0"); ++ memcpy((void *)dst_pmd_t_pg, (void *)src_pmd_t_pg, PAGE_SIZE); ++ asm volatile("msr pan, #1"); ++ #else ++ // Get va of new and old pmd table page. ++ dst_pmd_t_pg = (unsigned long)__va(pud_page_paddr(*dst_pud)); ++ src_pmd_t_pg = (unsigned long)__va(pud_page_paddr(*src_pud)); ++ // printk("IEE: src_pmd_t:%lx, dst_pmd_t:%lx", src_pmd_t_pg, dst_pmd_t_pg); ++ // Copy all content from source pmd table. Disable pan to manipulate inside iee. ++ memcpy(dst_pmd_t_pg, src_pmd_t_pg, PAGE_SIZE); ++ #endif ++ 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 = iee_si_copy_huge_pmd(mm, dst_pmd, src_pmd, ++ addr); ++ if (err == -ENOMEM) ++ return -ENOMEM; ++ if (!err) ++ continue; ++ } ++ if (pmd_none_or_clear_bad(src_pmd)) { ++ continue; ++ } ++ if (iee_si_copy_pte_range(mm, dst_pmd, src_pmd, addr, next)) ++ return -ENOMEM; ++ } while (dst_pmd++, src_pmd++, addr = next, addr != end); ++ return 0; ++} ++ ++#if defined(__PAGETABLE_PUD_FOLDED) || !defined(CONFIG_MMU) ++static inline int __iee_si_pud_alloc(struct mm_struct *mm, p4d_t *p4d, ++ unsigned long address) ++{ ++ return 0; ++} ++#endif ++ ++#ifndef __PAGETABLE_PUD_FOLDED ++/* ++ * Allocate page upper directory for IEE SI codes. ++ * Would do p4d_populate anyway and overwrite p4d entry. ++ */ ++static int __init __iee_si_pud_alloc(struct mm_struct *mm, p4d_t *p4d, unsigned long address) ++{ ++ unsigned long iee_addr; ++ pud_t *new = pud_alloc_one(mm, address); ++ if (!new) ++ return -ENOMEM; ++ ++ smp_wmb(); /* See comment in __pte_alloc */ ++ ++ spin_lock(&mm->page_table_lock); ++ #ifdef CONFIG_PTP ++ /* Valid iee mapping of the allocated page. */ ++ iee_addr = __phys_to_iee(__pa(new)); ++ set_iee_page_valid(iee_addr); ++ iee_set_logical_mem_ro((unsigned long)new); ++ // printk("IEE: allocated new pud, set iee:%lx valid...", iee_addr); ++ #endif ++ mm_inc_nr_puds(mm); ++ // printk("IEE: populating to p4d, new val:%lx", new); ++ p4d_populate(mm, p4d, new); ++ spin_unlock(&mm->page_table_lock); ++ return 0; ++} ++#endif /* __PAGETABLE_PUD_FOLDED */ ++ ++static inline pud_t *iee_si_pud_alloc(struct mm_struct *mm, p4d_t *p4d, ++ unsigned long address) ++{ ++ return (__iee_si_pud_alloc(mm, p4d, address)) ? ++ NULL : pud_offset(p4d, address); ++} ++ ++/* ++ * Copy pud table from kernel mappings to iee mappings ++ */ ++static inline int iee_si_copy_pud_range(struct mm_struct *mm, p4d_t *dst_p4d, ++ p4d_t *src_p4d, unsigned long addr, ++ unsigned long end) ++{ ++ pud_t *src_pud, *dst_pud; ++ unsigned long next, src_pud_t_pg, dst_pud_t_pg; ++ dst_pud = iee_si_pud_alloc(mm, dst_p4d, addr); ++ if (!dst_pud) ++ return -ENOMEM; ++ src_pud = pud_offset(src_p4d, addr); ++ #ifdef CONFIG_PTP ++ // Get iee va of new and old PUD table page. ++ // printk("IEE: src_p4d_t:%lx, dst_p4d_t:%lx", src_p4d, dst_p4d); ++ dst_pud_t_pg = (unsigned long)__phys_to_iee(p4d_page_paddr(*dst_p4d)); ++ src_pud_t_pg = (unsigned long)__phys_to_iee(p4d_page_paddr(*src_p4d)); ++ // printk("IEE: src_pud_t:%lx, dst_pud_t:%lx", src_pud_t_pg, dst_pud_t_pg); ++ // Copy all content from source PUD table. Disable pan to manipulate inside iee. ++ asm volatile("msr pan, #0"); ++ memcpy((void *)dst_pud_t_pg, (void *)src_pud_t_pg, PAGE_SIZE); ++ asm volatile("msr pan, #1"); ++ #else ++ // Get iee va of new and old PUD table page. ++ // printk("IEE: src_p4d_t:%lx, dst_p4d_t:%lx", src_p4d, dst_p4d); ++ dst_pud_t_pg = (unsigned long)__va(p4d_page_paddr(*dst_p4d)); ++ src_pud_t_pg = (unsigned long)__va(p4d_page_paddr(*src_p4d)); ++ // printk("IEE: src_pud_t:%lx, dst_pud_t:%lx", src_pud_t_pg, dst_pud_t_pg); ++ // Copy all content from source PUD table. Disable pan to manipulate inside iee. ++ memcpy(dst_pud_t_pg, src_pud_t_pg, PAGE_SIZE); ++ #endif ++ do { ++ next = pud_addr_end(addr, end); ++ if (pud_trans_huge(*src_pud) || pud_devmap(*src_pud)) { ++ continue; ++ /* fall through */ ++ } ++ if (pud_none_or_clear_bad(src_pud)) ++ continue; ++ if (iee_si_copy_pmd_range(mm, dst_pud, src_pud, addr, next)) ++ return -ENOMEM; ++ } while (dst_pud++, src_pud++, addr = next, addr != end); ++ return 0; ++} ++ ++/** ++ * Copy mappings from kernel pagetables to iee pagetables level by level ++ * @mm: the corresponding mm_struct of the new pgd. ++ * @dst_pgd: destination pgd entry ++ * @src_pgd: source pgd entry ++ * @addr: the start address of protected zone ++ * @end: the end address of protected zone ++ */ ++static inline int iee_si_copy_p4d_range(struct mm_struct *mm, pgd_t *dst_pgd, ++ pgd_t *src_pgd, unsigned long addr, ++ unsigned long end) ++{ ++ p4d_t *src_p4d, *dst_p4d; ++ unsigned long next; ++ dst_p4d = p4d_alloc(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 (iee_si_copy_pud_range(mm, dst_p4d, src_p4d, addr, next)) { ++ return -ENOMEM; ++ } ++ } while (dst_p4d++, src_p4d++, addr = next, addr != end); ++ return 0; ++} ++ ++/** ++ * int iee_si_copy_and_clear - Copy mappings of given address range from kernel to iee, ++ * and clear them on kernel pgd to make the isolation. ++ * The given region would be protected and invisible to kernel. ++ * Remind that iee_pg_dir would reuse kernel pgtable entries so iee can access kernel easily. ++ * @mm: the corresponding mm_struct of the new pgd. if it is not init_mm then kernel would take ++ * this pgd as users. ++ * @src_pg_dir: original kernel pgd, swapper_pg_dir ++ * @addr: the starting address of protected area ++ * @end: the end address of protected area ++ */ ++static int __init iee_si_copy_and_clear(struct mm_struct *mm, pgd_t *src_pg_dir, ++ unsigned long addr, unsigned long end) ++{ ++ int ret = 0; ++ unsigned long next; ++ pgd_t *src_pgd, *dst_pgd; ++ // Copy all entries from src_pg_dir first to reuse the original mappings. ++ memcpy(iee_pg_dir, src_pg_dir, PAGE_SIZE); ++ ++ src_pgd = pgd_offset_pgd(src_pg_dir, addr); ++ dst_pgd = pgd_offset_pgd(iee_pg_dir, addr); ++ // printk("IEE: src_pgd:%lx, dst_pgd:%lx", src_pgd, dst_pgd); ++ do { ++ next = pgd_addr_end(addr, end); ++ if (pgd_none_or_clear_bad(src_pgd)) ++ continue; ++ if (unlikely(iee_si_copy_p4d_range(mm, dst_pgd, src_pgd, addr, ++ next))) { ++ ret = -ENOMEM; ++ break; ++ } ++ } while (dst_pgd++, src_pgd++, addr = next, addr != end); ++ ++ return ret; ++} ++ ++void inline iee_si_set_base_swapper_cnp(void) ++{ ++ /* phys_to_ttbr() zeros lower 2 bits of ttbr with 52-bit PA */ ++ if (system_supports_cnp()) { ++ iee_base_swapper_pg_dir |= TTBR_CNP_BIT; ++ } ++} ++ ++extern unsigned long __iee_si_text_start[]; ++extern unsigned long __iee_exec_exit_pg[]; ++ ++/* Remap protected area on iee pgd to achieve the isolation. */ ++void __init isolate_iee_si(void) ++{ ++ /* Modify page prot of iee si setions before copy mappings. */ ++ unsigned long va = (unsigned long)__iee_si_base_start; ++ iee_si_set_page_attr(va, PTE_PXN | PTE_UXN | PTE_USER | PTE_RDONLY | PTE_NG); ++ va = (unsigned long)__iee_si_data_start; ++ iee_si_set_page_attr(va, PTE_PXN | PTE_UXN | PTE_USER | PTE_RDONLY | PTE_NG); ++ ++ /* Build the isolation on two mappings. */ ++ if(iee_si_copy_and_clear(&init_mm, swapper_pg_dir,(unsigned long)__iee_si_text_start, ++ (unsigned long)__iee_exec_exit_pg) == 0) ++ pr_info("IEE: isolated region is built successfully."); ++} ++#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 < (((unsigned long)0xffff << 48) + IEE_OFFSET)) | (addr > (((unsigned long)0xffff8 << 44)))) ++ 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); + +- return kfence_pool; ++ 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 arm64_kfence_map_pool(phys_addr_t kfence_pool, pgd_t *pgdp) ++static void __init init_iee_for_one_region(pgd_t *pgdir, unsigned long va_start, unsigned long va_end) + { +- 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); +-} +-#else /* CONFIG_KFENCE */ ++ unsigned long addr, end, next; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, va_start); + +-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) { } ++ addr = va_start & PAGE_MASK; ++ end = PAGE_ALIGN(va_end); + +-#endif /* CONFIG_KFENCE */ ++ do { ++ next = pgd_addr_end(addr, end); ++ move_pud_table_into_iee(pgdp, addr, next); ++ } while (pgdp++, addr = next, addr != end); ++} + +-static void __init map_mem(pgd_t *pgdp) ++static void __init init_iee(void) + { +- 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); ++ unsigned long iee_addr; + phys_addr_t start, end; +- phys_addr_t early_kfence_pool; +- int flags = NO_EXEC_MAPPINGS; + u64 i; +- +- /* +- * 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(); +- +- if (can_set_direct_map()) +- 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); +- +- /* map all the memory banks */ ++ 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); ++ // put iee_pg_dir inside iee for sensitive inst isolation ++ iee_addr = (unsigned long)__phys_to_iee(__pa_symbol(iee_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; +@@ -609,192 +2147,193 @@ 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); ++ 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)); + } +- +- /* +- * 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. +- */ +- __map_memblock(pgdp, kernel_start, kernel_end, +- PAGE_KERNEL, NO_CONT_MAPPINGS); +- memblock_clear_nomap(kernel_start, kernel_end - kernel_start); +- arm64_kfence_map_pool(early_kfence_pool, pgdp); + } + +-void mark_rodata_ro(void) ++static void iee_set_kernel_upage_pre_init(unsigned long addr) + { +- unsigned long section_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); +- +- debug_checkwx(); +-} ++ pgd_t *pgdir = swapper_pg_dir; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, addr); + +-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; ++ p4d_t *p4dp = p4d_offset(pgdp, addr); ++ p4d_t p4d = READ_ONCE(*p4dp); + +- BUG_ON(!PAGE_ALIGNED(pa_start)); +- BUG_ON(!PAGE_ALIGNED(size)); ++ pud_t *pudp = pud_offset(p4dp, addr); + +- __create_pgd_mapping(pgdp, pa_start, (unsigned long)va_start, size, prot, +- early_pgtable_alloc, flags); ++ pmd_t *pmdp = pmd_offset(pudp, addr); + +- if (!(vm_flags & VM_NO_GUARD)) +- size += PAGE_SIZE; ++ pte_t *ptep = pte_offset_kernel(pmdp, addr); + +- vma->addr = va_start; +- vma->phys_addr = pa_start; +- vma->size = size; +- vma->flags = VM_MAP | vm_flags; +- vma->caller = __builtin_return_address(0); ++ int i; + +- vm_area_add_early(vma); ++ __iee_p4d_populate_pre_init(p4dp, __p4d_to_phys(p4d), PGD_APT | PUD_TYPE_TABLE); ++ 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 pgprot_t kernel_exec_prot(void) ++static void __init iee_set_pte_table_ro(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 logical_addr = (unsigned long)__va(__pmd_to_phys(pmd)); ++ iee_set_logical_mem_ro(logical_addr); + } + +-#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +-static int __init map_entry_trampoline(void) ++static void __init iee_set_pmd_table_ro(pud_t *pudp, unsigned long addr, unsigned long end) + { +- 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); +- __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); ++ 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); + +- return 0; ++ 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); + } +-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 iee_set_pud_table_ro(pgd_t *pgdp, unsigned long addr, unsigned long end) + { +- u64 pfr1; +- +- if (!IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)) +- return false; ++ 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); + +- pfr1 = __read_sysreg_by_encoding(SYS_ID_AA64PFR1_EL1); +- return cpuid_feature_extract_unsigned_field(pfr1, +- ID_AA64PFR1_EL1_BT_SHIFT); ++ 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); + } + +-/* +- * Create fine-grained mappings for the kernel. +- */ +-static void __init map_kernel(pgd_t *pgdp) ++static void __init iee_mark_pgtable_for_one_region_ro(pgd_t *pgdir, unsigned long va_start, unsigned long va_end) + { +- static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_inittext, +- vmlinux_initdata, vmlinux_data; +- +- /* +- * 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); ++ unsigned long addr, end, next; ++ pgd_t *pgdp = pgd_offset_pgd(pgdir, va_start); + +- /* +- * 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); ++ addr = va_start & PAGE_MASK; ++ end = PAGE_ALIGN(va_end); + +- fixmap_copy(pgdp); +- kasan_copy_shadow(pgdp); ++ do { ++ next = pgd_addr_end(addr, end); ++ iee_set_pud_table_ro(pgdp, addr, next); ++ } while (pgdp++, addr = next, addr != end); + } + +-static void __init create_idmap(void) ++static void __init iee_mark_all_lm_pgtable_ro(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); +- } +- __create_pgd_mapping(pgd, start, start, size, PAGE_KERNEL_ROX, +- early_pgtable_alloc, 0); +- +- if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) { +- extern u32 __idmap_kpti_flag; +- u64 pa = __pa_symbol(&__idmap_kpti_flag); +- ++ 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 ++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)); +@@ -802,7 +2341,24 @@ 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); ++ // map_iee_si(pgdp); ++ #endif ++ ++ // Avoid using iee code to modify pgtable before iee initialized. ++ #ifdef CONFIG_PTP ++ pgd_clear_fixmap_init(); ++ #else + pgd_clear_fixmap(); ++ #endif ++ ++ #ifdef CONFIG_IEE ++ // Initialize iee_pg_dir. ++ memcpy(iee_pg_dir, swapper_pg_dir, PAGE_SIZE); ++ flush_tlb_all(); ++ #endif + + cpu_replace_ttbr1(lm_alias(swapper_pg_dir), init_idmap_pg_dir); + init_mm.pgd = swapper_pg_dir; +@@ -813,6 +2369,80 @@ 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 ++ 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))); ++ #else ++ iee_set_kernel_upage((unsigned long)init_iee_stack_begin); ++ iee_set_kernel_upage((unsigned long)__va(__pa_symbol(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))); ++ // 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)); ++ #ifdef CONFIG_PTP ++ iee_set_token_page_valid_pre_init(init_token, new); ++ #else ++ iee_set_token_page_valid(init_token, new); ++ #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; ++ #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 ++ ++ #ifdef CONFIG_PTP ++ // IEE ready. ++ // Pgtable writing before uses logical memory and after uses IEE memory. ++ ++ // Set the logical va of existing pgtable readonly. ++ iee_mark_all_lm_pgtable_ro(); ++ #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(); ++ ++ // Flush tlb to enable IEE. ++ flush_tlb_all(); ++ ++ // 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 ++#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_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); ++#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_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); + } +@@ -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 + else + kmem_cache_free(pgd_cache, pgd); + } +diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S +index 14fdf645edc8..2d71303363e6 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) +@@ -105,6 +107,19 @@ SYM_FUNC_START(cpu_do_suspend) + ret + SYM_FUNC_END(cpu_do_suspend) + ++ ++#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 ++ + /** + * 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 + + offset_ttbr1 x0, x3 ++ + msr ttbr1_el1, x0 + isb + +diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c +index 83f5bb57fa4c..85c4d6c191da 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 + efi_memmap_unmap(); ++ #endif + + 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_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); ++} ++#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); ++ #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 ++ + 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/exec.c b/fs/exec.c +index 73b833e8b548..cae7ef0d3592 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; +@@ -1004,6 +1012,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); +@@ -1614,12 +1626,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 ef817a0475ff..7b6a3b2a57ce 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -15,6 +15,10 @@ + + #include + ++#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); + + 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 + ++#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; + + 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; + +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 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 + + #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 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); + 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" + ++#ifdef CONFIG_CREDP ++#include ++#endif ++ + #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 54723fceb776..fd08622430c2 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -35,6 +35,11 @@ + #include + #include + ++#ifdef CONFIG_CREDP ++#include ++#endif ++ ++ + #include "internal.h" + + int do_truncate(struct mnt_idmap *idmap, struct dentry *dentry, +@@ -414,17 +419,32 @@ 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 + 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 { ++ iee_set_cred_cap_effective(override_cred, __cap_empty_set); ++ } 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 +464,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 033fc0458a3d..2afa31ead2b5 100644 +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -16,6 +16,10 @@ + #include + #include "overlayfs.h" + ++#ifdef CONFIG_CREDP ++#include ++#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 c71d185980c0..d84624b4c506 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"); +@@ -1482,7 +1486,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); ++ } ++ #else + 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..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; + + /* create a new cifs key */ +@@ -212,8 +216,13 @@ init_cifs_spnego(void) + * 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 + 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..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" + ++#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; + + 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); + + #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 + ++#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) + ++#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) + + 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); + } + +@@ -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)); + } + +@@ -73,6 +89,13 @@ static inline pgtable_t __pte_alloc_one(struct mm_struct *mm, gfp_t gfp) + return NULL; + } + ++ #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); + } + +@@ -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) + { ++ #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)); ++ #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); + + 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 ++ + 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; ++ #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); ++ #endif + pagetable_free(virt_to_ptdesc(pud)); + } + +diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h +index 5896b7bc981f..ac15daf6c949 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 = .; + ++#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 + */ +@@ -371,8 +382,8 @@ + BRANCH_PROFILE() \ + TRACE_PRINTKS() \ + BPF_RAW_TP() \ +- TRACEPOINT_STR() +- ++ TRACEPOINT_STR() \ ++ KOI_DATA() + /* + * Data section helpers + */ +@@ -1099,6 +1110,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 ++#endif + + /* + * Writeable data. +@@ -1116,6 +1135,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..0c288ef3a7ee 100644 +--- a/include/linux/cred.h ++++ b/include/linux/cred.h +@@ -18,6 +18,10 @@ + #include + #include + ++#ifdef CONFIG_CREDP ++#include ++#endif ++ + struct cred; + struct inode; + +@@ -153,6 +157,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) ++{ ++ iee_rw_gate(IEE_OP_SET_CRED_NON_RCU,cred,non_rcu); ++ *(int *)(&(((struct rcu_head *)(cred->rcu.func))->next)) = non_rcu; ++} ++ ++static bool noinline iee_set_cred_atomic_op_usage(struct cred *cred, int flag) ++{ ++ bool ret; ++ ret = iee_rw_gate(IEE_OP_SET_CRED_ATOP_USAGE,cred,flag); ++ 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); +@@ -202,7 +222,11 @@ 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); ++ #ifdef CONFIG_CREDP ++ iee_set_cred_atomic_op_usage(cred,AT_INC); ++ return cred; ++ #endif ++ return get_new_cred_many(cred, 1); // XXXzgc atomic_inc -> get_new_cred_many + } + + /** +@@ -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); + } + +@@ -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; ++ #ifdef CONFIG_CREDP ++ if (!iee_set_cred_atomic_op_usage(nonconst_cred,AT_INC_NOT_ZERO)) ++ 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; + } + +@@ -270,8 +308,13 @@ static inline void put_cred_many(const struct cred *_cred, int nr) + struct cred *cred = (struct cred *) _cred; + + if (cred) { ++ #ifdef CONFIG_CREDP ++ if (iee_set_cred_atomic_op_usage(cred,AT_DEC_AND_TEST)) ++ __put_cred(cred); ++ #else + if (atomic_long_sub_and_test(nr, &cred->usage)) + __put_cred(cred); ++ #endif + } + } + +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 4e89a4aac75a..c8e8b574f095 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -735,6 +735,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 c3452e1830ca..23b500afb7ae 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/include/linux/stacktrace.h b/include/linux/stacktrace.h +index 97455880ac41..bfbb84f06180 100644 +--- a/include/linux/stacktrace.h ++++ b/include/linux/stacktrace.h +@@ -8,6 +8,11 @@ + struct task_struct; + struct pt_regs; + ++#ifdef CONFIG_IEE ++unsigned int stack_trace_save_iee(unsigned long *store, unsigned int size, ++ unsigned int skipnr); ++#endif ++ + #ifdef CONFIG_ARCH_STACKWALK + + /** +diff --git a/init/main.c b/init/main.c +index ba7da8fe83ea..71eb2999b513 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -101,6 +101,12 @@ + #include + #include + ++#ifdef CONFIG_IEE ++#include ++#include ++#include ++#endif ++ + #include + #include + #include +@@ -111,6 +117,10 @@ + + #include + ++#ifdef CONFIG_PTP ++extern void *bm_pte_addr; ++#endif ++ + static int kernel_init(void *); + + /* +@@ -877,6 +887,9 @@ void start_kernel(void) + { + char *command_line; + char *after_dashes; ++ #ifdef CONFIG_IEE ++ unsigned int cpu; ++ #endif + + set_task_stack_end_magic(&init_task); + smp_setup_processor_id(); +@@ -901,6 +914,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])); ++ } ++ #endif + smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ + boot_cpu_hotplug_init(); + +@@ -1431,6 +1454,125 @@ void __weak free_initmem(void) + free_initmem_default(POISON_FREE_INITMEM); + } + ++#ifdef CONFIG_IEE ++ ++// Set up breakpoint control registers to protect iee rwx gate ++static void __init iee_si_init_dbg(void) ++{ ++ unsigned long mdscr; ++ unsigned long dbgbcr, dbgbvr; ++ ++ // use afsr0_el1 to mark whether user proc user breakpoint 0 ++ write_sysreg(0, afsr0_el1); ++ ++ // set mdscr_el1.MDE to enable breakpoint exception ++ mdscr = read_sysreg(mdscr_el1); ++ mdscr |= DBG_MDSCR_MDE | DBG_MDSCR_KDE; ++ write_sysreg(mdscr, mdscr_el1); ++ ++ // set breakpoint control registers ++ dbgbcr = IEE_DBGBCR; ++ // calculate the location of msr ttbr1 inst. ++#ifdef CONFIG_KOI ++ dbgbvr = (unsigned long)(iee_rwx_gate_entry + 120); ++#else ++ dbgbvr = (unsigned long)(iee_rwx_gate_entry + 36); ++#endif ++ write_sysreg(dbgbcr, dbgbcr0_el1); ++ write_sysreg(dbgbvr, dbgbvr0_el1); ++ isb(); ++} ++ ++/* All software preparation for iee rwx gate is done after this function. */ ++static void __init iee_si_sw_init_end(void) ++{ ++ // void (*__jump_to_iee_si)(int flag, ...); ++ // remove exec permission of idmap functions inside kernel image. ++ // mark_idmap_vmallc_map_ROU(); ++ // test 0: jump to the start of protected area ++ // __jump_to_iee_si = IEE_SI_PGD_ENTRY; ++ ++ // test 1: jump to the inst of msr ttbr1 to test breakpoint prot ++ // iee_si_init_dbg(); ++ // asm volatile("mrs x13, daif"); ++ // asm volatile("msr daifset, #0b1010"); ++ // __jump_to_iee_si = IEE_SI_PGD_ENTRY - 36; ++ // __jump_to_iee_si(IEE_SI_TEST); ++ // asm volatile("msr daif, x13"); ++ ++ /* Cpu features has been initialized now. Check whether cnp is enabled.*/ ++ iee_si_set_base_swapper_cnp(); ++ /* ++ * Finally finish isolation by remap iee si setions and clear their kernel mapping. ++ */ ++ isolate_iee_si(); ++ // iee_si_handler(IEE_SI_TEST); ++ flush_tlb_all(); ++} ++ ++atomic_t __initdata iee_si_cpu_cnt; ++ ++static int __init iee_si_hw_init_cpu(void *__unused) ++{ ++ int total_cpu; ++ iee_si_init_dbg(); ++ // loop until setting all cpus ++ atomic_inc(&iee_si_cpu_cnt); ++ total_cpu = num_online_cpus(); ++ while (atomic_read(&iee_si_cpu_cnt) < total_cpu) ++ cpu_relax(); ++ ++ return 0; ++} ++// setup hw features on all online cpus ++static void __init iee_si_hw_init(void) ++{ ++ atomic_set(&iee_si_cpu_cnt, 0); ++ stop_machine(iee_si_hw_init_cpu, NULL, cpu_online_mask); ++ pr_info("IEE hw config done.\n"); ++} ++ ++static void __init iee_si_init_end(void) ++{ ++ iee_si_hw_init(); ++ // protect iee si metadata to finish initialization. ++ iee_si_sw_init_end(); ++} ++ ++static void iee_si_test_end(void) ++{ ++ pr_info("IEE: testing iee_exec_entry sctlr...\n"); ++ iee_rwx_gate_entry(IEE_WRITE_SCTLR, read_sysreg(sctlr_el1)& ~SCTLR_ELx_M); ++ pr_info("IEE: testing iee_exec_entry ttbr0_el1...\n"); ++ iee_rwx_gate_entry(IEE_WRITE_TTBR0, read_sysreg(ttbr0_el1)); ++ pr_info("IEE: testing iee_exec_entry vbar...\n"); ++ iee_rwx_gate_entry(IEE_WRITE_VBAR, read_sysreg(vbar_el1)); ++ pr_info("IEE: testing iee_exec_entry tcr...\n"); ++ iee_rwx_gate_entry(IEE_WRITE_TCR, read_sysreg(tcr_el1)); ++ pr_info("IEE: testing iee_exec_entry mdscr...\n"); ++ iee_rwx_gate_entry(IEE_WRITE_MDSCR, read_sysreg(mdscr_el1)); ++ 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))); ++ 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); ++ #endif ++} ++#else ++static void __init iee_si_hw_init(void){}; ++ ++static void iee_si_test_end(void) ++{ ++ pr_info("IEE: CONFIG_IEE not selected.\n"); ++} ++ ++#endif ++ + static int __ref kernel_init(void *unused) + { + int ret; +@@ -1441,6 +1583,13 @@ 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 ++ #ifdef CONFIG_IEE ++ // init hw features that iee_si uses ++ iee_si_init_end(); ++ #endif + /* need to finish all async __init code before freeing the memory */ + async_synchronize_full(); + +@@ -1458,6 +1607,9 @@ static int __ref kernel_init(void *unused) + */ + pti_finalize(); + ++ // test iee_si_code. ++ iee_si_test_end(); ++ + system_state = SYSTEM_RUNNING; + numa_default_policy(); + +@@ -1544,6 +1696,12 @@ static noinline void __init kernel_init_freeable(void) + if (disable_sdei_nmi_watchdog) + lockup_detector_init(); + ++ // zgcXXX: should it happen before `lockup_detector_init()` ? ++ #ifdef CONFIG_IEE ++ /* Copy swapper to iee_pg_dir again before smp init to handle KASLR issues. */ ++ memcpy(iee_pg_dir, swapper_pg_dir, PAGE_SIZE); ++ #endif ++ + smp_init(); + sched_init_smp(); + +diff --git a/kernel/cred.c b/kernel/cred.c +index c033a201c808..ed4c54a18a57 100644 +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -20,6 +20,11 @@ + #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 struct kmem_cache *cred_jar; ++#ifdef CONFIG_CREDP ++static struct kmem_cache *rcu_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 +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); ++#endif ++} ++ ++static inline int read_cred_subscribers(const struct cred *cred) ++{ ++#ifdef CONFIG_DEBUG_CREDENTIALS ++ return atomic_read(&cred->subscribers); ++#else ++ return 0; ++#endif ++} ++ ++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) + { ++ #ifdef CONFIG_CREDP ++ struct cred *cred = *(struct cred **)(rcu + 1); ++ #else + struct cred *cred = container_of(rcu, struct cred, rcu); ++ #endif + + 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)); ++ #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); + ++ #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 ++ #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); + +@@ -178,7 +257,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_DEBUG_CREDENTIALS ++ new->magic = CRED_MAGIC; ++ #endif ++ + 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 ++ + kdebug("prepare_creds() alloc %p", new); + + old = task->cred; ++ #ifdef CONFIG_CREDP ++ iee_copy_cred(old,new); ++ ++ iee_set_cred_non_rcu(new,0); ++ iee_set_cred_atomic_set_usage(new,1); ++ #else + memcpy(new, old, sizeof(struct cred)); + + 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,7 +334,11 @@ struct cred *prepare_creds(void) + #endif + + #ifdef CONFIG_SECURITY ++#ifdef CONFIG_CREDP ++ iee_set_cred_security(new,NULL); ++#else + new->security = NULL; ++#endif + #endif + + new->ucounts = get_ucounts(new->ucounts); +@@ -265,15 +371,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 + + /* 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_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 + + return new; + } +@@ -327,7 +448,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 +462,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 + +@@ -606,8 +735,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,27 +780,50 @@ 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); ++ #else + *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); + + #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_SECURITY ++#ifdef CONFIG_CREDP ++ iee_set_cred_security(new,NULL); ++#else + new->security = NULL; ++#endif + #endif + new->ucounts = get_ucounts(new->ucounts); + if (!new->ucounts) +@@ -727,8 +892,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 + new->fsuid = inode->i_uid; + new->fsgid = inode->i_gid; ++ #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); ++ #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 caa8a5530883..df1800be0a18 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -115,6 +115,10 @@ + #define CREATE_TRACE_POINTS + #include + ++#ifdef CONFIG_IEE ++#include ++#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) + + # 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) + + 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); + } + +@@ -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); + + if (!new) + return NULL; +@@ -602,8 +608,15 @@ 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_IEE ++ void *iee_stack; ++ #endif + #ifdef CONFIG_SECCOMP + WARN_ON_ONCE(tsk->seccomp.filter); + #endif +@@ -633,6 +646,45 @@ void free_task(struct task_struct *tsk) + if (dynamic_affinity_enabled()) + sched_prefer_cpus_free(tsk); + #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); ++#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); ++ } ++#endif ++#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) + + #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; +@@ -751,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); + } +@@ -823,7 +875,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 */ + +@@ -831,20 +883,22 @@ static void check_mm(struct mm_struct *mm) + { + int i; + +- 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"); + + for (i = 0; i < NR_MM_COUNTERS; i++) { + long x = percpu_counter_sum(&mm->rss_stat[i]); + + 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); + } + + 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)); + + #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS + VM_BUG_ON_MM(mm->pmd_huge_pte, mm); +@@ -995,14 +1049,6 @@ void __put_task_struct(struct task_struct *tsk) + } + EXPORT_SYMBOL_GPL(__put_task_struct); + +-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) { } + + /* +@@ -1020,8 +1066,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); + + if (threads > max_threads_suggested) + threads = max_threads_suggested; +@@ -1056,17 +1102,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; + + /* 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 ++ task_struct_cachep = ++ kmem_cache_create_usercopy("task_struct", arch_task_struct_size, ++ align, SLAB_PANIC | SLAB_ACCOUNT, ++ useroffset, usersize, NULL); ++ #endif + #endif + + /* do the arch specific task caches init */ +@@ -1074,8 +1127,8 @@ void __init fork_init(void) + + set_max_threads(MAX_THREADS); + +- 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]; + +@@ -1088,8 +1141,8 @@ void __init fork_init(void) + set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK, RLIM_INFINITY); + + #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 + + scs_init(); +@@ -1099,7 +1152,7 @@ void __init fork_init(void) + } + + int __weak arch_dup_task_struct(struct task_struct *dst, +- struct task_struct *src) ++ struct task_struct *src) + { + *dst = *src; + return 0; +@@ -1110,14 +1163,14 @@ void set_task_stack_end_magic(struct task_struct *tsk) + unsigned long *stackend; + + 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; + +@@ -1290,7 +1343,7 @@ static void mm_init_uprobes_state(struct mm_struct *mm) + } + + 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); +@@ -1412,8 +1465,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); + + __mmput(mm); + } +@@ -1589,13 +1642,12 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) + struct mm_struct *mm; + int err; + +- err = down_read_killable(&task->signal->exec_update_lock); ++ err = down_read_killable(&task->signal->exec_update_lock); + if (err) + return ERR_PTR(err); + + 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); + } +@@ -1618,7 +1670,7 @@ static void complete_vfork_done(struct task_struct *tsk) + } + + 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; +@@ -1669,8 +1721,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; + } +@@ -1754,6 +1806,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; + + /* +@@ -1775,6 +1831,10 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) + } + + 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; +@@ -1992,8 +2052,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; +@@ -2254,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 int koi_add_page_mapping(unsigned long dst, unsigned long src); ++#endif ++ ++ + #ifdef CONFIG_RV + static void rv_task_fork(struct task_struct *p) + { +@@ -2286,15 +2352,21 @@ __latent_entropy struct task_struct *copy_process( + struct file *pidfile = NULL; + const u64 clone_flags = args->flags; + struct nsproxy *nsp = current->nsproxy; ++ #ifdef CONFIG_IEE ++ gfp_t gfp; ++ void *pstack; ++ #endif + + /* + * 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); + +- 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); + + /* +@@ -2319,7 +2391,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); + + /* +@@ -2364,6 +2436,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); ++ #endif ++ + p->flags &= ~PF_KTHREAD; + if (args->kthread) + p->flags |= PF_KTHREAD; +@@ -2385,7 +2466,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; + + ftrace_graph_init_task(p); + +@@ -2496,10 +2578,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 + + p->pagefault_disabled = 0; +@@ -2512,8 +2594,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); +@@ -2600,7 +2682,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); + + /* +@@ -2679,7 +2761,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) +@@ -2743,8 +2825,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); +@@ -2895,8 +2978,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), +@@ -3060,8 +3143,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); +@@ -3071,35 +3154,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, + }; + + return kernel_clone(&args); +@@ -3155,21 +3233,21 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, + return -EINVAL; + + *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 (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; + + kargs->set_tid = kset_tid; +@@ -3264,7 +3342,8 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size) + } + #endif + +-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; +@@ -3272,8 +3351,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) +@@ -3281,8 +3360,7 @@ void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data + leader = child; + goto down; + } +-up: +- ; ++ up:; + } + } + +@@ -3359,11 +3437,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 +@@ -3474,7 +3552,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) +@@ -3485,8 +3563,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; + +@@ -3583,8 +3661,8 @@ int unshare_files(void) + return 0; + } + +-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) + { +@@ -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 + } + + 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 + ++#ifdef CONFIG_IEE ++#include ++#endif ++ + + 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); ++ #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); ++ #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 + ++#ifdef CONFIG_IEE ++#include ++#endif ++ + #include "smpboot.h" + + #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 + } + } + +diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c +index 9ed5ce989415..85ded4f4b630 100644 +--- a/kernel/stacktrace.c ++++ b/kernel/stacktrace.c +@@ -15,6 +15,10 @@ + #include + #include + ++#ifdef CONFIG_IEE ++#include ++#endif ++ + /** + * stack_trace_print - Print the entries in the stack trace + * @entries: Pointer to storage array +@@ -94,6 +98,23 @@ static bool stack_trace_consume_entry(void *cookie, unsigned long addr) + return c->len < c->size; + } + ++#ifdef CONFIG_IEE ++static bool stack_trace_consume_entry_iee(void *cookie, unsigned long addr) ++{ ++ struct stacktrace_cookie *c = cookie; ++ ++ if (c->len >= c->size) ++ return false; ++ ++ if (c->skip > 0) { ++ c->skip--; ++ return true; ++ } ++ iee_write_in_byte(&(c->store[c->len++]), addr, 8); ++ return c->len < c->size; ++} ++#endif ++ + static bool stack_trace_consume_entry_nosched(void *cookie, unsigned long addr) + { + if (in_sched_functions(addr)) +@@ -124,6 +145,23 @@ unsigned int stack_trace_save(unsigned long *store, unsigned int size, + } + EXPORT_SYMBOL_GPL(stack_trace_save); + ++#ifdef CONFIG_IEE ++unsigned int stack_trace_save_iee(unsigned long *store, unsigned int size, ++ unsigned int skipnr) ++{ ++ stack_trace_consume_fn consume_entry = stack_trace_consume_entry_iee; ++ struct stacktrace_cookie c = { ++ .store = store, ++ .size = size, ++ .skip = skipnr + 1, ++ }; ++ ++ arch_stack_walk(consume_entry, &c, current, NULL); ++ return c.len; ++} ++EXPORT_SYMBOL_GPL(stack_trace_save_iee); ++#endif ++ + /** + * stack_trace_save_tsk - Save a task stack trace into a storage array + * @task: The task to examine +diff --git a/kernel/sys.c b/kernel/sys.c +index 7a4ae6d5aecd..a4a607e8d1c2 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -75,6 +75,10 @@ + #include + #include + ++#ifdef CONFIG_CREDP ++#include ++#endif ++ + #include "uid16.h" + + #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; + } + + 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); ++ #else + 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_user(new,new_user); ++ #else + new->user = new_user; ++ #endif + return 0; + } + +@@ -549,7 +589,11 @@ long __sys_setreuid(uid_t ruid, uid_t euid) + + retval = -EPERM; + if (ruid != (uid_t) -1) { ++ #ifdef CONFIG_CREDP ++ iee_set_cred_uid(new,kruid); ++ #else + 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) + } + + 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 + + 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)) { ++ #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; + } + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_euid(new,kuid); ++ iee_set_cred_fsuid(new,kuid); ++ #else + new->fsuid = new->euid = kuid; ++ #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) ++ #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 + + 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 (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 + + 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 @@ + + #include + ++#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; + + 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 + ++#ifdef CONFIG_CREDP ++#include ++#endif ++ + 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/mm/Kconfig b/mm/Kconfig +index cdbb1ceaa554..0540d445eedb 100644 +--- a/mm/Kconfig ++++ b/mm/Kconfig +@@ -530,6 +530,18 @@ config NUMA_KEEP_MEMINFO + config MEMORY_ISOLATION + bool + ++# 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 (ptep_clear_young_notify(vma, addr, pte)) + folio_set_young(folio); + +diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c +index 48e329ea5ba3..495848c451b6 100644 +--- a/mm/debug_vm_pgtable.c ++++ b/mm/debug_vm_pgtable.c +@@ -444,7 +444,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); +@@ -464,7 +468,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 + 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); +@@ -503,7 +511,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); ++ #else + WRITE_ONCE(*args->pudp, pud); ++ #endif + pud_clear(args->pudp); + pud = READ_ONCE(*args->pudp); + WARN_ON(!pud_none(pud)); +@@ -540,7 +552,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); ++ #else + WRITE_ONCE(*args->p4dp, p4d); ++ #endif + p4d_clear(args->p4dp); + p4d = READ_ONCE(*args->p4dp); + WARN_ON(!p4d_none(p4d)); +@@ -574,7 +590,11 @@ static void __init pgd_clear_tests(struct pgtable_debug_args *args) + + pr_debug("Validating PGD clear\n"); + 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)); +@@ -642,7 +662,11 @@ static void __init pmd_clear_tests(struct pgtable_debug_args *args) + + pr_debug("Validating PMD clear\n"); + pmd = __pmd(pmd_val(pmd) | RANDOM_ORVALUE); ++ #ifdef CONFIG_PTP ++ set_pmd(args->pmdp, pmd); ++ #else + 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; ++ ++ 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 5a2131be4540..88b29e607032 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -38,6 +38,10 @@ + #include + #include + ++#ifdef CONFIG_PTP ++#include ++#endif ++ + #include + #include + #include "internal.h" +@@ -2217,6 +2221,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 + + /* + * Leave pmd empty until pte is filled note that it is fine to delay +@@ -2229,7 +2237,14 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma, + old_pmd = pmdp_huge_clear_flush(vma, haddr, pmd); + + 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); + + pte = pte_offset_map(&_pmd, haddr); + VM_BUG_ON(!pte); +@@ -2261,6 +2276,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 + + VM_BUG_ON(haddr & ~HPAGE_PMD_MASK); + VM_BUG_ON_VMA(vma->vm_start > haddr, vma); +@@ -2387,7 +2406,14 @@ 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); ++ #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); ++ #endif ++ //pmd_populate(mm, &_pmd, pgtable); ++ _pmd = __pmd(__phys_to_pmd_val(page_to_phys(pgtable)) | PMD_TYPE_TABLE); + + 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_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); ++} ++#endif +diff --git a/mm/memory.c b/mm/memory.c +index 9a0b8f2f6f4b..4384f5aac0a9 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -80,6 +80,10 @@ + #include + #include + ++#ifdef CONFIG_PTP ++#include ++#endif ++ + #include + + #include +@@ -5661,6 +5665,11 @@ int __pud_alloc(struct mm_struct *mm, p4d_t *p4d, unsigned long address) + + 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); ++ #endif + mm_inc_nr_puds(mm); + smp_wmb(); /* See comment in pmd_install() */ + p4d_populate(mm, p4d, new); +@@ -5685,6 +5694,11 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) + + 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); ++ #endif + mm_inc_nr_pmds(mm); + smp_wmb(); /* See comment in pmd_install() */ + pud_populate(mm, pud, new); +diff --git a/mm/mm_init.c b/mm/mm_init.c +index 0a3c20a00318..a32dc6d50952 100644 +--- a/mm/mm_init.c ++++ b/mm/mm_init.c +@@ -2829,4 +2829,10 @@ void __init mm_core_init(void) + pti_init(); + kmsan_init_runtime(); + mm_cache_init(); ++ ++ #ifdef CONFIG_IEE ++ /* Copy swapper to iee_pg_dir again after vmemmap is built. */ ++ memcpy(iee_pg_dir, swapper_pg_dir, PAGE_SIZE); ++ flush_tlb_all(); ++ #endif + } +diff --git a/mm/slub.c b/mm/slub.c +index f7940048138c..199e5e9c3781 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -42,6 +42,11 @@ + #include + #include + ++#ifdef CONFIG_IEE ++#include ++#include ++#endif ++ + #include + #include + +@@ -302,6 +307,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 */ +@@ -314,6 +320,7 @@ struct track { + }; + + enum track_item { TRACK_ALLOC, TRACK_FREE }; ++#endif + + #ifdef SLAB_SUPPORTS_SYSFS + static int sysfs_slab_add(struct kmem_cache *); +@@ -364,7 +371,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 + + /* + * Returns freelist pointer (ptr). With hardening, this is obfuscated +@@ -449,7 +458,14 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp) + #endif + + 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); ++ #else + *(freeptr_t *)freeptr_addr = freelist_ptr_encode(s, fp, freeptr_addr); ++ #endif + } + + /* Loop over all objects in a slab */ +@@ -782,6 +798,24 @@ static noinline depot_stack_handle_t set_track_prepare(void) + + return handle; + } ++#ifdef CONFIG_IEE ++static noinline depot_stack_handle_t set_track_prepare_iee(struct kmem_cache *s) ++{ ++ depot_stack_handle_t handle; ++ unsigned long entries[TRACK_ADDRS_COUNT]; ++ unsigned int nr_entries; ++ ++ if (IS_ENABLED(CONFIG_CREDP) && strcmp(s->name, "cred_jar") == 0) { ++ nr_entries = stack_trace_save_iee(entries, ARRAY_SIZE(entries), 3); ++ } ++ else { ++ nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 3); ++ } ++ handle = stack_depot_save(entries, nr_entries, GFP_NOWAIT); ++ ++ return handle; ++} ++#endif + #else + static inline depot_stack_handle_t set_track_prepare(void) + { +@@ -794,7 +828,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) && 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; + #endif +@@ -802,12 +863,17 @@ static void set_track_update(struct kmem_cache *s, void *object, + p->cpu = smp_processor_id(); + p->pid = current->pid; + p->when = jiffies; ++#endif + } + + static __always_inline void set_track(struct kmem_cache *s, void *object, + enum track_item alloc, unsigned long addr) + { ++#ifdef CONFIG_IEE ++ depot_stack_handle_t handle = set_track_prepare_iee(s); ++#else + depot_stack_handle_t handle = set_track_prepare(); ++#endif + + set_track_update(s, object, alloc, addr, handle); + } +@@ -820,7 +886,14 @@ static void init_tracking(struct kmem_cache *s, void *object) + return; + + 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)); ++ #else + memset(p, 0, 2*sizeof(struct track)); ++ #endif + } + + static void print_track(const char *s, struct track *t, unsigned long pr_time) +@@ -1030,7 +1103,14 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) + unsigned int poison_size = s->object_size; + + 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 + + if (slub_debug_orig_size(s) && val == SLUB_RED_ACTIVE) { + /* +@@ -1043,12 +1123,34 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) + } + + 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; ++ } ++ #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) && 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); ++ #else + memset(p + poison_size, val, s->inuse - poison_size); ++ #endif ++ ++ } + } + + static void restore_bytes(struct kmem_cache *s, char *message, u8 data, +@@ -1418,7 +1520,14 @@ void setup_slab_debug(struct kmem_cache *s, struct slab *slab, void *addr) + return; + + 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)); ++ #else + memset(kasan_reset_tag(addr), POISON_INUSE, slab_size(slab)); ++ #endif + metadata_access_disable(); + } + +@@ -2001,6 +2110,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; ++ #endif + + flags &= gfp_allowed_mask; + +@@ -2015,6 +2127,9 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) + alloc_gfp = (alloc_gfp | __GFP_NOMEMALLOC) & ~__GFP_RECLAIM; + + slab = alloc_slab_page(alloc_gfp, node, oo); ++ #ifdef CONFIG_IEE ++ order = oo_order(oo); ++ #endif + if (unlikely(!slab)) { + oo = s->min; + alloc_gfp = flags; +@@ -2023,6 +2138,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); +@@ -2032,6 +2150,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 ++ #endif ++ + account_slab(slab, oo_order(oo), s, flags); + + slab->slab_cache = s; +@@ -2084,6 +2241,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)); ++ } ++ } ++ } ++ #endif ++ #endif ++ + __free_pages(&folio->page, order); + } + +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 + ++#ifdef CONFIG_PTP ++#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) + { + pte_t *pte = pte_offset_kernel(pmd, addr); ++ #ifdef CONFIG_PTP ++ unsigned long iee_addr; ++ #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); + } ++#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); + } +@@ -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; ++ #endif + + if (!p) + return NULL; + memset(p, 0, size); + ++ #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 ++ + return p; + } + +diff --git a/mm/swap.c b/mm/swap.c +index cd8f0150ba3a..32b3b9818dc8 100644 +--- a/mm/swap.c ++++ b/mm/swap.c +@@ -38,6 +38,10 @@ + #include + #include + ++#ifdef CONFIG_PTP ++#include ++#endif ++ + #include "internal.h" + + #define CREATE_TRACE_POINTS +@@ -121,6 +125,15 @@ static void __folio_put_large(struct folio *folio) + + void __folio_put(struct folio *folio) + { ++#ifdef CONFIG_PTP ++ if(folio_ref_count(folio) == 0) ++ { ++ unsigned long iee_addr = __phys_to_iee(__pa(page_address(&folio->page))); ++ set_iee_page_invalid(iee_addr); ++ iee_set_logical_mem_rw((unsigned long)page_address(&folio->page)); ++ } ++#endif ++ + if (unlikely(folio_is_zone_device(folio))) + free_zone_device_page(&folio->page); + else if (unlikely(folio_test_large(folio))) +diff --git a/mm/vmalloc.c b/mm/vmalloc.c +index 31761425d7a8..7145b071185c 100644 +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -2949,7 +2949,7 @@ static int vmap_pfn_apply(pte_t *pte, unsigned long addr, void *private) + + 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/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c +index 01e54b46ae0b..b94f8dd54281 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_CREDP ++#include ++#endif ++ + MODULE_DESCRIPTION("DNS Resolver"); + MODULE_AUTHOR("Wang Lei"); + MODULE_LICENSE("GPL"); +@@ -358,8 +362,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); ++ #else + cred->thread_keyring = keyring; + cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; ++ #endif + dns_resolver_cache = cred; + + kdebug("DNS resolver keyring: %d\n", key_serial(keyring)); +diff --git a/security/commoncap.c b/security/commoncap.c +index bc0521104197..09e7a26102c9 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 + + if (caps->permitted.val & ~new->cap_permitted.val) + /* insufficient to execute correctly */ +@@ -726,7 +747,13 @@ static int get_file_caps(struct linux_binprm *bprm, struct file *file, + int rc = 0; + struct cpu_vfs_cap_data vcaps; + ++ #ifdef CONFIG_CREDP ++ do { ++ iee_set_cred_cap_permitted(bprm->cred, __cap_empty_set); ++ } while (0); ++ #else + cap_clear(bprm->cred->cap_permitted); ++ #endif + + if (!file_caps_enabled) + return 0; +@@ -757,7 +784,13 @@ static int get_file_caps(struct linux_binprm *bprm, struct file *file, + + out: + if (rc) ++ #ifdef CONFIG_CREDP ++ do { ++ iee_set_cred_cap_permitted(bprm->cred, __cap_empty_set); ++ } while (0); ++ #else + cap_clear(bprm->cred->cap_permitted); ++ #endif + + return rc; + } +@@ -809,8 +842,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)); ++ #else + new->cap_permitted = cap_combine(old->cap_bset, + old->cap_inheritable); ++ #endif + } + /* + * If only the real uid is 0, we do not set the effective bit. +@@ -919,34 +957,69 @@ 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)); ++ #else + 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->suid = new->fsuid = new->euid; + new->sgid = new->fsgid = new->egid; ++ #endif + + /* File caps or setid cancels ambient. */ + if (has_fcap || is_setid) ++ #ifdef CONFIG_CREDP ++ do { ++ iee_set_cred_cap_ambient(new, __cap_empty_set); ++ } while (0); ++ #else + cap_clear(new->cap_ambient); ++ #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)); ++ #else + new->cap_permitted = cap_combine(new->cap_permitted, new->cap_ambient); ++ #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); ++ #else + new->cap_effective = new->cap_permitted; ++ #endif + else ++ #ifdef CONFIG_CREDP ++ iee_set_cred_cap_effective(new,new->cap_ambient); ++ #else + new->cap_effective = new->cap_ambient; ++ #endif + + if (WARN_ON(!cap_ambient_invariant_ok(new))) + return -EPERM; +@@ -957,7 +1030,11 @@ int cap_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file) + return ret; + } + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_securebits(new,new->securebits & ~issecure_mask(SECURE_KEEP_CAPS)); ++ #else + new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); ++ #endif + + if (WARN_ON(!cap_ambient_invariant_ok(new))) + return -EPERM; +@@ -1092,8 +1169,17 @@ 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 { ++ iee_set_cred_cap_permitted(new, __cap_empty_set); ++ } while (0); ++ do { ++ iee_set_cred_cap_effective(new, __cap_empty_set); ++ } while (0); ++ #else + cap_clear(new->cap_permitted); + cap_clear(new->cap_effective); ++ #endif + } + + /* +@@ -1101,12 +1187,28 @@ 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 { ++ iee_set_cred_cap_ambient(new, __cap_empty_set); ++ } while (0); ++ #else + cap_clear(new->cap_ambient); ++ #endif + } + if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid)) ++ #ifdef CONFIG_CREDP ++ do { ++ iee_set_cred_cap_effective(new, __cap_empty_set); ++ } while (0); ++ #else + cap_clear(new->cap_effective); ++ #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 + new->cap_effective = new->cap_permitted; ++ #endif + } + + /** +@@ -1142,13 +1244,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 +1354,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); ++ } ++ #else + cap_lower(new->cap_bset, cap); ++ #endif + return commit_creds(new); + } + +@@ -1319,7 +1438,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 +1461,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 +1482,13 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, + new = prepare_creds(); + if (!new) + return -ENOMEM; ++ #ifdef CONFIG_CREDP ++ do { ++ iee_set_cred_cap_ambient(new, __cap_empty_set); ++ } while (0); ++ #else + cap_clear(new->cap_ambient); ++ #endif + return commit_creds(new); + } + +@@ -1375,9 +1512,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); + } + +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 + + #define KEY_MAX_DESC_SIZE 4096 + +@@ -1155,7 +1158,11 @@ static int keyctl_change_reqkey_auth(struct key *key) + return -ENOMEM; + + 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 + + return commit_creds(new); + } +@@ -1432,7 +1439,11 @@ long keyctl_set_reqkey_keyring(int reqkey_defl) + } + + 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 +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); ++ #else + newwork = &cred->rcu; ++ #endif + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_session_keyring(cred,key_ref_to_ptr(keyring_r)); ++ #else + cred->session_keyring = key_ref_to_ptr(keyring_r); ++ #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; +diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c +index b5d5333ab330..3dc8dc430300 100644 +--- a/security/keys/process_keys.c ++++ b/security/keys/process_keys.c +@@ -19,6 +19,10 @@ + #include + #include "internal.h" + ++#ifdef CONFIG_CREDP ++#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) + if (IS_ERR(keyring)) + return PTR_ERR(keyring); + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_thread_keyring(new,keyring); ++ #else + new->thread_keyring = keyring; ++ #endif + return 0; + } + +@@ -279,7 +287,11 @@ int install_process_keyring_to_cred(struct cred *new) + if (IS_ERR(keyring)) + return PTR_ERR(keyring); + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_process_keyring(new,keyring); ++ #else + new->process_keyring = keyring; ++ #endif + return 0; + } + +@@ -338,7 +350,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) + + /* install the keyring */ + old = cred->session_keyring; ++ #ifdef CONFIG_CREDP ++ iee_set_cred_session_keyring(cred,keyring); ++ #else + cred->session_keyring = keyring; ++ #endif + + if (old) + key_put(old); +@@ -911,7 +927,11 @@ long join_session_keyring(const char *name) + void key_change_session_keyring(struct callback_head *twork) + { + const struct cred *old = current_cred(); ++ #ifdef CONFIG_CREDP ++ struct cred *new = *(struct cred **)(twork + 1); ++ #else + struct cred *new = container_of(twork, struct cred, rcu); ++ #endif + + if (unlikely(current->flags & PF_EXITING)) { + put_cred(new); +@@ -925,6 +945,37 @@ void key_change_session_keyring(struct callback_head *twork) + return; + } + ++ /* If get_ucounts fails more bits are needed in the refcount */ ++ if (unlikely(!get_ucounts(old->ucounts))) { ++ WARN_ONCE(1, "In %s get_ucounts failed\n", __func__); ++ put_cred(new); ++ return; ++ } ++ ++ #ifdef CONFIG_CREDP ++ iee_set_cred_uid(new,old-> uid); ++ iee_set_cred_euid(new,old-> euid); ++ iee_set_cred_suid(new,old-> suid); ++ iee_set_cred_fsuid(new,old->fsuid); ++ iee_set_cred_gid(new,old-> gid); ++ iee_set_cred_egid(new,old-> egid); ++ iee_set_cred_sgid(new,old-> sgid); ++ iee_set_cred_fsgid(new,old->fsgid); ++ iee_set_cred_user(new,get_uid(old->user)); ++ iee_set_cred_user_ns(new,get_user_ns(old->user_ns)); ++ iee_set_cred_group_info(new,get_group_info(old->group_info)); ++ ++ iee_set_cred_securebits(new,old->securebits); ++ iee_set_cred_cap_inheritable(new,old->cap_inheritable); ++ iee_set_cred_cap_permitted(new,old->cap_permitted); ++ iee_set_cred_cap_effective(new,old->cap_effective); ++ iee_set_cred_cap_ambient(new,old->cap_ambient); ++ iee_set_cred_cap_bset(new,old->cap_bset); ++ ++ iee_set_cred_jit_keyring(new,old->jit_keyring); ++ 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 +999,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/security.c b/security/security.c +index 23b129d482a7..6dc42370d573 100644 +--- a/security/security.c ++++ b/security/security.c +@@ -30,6 +30,9 @@ + #include + #include + #include ++#ifdef CONFIG_CREDP ++#include ++#endif + + /* How many LSMs were built into the kernel? */ + #define LSM_COUNT (__end_lsm_info - __start_lsm_info) +@@ -570,11 +573,19 @@ EXPORT_SYMBOL(unregister_blocking_lsm_notifier); + static int lsm_cred_alloc(struct cred *cred, gfp_t gfp) + { + if (blob_sizes.lbs_cred == 0) { ++ #ifdef CONFIG_CREDP ++ iee_set_cred_security(cred,NULL); ++ #else + cred->security = NULL; ++ #endif + return 0; + } + ++ #ifdef CONFIG_CREDP ++ iee_set_cred_security(cred,kzalloc(blob_sizes.lbs_cred, gfp)); ++ #else + cred->security = kzalloc(blob_sizes.lbs_cred, gfp); ++ #endif + if (cred->security == NULL) + return -ENOMEM; + return 0; +@@ -2932,7 +2943,11 @@ void security_cred_free(struct cred *cred) + call_void_hook(cred_free, cred); + + kfree(cred->security); ++ #ifdef CONFIG_CREDP ++ iee_set_cred_security(cred,NULL); ++ #else + cred->security = NULL; ++ #endif + } + + /** +-- +2.33.0 + diff --git a/haoc-kernel.spec b/haoc-kernel.spec new file mode 100644 index 0000000..495fb8b --- /dev/null +++ b/haoc-kernel.spec @@ -0,0 +1,5003 @@ +%define with_signmodules 1 +%define with_kabichk 0 + +# Default without toolchain_clang +%bcond_with toolchain_clang + +%if %{with toolchain_clang} +%global toolchain clang +%endif + +%bcond_with clang_lto + +%if %{with clang_lto} && "%{toolchain}" != "clang" +{error:clang_lto requires --with toolchain_clang} +%endif + +%define modsign_cmd %{SOURCE10} + +%global Arch $(echo %{_host_cpu} | sed -e s/i.86/x86/ -e s/x86_64/x86/ -e s/aarch64.*/arm64/ -e s/riscv.*/riscv/) + +%global KernelVer %{version}-%{release}.%{_target_cpu} +%global debuginfodir /usr/lib/debug + +%global upstream_version 6.6 +%global upstream_sublevel 0 +%global devel_release 12 +%global maintenance_release .0.0 +%global pkg_release .8 + +%define with_debuginfo 1 +# Do not recompute the build-id of vmlinux in find-debuginfo.sh +%global _missing_build_ids_terminate_build 1 +%global _no_recompute_build_ids 1 +%undefine _include_minidebuginfo +%undefine _include_gdb_index +%undefine _unique_build_ids + +%define with_source 1 + +%define with_python2 0 + +# failed if there is new config options +%define listnewconfig_fail 0 + +%ifarch aarch64 +%define with_64kb %{?_with_64kb: 1} %{?!_with_64kb: 0} +%if %{with_64kb} +%global package64kb -64kb +%endif +%else +%define with_64kb 0 +%endif + +#default is enabled. You can disable it with --without option +%define with_perf %{?_without_perf: 0} %{?!_without_perf: 1} + +Name: kernel%{?package64kb} +Version: %{upstream_version}.%{upstream_sublevel} +Release: %{devel_release}%{?maintenance_release}%{?pkg_release} +Summary: Linux Kernel +License: GPLv2 +URL: http://www.kernel.org/ +Source0: kernel.tar.gz +Source10: sign-modules +Source11: x509.genkey +Source12: extra_certificates +# openEuler RPM PGP certificates: +# 1. openeuler +Source13: RPM-GPG-KEY-openEuler-compass-ci +Source14: process_pgp_certs.sh + +%if 0%{?with_kabichk} +Source18: check-kabi +Source20: Module.kabi_aarch64 +Source21: Module.kabi_x86_64 +%endif + +Source200: mkgrub-menu-aarch64.sh + +Source2000: cpupower.service +Source2001: cpupower.config + +%if 0%{?with_patch} +Source9000: apply-patches +Source9001: guards +Source9002: series.conf +Source9998: patches.tar.bz2 +%endif + +Patch0002: 0002-cpupower-clang-compile-support.patch +Patch0003: 0003-x86_energy_perf_policy-clang-compile-support.patch +Patch0004: 0004-turbostat-clang-compile-support.patch +Patch0005: 0005-haoc-kernel.patch + +#BuildRequires: +BuildRequires: module-init-tools, patch >= 2.5.4, bash >= 2.03, tar +BuildRequires: bzip2, xz, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk +BuildRequires: libcap-devel, libcap-ng-devel, rsync +BuildRequires: gcc >= 3.4.2, binutils >= 2.12 +BuildRequires: hostname, net-tools, bc +BuildRequires: xmlto, asciidoc +BuildRequires: openssl-devel openssl +BuildRequires: hmaccalc +BuildRequires: ncurses-devel +#BuildRequires: pesign >= 0.109-4 +BuildRequires: elfutils-libelf-devel +BuildRequires: rpm >= 4.14.2 +#BuildRequires: sparse >= 0.4.1 +%if 0%{?with_python2} +BuildRequires: python-devel +%endif + +BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel perl(ExtUtils::Embed) bison +BuildRequires: audit-libs-devel libpfm-devel libtraceevent-devel +BuildRequires: pciutils-devel gettext +BuildRequires: rpm-build, elfutils +BuildRequires: numactl-devel python3-devel glibc-static python3-docutils +BuildRequires: perl-generators perl(Carp) libunwind-devel gtk2-devel libbabeltrace-devel java-1.8.0-openjdk java-1.8.0-openjdk-devel perl-devel + +%if 0%{?openEuler_sign_rsa} +BuildRequires: sign-openEuler +%endif + +AutoReq: no +AutoProv: yes + +Conflicts: device-mapper-libs < 1.02.63-2 e2fsprogs < 1.37-4 initscripts < 7.23 iptables < 1.3.2-1 +Conflicts: ipw2200-firmware < 2.4 isdn4k-utils < 3.2-32 iwl4965-firmware < 228.57.2 jfsutils < 1.1.7-2 +Conflicts: mdadm < 3.2.1-5 nfs-utils < 1.0.7-12 oprofile < 0.9.1-2 ppp < 2.4.3-3 procps < 3.2.5-6.3 +Conflicts: reiserfs-utils < 3.6.19-2 selinux-policy-targeted < 1.25.3-14 squashfs-tools < 4.0 +Conflicts: udev < 063-6 util-linux < 2.12 wireless-tools < 29-3 xfsprogs < 2.6.13-4 + +Provides: kernel-%{_target_cpu} = %{version}-%{release} kernel-drm = 4.3.0 kernel-drm-nouveau = 16 kernel-modeset = 1 +Provides: kernel-uname-r = %{KernelVer} kernel=%{KernelVer} + +Requires: dracut >= 001-7 grubby >= 8.28-2 initscripts >= 8.11.1-1 linux-firmware >= 20100806-2 module-init-tools >= 3.16-2 + +ExclusiveArch: noarch aarch64 i686 x86_64 riscv64 +ExclusiveOS: Linux + +%if %{with_perf} +BuildRequires: flex xz-devel libzstd-devel +BuildRequires: java-devel +%endif + +BuildRequires: dwarves +BuildRequires: clang >= 10.0.0 +BuildRequires: llvm +BuildRequires: llvm-devel +%if %{with clang_lto} +BuildRequires: lld +%endif + +%description +The Linux Kernel, the operating system core itself. + +%package headers +Summary: Header files for the Linux kernel for use by glibc +Obsoletes: glibc-kernheaders < 3.0-46 +Provides: glibc-kernheaders = 3.0-46 +%description headers +Kernel-headers includes the C header files that specify the interface +between the Linux kernel and userspace libraries and programs. The +header files define structures and constants that are needed for +building most standard programs and are also needed for rebuilding the +glibc package. + + +%package devel +Summary: Development package for building kernel modules to match the %{KernelVer} kernel +AutoReqProv: no +Provides: kernel-devel-uname-r = %{KernelVer} +Provides: kernel-devel-%{_target_cpu} = %{version}-%{release} +Requires: perl findutils + +%description devel +This package provides kernel headers and makefiles sufficient to build modules +against the %{KernelVer} kernel package. + +%package tools +Summary: Assortment of tools for the Linux kernel +Provides: %{name}-tools-libs +Obsoletes: %{name}-tools-libs +Provides: cpufreq-utils = 1:009-0.6.p1 +Provides: cpufrequtils = 1:009-0.6.p1 +Obsoletes: cpufreq-utils < 1:009-0.6.p1 +Obsoletes: cpufrequtils < 1:009-0.6.p1 +Obsoletes: cpuspeed < 1:1.5-16 +%description tools +This package contains the tools/ directory from the kernel source +and the supporting documentation. + +%package tools-devel +Summary: Assortment of tools for the Linux kernel +Requires: %{name}-tools = %{version}-%{release} +Requires: %{name}-tools-libs = %{version}-%{release} +Provides: %{name}-tools-libs-devel = %{version}-%{release} +Obsoletes: %{name}-tools-libs-devel +%description tools-devel +This package contains the development files for the tools/ directory from +the kernel source. + +%if %{with_perf} +%package -n perf +Summary: Performance monitoring for the Linux kernel +%description -n perf +This package contains the perf tool, which enables performance monitoring +of the Linux kernel. + +%if 0%{?with_python2} +%package -n python2-perf +Provides: python-perf = %{version}-%{release} +Obsoletes: python-perf +Summary: Python bindings for apps which will manipulate perf events + +%description -n python2-perf +A Python module that permits applications written in the Python programming +language to use the interface to manipulate perf events. +%endif + +%package -n python3-perf +Summary: Python bindings for apps which will manipulate perf events +%description -n python3-perf +A Python module that permits applications written in the Python programming +language to use the interface to manipulate perf events. +# with_perf +%endif + +%package -n bpftool +Summary: Inspection and simple manipulation of eBPF programs and maps +%description -n bpftool +This package contains the bpftool, which allows inspection and simple +manipulation of eBPF programs and maps. + +%package source +Summary: the kernel source +%description source +This package contains vaious source files from the kernel. + +%if 0%{?with_debuginfo} +%define _debuginfo_template %{nil} +%define _debuginfo_subpackages 0 + +%define debuginfo_template(n:) \ +%package -n %{-n*}-debuginfo\ +Summary: Debug information for package %{-n*}\ +Group: Development/Debug\ +AutoReq: 0\ +AutoProv: 1\ +%description -n %{-n*}-debuginfo\ +This package provides debug information for package %{-n*}.\ +Debug information is useful when developing applications that use this\ +package or when debugging this package.\ +%{nil} + +%debuginfo_template -n kernel +%files -n kernel-debuginfo -f kernel-debugfiles.list -f debugfiles.list +%{expand:%%global _find_debuginfo_opts %{?_find_debuginfo_opts} --keep-section '.BTF' -p '.*/%{KernelVer}/.*|.*/vmlinux|XXX' -o kernel-debugfiles.list} + +%debuginfo_template -n bpftool +%files -n bpftool-debuginfo -f bpftool-debugfiles.list +%{expand:%%global _find_debuginfo_opts %{?_find_debuginfo_opts} -p '.*%{_sbindir}/bpftool.*(\.debug)?|XXX' -o bpftool-debugfiles.list} + +%debuginfo_template -n kernel-tools +%files -n kernel-tools-debuginfo -f kernel-tools-debugfiles.list +%{expand:%%global _find_debuginfo_opts %{?_find_debuginfo_opts} -p '.*%{_bindir}/centrino-decode.*(\.debug)?|.*%{_bindir}/powernow-k8-decode.*(\.debug)?|.*%{_bindir}/cpupower.*(\.debug)?|.*%{_libdir}/libcpupower.*|.*%{_libdir}/libcpupower.*|.*%{_bindir}/turbostat.(\.debug)?|.*%{_bindir}/.*gpio.*(\.debug)?|.*%{_bindir}/.*iio.*(\.debug)?|.*%{_bindir}/tmon.*(.debug)?|XXX' -o kernel-tools-debugfiles.list} + +%if %{with_perf} +%debuginfo_template -n perf +%files -n perf-debuginfo -f perf-debugfiles.list +%{expand:%%global _find_debuginfo_opts %{?_find_debuginfo_opts} -p '.*%{_bindir}/perf.*(\.debug)?|.*%{_libexecdir}/perf-core/.*|.*%{_libdir}/traceevent/.*|XXX' -o perf-debugfiles.list} + +%if 0%{?with_python2} +%debuginfo_template -n python2-perf +%files -n python2-perf-debuginfo -f python2-perf-debugfiles.list +%{expand:%%global _find_debuginfo_opts %{?_find_debuginfo_opts} -p '.*%{python2_sitearch}/perf.*(.debug)?|XXX' -o python2-perf-debugfiles.list} +%endif + +%debuginfo_template -n python3-perf +%files -n python3-perf-debuginfo -f python3-perf-debugfiles.list +%{expand:%%global _find_debuginfo_opts %{?_find_debuginfo_opts} -p '.*%{python3_sitearch}/perf.*(.debug)?|XXX' -o python3-perf-debugfiles.list} +#with_perf +%endif + +%endif + +%prep + +%setup -q -n kernel-%{version} -c + +%if 0%{?with_patch} +tar -xjf %{SOURCE9998} +%endif + +mv kernel linux-%{KernelVer} +cd linux-%{KernelVer} + +# process PGP certs +cp %{SOURCE13} . +cp %{SOURCE14} . +sh %{SOURCE14} +cp pubring.gpg certs + +%if 0%{?with_patch} +cp %{SOURCE9000} . +cp %{SOURCE9001} . +cp %{SOURCE9002} . + +if [ ! -d patches ];then + mv ../patches . +fi + +Applypatches() +{ + set -e + set -o pipefail + local SERIESCONF=$1 + local PATCH_DIR=$2 + sed -i '/^#/d' $SERIESCONF + sed -i '/^[\s]*$/d' $SERIESCONF + ( + echo "trap 'echo \"*** patch \$_ failed ***\"' ERR" + echo "set -ex" + cat $SERIESCONF | \ + sed "s!^!patch -s -F0 -E -p1 --no-backup-if-mismatch -i $PATCH_DIR/!" \ + ) | sh +} + +Applypatches series.conf %{_builddir}/kernel-%{version}/linux-%{KernelVer} +%endif + +%if "%toolchain" == "clang" +%patch0002 -p1 +%patch0003 -p1 +%patch0004 -p1 +%endif + +%patch0005 -p1 + +find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null +find . -name .gitignore -exec rm -f {} \; >/dev/null + +%if 0%{?with_signmodules} + cp %{SOURCE11} certs/. +%endif + +%if 0%{?with_source} +# Copy directory backup for kernel-source +cp -a ../linux-%{KernelVer} ../linux-%{KernelVer}-source +find ../linux-%{KernelVer}-source -type f -name "\.*" -exec rm -rf {} \; >/dev/null +%endif + +cp -a tools/perf tools/python3-perf + +%build +cd linux-%{KernelVer} + +perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = -%{release}.%{_target_cpu}/" Makefile + +## make linux +make mrproper %{_smp_mflags} + +%if %{with_64kb} +sed -i arch/arm64/configs/openeuler_defconfig -e 's/^CONFIG_ARM64_4K_PAGES.*/CONFIG_ARM64_64K_PAGES=y/' +sed -i arch/arm64/configs/openeuler_defconfig -e 's/^CONFIG_ARM64_PA_BITS=.*/CONFIG_ARM64_PA_BITS=52/' +sed -i arch/arm64/configs/openeuler_defconfig -e 's/^CONFIG_ARM64_PA_BITS_.*/CONFIG_ARM64_PA_BITS_52=y/' +sed -i arch/arm64/configs/openeuler_defconfig -e 's/^CONFIG_ARM64_VA_BITS=.*/CONFIG_ARM64_VA_BITS=52/' +sed -i arch/arm64/configs/openeuler_defconfig -e 's/^CONFIG_ARM64_VA_BITS_.*/CONFIG_ARM64_VA_BITS_52=y/' +%endif + +%if "%toolchain" == "clang" + +%ifarch s390x ppc64le +%global llvm_ias 0 +%else +%global llvm_ias 1 +%endif + +%global clang_make_opts HOSTCC=clang CC=clang LLVM_IAS=%{llvm_ias} + +%if %{with clang_lto} +%global clang_make_opts %{clang_make_opts} HOSTLD=ld.lld LD=ld.lld AR=llvm-ar NM=llvm-nm HOSTAR=llvm-ar HOSTNM=llvm-nm +%endif + +%endif + +%global make %{__make} %{?clang_make_opts} HOSTCFLAGS="%{?build_cflags}" HOSTLDFLAGS="%{?build_ldflags}" + +%{make} ARCH=%{Arch} openeuler_defconfig + +%if %{with clang_lto} +scripts/config -e LTO_CLANG_FULL +sed -i 's/# CONFIG_LTO_CLANG_FULL is not set/CONFIG_LTO_CLANG_FULL=y/' .config +sed -i 's/CONFIG_LTO_NONE=y/# CONFIG_LTO_NONE is not set/' .config +%endif + +TargetImage=$(basename $(make -s image_name)) + +%{make} ARCH=%{Arch} $TargetImage %{?_smp_mflags} +%{make} ARCH=%{Arch} modules %{?_smp_mflags} + +%if 0%{?with_kabichk} + chmod 0755 %{SOURCE18} + if [ -e $RPM_SOURCE_DIR/Module.kabi_%{_target_cpu} ]; then + %{SOURCE18} -k $RPM_SOURCE_DIR/Module.kabi_%{_target_cpu} -s Module.symvers || exit 1 + else + echo "**** NOTE: Cannot find reference Module.kabi file. ****" + fi +%endif + +# aarch64 make dtbs +%ifarch aarch64 riscv64 + %{make} ARCH=%{Arch} dtbs +%endif + +## make tools +%if %{with_perf} +# perf +%global perf_make \ + make %{?clang_make_opts} EXTRA_LDFLAGS="%[ "%{toolchain}" == "clang" ? "-z now" : "" ]" EXTRA_CFLAGS="%[ "%{toolchain}" == "clang" ? "" : "-Wl,-z,now" ] -g -Wall -fstack-protector-strong -fPIC" EXTRA_PERFLIBS="-fpie -pie" %{?_smp_mflags} -s V=1 WERROR=0 NO_LIBUNWIND=1 HAVE_CPLUS_DEMANGLE=1 NO_GTK2=1 NO_LIBNUMA=1 NO_STRLCPY=1 prefix=%{_prefix} +%if 0%{?with_python2} +%global perf_python2 -C tools/perf PYTHON=%{__python2} +%global perf_python3 -C tools/python3-perf PYTHON=%{__python3} +%else +%global perf_python3 -C tools/perf PYTHON=%{__python3} +%endif + +chmod +x tools/perf/check-headers.sh +# perf +%if 0%{?with_python2} +%{perf_make} %{perf_python2} all +%endif + +# make sure check-headers.sh is executable +chmod +x tools/python3-perf/check-headers.sh +%{perf_make} %{perf_python3} all + +pushd tools/perf/Documentation/ +%{make} %{?_smp_mflags} man +popd +%endif + +# bpftool +pushd tools/bpf/bpftool +%{make} +popd + +# cpupower +chmod +x tools/power/cpupower/utils/version-gen.sh +%{make} %{?_smp_mflags} -C tools/power/cpupower CPUFREQ_BENCH=false +%ifarch %{ix86} + pushd tools/power/cpupower/debug/i386 + %{make} %{?_smp_mflags} centrino-decode powernow-k8-decode + popd +%endif +%ifarch x86_64 + pushd tools/power/cpupower/debug/x86_64 + %{make} %{?_smp_mflags} centrino-decode powernow-k8-decode + popd +%endif +%ifarch %{ix86} x86_64 + pushd tools/power/x86/x86_energy_perf_policy/ + %{make} + popd + pushd tools/power/x86/turbostat + %{make} + popd +%endif +# thermal +pushd tools/thermal/tmon/ +%{make} +popd +# iio +pushd tools/iio/ +%{make} +popd +# gpio +pushd tools/gpio/ +%{make} +popd +# kvm +pushd tools/kvm/kvm_stat/ +%{make} %{?_smp_mflags} man +popd + +%install +%if 0%{?with_source} + %define _python_bytecompile_errors_terminate_build 0 + mkdir -p $RPM_BUILD_ROOT/usr/src/ + mv linux-%{KernelVer}-source $RPM_BUILD_ROOT/usr/src/linux-%{KernelVer} + cp linux-%{KernelVer}/.config $RPM_BUILD_ROOT/usr/src/linux-%{KernelVer}/ +%endif + +cd linux-%{KernelVer} + +## install linux + +# deal with kernel-source, now we don't need kernel-source +#mkdir $RPM_BUILD_ROOT/usr/src/linux-%{KernelVer} +#tar cf - --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git --exclude=.tmp_versions --exclude=*vmlinux* --exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation --exclude=.config.old --exclude=.missing-syscalls.d --exclude=patches . | tar xf - -C %{buildroot}/usr/src/linux-%{KernelVer} + +mkdir -p $RPM_BUILD_ROOT/boot +dd if=/dev/zero of=$RPM_BUILD_ROOT/boot/initramfs-%{KernelVer}.img bs=1M count=20 + +install -m 755 $(make -s image_name) $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer} + +%if 0%{?openEuler_sign_rsa} + echo "start sign" + %ifarch %arm aarch64 + gunzip -c $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer}>$RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer}.unzip.efi + /opt/sign-openEuler/client --config /opt/sign-openEuler/config.toml add --key-name default-x509ee --file-type efi-image --key-type x509ee --sign-type authenticode $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer}.unzip.efi + mv $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer}.unzip.efi $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer}.unzip + gzip -c $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer}.unzip>$RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer} + rm -f $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer}.unzip + %endif + %ifarch x86_64 + mv $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer} $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer}.efi + /opt/sign-openEuler/client --config /opt/sign-openEuler/config.toml add --key-name default-x509ee --file-type efi-image --key-type x509ee --sign-type authenticode $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer}.efi + mv $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer}.efi $RPM_BUILD_ROOT/boot/vmlinuz-%{KernelVer} + %endif +%endif + +pushd $RPM_BUILD_ROOT/boot +sha512hmac ./vmlinuz-%{KernelVer} >./.vmlinuz-%{KernelVer}.hmac +popd + +install -m 644 .config $RPM_BUILD_ROOT/boot/config-%{KernelVer} +install -m 644 System.map $RPM_BUILD_ROOT/boot/System.map-%{KernelVer} + +gzip -c9 < Module.symvers > $RPM_BUILD_ROOT/boot/symvers-%{KernelVer}.gz + +mkdir -p $RPM_BUILD_ROOT%{_sbindir} +install -m 755 %{SOURCE200} $RPM_BUILD_ROOT%{_sbindir}/mkgrub-menu-%{version}-%{devel_release}%{?maintenance_release}%{?pkg_release}.sh + + +%if 0%{?with_debuginfo} + mkdir -p $RPM_BUILD_ROOT%{debuginfodir}/lib/modules/%{KernelVer} + cp vmlinux $RPM_BUILD_ROOT%{debuginfodir}/lib/modules/%{KernelVer} +%endif + +# deal with module, if not kdump +%{make} ARCH=%{Arch} INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_install KERNELRELEASE=%{KernelVer} mod-fw= +######## to collect ko to module.filelist about netwoking. block. drm. modesetting ############### +pushd $RPM_BUILD_ROOT/lib/modules/%{KernelVer} +find -type f -name "*.ko" >modnames + +# mark modules executable so that strip-to-file can strip them +xargs --no-run-if-empty chmod u+x < modnames + +# Generate a list of modules for block and networking. + +grep -F /drivers/ modnames | xargs --no-run-if-empty nm -upA | +sed -n 's,^.*/\([^/]*\.ko\): *U \(.*\)$,\1 \2,p' > drivers.undef + +collect_modules_list() +{ + sed -r -n -e "s/^([^ ]+) \\.?($2)\$/\\1/p" drivers.undef | + LC_ALL=C sort -u > modules.$1 + if [ ! -z "$3" ]; then + sed -r -e "/^($3)\$/d" -i modules.$1 + fi +} + +collect_modules_list networking \ + 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register|rt2x00(pci|usb)_probe|register_netdevice' +collect_modules_list block \ + 'ata_scsi_ioctl|scsi_add_host|scsi_add_host_with_dma|blk_alloc_queue|blk_init_queue|register_mtd_blktrans|scsi_esp_register|scsi_register_device_handler|blk_queue_physical_block_size|ahci_platform_get_resources' 'pktcdvd.ko|dm-mod.ko' +collect_modules_list drm \ + 'drm_open|drm_init' +collect_modules_list modesetting \ + 'drm_crtc_init' + +# detect missing or incorrect license tags +rm -f modinfo +while read i +do + echo -n "$i " >> modinfo + /sbin/modinfo -l $i >> modinfo +done < modnames + +grep -E -v \ + 'GPL( v2)?$|Dual BSD/GPL$|Dual MPL/GPL$|GPL and additional rights$' \ + modinfo && exit 1 + +rm -f modinfo modnames drivers.undef + +for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap +do + rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/modules.$i +done +popd +# modsign module ko;need after find-debuginfo,strip +%define __modsign_install_post \ + if [ "%{with_signmodules}" -eq "1" ];then \ + cp certs/signing_key.pem . \ + cp certs/signing_key.x509 . \ + chmod 0755 %{modsign_cmd} \ + %{modsign_cmd} $RPM_BUILD_ROOT/lib/modules/%{KernelVer} || exit 1 \ + fi \ + find $RPM_BUILD_ROOT/lib/modules/ -type f -name '*.ko' | xargs -n1 -P`nproc --all` xz; \ +%{nil} + +# deal with header +%{make} ARCH=%{Arch} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr KBUILD_SRC= headers_install +find $RPM_BUILD_ROOT/usr/include -name "\.*" -exec rm -rf {} \; + +# dtbs install +%ifarch aarch64 riscv64 + mkdir -p $RPM_BUILD_ROOT/boot/dtb-%{KernelVer} + install -m 644 $(find arch/%{Arch}/boot -name "*.dtb") $RPM_BUILD_ROOT/boot/dtb-%{KernelVer}/ + rm -f $(find arch/$Arch/boot -name "*.dtb") +%endif + +# deal with vdso +%{make} -s ARCH=%{Arch} INSTALL_MOD_PATH=$RPM_BUILD_ROOT vdso_install KERNELRELEASE=%{KernelVer} +if [ ! -s ldconfig-kernel.conf ]; then + echo "# Placeholder file, no vDSO hwcap entries used in this kernel." >ldconfig-kernel.conf +fi +install -D -m 444 ldconfig-kernel.conf $RPM_BUILD_ROOT/etc/ld.so.conf.d/kernel-%{KernelVer}.conf + +# deal with /lib/module/ path- sub path: build source kernel +rm -f $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build +rm -f $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/source +mkdir -p $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build +mkdir -p $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/extra +mkdir -p $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/updates +mkdir -p $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/weak-updates +############ to do collect devel file ######### +# 1. Makefile And Kconfig, .config sysmbol +# 2. scrpits dir +# 3. .h file +find -type f \( -name "Makefile*" -o -name "Kconfig*" \) -exec cp --parents {} $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build \; +for f in Module.symvers System.map Module.markers .config;do + test -f $f || continue + cp $f $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build +done + +cp -a scripts $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build +if [ -d arch/%{Arch}/scripts ]; then + cp -a arch/%{Arch}/scripts $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/arch/%{_arch} || : +fi +if [ -f arch/%{Arch}/*lds ]; then + cp -a arch/%{Arch}/*lds $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/arch/%{_arch}/ || : +fi +find $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/scripts/ -name "*.o" -exec rm -rf {} \; + +if [ -d arch/%{Arch}/include ]; then + cp -a --parents arch/%{Arch}/include $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/ +fi +cp -a include $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/include + +if [ -f arch/%{Arch}/kernel/module.lds ]; then + cp -a --parents arch/%{Arch}/kernel/module.lds $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/ +fi + +# module.lds is moved to scripts by commit 596b0474d3d9 in linux 5.10. +if [ -f scripts/module.lds ]; then + cp -a --parents scripts/module.lds $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/ +fi + +%ifarch aarch64 + cp -a --parents arch/arm/include/asm $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/ +%endif + +# copy objtool for kernel-devel (needed for building external modules) +if grep -q CONFIG_OBJTOOL=y .config; then + mkdir -p $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/tools/objtool + cp -a tools/objtool/objtool $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/tools/objtool +fi + +# Make sure the Makefile and version.h have a matching timestamp so that +# external modules can be built +touch -r $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/Makefile $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/include/generated/uapi/linux/version.h +touch -r $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/.config $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/include/generated/autoconf.h +# for make prepare +if [ ! -f $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/include/config/auto.conf ];then + cp .config $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build/include/config/auto.conf +fi + +mkdir -p %{buildroot}/usr/src/kernels +mv $RPM_BUILD_ROOT/lib/modules/%{KernelVer}/build $RPM_BUILD_ROOT/usr/src/kernels/%{KernelVer} + +find $RPM_BUILD_ROOT/usr/src/kernels/%{KernelVer} -name ".*.cmd" -exec rm -f {} \; + +pushd $RPM_BUILD_ROOT/lib/modules/%{KernelVer} +ln -sf /usr/src/kernels/%{KernelVer} build +ln -sf build source +popd + + +# deal with doc , now we don't need + + +# deal with kernel abi whitelists. now we don't need + + +## install tools +%if %{with_perf} +# perf +# perf tool binary and supporting scripts/binaries +%if 0%{?with_python2} +%{perf_make} %{perf_python2} DESTDIR=%{buildroot} lib=%{_lib} install-bin +%else +%{perf_make} %{perf_python3} DESTDIR=%{buildroot} lib=%{_lib} install-bin +%endif +# remove the 'trace' symlink. +rm -f %{buildroot}%{_bindir}/trace + +# remove examples +rm -rf %{buildroot}/usr/lib/perf/examples +# remove the stray header file that somehow got packaged in examples +rm -rf %{buildroot}/usr/lib/perf/include/bpf/ + +# python-perf extension +%{perf_make} %{perf_python3} DESTDIR=%{buildroot} install-python_ext +%if 0%{?with_python2} +%{perf_make} %{perf_python2} DESTDIR=%{buildroot} install-python_ext +%endif + +# perf man pages (note: implicit rpm magic compresses them later) +install -d %{buildroot}/%{_mandir}/man1 +install -pm0644 tools/kvm/kvm_stat/kvm_stat.1 %{buildroot}/%{_mandir}/man1/ +install -pm0644 tools/perf/Documentation/*.1 %{buildroot}/%{_mandir}/man1/ +%endif + +# bpftool +pushd tools/bpf/bpftool +%{make} DESTDIR=%{buildroot} prefix=%{_prefix} bash_compdir=%{_sysconfdir}/bash_completion.d/ mandir=%{_mandir} install doc-install +popd + +# resolve_btfids +mkdir -p %{buildroot}/usr/src/kernels/%{KernelVer}/tools/bpf/resolve_btfids +cp tools/bpf/resolve_btfids/resolve_btfids %{buildroot}/usr/src/kernels/%{KernelVer}/tools/bpf/resolve_btfids + +# cpupower +%{make} -C tools/power/cpupower DESTDIR=%{buildroot} libdir=%{_libdir} mandir=%{_mandir} CPUFREQ_BENCH=false install +rm -f %{buildroot}%{_libdir}/*.{a,la} +%find_lang cpupower +mv cpupower.lang ../ +%ifarch %{ix86} + pushd tools/power/cpupower/debug/i386 + install -m755 centrino-decode %{buildroot}%{_bindir}/centrino-decode + install -m755 powernow-k8-decode %{buildroot}%{_bindir}/powernow-k8-decode + popd +%endif +%ifarch x86_64 + pushd tools/power/cpupower/debug/x86_64 + install -m755 centrino-decode %{buildroot}%{_bindir}/centrino-decode + install -m755 powernow-k8-decode %{buildroot}%{_bindir}/powernow-k8-decode + popd +%endif +chmod 0755 %{buildroot}%{_libdir}/libcpupower.so* +mkdir -p %{buildroot}%{_unitdir} %{buildroot}%{_sysconfdir}/sysconfig +install -m644 %{SOURCE2000} %{buildroot}%{_unitdir}/cpupower.service +install -m644 %{SOURCE2001} %{buildroot}%{_sysconfdir}/sysconfig/cpupower +%ifarch %{ix86} x86_64 + mkdir -p %{buildroot}%{_mandir}/man8 + pushd tools/power/x86/x86_energy_perf_policy + %{make} DESTDIR=%{buildroot} install + popd + pushd tools/power/x86/turbostat + %{make} DESTDIR=%{buildroot} install + popd +%endif +# thermal +pushd tools/thermal/tmon +%{make} INSTALL_ROOT=%{buildroot} install +popd +# iio +pushd tools/iio +%{make} DESTDIR=%{buildroot} install +popd +# gpio +pushd tools/gpio +%{make} DESTDIR=%{buildroot} install +popd +# kvm +pushd tools/kvm/kvm_stat +%{make} INSTALL_ROOT=%{buildroot} install-tools +popd + +%define __spec_install_post\ +%{?__debug_package:%{__debug_install_post}}\ +%{__arch_install_post}\ +%{__os_install_post}\ +%{__modsign_install_post}\ +%{nil} + +%post +%{_sbindir}/new-kernel-pkg --package kernel --install %{KernelVer} || exit $? + +%preun +if [ `uname -i` == "aarch64" ] && + [ -f /boot/EFI/grub2/grub.cfg ]; then + /usr/bin/sh %{_sbindir}/mkgrub-menu-%{version}-%{devel_release}%{?maintenance_release}%{?pkg_release}.sh %{version}-%{release}.aarch64 /boot/EFI/grub2/grub.cfg remove +fi + +%postun +%{_sbindir}/new-kernel-pkg --rminitrd --rmmoddep --remove %{KernelVer} || exit $? +if [ -x %{_sbindir}/weak-modules ] +then + %{_sbindir}/weak-modules --remove-kernel %{KernelVer} || exit $? +fi + +# remove empty directory +if [ -d /lib/modules/%{KernelVer} ] && [ "`ls -A /lib/modules/%{KernelVer}`" = "" ]; then + rm -rf /lib/modules/%{KernelVer} +fi + +%posttrans +%{_sbindir}/new-kernel-pkg --package kernel --mkinitrd --dracut --depmod --update %{KernelVer} || exit $? +%{_sbindir}/new-kernel-pkg --package kernel --rpmposttrans %{KernelVer} || exit $? +if [ `uname -i` == "aarch64" ] && + [ -f /boot/EFI/grub2/grub.cfg ]; then + /usr/bin/sh %{_sbindir}/mkgrub-menu-%{version}-%{devel_release}%{?maintenance_release}%{?pkg_release}.sh %{version}-%{release}.aarch64 /boot/EFI/grub2/grub.cfg update +fi +if [ -x %{_sbindir}/weak-modules ] +then + %{_sbindir}/weak-modules --add-kernel %{KernelVer} || exit $? +fi +%{_sbindir}/new-kernel-pkg --package kernel --mkinitrd --dracut --depmod --update %{KernelVer} || exit $? +%{_sbindir}/new-kernel-pkg --package kernel --rpmposttrans %{KernelVer} || exit $? + +%post devel +if [ -f /etc/sysconfig/kernel ] +then + . /etc/sysconfig/kernel || exit $? +fi +if [ "$HARDLINK" != "no" -a -x /usr/sbin/hardlink ] +then + (cd /usr/src/kernels/%{KernelVer} && + /usr/bin/find . -type f | while read f; do + hardlink -c /usr/src/kernels/*.oe*.*/$f $f + done) +fi + +%post -n %{name}-tools +/sbin/ldconfig +%systemd_post cpupower.service + +%preun -n %{name}-tools +%systemd_preun cpupower.service + +%postun -n %{name}-tools +/sbin/ldconfig +%systemd_postun cpupower.service + +%files +%defattr (-, root, root) +%doc +/boot/config-* +%ifarch aarch64 riscv64 +/boot/dtb-* +%endif +/boot/symvers-* +/boot/System.map-* +/boot/vmlinuz-* +%ghost /boot/initramfs-%{KernelVer}.img +/boot/.vmlinuz-*.hmac +/etc/ld.so.conf.d/* +/lib/modules/%{KernelVer}/ +%exclude /lib/modules/%{KernelVer}/source +%exclude /lib/modules/%{KernelVer}/build +%{_sbindir}/mkgrub-menu*.sh + +%files devel +%defattr (-, root, root) +%doc +/lib/modules/%{KernelVer}/source +/lib/modules/%{KernelVer}/build +/usr/src/kernels/%{KernelVer} + +%files headers +%defattr (-, root, root) +/usr/include/* + +%if %{with_perf} +%files -n perf +%{_bindir}/perf +%{_libdir}/libperf-jvmti.so +%{_libexecdir}/perf-core +%{_datadir}/perf-core/ +%{_mandir}/man[1-8]/perf* +%{_sysconfdir}/bash_completion.d/perf +%doc linux-%{KernelVer}/tools/perf/Documentation/examples.txt +%dir %{_datadir}/doc/perf-tip +%{_datadir}/doc/perf-tip/* +%license linux-%{KernelVer}/COPYING + +%if 0%{?with_python2} +%files -n python2-perf +%license linux-%{KernelVer}/COPYING +%{python2_sitearch}/* +%endif + +%files -n python3-perf +%license linux-%{KernelVer}/COPYING +%{python3_sitearch}/* +%endif + +%files -n %{name}-tools -f cpupower.lang +%{_bindir}/cpupower +%ifarch %{ix86} x86_64 +%{_bindir}/centrino-decode +%{_bindir}/powernow-k8-decode +%endif +%{_unitdir}/cpupower.service +%{_datadir}/bash-completion/completions/cpupower +%{_mandir}/man[1-8]/cpupower* +%config(noreplace) %{_sysconfdir}/sysconfig/cpupower +%ifarch %{ix86} x86_64 +%{_bindir}/x86_energy_perf_policy +%{_mandir}/man8/x86_energy_perf_policy* +%{_bindir}/turbostat +%{_mandir}/man8/turbostat* +%endif +%{_bindir}/tmon +%{_bindir}/iio_event_monitor +%{_bindir}/iio_generic_buffer +%{_bindir}/lsiio +%{_bindir}/lsgpio +%{_bindir}/gpio-hammer +%{_bindir}/gpio-event-mon +%{_bindir}/gpio-watch +%{_mandir}/man1/kvm_stat* +%{_bindir}/kvm_stat +%{_libdir}/libcpupower.so.1 +%{_libdir}/libcpupower.so.0.0.1 +%license linux-%{KernelVer}/COPYING + +%files -n %{name}-tools-devel +%{_libdir}/libcpupower.so +%{_includedir}/cpufreq.h +%{_includedir}/cpuidle.h + +%files -n bpftool +%{_sbindir}/bpftool +%{_sysconfdir}/bash_completion.d/bpftool +%{_mandir}/man8/bpftool-cgroup.8.gz +%{_mandir}/man8/bpftool-map.8.gz +%{_mandir}/man8/bpftool-prog.8.gz +%{_mandir}/man8/bpftool-perf.8.gz +%{_mandir}/man8/bpftool.8.gz +%{_mandir}/man8/bpftool-btf.8.gz +%{_mandir}/man8/bpftool-feature.8.gz +%{_mandir}/man8/bpftool-gen.8.gz +%{_mandir}/man8/bpftool-iter.8.gz +%{_mandir}/man8/bpftool-link.8.gz +%{_mandir}/man8/bpftool-net.8.gz +%{_mandir}/man8/bpftool-struct_ops.8.gz +%license linux-%{KernelVer}/COPYING + +%if 0%{?with_source} +%files source +%defattr(-,root,root) +/usr/src/linux-%{KernelVer}/* +/usr/src/linux-%{KernelVer}/.config +%endif + +%changelog +* Thu Mar 14 2024 Zheng Zengkai - 6.6.0-12.0.0.8 +- !5174 [OLK-6.6][sync from OLK-5.10] Introduce multiple LPI translation caches +- KVM:arm64:vgic update openEuler's config's to enable MULTI_LPI_TRANSLATE_CACHE +- KVM: arm64: vgic-its: Do not execute invalidate MSI-LPI translation cache on movi command +- KVM: arm64: vgic-its: Introduce multiple LPI translation caches +- !5208 Revert “Fix the header file location error and adjust the function and structure version.” +- Revert “Fix the header file location error and adjust the function and structure version.” +- !5199 v2 mTHP anon support +- uprobes: use pagesize-aligned virtual address when replacing pages +- selftests/mm/cow: add tests for anonymous multi-size THP +- selftests/mm/cow: generalize do_run_with_thp() helper +- selftests/mm/khugepaged: enlighten for multi-size THP +- selftests/mm: support multi-size THP interface in thp_settings +- selftests/mm: factor out thp settings management +- selftests/mm/kugepaged: restore thp settings at exit +- mm: thp: support allocation of anonymous multi-size THP +- mm: thp: introduce multi-size THP sysfs interface +- mm: non-pmd-mappable, large folios for folio_add_new_anon_rmap() +- mm: allow deferred splitting of arbitrary anon large folios +- mm/readahead: do not allow order-1 folio +- mm: more ptep_get() conversion +- mm/thp: fix "mm: thp: kill __transhuge_page_enabled()" +- memory: move exclusivity detection in do_wp_page() into wp_can_reuse_anon_folio() +- mm/rmap: convert page_move_anon_rmap() to folio_move_anon_rmap() +- mm/rmap: move SetPageAnonExclusive() out of page_move_anon_rmap() +- mm/rmap: pass folio to hugepage_add_anon_rmap() +- mm/rmap: simplify PageAnonExclusive sanity checks when adding anon rmap +- mm/rmap: warn on new PTE-mapped folios in page_add_anon_rmap() +- mm/rmap: move folio_test_anon() check out of __folio_set_anon() +- mm/rmap: move SetPageAnonExclusive out of __page_set_anon_rmap() +- mm/rmap: drop stale comment in page_add_anon_rmap and hugepage_add_anon_rmap() +- !4908 cgroup/cpuset: add exclusive and exclusive.effective for v2 +- cgroup/cpuset: Fix retval in update_cpumask() +- cgroup/cpuset: Fix a memory leak in update_exclusive_cpumask() +- cgroup/cpuset: Cleanup signedness issue in cpu_exclusive_check() +- cgroup/cpuset: Enable invalid to valid local partition transition +- cgroup/cpuset: Check partition conflict with housekeeping setup +- cgroup/cpuset: Introduce remote partition +- cgroup/cpuset: Add cpuset.cpus.exclusive for v2 +- cgroup/cpuset: Add cpuset.cpus.exclusive.effective for v2 +- !5159 【OLK-6.6】iommu: reserve KABI for struct iommu_ops +- [OLK-6.6] iommu:kabi reserver space for struct iommu_ops +- !5149 net: hns3: add support some customized exception handling interfaces +- net: hns3: add input parameters checking +- net: hns3: add extend interface support for read and write phy register +- net: hns3: add support set led +- net: hns3: add support set mac state +- net: hns3: add support detect port wire type +- net: hns3: add support PF provides customized interfaces to detect port faults. +- net: hns3: support set pfc pause trans time +- net: hns3: add support disable nic clock +- net: hns3: add support config and query serdes lane status +- net: hns3: add supports configure optical module enable +- net: hns3: add support query the presence of optical module +- net: hns3: add support modified tx timeout +- net: hns3: add support query port ext information +- net: hns3: add support configuring function-level interrupt affinity +- net: hns3: add support clear mac statistics +- net: hns3: add support to get/set 1d torus param +- net: hns3: add supports fast reporting of faulty nodes +- net: hns3: add supports pfc storm detection and suppression +- net: hns3: add support customized exception handling interfaces +- !4761 [OLK-6.6] backport 6.7 kernel signal patch +- riscv: signal: handle syscall restart before get_signal +- !5151 intel-sig: configs: enable TPMI related configs for OLK6.6 +- config: update Intel TPMI based driver configs to openeuler_defconfig for x86 +- !5150 intel-sig: configs: enable PMT related configs for OLK6.6 +- config: x86: Intel: enabled PMT SDSI TPMI configs +- !4427 【OLK-6.6】watchdog: Support watchdog_sdei coexist with existing watchdogs +- watchdog: Support watchdog_sdei coexist with existing watchdogs +- !4776 [OLK-6.6] kabi:reserve space for msi expansion +- [OLK-6.6] kabi:reserve space for msi expansion +- !5041 [OLK-6.6] support the AMD Zen5 Turin +- x86/CPU/AMD: Add more models to X86_FEATURE_ZEN5 +- x86/CPU/AMD: Add X86_FEATURE_ZEN5 +- x86/CPU/AMD: Add X86_FEATURE_ZEN1 +- x86/CPU/AMD: Drop now unused CPU erratum checking function +- x86/CPU/AMD: Get rid of amd_erratum_1485[] +- x86/CPU/AMD: Get rid of amd_erratum_400[] +- x86/CPU/AMD: Get rid of amd_erratum_383[] +- x86/CPU/AMD: Get rid of amd_erratum_1054[] +- x86/CPU/AMD: Move the DIV0 bug detection to the Zen1 init function +- x86/CPU/AMD: Move Zenbleed check to the Zen2 init function +- x86/CPU/AMD: Rename init_amd_zn() to init_amd_zen_common() +- x86/CPU/AMD: Call the spectral chicken in the Zen2 init function +- x86/CPU/AMD: Move erratum 1076 fix into the Zen1 init function +- x86/CPU/AMD: Move the Zen3 BTC_NO detection to the Zen3 init function +- x86/CPU/AMD: Carve out the erratum 1386 fix +- x86/CPU/AMD: Add ZenX generations flags +- !5036 [OLK-6.6] Do not serialize MSR accesses on AMD +- x86/barrier: Do not serialize MSR accesses on AMD +- !5134 modpost: Optimize symbol search from linear to binary search +- modpost: Optimize symbol search from linear to binary search +- !4826 add sw64 architecture support +- drivers: vfio: add sw64 support +- drivers: usb: add sw64 support +- drivers: tty: add sw64 support +- drivers: spi: add sw64 support +- drivers: scsi: add sw64 support +- drivers: rtc: add sw64 rtc support +- drivers: qemu_fw_cfg: add sw64 support +- drivers: platform: add sw64 support +- drivers: pci: add sw64 support +- drivers: misc: add sw64 support +- drivers: mfd: add sw64 support +- drivers: irqchip: add sw64 support +- drivers: iommu: add sw64 support +- drivers: i2c: add sw64 support +- drivers: hwmon: add sw64 support +- drivers: gpio: add sw64 support +- drivers: efi: add sw64 support +- !4927 ima: digest list new support modsig +- ima: digest list new support modsig +- !4971 net: hns3: backport some patch from kernel 6.7 +- net: hns3: add some link modes for hisilicon device +- net: hns3: add vf fault detect support +- net: hns3: add hns3 vf fault detect cap bit support +- !5040 [OLK-6.6] Add support for Vendor Defined Error Types in Einj Module +- ACPI: APEI: EINJ: Add support for vendor defined error types +- platform/chrome: cros_ec_debugfs: Fix permissions for panicinfo +- fs: debugfs: Add write functionality to debugfs blobs +- ACPI: APEI: EINJ: Refactor available_error_type_show() +- !5039 [OLK-6.6] Fix disabling memory if DVSEC CXL Range does not match a CFMWS window +- cxl/pci: Fix disabling memory if DVSEC CXL Range does not match a CFMWS window +- !5047 Backport etmem swapcache recalim feature to OLK 6.6 +- etmem: add swapcache reclaim to etmem +- etmem: Expose symbol reclaim_folio_list +- !4514 [OLK-6.6] kabi: IOMMU subsystem reservation +- kabi: IOMMU reservations +- kabi: bus_type, device_driver, dev_pm_ops reservation +- !5056 erofs: fix handling kern_mount() failure +- erofs: fix handling kern_mount() failure +- !5059 dm: limit the number of targets and parameter size area +- dm: limit the number of targets and parameter size area +- !5021 LoongArch: fix some known issue and update defconfig +- LoongArch: enable CONFIG_DEBUG_INFO_BTF by default +- net: stmmac: fix potential double free of dma descriptor resources +- drm/radeon: Workaround radeon driver bug for Loongson +- irqchip/loongson-liointc: Set different isr for differnt core +- LoongArch: kdump: Add high memory reservation +- LoongArch: Fix kdump failure on v40 interface specification +- LoongArch: kexec: Add compatibility with old interfaces +- LoongArch: kdump: Add memory reservation for old kernel +- LoongArch: defconfig: Enable a large number of configurations +- irqchip/loongson-pch-pic: 7a1000 int_clear reg must use 64bit write. +- LoongArch: Remove generic irq migration +- LoongArch: Adapted SECTION_SIZE_BITS with page size +- !4689 Remove WQ_FLAG_BOOKMARK flag +- sched: remove wait bookmarks +- filemap: remove use of wait bookmarks +- !5024 v2 vmemmap optimize bugfix +- mm: hugetlb_vmemmap: allow alloc vmemmap pages fallback to other nodes +- mm: hugetlb_vmemmap: fix hugetlb page number decrease failed on movable nodes +- !4653 [OLK-6.6] Add support for Mucse Network Adapter(N10/N400) +- drivers: initial support for rnp drivers from Mucse Technology +- !4935 RDMA/hns: Support userspace configuring congestion control algorithm with QP granularity +- RDMA/hns: Support userspace configuring congestion control algorithm with QP granularity +- RDMA/hns: Fix mis-modifying default congestion control algorithm +- !4993 v3 kworker: Fix the problem of ipsan performance degradation +- Add kernel compilation configuration options +- iscsi: use dynamic single thread workqueue to improve performance +- workqueue: add member for NUMA aware order workqueue and implement NUMA affinity for single thread workqueue +- !4930 erofs: fix lz4 inplace decompression +- erofs: fix lz4 inplace decompression +- !4082 【OLK-6.6】KVM: arm64: vtimer irq bypass support +- mbigen: probe mbigen driver with arch_initcall +- mbigen: vtimer: disable vtimer mbigen probe when vtimer_irqbypass disabled +- mbigen: Sets the regs related to vtimer irqbypass +- KVM: arm64: vgic-v3: Clearing pending status of vtimer on guest reset +- mbigen: vtimer: add support for MBIX1_CPPI_NEGEDGE_CLR_EN_SETR(CLRR) +- KVM: arm64: arch_timer: Make vtimer_irqbypass a Distributor attr +- KVM: arm64: vtimer: Expose HW-based vtimer interrupt in debugfs +- KVM: arm64: GICv4.1: Allow non-trapping WFI when using direct vtimer interrupt +- KVM: arm64: GICv4.1: Add support for MBIGEN save/restore +- KVM: arm64: arch_timer: Rework vcpu init/reset logic +- KVM: arm64: arch_timer: Probe vtimer irqbypass capability +- KVM: arm64: GICv4.1: Enable vtimer vPPI irqbypass config +- KVM: arm64: GICv4.1: Add direct injection capability to PPI registers +- KVM: arm64: vgic: Add helper for vtimer vppi info register +- KVM: arm64: GICv4.1: Inform the HiSilicon vtimer irqbypass capability +- irqchip/gic-v4.1: Probe vtimer irqbypass capability at RD level +- irqchip/gic-v4.1: Rework its_alloc_vcpu_sgis() to support vPPI allocation +- irqchip/gic-v4.1: Rework get/set_irqchip_state callbacks of GICv4.1-sgi chip +- irqchip/gic-v4.1: Extend VSGI command to support the new vPPI +- irqchip/gic-v4.1: Detect ITS vtimer interrupt bypass capability +- mbigen: vtimer mbigen driver support +- mbigen: vtimer: isolate mbigen vtimer funcs with macro +- !4875 [OLK-6.6] backport latest v6.8 iommu fixes +- iommufd/selftest: Don't check map/unmap pairing with HUGE_PAGES +- iommufd: Fix protection fault in iommufd_test_syz_conv_iova +- iommufd/selftest: Fix mock_dev_num bug +- iommufd: Fix iopt_access_list_id overwrite bug +- iommu/sva: Fix SVA handle sharing in multi device case +- !4867 ext4: regenerate buddy after block freeing failed if under fc replay +- ext4: regenerate buddy after block freeing failed if under fc replay +- !4851 cachefiles: fix memory leak in cachefiles_add_cache() +- cachefiles: fix memory leak in cachefiles_add_cache() +- !4913 RDMA/hns: Support SCC parameter configuration and reporting of the down/up event of the HNS RoCE network port +- RDMA/hns: Add support for sending port down event fastly +- RDMA/hns: Deliver net device event to ofed +- RDMA/hns: Support congestion control algorithm parameter configuration +- !4670 crypto HiSilicon round main line code +- crypto: hisilicon/qm - change function type to void +- crypto: hisilicon/qm - obtain stop queue status +- crypto: hisilicon/qm - add stop function by hardware +- crypto: hisilicon/sec - remove unused parameter +- crypto: hisilicon/sec2 - fix some cleanup issues +- crypto: hisilicon/sec2 - modify nested macro call +- crypto: hisilicon/sec2 - updates the sec DFX function register +- crypto: hisilicon - Fix smp_processor_id() warnings +- crypto: hisilicon/qm - dump important registers values before resetting +- crypto: hisilicon/qm - support get device state +- crypto: hisilicon/sec2 - optimize the error return process +- crypto: hisilicon/qm - delete a dbg function +- crypto: hisilicon/sec2 - Remove cfb and ofb +- crypto: hisilicon/zip - save capability registers in probe process +- crypto: hisilicon/sec2 - save capability registers in probe process +- crypto: hisilicon/hpre - save capability registers in probe process +- crypto: hisilicon/qm - save capability registers in qm init process +- crypto: hisilicon/qm - add a function to set qm algs +- crypto: hisilicon/qm - add comments and remove redundant array element +- crypto: hisilicon/qm - simplify the status of qm +- crypto: hisilicon/sgl - small cleanups for sgl.c +- crypto: hisilicon/zip - add zip comp high perf mode configuration +- crypto: hisilicon/qm - remove incorrect type cast +- crypto: hisilicon/qm - print device abnormal information +- crypto: hisilicon/trng - Convert to platform remove callback returning void +- crypto: hisilicon/sec - Convert to platform remove callback returning void +- crypto: hisilicon/qm - fix EQ/AEQ interrupt issue +- crypto: hisilicon/qm - alloc buffer to set and get xqc +- crypto: hisilicon/qm - check function qp num before alg register +- crypto: hisilicon/qm - fix the type value of aeq +- crypto: hisilicon/sec - fix for sgl unmmap problem +- crypto: hisilicon/zip - remove zlib and gzip +- crypto: hisilicon/zip - support deflate algorithm +- uacce: make uacce_class constant +- !4725 [OLK-6.6] merge upstream net-v6.7 all wangxun patches +- net: fill in MODULE_DESCRIPTION()s for wx_lib +- wangxun: select CONFIG_PHYLINK where needed +- net: wangxun: add ethtool_ops for msglevel +- net: wangxun: add coalesce options support +- net: wangxun: add ethtool_ops for ring parameters +- net: wangxun: add flow control support +- net: ngbe: convert phylib to phylink +- net: txgbe: use phylink bits added in libwx +- net: libwx: add phylink to libwx +- net: wangxun: remove redundant kernel log +- net: ngbe: add ethtool stats support +- net: txgbe: add ethtool stats support +- net: wangxun: move MDIO bus implementation to the library +- net: libwx: fix memory leak on free page +- net: libwx: support hardware statistics +- net: wangxun: fix changing mac failed when running +- !4841 Intel-sig: intel_idle: add Sierra Forest SoC support on 6.6 +- intel_idle: add Sierra Forest SoC support +- !4834 ras: fix return type of log_arm_hw_error when not add CONFIG_RAS_ARM_EVENT_INFO config +- ras: fix return type of log_arm_hw_error when not add CONFIG_RAS_ARM_EVENT_INFO config +- !4845 PCI: Avoid potential out-of-bounds read in pci_dev_for_each_resource() +- PCI: Avoid potential out-of-bounds read in pci_dev_for_each_resource() +- !4773 Add loongarch kernel kvm support +- loongarch/kernel: Fix loongarch compilation error +- LoongArch: KVM: Add returns to SIMD stubs +- LoongArch: KVM: Streamline kvm_check_cpucfg() and improve comments +- LoongArch: KVM: Rename _kvm_get_cpucfg() to _kvm_get_cpucfg_mask() +- LoongArch: KVM: Fix input validation of _kvm_get_cpucfg() & kvm_check_cpucfg() +- irqchip/loongson-eiointc: Use correct struct type in eiointc_domain_alloc() +- LoongArch: KVM: Add LASX (256bit SIMD) support +- LoongArch: KVM: Add LSX (128bit SIMD) support +- LoongArch: KVM: Fix timer emulation with oneshot mode +- LoongArch: KVM: Remove kvm_acquire_timer() before entering guest +- LoongArch: KVM: Allow to access HW timer CSR registers always +- LoongArch: KVM: Remove SW timer switch when vcpu is halt polling +- LoongArch: KVM: Optimization for memslot hugepage checking +- LoongArch: Implement constant timer shutdown interface +- LoongArch: KVM: Add maintainers for LoongArch KVM +- LoongArch: KVM: Supplement kvm document about LoongArch-specific part +- LoongArch: KVM: Enable kvm config and add the makefile +- LoongArch: KVM: Implement vcpu world switch +- LoongArch: KVM: Implement kvm exception vectors +- LoongArch: KVM: Implement handle fpu exception +- LoongArch: KVM: Implement handle mmio exception +- LoongArch: KVM: Implement handle gspr exception +- LoongArch: KVM: Implement handle idle exception +- LoongArch: KVM: Implement handle iocsr exception +- LoongArch: KVM: Implement handle csr exception +- LoongArch: KVM: Implement kvm mmu operations +- LoongArch: KVM: Implement virtual machine tlb operations +- LoongArch: KVM: Implement vcpu timer operations +- LoongArch: KVM: Implement misc vcpu related interfaces +- LoongArch: KVM: Implement vcpu load and vcpu put operations +- LoongArch: KVM: Implement vcpu interrupt operations +- LoongArch: KVM: Implement fpu operations for vcpu +- LoongArch: KVM: Implement basic vcpu ioctl interfaces +- LoongArch: KVM: Implement basic vcpu interfaces +- LoongArch: KVM: Add vcpu related header files +- LoongArch: KVM: Implement VM related functions +- LoongArch: KVM: Implement kvm hardware enable, disable interface +- LoongArch: KVM: Implement kvm module related interface +- LoongArch: KVM: Add kvm related header files +- !3951 【OLK-6.6】KVM/arm64: support virt_dev irqbypass +- KVM: arm64: update arm64 openeuler_defconfig for CONFIG_VIRT_PLAT_DEV +- KVM: arm64: sdev: Support virq bypass by INT/VSYNC command +- KVM: arm64: kire: irq routing entry cached the relevant cache data +- KVM: arm64: Introduce shadow device +- virt_plat_dev: Register the virt platform device driver +- irqchip/gic-v3-its: Add virt platform devices MSI support +- irqchip/gic-v3-its: Alloc/Free device id from pools for virtual devices +- irqchip/gic-v3-its: Introduce the reserved device ID pools +- !4425 【OLK-6.6】arm64/nmi: Support for FEAT_NMI +- irqchip/gic-v3: Fix hard LOCKUP caused by NMI being masked +- config: enable CONFIG_ARM64_NMI and CONFIG_HARDLOCKUP_DETECTOR_PERF for arm64 +- irqchip/gic-v3: Implement FEAT_GICv3_NMI support +- arm64/nmi: Add Kconfig for NMI +- arm64/nmi: Add handling of superpriority interrupts as NMIs +- arm64/irq: Document handling of FEAT_NMI in irqflags.h +- arm64/entry: Don't call preempt_schedule_irq() with NMIs masked +- arm64/nmi: Manage masking for superpriority interrupts along with DAIF +- KVM: arm64: Hide FEAT_NMI from guests +- arm64/cpufeature: Detect PE support for FEAT_NMI +- arm64/idreg: Add an override for FEAT_NMI +- arm64/hyp-stub: Enable access to ALLINT +- arm64/asm: Introduce assembly macros for managing ALLINT +- arm64/sysreg: Add definitions for immediate versions of MSR ALLINT +- arm64/booting: Document boot requirements for FEAT_NMI +- !4679 f2fs: fix to avoid dirent corruption +- f2fs: fix to avoid dirent corruption +- !4730 coresight: trbe: Enable ACPI based devices +- coresight: trbe: Enable ACPI based TRBE devices +- coresight: trbe: Add a representative coresight_platform_data for TRBE +- !4807 [OLK-6.6] Intel: backport KVM LAM from v6.8 to OLK-6.6 +- KVM: x86: Use KVM-governed feature framework to track "LAM enabled" +- KVM: x86: Advertise and enable LAM (user and supervisor) +- KVM: x86: Virtualize LAM for user pointer +- KVM: x86: Virtualize LAM for supervisor pointer +- KVM: x86: Untag addresses for LAM emulation where applicable +- KVM: x86: Introduce get_untagged_addr() in kvm_x86_ops and call it in emulator +- KVM: x86: Remove kvm_vcpu_is_illegal_gpa() +- KVM: x86: Add & use kvm_vcpu_is_legal_cr3() to check CR3's legality +- KVM: x86/mmu: Drop non-PA bits when getting GFN for guest's PGD +- KVM: x86: Add X86EMUL_F_INVLPG and pass it in em_invlpg() +- KVM: x86: Add an emulation flag for implicit system access +- KVM: x86: Consolidate flags for __linearize() +- !4700 efivarfs: force RO when remounting if SetVariable is not supported +- efivarfs: force RO when remounting if SetVariable is not supported +- !4785 Support PV-sched feature +- KVM: arm64: Support the vCPU preemption check +- KVM: arm64: Add interface to support vCPU preempted check +- KVM: arm64: Support pvsched preempted via shared structure +- KVM: arm64: Implement PV_SCHED_FEATURES call +- KVM: arm64: Document PV-sched interface +- !4629 add sw64 architecture support +- drivers: cpufreq: add sw64 support +- drivers: clocksource: add sw64 support +- drivers: acpi: add sw64 support +- selftests: fix sw64 support +- perf: fix sw64 support +- perf: add sw64 support +- tools: fix basic sw64 support +- tools: add basic sw64 support +- sw64: fix ftrace support +- sw64: fix audit support +- sw64: fix kexec support +- sw64: fix PCI support +- sw64: fix KVM support +- sw64: fix module support +- sw64: fix ACPI support +- sw64: fix rrk support +- sw64: fix ELF support +- !4727 RAS: Report ARM processor information to userspace +- RAS: Report ARM processor information to userspace +- !4769 [sync] PR-4729: serial: 8250: omap: Don't skip resource freeing if pm_runtime_resume_and_get() failed +- serial: 8250: omap: Don't skip resource freeing if pm_runtime_resume_and_get() failed +- !4781 x86/fpu: Stop relying on userspace for info to fault in xsave buffer +- x86/fpu: Stop relying on userspace for info to fault in xsave buffer +- !4787 v2 gfs2: Fix kernel NULL pointer dereference in gfs2_rgrp_dump +- gfs2: Fix kernel NULL pointer dereference in gfs2_rgrp_dump +- !4789 v2 fix CVE-2024-26590 +- erofs: fix inconsistent per-file compression format +- erofs: simplify compression configuration parser +- !4736 PCIe and miniIO OLK-5.10 branch partial code round OLK-6.6 branch +- xhci:fix USB xhci controller issue +- spi: hisi-sfc-v3xx: return IRQ_NONE if no interrupts were detected +- Add the verification operation after the bus recovery operation obtains resources through the ACPI +- i2c: hisi: Add gpio bus recovery support +- gpio: hisi: Fix format specifier +- perf hisi-ptt: Fix one memory leakage in hisi_ptt_process_auxtrace_event() +- Fix the header file location error and adjust the function and structure version. +- hwtracing: hisi_ptt: Don't try to attach a task +- hwtracing: hisi_ptt: Optimize the trace data committing +- hwtracing: hisi_ptt: Handle the interrupt in hardirq context +- hwtracing: hisi_ptt: Disable interrupt after trace end +- !4802 Export vcpu stat via debugfs +- kvm: debugfs: add EXIT_REASON_PREEMPTION_TIMER to vcpu_stat +- kvm: debugfs: add fastpath msr_wr exits to debugfs statistics +- kvm: debugfs: Export x86 kvm exits to vcpu_stat +- kvm: debugfs: aarch64 export cpu time related items to debugfs +- kvm: debugfs: export remaining aarch64 kvm exit reasons to debugfs +- kvm: debugfs: Export vcpu stat via debugfs +- !4676 [OLK-6.6] kabi/iommu: Backport patches from upstream and maintainer tree +- iommu/sva: Restore SVA handle sharing +- iommu/arm-smmu-v3: Do not use GFP_KERNEL under as spinlock +- Revert "iommu/arm-smmu: Convert to domain_alloc_paging()" +- iommu/vt-d: Fix constant-out-of-range warning +- iommu/vt-d: Set SSADE when attaching to a parent with dirty tracking +- iommu/vt-d: Add missing dirty tracking set for parent domain +- iommu/vt-d: Wrap the dirty tracking loop to be a helper +- iommu/vt-d: Remove domain parameter for intel_pasid_setup_dirty_tracking() +- iommu/vt-d: Add missing device iotlb flush for parent domain +- iommu/vt-d: Update iotlb in nested domain attach +- iommu/vt-d: Add missing iotlb flush for parent domain +- iommu/vt-d: Add __iommu_flush_iotlb_psi() +- iommu/vt-d: Track nested domains in parent +- iommu: Make iommu_report_device_fault() return void +- iommu: Make iopf_group_response() return void +- iommu: Track iopf group instead of last fault +- iommu: Improve iopf_queue_remove_device() +- iommu: Use refcount for fault data access +- iommu: Refine locking for per-device fault data management +- iommu: Separate SVA and IOPF +- iommu: Make iommu_queue_iopf() more generic +- iommu: Prepare for separating SVA and IOPF +- iommu: Merge iommu_fault_event and iopf_fault +- iommu: Remove iommu_[un]register_device_fault_handler() +- iommu: Merge iopf_device_param into iommu_fault_param +- iommu: Cleanup iopf data structure definitions +- iommu: Remove unrecoverable fault data +- iommu/arm-smmu-v3: Remove unrecoverable faults reporting +- iommu: Move iommu fault data to linux/iommu.h +- iommu/iova: use named kmem_cache for iova magazines +- iommu/iova: Reorganise some code +- iommu/iova: Tidy up iova_cache_get() failure +- selftests/iommu: fix the config fragment +- iommufd: Reject non-zero data_type if no data_len is provided +- iommufd/iova_bitmap: Consider page offset for the pages to be pinned +- iommufd/selftest: Add mock IO hugepages tests +- iommufd/selftest: Hugepage mock domain support +- iommufd/selftest: Refactor mock_domain_read_and_clear_dirty() +- iommufd/selftest: Refactor dirty bitmap tests +- iommufd/iova_bitmap: Handle recording beyond the mapped pages +- iommufd/selftest: Test u64 unaligned bitmaps +- iommufd/iova_bitmap: Switch iova_bitmap::bitmap to an u8 array +- iommufd/iova_bitmap: Bounds check mapped::pages access +- powerpc/iommu: Fix the missing iommu_group_put() during platform domain attach +- powerpc: iommu: Bring back table group release_ownership() call +- iommu: Allow ops->default_domain to work when !CONFIG_IOMMU_DMA +- iommufd/selftest: Check the bus type during probe +- iommu/vt-d: Add iotlb flush for nested domain +- iommufd: Add data structure for Intel VT-d stage-1 cache invalidation +- iommufd/selftest: Add coverage for IOMMU_HWPT_INVALIDATE ioctl +- iommufd/selftest: Add IOMMU_TEST_OP_MD_CHECK_IOTLB test op +- iommufd/selftest: Add mock_domain_cache_invalidate_user support +- iommu: Add iommu_copy_struct_from_user_array helper +- iommufd: Add IOMMU_HWPT_INVALIDATE +- iommu: Add cache_invalidate_user op +- iommu: Don't reserve 0-length IOVA region +- iommu/sva: Fix memory leak in iommu_sva_bind_device() +- iommu/dma: Trace bounce buffer usage when mapping buffers +- iommu/tegra: Use tegra_dev_iommu_get_stream_id() in the remaining places +- acpi: Do not return struct iommu_ops from acpi_iommu_configure_id() +- iommu: Mark dev_iommu_priv_set() with a lockdep +- iommu: Mark dev_iommu_get() with lockdep +- iommu/of: Use -ENODEV consistently in of_iommu_configure() +- iommmu/of: Do not return struct iommu_ops from of_iommu_configure() +- iommu: Remove struct iommu_ops *iommu from arch_setup_dma_ops() +- iommu: Set owner token to SVA domain +- mm: Deprecate pasid field +- iommu: Support mm PASID 1:n with sva domains +- mm: Add structure to keep sva information +- iommu: Add mm_get_enqcmd_pasid() helper function +- iommu/vt-d: Remove mm->pasid in intel_sva_bind_mm() +- iommu: Change kconfig around IOMMU_SVA +- iommu: Extend LPAE page table format to support custom allocators +- iommu: Allow passing custom allocators to pgtable drivers +- iommu: Clean up open-coded ownership checks +- iommu: Retire bus ops +- iommu/arm-smmu: Don't register fwnode for legacy binding +- iommu: Decouple iommu_domain_alloc() from bus ops +- iommu: Validate that devices match domains +- iommu: Decouple iommu_present() from bus ops +- iommu: Factor out some helpers +- iommu: Map reserved memory as cacheable if device is coherent +- iommu/vt-d: Move inline helpers to header files +- iommu/vt-d: Remove unused vcmd interfaces +- iommu/vt-d: Remove unused parameter of intel_pasid_setup_pass_through() +- iommu/vt-d: Refactor device_to_iommu() to retrieve iommu directly +- iommu/virtio: Add ops->flush_iotlb_all and enable deferred flush +- iommu/virtio: Make use of ops->iotlb_sync_map +- iommu/arm-smmu: Convert to domain_alloc_paging() +- iommu/arm-smmu: Pass arm_smmu_domain to internal functions +- iommu/arm-smmu: Implement IOMMU_DOMAIN_BLOCKED +- iommu/arm-smmu: Convert to a global static identity domain +- iommu/arm-smmu: Reorganize arm_smmu_domain_add_master() +- iommu/arm-smmu-v3: Remove ARM_SMMU_DOMAIN_NESTED +- iommu/arm-smmu-v3: Master cannot be NULL in arm_smmu_write_strtab_ent() +- iommu/arm-smmu-v3: Add a type for the STE +- iommu/apple-dart: Fix spelling mistake "grups" -> "groups" +- iommu/apple-dart: Use readl instead of readl_relaxed for consistency +- iommu/apple-dart: Add support for t8103 USB4 DART +- iommu/apple-dart: Write to all DART_T8020_STREAM_SELECT +- dt-bindings: iommu: dart: Add t8103-usb4-dart compatible +- iommufd: Do not UAF during iommufd_put_object() +- iommufd: Add iommufd_ctx to iommufd_put_object() +- iommu/vt-d: Support enforce_cache_coherency only for empty domains +- iommu: Flow ERR_PTR out from __iommu_domain_alloc() +- iommu/dma: Use a large flush queue and timeout for shadow_on_flush +- iommu/dma: Allow a single FQ in addition to per-CPU FQs +- iommu/s390: Disable deferred flush for ISM devices +- s390/pci: Use dma-iommu layer +- s390/pci: prepare is_passed_through() for dma-iommu +- iommu: Allow .iotlb_sync_map to fail and handle s390's -ENOMEM return +- iommu/dart: Remove the force_bypass variable +- iommu/dart: Call apple_dart_finalize_domain() as part of alloc_paging() +- iommu/dart: Convert to domain_alloc_paging() +- iommu/dart: Move the blocked domain support to a global static +- iommu/dart: Use static global identity domains +- iommufd: Convert to alloc_domain_paging() +- iommu/vt-d: Use ops->blocked_domain +- iommu/vt-d: Update the definition of the blocking domain +- iommu: Move IOMMU_DOMAIN_BLOCKED global statics to ops->blocked_domain +- iommu: change iommu_map_sgtable to return signed values +- powerpc/iommu: Do not do platform domain attach atctions after probe +- iommu: Fix return code in iommu_group_alloc_default_domain() +- iommu: Do not use IOMMU_DOMAIN_DMA if CONFIG_IOMMU_DMA is not enabled +- iommu: Remove duplicate include +- iommu: Improve map/unmap sanity checks +- iommu: Retire map/unmap ops +- iommu/tegra-smmu: Update to {map,unmap}_pages +- iommu/sun50i: Update to {map,unmap}_pages +- iommu/rockchip: Update to {map,unmap}_pages +- iommu/omap: Update to {map,unmap}_pages +- iommu/exynos: Update to {map,unmap}_pages +- iommu/omap: Convert to generic_single_device_group() +- iommu/ipmmu-vmsa: Convert to generic_single_device_group() +- iommu/rockchip: Convert to generic_single_device_group() +- iommu/sprd: Convert to generic_single_device_group() +- iommu/sun50i: Convert to generic_single_device_group() +- iommu: Add generic_single_device_group() +- iommu: Remove useless group refcounting +- iommu: Convert remaining simple drivers to domain_alloc_paging() +- iommu: Convert simple drivers with DOMAIN_DMA to domain_alloc_paging() +- iommu: Add ops->domain_alloc_paging() +- iommu: Add __iommu_group_domain_alloc() +- iommu: Require a default_domain for all iommu drivers +- iommu/sun50i: Add an IOMMU_IDENTITIY_DOMAIN +- iommu/mtk_iommu: Add an IOMMU_IDENTITIY_DOMAIN +- iommu/ipmmu: Add an IOMMU_IDENTITIY_DOMAIN +- iommu/qcom_iommu: Add an IOMMU_IDENTITIY_DOMAIN +- iommu: Remove ops->set_platform_dma_ops() +- iommu/msm: Implement an IDENTITY domain +- iommu/omap: Implement an IDENTITY domain +- iommu/tegra-smmu: Support DMA domains in tegra +- iommu/tegra-smmu: Implement an IDENTITY domain +- iommu/exynos: Implement an IDENTITY domain +- iommu: Allow an IDENTITY domain as the default_domain in ARM32 +- iommu: Reorganize iommu_get_default_domain_type() to respect def_domain_type() +- iommu/mtk_iommu_v1: Implement an IDENTITY domain +- iommu/tegra-gart: Remove tegra-gart +- iommu/fsl_pamu: Implement a PLATFORM domain +- iommu: Add IOMMU_DOMAIN_PLATFORM for S390 +- powerpc/iommu: Setup a default domain and remove set_platform_dma_ops +- iommu: Add IOMMU_DOMAIN_PLATFORM +- iommu: Add iommu_ops->identity_domain +- iommu/vt-d: debugfs: Support dumping a specified page table +- iommu/vt-d: debugfs: Create/remove debugfs file per {device, pasid} +- iommu/vt-d: debugfs: Dump entry pointing to huge page +- iommu/virtio: Add __counted_by for struct viommu_request and use struct_size() +- iommu/arm-smmu-v3-sva: Remove bond refcount +- iommu/arm-smmu-v3-sva: Remove unused iommu_sva handle +- iommu/arm-smmu-v3: Rename cdcfg to cd_table +- iommu/arm-smmu-v3: Update comment about STE liveness +- iommu/arm-smmu-v3: Cleanup arm_smmu_domain_finalise +- iommu/arm-smmu-v3: Move CD table to arm_smmu_master +- iommu/arm-smmu-v3: Refactor write_ctx_desc +- iommu/arm-smmu-v3: move stall_enabled to the cd table +- iommu/arm-smmu-v3: Encapsulate ctx_desc_cfg init in alloc_cd_tables +- iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg +- iommu/arm-smmu-v3: Move ctx_desc out of s1_cfg +- iommu/tegra-smmu: Drop unnecessary error check for for debugfs_create_dir() +- powerpc: Remove extern from function implementations +- iommufd: Organize the mock domain alloc functions closer to Joerg's tree +- iommu/vt-d: Disallow read-only mappings to nest parent domain +- iommu/vt-d: Add nested domain allocation +- iommu/vt-d: Set the nested domain to a device +- iommu/vt-d: Make domain attach helpers to be extern +- iommu/vt-d: Add helper to setup pasid nested translation +- iommu/vt-d: Add helper for nested domain allocation +- iommu/vt-d: Extend dmar_domain to support nested domain +- iommufd: Add data structure for Intel VT-d stage-1 domain allocation +- iommufd/selftest: Add coverage for IOMMU_HWPT_ALLOC with nested HWPTs +- iommufd/selftest: Add nested domain allocation for mock domain +- iommu: Add iommu_copy_struct_from_user helper +- iommufd: Add a nested HW pagetable object +- iommu: Pass in parent domain with user_data to domain_alloc_user op +- iommufd: Share iommufd_hwpt_alloc with IOMMUFD_OBJ_HWPT_NESTED +- iommufd: Derive iommufd_hwpt_paging from iommufd_hw_pagetable +- iommufd/device: Wrap IOMMUFD_OBJ_HWPT_PAGING-only configurations +- iommufd: Rename IOMMUFD_OBJ_HW_PAGETABLE to IOMMUFD_OBJ_HWPT_PAGING +- iommu: Add IOMMU_DOMAIN_NESTED +- iommufd: Only enforce cache coherency in iommufd_hw_pagetable_alloc +- iommufd: Fix spelling errors in comments +- !4767 reserve space for arch related structures +- kabi: reserve space for struct mfd_cell +- kabi: reserve space for struct irq_work +- !4709 mtd: Fix gluebi NULL pointer dereference caused by ftl notifier +- mtd: Fix gluebi NULL pointer dereference caused by ftl notifier +- !4738 blk-mq: fix IO hang from sbitmap wakeup race +- blk-mq: fix IO hang from sbitmap wakeup race +- !4561 sched: migtate user interface from smart grid to sched bpf +- sched: migtate user interface from smart grid to sched bpf +- !4026 [OLK-6.6]Add support for Mont-TSSE +- add support for Mont-TSSE Driver +- !4564 v2 reserve space for arm64 related structures +- kabi: reserve space for processor.h +- kabi: reserve space for fb.h +- kabi: reserve space for efi.h +- !4675 v5 Backport vDPA migration support patches +- vdpa: add CONFIG_VHOST_VDPA_MIGRATION +- vdpa: add vmstate header file +- vhost-vdpa: add reset state params to indicate reset level +- vhost-vdpa: allow set feature VHOST_F_LOG_ALL when been negotiated. +- vhost-vdpa: fix msi irq request err +- vhost-vdpa: Allow transparent MSI IOV +- vhost: add VHOST feature VHOST_BACKEND_F_BYTEMAPLOG +- vhost-vdpa: add uAPI for device migration status +- vdpa: add vdpa device migration status ops +- vhost-vdpa: add uAPI for device buffer +- vdpa: add device state operations +- vhost-vdpa: add uAPI for logging +- vdpa: add log operations +- !4660 Intel: Backport to fix In Field Scan(IFS) SAF for GNR & SRF +- platform/x86/intel/ifs: Call release_firmware() when handling errors. +- !4652 RDMA/hns: Support SCC context query and DSCP configuration. +- RDMA/hns: Support DSCP of userspace +- RDMA/hns: Append SCC context to the raw dump of QP Resource +- !4628 fs:/dcache.c: fix negative dentry flag warning in dentry_free +- fs:/dcache.c: fix negative dentry flag warning in dentry_free +- !4654 hisi_ptt: Move type check to the beginning of hisi_ptt_pmu_event_init() +- hwtracing: hisi_ptt: Move type check to the beginning of hisi_ptt_pmu_event_init() +- !3880 ima: Add IMA digest lists extension +- ima: add default INITRAMFS_FILE_METADATA and EVM_DEFAULT_HASH CONFIG +- ima: don't allow control characters in policy path +- ima: Add max size for IMA digest database +- config: add digest list options for arm64 and x86 +- evm: Propagate choice of HMAC algorithm in evm_crypto.c +- ima: Execute parser to upload digest lists not recognizable by the kernel +- evm: Extend evm= with x509. allow_metadata_writes and complete values +- ima: Add parser keyword to the policy +- ima: Allow direct upload of digest lists to securityfs +- ima: Search key in the built-in keyrings +- certs: Introduce search_trusted_key() +- KEYS: Provide a function to load keys from a PGP keyring blob +- KEYS: Introduce load_pgp_public_keyring() +- KEYS: Provide PGP key description autogeneration +- KEYS: PGP data parser +- PGPLIB: Basic packet parser +- PGPLIB: PGP definitions (RFC 4880) +- rsa: add parser of raw format +- mpi: introduce mpi_key_length() +- ima: Add Documentation/security/IMA-digest-lists.txt +- ima: Introduce appraise_exec_immutable policy +- ima: Introduce appraise_exec_tcb policy +- ima: Introduce exec_tcb policy +- ima: Add meta_immutable appraisal type +- evm: Add support for digest lists of metadata +- ima: Add support for appraisal with digest lists +- ima: Add support for measurement with digest lists +- ima: Load all digest lists from a directory at boot time +- ima: Introduce new hook DIGEST_LIST_CHECK +- ima: Introduce new securityfs files +- ima: Prevent usage of digest lists not measured or appraised +- ima: Add parser of compact digest list +- ima: Use ima_show_htable_value to show violations and hash table data +- ima: Generalize policy file operations +- ima: Generalize ima_write_policy() and raise uploaded data size limit +- ima: Generalize ima_read_policy() +- ima: Allow choice of file hash algorithm for measurement and audit +- ima: Add enforce-evm and log-evm modes to strictly check EVM status +- init: Add kernel option to force usage of tmpfs for rootfs +- gen_init_cpio: add support for file metadata +- initramfs: read metadata from special file METADATA!!! +- initramfs: add file metadata +- !4542 Support feature TLBI DVMBM +- KVM: arm64: Implement the capability of DVMBM +- KVM: arm64: Add kvm_arch::sched_cpus and sched_lock +- KVM: arm64: Add kvm_vcpu_arch::sched_cpus and pre_sched_cpus +- KVM: arm64: Probe and configure DVMBM capability on HiSi CPUs +- KVM: arm64: Support a new HiSi CPU type +- KVM: arm64: Only probe Hisi ncsnp feature on Hisi CPUs +- KVM: arm64: Add support for probing Hisi ncsnp capability +- KVM: arm64: Probe Hisi CPU TYPE from ACPI/DTB +- !4661 [OLK-6.6] Fix gic support for Phytium S2500 +- Enable CONFIG_ARCH_PHYTIUM +- Fix gic support for Phytium S2500 +- !4644 f2fs: explicitly null-terminate the xattr list +- f2fs: explicitly null-terminate the xattr list +- !4637 Using smmu IIDR registers +- iommu/arm-smmu-v3: Enable iotlb_sync_map according to SMMU_IIDR +- Revert "iommu/arm-smmu-v3: Add a SYNC command to avoid broken page table prefetch" +- !4506 ubi: fastmap: Optimize ubi wl algorithm to improve flash service life +- ubi: fastmap: Add control in 'UBI_IOCATT' ioctl to reserve PEBs for filling pools +- ubi: fastmap: Add module parameter to control reserving filling pool PEBs +- ubi: fastmap: Fix lapsed wear leveling for first 64 PEBs +- ubi: fastmap: Get wl PEB even ec beyonds the 'max' if free PEBs are run out +- ubi: fastmap: may_reserve_for_fm: Don't reserve PEB if fm_anchor exists +- ubi: fastmap: Remove unneeded break condition while filling pools +- ubi: fastmap: Wait until there are enough free PEBs before filling pools +- ubi: fastmap: Use free pebs reserved for bad block handling +- ubi: Replace erase_block() with sync_erase() +- ubi: fastmap: Allocate memory with GFP_NOFS in ubi_update_fastmap +- ubi: fastmap: erase_block: Get erase counter from wl_entry rather than flash +- ubi: fastmap: Fix missed ec updating after erasing old fastmap data block +- !4624 6.6: i2c: Optimized the value setting of maxwrite limit to fifo depth - 1 +- i2c: hisi: Add clearing tx aempty interrupt operation +- i2c: hisi: Optimized the value setting of maxwrite limit to fifo depth - 1 +- !4631 Add kabi reserve +- drm/ttm: Add kabi reserve in ttm_tt.h +- drm/ttm: Add kabi reserve in ttm_resource.h +- drm/ttm: Add kabi reserve in ttm_bo.h +- drm: Add kabi reserve in drm_gpu_scheduler.h +- drm: Add kabi reserve in drm_syncobj.h +- drm: Add kabi reserve in drm_plane.h +- drm: Add kabi reserve in drm_modeset_lock.h +- drm: Add kabi reserve in drm_mode_config.h +- sbitmap: Add kabi reserve +- xarray: Reserve kabi for xa_state +- delayacct: Reserve kabi for task_delay_info + +* Mon Feb 26 2024 huangzq6 - 6.6.0-10.0.0.7 +- add signature for vmlinux + +* Wed Feb 21 2024 Zheng Zengkai - 6.6.0-10.0.0.6 +- !4598 [OLK-6.6] Add iommu support for Phytium S2500 +- Add iommu support for Phytium S2500 +- !4596 add sw64 architecture support +- sw64: fix build support +- sw64: add dynamic turning on/off cores support +- sw64: add dynamic frequency scaling support +- sw64: add kgdb support +- sw64: add jump_label support +- sw64: add uprobe support +- sw64: add kprobe support +- sw64: add kernel relocation support +- sw64: add ftrace support +- sw64: add hibernation support +- sw64: add suspend support +- sw64: add eBPF JIT support +- sw64: add kdump support +- sw64: add kexec support +- sw64: add perf events support +- sw64: add qspinlock support +- sw64: add stacktrace support +- !4567 Support feature TWED +- KVM: arm64: Make use of TWED feature +- arm64: cpufeature: TWED support detection +- !4383 [OLK-6.6] kabi: add more x86/cpu reservations in cpu feature bits and bug bits +- kabi: reserve x86 cpu bug fields +- kabi: reserve x86 cpu capability fields +- !3695 x86: Add x86 related kabi reservations +- x86: Add x86 related kabi reservations +- !4589 fs,hugetlb: fix NULL pointer dereference in hugetlbs_fill_super +- fs,hugetlb: fix NULL pointer dereference in hugetlbs_fill_super +- !4451 v5 kabi reserve patches +- kabi: reserve space for arm64 cpufeature related structure +- kabi: reserve space for power management related structure +- energy_model: Add kabi_reserve +- pm: pm.h: Add kabi_reserve +- pm: pm_domain.h: Add kabi_reserve +- drm: drm_gem.h: Add kabi_reserve +- drm: drm_fourcc.h: Add kabi_reserve +- drm: drm_file.h: Add kabi_reserve +- drm: drm_fb_helper.h: Add kabi_reserve +- drm: drm_drv.h: Add kabi_reserve +- drm: drm_device.h: Add kabi_reserve +- drm: drm_crtc.h: Add kabi_reserve +- drm: drm_connector.h: Add kabi_reserve +- drm: drm_client.h: Add kabi_reserve +- drm: drm_atomic.h: Add kabi_reserve +- irqdomain: Add kabi_reserve in irqdomain +- irq_desc: Add kabi_reserve in irq_desc +- irq: Add kabi_reserve in irq +- interrupt: Add kabi_reserve in interrupt.h +- msi: Add kabi_reserve in msi.h +- kabi: reserve space for struct cpu_stop_work +- KABI: reserve space for struct input_dev +- !4557 Add ZONE_EXTMEM to avoid kabi broken +- openeuler_defconfig: enable CONFIG_ZONE_EXTMEM for arm64 +- mm: add ZONE_EXTMEM for future extension to avoid kabi broken +- !4569 add sw64 architecture support +- sw64: add KVM support +- sw64: add EFI support +- sw64: add DMA support +- sw64: add ACPI support +- sw64: add device trees +- sw64: add MSI support +- sw64: add PCI support +- sw64: add default configs +- sw64: add NUMA support +- sw64: add SMP support +- sw64: add VDSO support +- sw64: add some library functions +- sw64: add some other routines +- sw64: add some common routines +- sw64: add module support +- sw64: add basic IO support +- sw64: add FPU support +- !3498 fuse: reserve space for future expansion +- kabi:fuse: reserve space for future expansion +- !4435 v2 kabi: reserve space for struct ptp_clock +- kabi: reserve space for struct ptp_clock +- !4584 v5 kabi reserve +- kabi: reserve space for struct clocksource +- kabi: reserve space for struct timer_list +- kabi: reserve space for struct ptp_clock_info +- kabi: reserve space for posix clock related structure +- kabi: reserve space for hrtimer related structures +- kabi: reserve space for kobject related structures +- !4049 openeuler_defconfig: Disable new HW_RANDOM support for arm64 +- openeuler_defconfig: Disable new HW_RANDOM support for arm64 +- !4582 cgroup/hugetlb: hugetlb accounting +- mm: memcg: fix split queue list crash when large folio migration +- hugetlb: memcg: account hugetlb-backed memory in memory controller +- memcontrol: only transfer the memcg data for migration +- memcontrol: add helpers for hugetlb memcg accounting +- !4347 【OLK-6.6】AMD: CXL RCH Protocol Error Handling supporting +- openeuler_defconfig: Enable CONFIG_PCIEAER_CXL=y +- cxl/hdm: Fix && vs || bug +- cxl/pci: Change CXL AER support check to use native AER +- cxl/core/regs: Rework cxl_map_pmu_regs() to use map->dev for devm +- cxl/core/regs: Rename phys_addr in cxl_map_component_regs() +- PCI/AER: Unmask RCEC internal errors to enable RCH downstream port error handling +- PCI/AER: Forward RCH downstream port-detected errors to the CXL.mem dev handler +- cxl/pci: Disable root port interrupts in RCH mode +- cxl/pci: Add RCH downstream port error logging +- cxl/pci: Map RCH downstream AER registers for logging protocol errors +- cxl/pci: Update CXL error logging to use RAS register address +- PCI/AER: Refactor cper_print_aer() for use by CXL driver module +- cxl/pci: Add RCH downstream port AER register discovery +- cxl/port: Remove Component Register base address from struct cxl_port +- cxl/pci: Remove Component Register base address from struct cxl_dev_state +- cxl/hdm: Use stored Component Register mappings to map HDM decoder capability +- cxl/pci: Store the endpoint's Component Register mappings in struct cxl_dev_state +- cxl/port: Pre-initialize component register mappings +- cxl/port: Rename @comp_map to @reg_map in struct cxl_register_map +- !4390 [OLK-6.6] Add kdump support for Phytium S2500 +- Add kdump support for Phytium S2500 +- !4459 v2 Introduce page eject for arm64 +- config: update defconfig for PAGE_EJECT +- mm: page_eject: Introuduce page ejection +- mm/memory-failure: introduce soft_online_page +- mm/hwpoison: Export symbol soft_offline_page +- !3699 [OLK-6.6] Enable CONFIG_IOMMUFD and CONFIG_VFIO_DEVICE_CDEV in x86/arm64 defconfig +- defconfig: enable CONFIG_IOMMUFD and CONFIG_VFIO_DEVICE_CDEV +- !4571 scsi: iscsi: kabi: KABI reservation for iscsi_transport +- scsi: iscsi: kabi: KABI reservation for iscsi_transport +- !4546 RDMA/hns: Support MR management +- RDMA/hns: Simplify 'struct hns_roce_hem' allocation +- RDMA/hns: Support adaptive PBL hopnum +- RDMA/hns: Support flexible umem page size +- RDMA/hns: Alloc MTR memory before alloc_mtt() +- RDMA/hns: Refactor mtr_init_buf_cfg() +- RDMA/hns: Refactor mtr find +- !4576 v6 Add support for ecmdq +- iommu/arm-smmu-v3: Allow disabling ECMDQs at boot time +- iommu/arm-smmu-v3: Add support for less than one ECMDQ per core +- iommu/arm-smmu-v3: Add arm_smmu_ecmdq_issue_cmdlist() for non-shared ECMDQ +- iommu/arm-smmu-v3: Ensure that a set of associated commands are inserted in the same ECMDQ +- iommu/arm-smmu-v3: Add support for ECMDQ register mode +- !3697 enable ARM64/X86 CONFIG_BPF_LSM config +- lsm: enable CONFIG_BPF_LSM for use bpf in lsm program +- !4537 mainline cgroup bufix +- cgroup: use legacy_name for cgroup v1 disable info +- blk-cgroup: bypass blkcg_deactivate_policy after destroying +- cgroup: Check for ret during cgroup1_base_files cft addition +- !4438 kabi: reserve space for workqueue subsystem related structure +- kabi: reserve space for workqueue subsystem related structure +- !4570 v2 scsi: reserve space for structures in scsi +- scsi: reserve space for structures in scsi +- !4566 v2 reserve kabi space for some structures +- libnvdimm: reserve space for structures in libnvdimm +- ata: libata: reserve space for structures in libata +- elevator: reserve space for structures in elevator + +* Wed Feb 7 2024 Zheng Zengkai - 6.6.0-9.0.0.5 +- !4545 add sw64 architecture support +- sw64: add signal handling support +- sw64: add system call support +- sw64: add hugetlb support +- sw64: add memory management +- sw64: add hardware match support +- sw64: add process management +- sw64: add exception handling support +- sw64: add irq handling support +- sw64: add timer support +- sw64: add topology setup routine +- sw64: add boot and setup routines +- sw64: add some other headers +- sw64: add ELF support +- sw64: add common headers +- sw64: add atomic/locking headers +- sw64: add CPU definition headers +- sw64: add build infrastructure +- !4423 kabi: reserve space for pci subsystem and thread_info +- kabi: reserve space for pci subsystem related structure +- kabi: reserve space for thread_info structure +- !3997 [OLK-6.6] openEuler-24.03 Phytium S2500 IPMI adaption +- ipmi_si: Phytium S2500 workaround for MMIO-based IPMI +- !3841 Add support for Hygon family 18h model 5h HD-Audio +- ALSA: hda: Fix single byte writing issue for Hygon family 18h model 5h +- ALSA: hda: Add support for Hygon family 18h model 5h HD-Audio +- !3835 Add support for Hygon model 6h L3 PMU +- perf/x86/uncore: Add L3 PMU support for Hygon family 18h model 6h +- !3698 enable ARM64/X86_64 CONFIG_MPTCP/CONFIG_MPTCP_IPV6 config +- mptcp: enable config CONFIG_MPTCP and CONFIG_MPTCP_IPV6 +- !3696 enable ARM64/X86 CONFIG_XDP_SOCKET、CONFIG_XDP_SOCKETS_DIAG config +- xdp: enable config CONFIG_XDP_SOCKETS and CONFIG_XDP_SOCKETS_DIAG +- !3183 [OLK-6.6] Add support Zhaoxin GPIO pinctrl +- configs: add CONFIG_PINCTRL_ZHAOXIN and KX7000 to m +- Add support Zhaoxin GPIO pinctrl +- !4539 nvme: kabi: KABI reservation for nvme_ctrl +- nvme: kabi: KABI reservation for nvme_ctrl +- !4527 v3 block: kabi: KABI reservation for blk-cgroup +- block: kabi: KABI reservation for blk-cgroup +- !4554 v3 kabi: Reserve KABI slots for fs module +- sysfs: kabi: Reserve KABI slots for bin_attribute struct +- profs: kabi: Reserve KABI slots for proc_ops struct +- dax: kabi: Reserve KABI slots for dax_* struct +- fs: kabi: Reserve KABI slots for nameidata struct +- xattr: kabi: Reserve KABI slots for xattr_handler struct +- kernfs: kabi: Reserve KABI slots for kernfs_* struct +- fanotify: kabi: Reserve KABI slots for fsnotify_* struct +- fscrypt: kabi: Reserve KABI slots for fscrypt_operations struct +- !3932 [OLK-6.6] 同步OLK-5.10 SMMU HTTU补丁 +- iommu/arm-smmu-v3: Add Arm SMMU HTTU config +- vfio/iommu_type1: Add support for manual dirty log clear +- vfio/iommu_type1: Optimize dirty bitmap population based on iommu HWDBM +- vfio/iommu_type1: Add HWDBM status maintenance +- iommu/arm-smmu-v3: Realize support_dirty_log iommu ops +- iommu/arm-smmu-v3: Realize clear_dirty_log iommu ops +- iommu/arm-smmu-v3: Realize sync_dirty_log iommu ops +- iommu/arm-smmu-v3: Realize switch_dirty_log iommu ops +- iommu/arm-smmu-v3: Add feature detection for BBML +- iommu/arm-smmu-v3: Enable HTTU for stage1 with io-pgtable mapping +- iommu/io-pgtable-arm: Add and realize clear_dirty_log ops +- iommu/io-pgtable-arm: Add and realize sync_dirty_log ops +- iommu/io-pgtable-arm: Add and realize merge_page ops +- iommu/io-pgtable-arm: Add and realize split_block ops +- iommu/io-pgtable-arm: Add __arm_lpae_set_pte +- iommu/io-pgtable-arm: Add quirk ARM_HD and ARM_BBMLx +- iommu: Introduce dirty log tracking framework +- iommu/arm-smmu-v3: Add support for Hardware Translation Table Update +- !4560 v5 block: reserve kabi space for general block layer structures +- block: reserve kabi space for general block layer structures +- !4168 Reserve syscall entries for kabi compatibility +- kabi: Reserve syscall entries for kabi compatibility +- arch: Reserve map_shadow_stack() syscall number for all architectures +- !4532 v2 fscache: reserve kabi for fscache structures +- fscache: reserve kabi for fscache structures +- !4543 v2 fs/dcache: kabi: KABI reservation for dentry +- fs/dcache: kabi: KABI reservation for dentry +- !4533 quota: kabi: KABI reservation for quota +- quota: kabi: KABI reservation for quota +- !4528 v3 jbd2: kabi: KABI reservation for jbd2 +- jbd2: kabi: KABI reservation for jbd2 +- !4483 block: kabi: KABI reservation for iocontext +- block: kabi: KABI reservation for iocontext +- !4455 scsi: iscsi: kabi: KABI reservation for scsi_transport_iscsi.h +- scsi: iscsi: kabi: KABI reservation for scsi_transport_iscsi.h +- !4456 scsi: scsi_transport_fc: kabi: KABI reservation for scsi_transport_fc +- scsi: scsi_transport_fc: kabi: KABI reservation for scsi_transport_fc +- !4472 nvmet-fc: kabi: KABI reservation for nvme_fc_port_template +- nvmet-fc: kabi: KABI reservation for nvme_fc_port_template +- !4474 scsi: libsas: kabi: KABI reservation for libsas +- scsi: libsas: kabi: KABI reservation for libsas +- !4463 RDMA/hns: Backport bugfix +- RDMA/hns: Fix memory leak in free_mr_init() +- RDMA/hns: Remove unnecessary checks for NULL in mtr_alloc_bufs() +- RDMA/hns: Add a max length of gid table +- RDMA/hns: Response dmac to userspace +- RDMA/hns: Rename the interrupts +- RDMA/hns: Support SW stats with debugfs +- RDMA/hns: Add debugfs to hns RoCE +- RDMA/hns: Fix inappropriate err code for unsupported operations +- !3838 Add support for Hygon model 4h EDAC +- EDAC/amd64: Adjust UMC channel for Hygon family 18h model 6h +- EDAC/amd64: Add support for Hygon family 18h model 6h +- EDAC/amd64: Add support for Hygon family 18h model 5h +- EDAC/mce_amd: Use struct cpuinfo_x86.logical_die_id for Hygon NodeId +- EDAC/amd64: Adjust address translation for Hygon family 18h model 4h +- EDAC/amd64: Add support for Hygon family 18h model 4h +- EDAC/amd64: Get UMC channel from the 6th nibble for Hygon +- !4408 v2 kabi: reserve space for struct acpi_device and acpi_scan_handler +- kabi: reserve space for struct acpi_device and acpi_scan_handler +- !4495 KABI reservation for driver +- audit: kabi: Remove extra semicolons +- ipmi: kabi: KABI reservation for ipmi +- mmc: kabi: KABI reservation for mmc +- mtd: kabi: KABI reservation for mtd +- tty: kabi: KABI reservation for tty +- !3831 Add support for loading Hygon microcode +- x86/microcode/hygon: Add microcode loading support for Hygon processors +- !4356 【OLK-6.6】AMD: support the UMC Performance Counters for Zen4 +- perf vendor events amd: Add Zen 4 memory controller events +- perf/x86/amd/uncore: Pass through error code for initialization failures, instead of -ENODEV +- perf/x86/amd/uncore: Fix uninitialized return value in amd_uncore_init() +- perf/x86/amd/uncore: Add memory controller support +- perf/x86/amd/uncore: Add group exclusivity +- perf/x86/amd/uncore: Use rdmsr if rdpmc is unavailable +- perf/x86/amd/uncore: Move discovery and registration +- perf/x86/amd/uncore: Refactor uncore management +- !4494 v2 writeback: kabi: KABI reservation for writeback +- writeback: kabi: KABI reservation for writeback +- !4491 sched/rt: Fix possible warn when push_rt_task +- sched/rt: Fix possible warn when push_rt_task +- !4396 [OLK-6.6] perf/x86/zhaoxin/uncore: add NULL pointer check after kzalloc +- perf/x86/zhaoxin/uncore: add NULL pointer check after kzalloc +- !4405 mm: improve performance of accounted kernel memory allocations +- mm: kmem: properly initialize local objcg variable in current_obj_cgroup() +- mm: kmem: reimplement get_obj_cgroup_from_current() +- percpu: scoped objcg protection +- mm: kmem: scoped objcg protection +- mm: kmem: make memcg keep a reference to the original objcg +- mm: kmem: add direct objcg pointer to task_struct +- mm: kmem: optimize get_obj_cgroup_from_current() +- !4500 fs: kabi: KABI reservation for vfs +- fs: kabi: KABI reservation for vfs +- !4505 iov_iter: kabi: KABI reservation for iov_iter +- iov_iter: kabi: KABI reservation for iov_iter +- !4486 v2 openeuler_defconfig: enable CONFIG_PAGE_CACHE_LIMIT +- openeuler_defconfig: enable CONFIG_PAGE_CACHE_LIMIT +- !4489 【OLK-6.6】AMD: fix brstack event for AMD Zen CPU +- perf/x86/amd: Reject branch stack for IBS events +- !4376 [OLK-6.6] Add Phytium Display Engine support to the OLK-6.6. +- DRM: Phytium display DRM doc +- DRM: Phytium display DRM driver +- !4385 v2 sched: remove __GENKSYMS__ used +- sched: remove __GENKSYMS__ used +- !4449 memory tiering: calculate abstract distance based on ACPI HMAT +- dax, kmem: calculate abstract distance with general interface +- acpi, hmat: calculate abstract distance with HMAT +- acpi, hmat: refactor hmat_register_target_initiators() +- memory tiering: add abstract distance calculation algorithms management +- !4362 ubifs: Queue up space reservation tasks if retrying many times +- ubifs: Queue up space reservation tasks if retrying many times +- !4450 change zswap's default allocator to zsmalloc +- openeuler_defconfig: set ZSWAP_ZPOOL_DEFAULT to ZSMALLOC +- zswap: change zswap's default allocator to zsmalloc +- !4298 misc for controlling fd +- cgroup/misc: support cgroup misc to control fd +- filescgroup: add adapter for legacy and misc cgroup +- filescgroup: rename filescontrol.c to legacy-filescontrol.c +- filescgroup: Add CONFIG_CGROUP_FILES at files_cgroup in files_struct +- filescgroup: remove files of dfl_cftypes. +- !4173 block: remove precise_iostat +- block: remove precise_iostat +- !4481 cred: kabi: KABI reservation for cred +- cred: kabi: KABI reservation for cred +- !4418 KABI: Add reserve space for sched structures +- KABI: Reserve space for fwnode.h +- KABI: Reserve space for struct module +- fork: Allocate a new task_struct_resvd object for fork task +- KABI: Add reserve space for sched structures +- !4355 v4 kabi reserve for memcg and cgroup_bpf +- cgroup_bpf/kabi: reserve space for cgroup_bpf related structures +- memcg/kabi: reserve space for memcg related structures +- !4476 net/kabi: Reserve space for net structures +- net/kabi: Reserve space for net structures +- !4440 v2 kabi:dma:add kabi reserve for dma_map_ops structure +- kabi:dma:add kabi reserve for dma_map_ops structure +- !4479 mm/memcontrol: fix out-of-bound access in mem_cgroup_sysctls_init +- mm/memcontrol: fix out-of-bound access in mem_cgroup_sysctls_init +- !4429 Remove unnecessary KABI reservation +- crypto: kabi: Removed unnecessary KABI reservation +- !4211 blk-mq: avoid housekeeping CPUs scheduling a worker on a non-housekeeping CPU +- blk-mq: avoid housekeeping CPUs scheduling a worker on a non-housekeeping CPU +- !4407 sched/topology: Fix cpus hotplug deadlock in check_node_limit() +- sched/topology: Fix cpus hotplug deadlock in check_node_limit() +- !4351 kabi: net: reserve space for net subsystem related structure +- kabi: net: reserve space for net subsystem related structure +- !4453 arm64/ascend: Make enable_oom_killer feature depends on ASCEND_FEATURE +- arm64/ascend: Make enable_oom_killer feature depends on ASCEND_FEATURE +- !4386 fix static scanning issues +- bond: fix static scanning issue with bond_broadcast_arp_or_nd_table_header +- tcp: fix static scanning issue with sysctl_local_port_allocation +- !4403 v2 kabi: net: reserve space for net related structure +- kabi: net: reserve space for net related structure +- !4406 v2 net/kabi: reserve space for net related structures +- net/kabi: reserve space for net related structures +- !4398 v2 vfs: reserve kabi space for vfs related structures +- vfs: reserve kabi space for vfs related structures +- !4372 kabi: reserve space for struct rate_sample +- kabi: reserve space for struct rate_sample +- !4322 cgroup_writeback: fix deadlock +- cgroup_writeback: fix deadlock in cgroup1_writeback +- !4414 Support srq record doorbell and support query srq context +- RDMA/hns: Support SRQ record doorbell +- RDMA/hns: Support SRQ restrack ops for hns driver +- RDMA/core: Add support to dump SRQ resource in RAW format +- RDMA/core: Add dedicated SRQ resource tracker function +- !4165 tlb: reserve fields for struct mmu_gather +- tlb: reserve fields for struct mmu_gather +- !4178 OLK-6.6 cred backport for kabi reserve +- cred: get rid of CONFIG_DEBUG_CREDENTIALS +- groups: Convert group_info.usage to refcount_t +- cred: switch to using atomic_long_t +- cred: add get_cred_many and put_cred_many +- !4343 v3 reserve KABI slots for file system or storage related structures +- mtd: kabi: Reserve KABI slots for mtd_device_xxx_register() related structures +- pipe: kabi: Reserve KABI slots for pipe_inode_info structure +- exportfs: kabi: Reserve KABI slots for export_operations structure +- !4200 Expose swapcache stat for memcg v1 +- memcg: remove unused do_memsw_account in memcg1_stat_format +- memcg: expose swapcache stat for memcg v1 +- !4140 backport some patches for kunpeng hccs +- soc: hisilicon: kunpeng_hccs: Support the platform with PCC type3 and interrupt ack +- doc: kunpeng_hccs: Fix incorrect email domain name +- soc: hisilicon: kunpeng_hccs: Remove an unused blank line +- soc: hisilicon: kunpeng_hccs: Add failure log for no _CRS method +- soc: hisilicon: kunpeng_hccs: Fix some incorrect format strings +- soc/hisilicon: kunpeng_hccs: Convert to platform remove callback returning void +- soc: kunpeng_hccs: Migrate to use generic PCC shmem related macros +- hwmon: (xgene) Migrate to use generic PCC shmem related macros +- i2c: xgene-slimpro: Migrate to use generic PCC shmem related macros +- ACPI: PCC: Add PCC shared memory region command and status bitfields +- !3641 Make the cpuinfo_cur_freq interface read correctly +- cpufreq: CPPC: Keep the target core awake when reading its cpufreq rate +- arm64: cpufeature: Export cpu_has_amu_feat() +- !4410 config: Update openeuler_defconfig base on current +- config: x86: Update openeuler_defconfig base on current source code +- config: arm64: Update openeuler_defconfig base on current source code +- !4400 v2 soc: hisilicon: hisi_hbmdev: Fix compile error +- soc: hisilicon: hisi_hbmdev: Fix compile error +- !4397 v2 cryptd: kabi: Fixed boot panic +- cryptd: kabi: Fixed boot panic +- !4393 [OLK-6.6] crypto: sm4: fix the build warning issue of sm4 driver +- crypto: sm4: fix the build warning issue of sm4 driver +- !4368 cgroup/misc: fix compiling waring +- cgroup/misc: fix compiling waring +- !4364 [OLK-6.6] crypto: sm3/sm4: fix zhaoxin sm3/sm4 driver file name mismatch issue +- crypto: sm3/sm4: fix zhaoxin sm3/sm4 driver file name mismatch issue +- !4204 arm64: Turn on CONFIG_IPI_AS_NMI in openeuler_defconfig +- arm64: Turn on CONFIG_IPI_AS_NMI in openeuler_defconfig +- !4314 tracing: Reserve kabi fields +- tracing: Reserve kabi fields +- !4301 v3 kabi: reserve space for cpu cgroup and cpuset cgroup related structures +- kabi: reserve space for cpu cgroup and cpuset cgroup related structures +- !4177 kabi: reserve space for bpf related structures +- kabi: reserve space for bpf related structures +- !4354 v7 KABI reservation for IMA and crypto +- ima: kabi: KABI reservation for IMA +- crypto: kabi: KABI reservation for crypto +- !4346 v2 pciehp: fix a race between pciehp and removing operations by sysfs +- pciehp: fix a race between pciehp and removing operations by sysfs +- !4146 tcp: fix compilation issue when CONFIG_SYSCTL is disabled +- tcp: fix compilation issue when CONFIG_SYSCTL is disabled +- !4066 smb: client: fix OOB in receive_encrypted_standard() +- smb: client: fix OOB in receive_encrypted_standard() +- !3995 net: config: enable network config +- net: config: enable network config +- !3745 【OLK-6.6】Support SMT control on arm64 +- config: enable CONFIG_HOTPLUG_SMT for arm64 +- arm64: Kconfig: Enable HOTPLUG_SMT +- arm64: topology: Support SMT control on ACPI based system +- arch_topology: Support SMT control for OF based system +- arch_topology: Support basic SMT control for the driver +- !4000 audit: kabi: KABI reservation for audit +- audit: kabi: KABI reservation for audit +- !4249 ubifs: fix possible dereference after free +- ubifs: fix possible dereference after free +- !3178 [OLK-6.6] Driver for Zhaoxin SM3 and SM4 algorithm +- configs: Add Zhaoxin SM3 and SM4 algorithm configs +- Add support for Zhaoxin GMI SM4 Block Cipher algorithm +- Add support for Zhaoxin GMI SM3 Secure Hash algorithm +- !4219 Initial cleanups for vCPU hotplug +- riscv: convert to use arch_cpu_is_hotpluggable() +- riscv: Switch over to GENERIC_CPU_DEVICES +- LoongArch: convert to use arch_cpu_is_hotpluggable() +- LoongArch: Use the __weak version of arch_unregister_cpu() +- LoongArch: Switch over to GENERIC_CPU_DEVICES +- x86/topology: convert to use arch_cpu_is_hotpluggable() +- x86/topology: use weak version of arch_unregister_cpu() +- x86/topology: Switch over to GENERIC_CPU_DEVICES +- arm64: convert to arch_cpu_is_hotpluggable() +- arm64: setup: Switch over to GENERIC_CPU_DEVICES using arch_register_cpu() +- drivers: base: Print a warning instead of panic() when register_cpu() fails +- drivers: base: Move cpu_dev_init() after node_dev_init() +- drivers: base: add arch_cpu_is_hotpluggable() +- drivers: base: Implement weak arch_unregister_cpu() +- drivers: base: Allow parts of GENERIC_CPU_DEVICES to be overridden +- drivers: base: Use present CPUs in GENERIC_CPU_DEVICES +- ACPI: Move ACPI_HOTPLUG_CPU to be disabled on arm64 and riscv +- Loongarch: remove arch_*register_cpu() exports +- x86/topology: remove arch_*register_cpu() exports +- x86: intel_epb: Don't rely on link order +- arch_topology: Make register_cpu_capacity_sysctl() tolerant to late CPUs +- arm64, irqchip/gic-v3, ACPI: Move MADT GICC enabled check into a helper +- ACPI: scan: Rename acpi_scan_device_not_present() to be about enumeration +- ACPI: scan: Use the acpi_device_is_present() helper in more places +- !4215 pci: Enable acs for QLogic HBA cards +- pci: Enable acs for QLogic HBA cards +- !4267 ksmbd: fix slab-out-of-bounds in smb_strndup_from_utf16() +- ksmbd: fix slab-out-of-bounds in smb_strndup_from_utf16() +- !4317 [OLK-6.6] cputemp: zhaoxin: fix HWMON_THERMAL namespace not import issue +- cputemp: zhaoxin: fix HWMON_THERMAL namespace not import issue. +- !3682 cgroup and ns kabi reserve +- cgroup/misc: reserve kabi for future misc development +- cgroup/psi: reserve kabi for future psi development +- namespace: kabi: reserve for future namespace development +- cgroup: kabi: reserve space for cgroup frame +- !4291 fs:/dcache.c: fix negative dentry limit not complete problem +- fs:/dcache.c: fix negative dentry limit not complete problem +- !4292 powerpc: Add PVN support for HeXin C2000 processor +- powerpc: Add PVN support for HeXin C2000 processor +- !3129 [OLK-6.6] Driver for Zhaoxin AES and SHA algorithm +- Add Zhaoxin aes/sha items in openeuler_config +- Add support for Zhaoxin SHA algorithm +- Add support for Zhaoxin AES algorithm +- !3959 kabi: mm: add kabi reserve for mm structure +- kabi: mm: add kabi reserve for mm structure +- !4046 [OLK-6.6] Add gic support for Phytium S2500 +- Add gic support for Phytium S2500 +- !3126 [OLK-6.6] Driver for Zhaoxin HW Random Number Generator +- Add CONFIG_HW_RANDOM_ZHAOXIN in openeuler_defconfig +- Add support for Zhaoxin HW Random Number Generator +- !3169 [OLK-6.6] x86/perf: Add uncore performance events support for Zhaoxin CPU +- x86/perf: Add uncore performance events support for Zhaoxin CPU +- !3187 [OLK-6.6] Add support for Zhaoxin I2C controller +- configs: add CONFIG_I2C_ZHAOXIN to m +- Add support for Zhaoxin I2C controller +- !4164 arch/mm/fault: fix major fault accounting when retrying under per-VMA lock +- arch/mm/fault: fix major fault accounting when retrying under per-VMA lock +- !3903 kabi: Reserve space for perf subsystem related structures +- kabi: Reserve space for perf subsystem related structures +- !4128 drm/qxl: Fix missing free_irq +- drm/qxl: Fix missing free_irq +- !4050 kabi: net: reserve space for net +- kabi: net: reserve space for net sunrpc subsystem related structure +- kabi: net: reserve space for net rdma subsystem related structure +- kabi: net: reserve space for net netfilter subsystem related structure +- kabi: net: reserve space for net can subsystem related structure +- kabi: net: reserve space for net bpf subsystem related structure +- kabi: net: reserve space for net base subsystem related structure +- !3774 [OLK-6.6] sched/fair: Scan cluster before scanning LLC in wake-up path +- sched/fair: Use candidate prev/recent_used CPU if scanning failed for cluster wakeup +- sched/fair: Scan cluster before scanning LLC in wake-up path +- sched: Add cpus_share_resources API +- !3125 [OLK-6.6] Driver for Zhaoxin Serial ATA IDE +- configs: enable CONFIG_SATA_ZHAOXIN to y +- Add support for Zhaoxin Serial ATA IDE. +- !4044 Set CONFIG_NODES_SHIFT to 8 +- openeuler_defconfig: set CONFIG_NODES_SHIFT to 8 for both x86_64/ARM64 +- x86/Kconfig: allow NODES_SHIFT to be set on MAXSMP +- !3840 Remove Hygon SMBus IMC detecting +- i2c-piix4: Remove the IMC detecting for Hygon SMBus +- !3839 Add support for Hygon model 4h k10temp +- hwmon/k10temp: Add support for Hygon family 18h model 5h +- hwmon/k10temp: Add support for Hygon family 18h model 4h +- !3837 Add support for Hygon model 4h northbridge +- x86/amd_nb: Add support for Hygon family 18h model 6h +- x86/amd_nb: Add support for Hygon family 18h model 5h +- x86/amd_nb: Add northbridge support for Hygon family 18h model 4h +- x86/amd_nb: Add Hygon family 18h model 4h PCI IDs +- !4199 Support large folio for mlock +- mm: mlock: avoid folio_within_range() on KSM pages +- mm: mlock: update mlock_pte_range to handle large folio +- mm: handle large folio when large folio in VM_LOCKED VMA range +- mm: add functions folio_in_range() and folio_within_vma() +- !4147 arm64: Add CONFIG_IPI_AS_NMI to IPI as NMI feature +- arm64: Add CONFIG_IPI_AS_NMI to IPI as NMI feature +- !4159 Backport iommufd dirty tracking from v6.7 +- iommu/vt-d: Set variable intel_dirty_ops to static +- iommufd/selftest: Fix _test_mock_dirty_bitmaps() +- iommufd/selftest: Fix page-size check in iommufd_test_dirty() +- iommu/vt-d: Enhance capability check for nested parent domain allocation +- iommufd/selftest: Test IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR flag +- iommufd/selftest: Test out_capabilities in IOMMU_GET_HW_INFO +- iommufd/selftest: Test IOMMU_HWPT_GET_DIRTY_BITMAP +- iommufd/selftest: Test IOMMU_HWPT_SET_DIRTY_TRACKING +- iommufd/selftest: Test IOMMU_HWPT_ALLOC_DIRTY_TRACKING +- iommufd/selftest: Expand mock_domain with dev_flags +- iommu/vt-d: Access/Dirty bit support for SS domains +- iommu/amd: Access/Dirty bit support in IOPTEs +- iommu/amd: Add domain_alloc_user based domain allocation +- iommufd: Add a flag to skip clearing of IOPTE dirty +- iommufd: Add capabilities to IOMMU_GET_HW_INFO +- iommufd: Add IOMMU_HWPT_GET_DIRTY_BITMAP +- iommufd: Add IOMMU_HWPT_SET_DIRTY_TRACKING +- iommufd: Add a flag to enforce dirty tracking on attach +- iommufd: Correct IOMMU_HWPT_ALLOC_NEST_PARENT description +- iommu: Add iommu_domain ops for dirty tracking +- iommufd/iova_bitmap: Move symbols to IOMMUFD namespace +- vfio: Move iova_bitmap into iommufd +- vfio/iova_bitmap: Export more API symbols +- iommufd/selftest: Rework TEST_LENGTH to test min_size explicitly +- iommu/vt-d: Add domain_alloc_user op +- iommufd/selftest: Add domain_alloc_user() support in iommu mock +- iommufd/selftest: Iterate idev_ids in mock_domain's alloc_hwpt test +- iommufd: Support allocating nested parent domain +- iommufd: Flow user flags for domain allocation to domain_alloc_user() +- iommufd: Use the domain_alloc_user() op for domain allocation +- iommu: Add new iommu op to create domains owned by userspace +- !4109 PCI: add a member in 'struct pci_bus' to record the original 'pci_ops' +- PCI: add a member in 'struct pci_bus' to record the original 'pci_ops' +- !4108 PCI/AER: increments pci bus reference count in aer-inject process +- PCI/AER: increments pci bus reference count in aer-inject process +- !4114 pci: do not save 'PCI_BRIDGE_CTL_BUS_RESET' +- pci: do not save 'PCI_BRIDGE_CTL_BUS_RESET' +- !4113 PCI: check BIR before mapping MSI-X Table +- PCI: check BIR before mapping MSI-X Table +- !4112 PCI: Fail MSI-X mapping if MSI-X Table offset is out of range of BAR space +- PCI: Fail MSI-X mapping if MSI-X Table offset is out of range of BAR space +- !4110 PCI: Add MCFG quirks for some Hisilicon Chip host controllers +- PCI: Add MCFG quirks for some Hisilicon Chip host controllers +- !4111 sysrq: avoid concurrently info printing by 'sysrq-trigger' +- sysrq: avoid concurrently info printing by 'sysrq-trigger' +- !4107 ntp: Avoid undefined behaviour in second_overflow() +- ntp: Avoid undefined behaviour in second_overflow() +- !4105 PCI/sysfs: Take reference on device to be removed +- PCI/sysfs: Take reference on device to be removed +- !3836 Add support for Hygon model 4h QoS +- x86/resctrl: Add Hygon QoS support +- !4154 Add per-node vmstat info and memcg info +- mm/vmstat: move pgdemote_* out of CONFIG_NUMA_BALANCING +- mm/vmstat: move pgdemote_* to per-node stats +- mm: memcg: add THP swap out info for anonymous reclaim +- !4170 mm/ksm: generalize ksm_process_profit +- mm/ksm: generalize ksm_process_profit +- !4120 arm_mpam: support mpam feature in OLK-6.6 +- arm_mpam: control memory bandwidth with hard limit flag +- fs/resctrl: Remove the limit on the number of CLOSID +- arm_mpam: resctrl: Update the rmid reallocation limit +- arm_mpam: resctrl: Call resctrl_exit() in the event of errors +- arm_mpam: resctrl: Tell resctrl about cpu/domain online/offline +- perf/arm-cmn: Stop claiming all the resources +- arm64: mpam: Select ARCH_HAS_CPU_RESCTRL +- arm_mpam: resctrl: Add dummy definition for free running counters +- arm_mpam: resctrl: Add empty definitions for fine-grained enables +- arm_mpam: resctrl: Add empty definitions for pseudo lock +- untested: arm_mpam: resctrl: Allow monitors to be configured +- arm_mpam: resctrl: Add resctrl_arch_rmid_read() and resctrl_arch_reset_rmid() +- arm_mpam: resctrl: Allow resctrl to allocate monitors +- untested: arm_mpam: resctrl: Add support for mbm counters +- untested: arm_mpam: resctrl: Add support for MB resource +- arm_mpam: resctrl: Add rmid index helpers +- arm64: mpam: Add helpers to change a tasks and cpu mpam partid/pmg values +- arm_mpam: resctrl: Add CDP emulation +- arm_mpam: resctrl: Implement helpers to update configuration +- arm_mpam: resctrl: Add resctrl_arch_get_config() +- arm_mpam: resctrl: Implement resctrl_arch_reset_resources() +- arm_mpam: resctrl: Pick a value for num_rmid +- arm_mpam: resctrl: Pick the caches we will use as resctrl resources +- arm_mpam: resctrl: Add boilerplate cpuhp and domain allocation +- arm_mpam: Add helper to reset saved mbwu state +- arm_mpam: Use long MBWU counters if supported +- arm_mpam: Probe for long/lwd mbwu counters +- arm_mpam: Track bandwidth counter state for overflow and power management +- arm_mpam: Add mpam_msmon_read() to read monitor value +- arm_mpam: Add helpers to allocate monitors +- arm_mpam: Probe and reset the rest of the features +- arm_mpam: Allow configuration to be applied and restored during cpu online +- arm_mpam: Use the arch static key to indicate when mpam is enabled +- arm_mpam: Register and enable IRQs +- arm_mpam: Extend reset logic to allow devices to be reset any time +- arm_mpam: Add a helper to touch an MSC from any CPU +- arm_mpam: Reset MSC controls from cpu hp callbacks +- arm_mpam: Merge supported features during mpam_enable() into mpam_class +- arm_mpam: Probe the hardware features resctrl supports +- arm_mpam: Probe MSCs to find the supported partid/pmg values +- arm_mpam: Add cpuhp callbacks to probe MSC hardware +- arm_mpam: Add MPAM MSC register layout definitions +- arm_mpam: Add the class and component structures for ris firmware described +- arm_mpam: Add probe/remove for mpam msc driver and kbuild boiler plate +- dt-bindings: arm: Add MPAM MSC binding +- ACPI / MPAM: Parse the MPAM table +- drivers: base: cacheinfo: Add helper to find the cache size from cpu+level +- cacheinfo: Expose the code to generate a cache-id from a device_node +- cacheinfo: Set cache 'id' based on DT data +- cacheinfo: Allow for >32-bit cache 'id' +- ACPI / PPTT: Add a helper to fill a cpumask from a cache_id +- ACPI / PPTT: Add a helper to fill a cpumask from a processor container +- ACPI / PPTT: Find PPTT cache level by ID +- ACPI / PPTT: Provide a helper to walk processor containers +- untested: KVM: arm64: Force guest EL1 to use user-space's partid configuration +- arm64: mpam: Context switch the MPAM registers +- KVM: arm64: Disable MPAM visibility by default, and handle traps +- KVM: arm64: Fix missing traps of guest accesses to the MPAM registers +- arm64: cpufeature: discover CPU support for MPAM +- arm64: head.S: Initialise MPAM EL2 registers and disable traps +- x86/resctrl: Move the filesystem portions of resctrl to live in '/fs/' +- x86/resctrl: Move the filesystem bits to headers visible to fs/resctrl +- fs/resctrl: Add boiler plate for external resctrl code +- x86/resctrl: Drop __init/__exit on assorted symbols +- x86/resctrl: Describe resctrl's bitmap size assumptions +- x86/resctrl: Claim get_domain_from_cpu() for resctrl +- x86/resctrl: Move get_config_index() to a header +- x86/resctrl: Move thread_throttle_mode_init() to be managed by resctrl +- x86/resctrl: Make resctrl_arch_pseudo_lock_fn() take a plr +- x86/resctrl: Make prefetch_disable_bits belong to the arch code +- x86/resctrl: Allow an architecture to disable pseudo lock +- x86/resctrl: Allow resctrl_arch_mon_event_config_write() to return an error +- x86/resctrl: Change mon_event_config_{read,write}() to be arch helpers +- x86/resctrl: Add resctrl_arch_is_evt_configurable() to abstract BMEC +- x86/resctrl: Export the is_mbm_*_enabled() helpers to asm/resctrl.h +- x86/resctrl: Stop using the for_each_*_rdt_resource() walkers +- x86/resctrl: Move max_{name,data}_width into resctrl code +- x86/resctrl: Move monitor exit work to a restrl exit call +- x86/resctrl: Move monitor init work to a resctrl init call +- x86/resctrl: Add a resctrl helper to reset all the resources +- x86/resctrl: Move resctrl types to a separate header +- x86/resctrl: Wrap resctrl_arch_find_domain() around rdt_find_domain() +- x86/resctrl: Export resctrl fs's init function +- x86/resctrl: Remove rdtgroup from update_cpu_closid_rmid() +- x86/resctrl: Add helper for setting CPU default properties +- x86/resctrl: Move ctrlval string parsing links away from the arch code +- x86/resctrl: Add a helper to avoid reaching into the arch code resource list +- x86/resctrl: Separate arch and fs resctrl locks +- x86/resctrl: Move domain helper migration into resctrl_offline_cpu() +- x86/resctrl: Add CPU offline callback for resctrl work +- x86/resctrl: Allow overflow/limbo handlers to be scheduled on any-but cpu +- x86/resctrl: Add CPU online callback for resctrl work +- x86/resctrl: Add helpers for system wide mon/alloc capable +- x86/resctrl: Make rdt_enable_key the arch's decision to switch +- x86/resctrl: Move alloc/mon static keys into helpers +- x86/resctrl: Make resctrl_mounted checks explicit +- x86/resctrl: Allow arch to allocate memory needed in resctrl_arch_rmid_read() +- x86/resctrl: Allow resctrl_arch_rmid_read() to sleep +- x86/resctrl: Queue mon_event_read() instead of sending an IPI +- x86/resctrl: Add cpumask_any_housekeeping() for limbo/overflow +- x86/resctrl: Move CLOSID/RMID matching and setting to use helpers +- x86/resctrl: Allocate the cleanest CLOSID by searching closid_num_dirty_rmid +- x86/resctrl: Use __set_bit()/__clear_bit() instead of open coding +- x86/resctrl: Track the number of dirty RMID a CLOSID has +- x86/resctrl: Allow RMID allocation to be scoped by CLOSID +- x86/resctrl: Access per-rmid structures by index +- x86/resctrl: Track the closid with the rmid +- x86/resctrl: Move rmid allocation out of mkdir_rdt_prepare() +- x86/resctrl: Create helper for RMID allocation and mondata dir creation +- x86/resctrl: kfree() rmid_ptrs from resctrl_exit() +- tick/nohz: Move tick_nohz_full_mask declaration outside the #ifdef +- x86/resctrl: Display RMID of resource group +- x86/resctrl: Add support for the files of MON groups only +- x86/resctrl: Display CLOSID for resource group +- x86/resctrl: Introduce "-o debug" mount option +- x86/resctrl: Move default group file creation to mount +- x86/resctrl: Unwind properly from rdt_enable_ctx() +- x86/resctrl: Rename rftype flags for consistency +- x86/resctrl: Simplify rftype flag definitions +- x86/resctrl: Add multiple tasks to the resctrl group at once +- x86/resctrl: Fix remaining kernel-doc warnings +- !3834 Add support for Hygon model 4h IOAPIC +- iommu/hygon: Add support for Hygon family 18h model 4h IOAPIC +- !3830 Add support for Hygon model 5h CPU cache +- x86/cpu: Get LLC ID for Hygon family 18h model 5h +- !3311 Add support for Hygon model 4h CPU topology +- x86/cpu/hygon: Fix __max_die_per_package for Hygon family 18h model 4h +- !3124 [OLK-6.6] Add support for Zhaoxin HDAC and codec +- ALSA: hda: Add support of Zhaoxin NB HDAC codec +- ALSA: hda: Add support of Zhaoxin NB HDAC +- ALSA: hda: Add support of Zhaoxin SB HDAC +- !3098 [OLK-6.6] Add support for Zhaoxin Processors +- x86/cpu: Add detect extended topology for Zhaoxin CPUs +- x86/cpufeatures: Add Zhaoxin feature bits +- !3742 arch/powerpc: add ppc little endian openuler defconfig +- arch/powerpc: add ppc little endian openuler defconfig +- !4099 Intel: Backport SRF LBR branch counter support to kernel v6.6 +- perf/x86/intel: Support branch counters logging +- perf/x86/intel: Reorganize attrs and is_visible +- perf: Add branch_sample_call_stack +- perf/x86: Add PERF_X86_EVENT_NEEDS_BRANCH_STACK flag +- perf: Add branch stack counters +- !3177 [OLK-6.6] Add MWAIT Cx support for Zhaoxin CPUs +- Add MWAIT Cx support for Zhaoxin CPUs +- !3170 [OLK-6.6] rtc: Fix set RTC time delay 500ms on some Zhaoxin SOCs +- rtc: Fix set RTC time delay 500ms on some Zhaoxin SOCs +- !3131 [OLK-6.6] Driver for Zhaoxin CPU core temperature monitoring +- Add CONFIG_SENSORS_ZHAOXIN_CPUTEMP in openeuler_defconfig +- Add support for Zhaoxin core temperature monitoring +- !3102 [OLK-6.6] x86/mce: Add Centaur MCA support +- x86/mce: Add Centaur MCA support +- !4116 Intel: Backport GNR/SRF PMU uncore support to kernel v6.6 +- perf/x86/intel/uncore: Support Sierra Forest and Grand Ridge +- perf/x86/intel/uncore: Support IIO free-running counters on GNR +- perf/x86/intel/uncore: Support Granite Rapids +- perf/x86/uncore: Use u64 to replace unsigned for the uncore offsets array +- perf/x86/intel/uncore: Generic uncore_get_uncores and MMIO format of SPR +- !4115 Intel: Backport In Field Scan(IFS) SAF & Array BIST support for GNR & SRF +- platform/x86/intel/ifs: ARRAY BIST for Sierra Forest +- platform/x86/intel/ifs: Add new error code +- platform/x86/intel/ifs: Add new CPU support +- platform/x86/intel/ifs: Metadata validation for start_chunk +- platform/x86/intel/ifs: Validate image size +- platform/x86/intel/ifs: Gen2 Scan test support +- platform/x86/intel/ifs: Gen2 scan image loading +- platform/x86/intel/ifs: Refactor image loading code +- platform/x86/intel/ifs: Store IFS generation number +- !4103 [OLK-6.6] Intel: microcode restructuring backport +- x86/setup: Make relocated_ramdisk a local variable of relocate_initrd() +- x86/microcode/intel: Add a minimum required revision for late loading +- x86/microcode: Prepare for minimal revision check +- x86/microcode: Handle "offline" CPUs correctly +- x86/apic: Provide apic_force_nmi_on_cpu() +- x86/microcode: Protect against instrumentation +- x86/microcode: Rendezvous and load in NMI +- x86/microcode: Replace the all-in-one rendevous handler +- x86/microcode: Provide new control functions +- x86/microcode: Add per CPU control field +- x86/microcode: Add per CPU result state +- x86/microcode: Sanitize __wait_for_cpus() +- x86/microcode: Clarify the late load logic +- x86/microcode: Handle "nosmt" correctly +- x86/microcode: Clean up mc_cpu_down_prep() +- x86/microcode: Get rid of the schedule work indirection +- x86/microcode: Mop up early loading leftovers +- x86/microcode/amd: Use cached microcode for AP load +- x86/microcode/amd: Cache builtin/initrd microcode early +- x86/microcode/amd: Cache builtin microcode too +- x86/microcode/amd: Use correct per CPU ucode_cpu_info +- x86/microcode: Remove pointless apply() invocation +- x86/microcode/intel: Rework intel_find_matching_signature() +- x86/microcode/intel: Reuse intel_cpu_collect_info() +- x86/microcode/intel: Rework intel_cpu_collect_info() +- x86/microcode/intel: Unify microcode apply() functions +- x86/microcode/intel: Switch to kvmalloc() +- x86/microcode/intel: Save the microcode only after a successful late-load +- x86/microcode/intel: Simplify early loading +- x86/microcode/intel: Cleanup code further +- x86/microcode/intel: Simplify and rename generic_load_microcode() +- x86/microcode/intel: Simplify scan_microcode() +- x86/microcode/intel: Rip out mixed stepping support for Intel CPUs +- x86/microcode/32: Move early loading after paging enable +- x86/boot/32: Temporarily map initrd for microcode loading +- x86/microcode: Provide CONFIG_MICROCODE_INITRD32 +- x86/boot/32: Restructure mk_early_pgtbl_32() +- x86/boot/32: De-uglify the 2/3 level paging difference in mk_early_pgtbl_32() +- x86/boot: Use __pa_nodebug() in mk_early_pgtbl_32() +- x86/boot/32: Disable stackprotector and tracing for mk_early_pgtbl_32() +- x86/microcode/amd: Fix snprintf() format string warning in W=1 build +- !4102 Intel: Backport Sierra Forest(SRF) perf cstate support to kernel OLK-6.6 +- perf/x86/intel/cstate: Add Grand Ridge support +- perf/x86/intel/cstate: Add Sierra Forest support +- x86/smp: Export symbol cpu_clustergroup_mask() +- perf/x86/intel/cstate: Cleanup duplicate attr_groups +- !4104 arm64: Add the arm64.nolse command line option +- arm64: Add the arm64.nolse command line option +- !4093 introduce smart_grid zone +- smart_grid: introduce smart_grid cmdline +- smart_grid: cpufreq: introduce smart_grid cpufreq control +- smart_grid: introduce smart_grid_strategy_ctrl sysctl +- smart_grid: introduce /proc/pid/smart_grid_level +- sched: introduce smart grid qos zone +- config: enable CONFIG_QOS_SCHED_SMART_GRID by default +- sched: smart grid: init sched_grid_qos structure on QOS purpose +- sched: Introduce smart grid scheduling strategy for cfs + +* Wed Jan 31 2024 Jialin Zhang - 6.6.0-6.0.0.4 +- Module.kabi_aarch64 and Module.kabi_x86_64 v1 + +* Tue Jan 23 2024 Zheng Zengkai - 6.6.0-6.0.0.3 +- !4087 backport two page_owner patchsets: +- mm/page_owner: record and dump free_pid and free_tgid +- tools/mm: update the usage output to be more organized +- tools/mm: fix the default case for page_owner_sort +- tools/mm: filter out timestamps for correct collation +- tools/mm: remove references to free_ts from page_owner_sort +- mm/page_owner: remove free_ts from page_owner output +- !4070 Backport etmem feature to OLK 6.6 +- etmem: enable etmem configurations +- etmem: add original kernel swap enabled options +- etmem: add etmem swap feature +- mm: Export symbol reclaim_pages +- etmem: add etmem scan feature +- mm: Export symbol walk_page_range +- mm: Export symbol __pud_trans_huge_lock +- etmem: add ETMEM scan feature CONFIG to mm/Kconfig +- etmem: add ETMEM feature CONFIG to mm/Kconfig +- !3444 LoongArch: fix some pci problems +- LoongArch: pci root bridige set acpi companion only when not acpi_disabled. +- PCI: irq: Add early_param pci_irq_limit to limit pci irq numbers +- PCI: fix X server auto probe fail when both ast and etnaviv drm present +- PCI: LS7A2000: fix GPU card error +- PCI: LS7A2000: fix pm transition of devices under pcie port +- LoongArch: fix some PCIE card not scanning properly +- PCI: fix kabi error caused by pm_suspend_target_state +- PCI: PM: fix pcie mrrs restoring +- PCI: Check if the pci controller can use both CFG0 and CFG1 mode to access configuration space +- PCI: Check if entry->offset already exist for mem resource +- LS7A2000: Add quirk for OHCI device rev 0x02 +- !4027 [OLK-6.6] Intel RDT non-contiguous CBM support +- Documentation/x86: Document resctrl's new sparse_masks +- x86/resctrl: Add sparse_masks file in info +- x86/resctrl: Enable non-contiguous CBMs in Intel CAT +- x86/resctrl: Rename arch_has_sparse_bitmaps +- !4098 sched: programmable: Fix is_cpu_allowed build error +- sched: programmable: Fix is_cpu_allowed build error +- !4072 cgroup/misc: openeuler_defconfig open misc config by default +- cgroup/misc: openeuler_defconfig open misc config by default +- !4053 sched: basic infrastructure for scheduler bpf +- openeuler_defconfig: enable CONFIG_BPF_SCHED +- sched: programmable: Add hook in can_migrate_task() +- sched: programmable: Add hook in select_task_rq_fair() +- sched: introduce bpf_sched_enable() +- sched: basic infrastructure for scheduler bpf +- sched: programmable: Add user interface of task tag +- sched: programmable: Add user interface of task group tag +- sched: programmable: Add a tag for the task group +- sched: programmable: Add a tag for the task +- sched: programmable: Introduce bpf sched +- !4068 mm/oom_kill: fix NULL pointer dereference in memcg_print_bad_task() +- mm/oom_kill: fix NULL pointer dereference in memcg_print_bad_task() +- !4036 ubi: fix slab-out-of-bounds in ubi_eba_get_ldesc+0xfb/0x130 +- ubi: fix slab-out-of-bounds in ubi_eba_get_ldesc+0xfb/0x130 +- !3971 optimize inlining +- make OPTIMIZE_INLINING config editable +- Revert "compiler: remove CONFIG_OPTIMIZE_INLINING entirely" +- !3631 drm: fix free illegal pointer when create drm_property_blob failed +- drm: fix free illegal pointer when create drm_property_blob failed +- !3958 Revert "drm/prime: Unexport helpers for fd/handle conversion" +- Revert "drm/prime: Unexport helpers for fd/handle conversion" +- !3670 Add initial openeuler_defconfig for riscv64 +- config: add initial openeuler_defconfig for riscv64 +- !3895 Spark SQL scenario bpf readahead optimization synchronization to OLK-6.6 +- selftests/bpf: Update the demo file_read_pattern to run on libbpf 1.0+ +- VFS: Rolling Back the fmode macro definition and structure members +- selftests/bpf: add demo for file read pattern detection +- ext4: add trace for the read and release of regular file +- xfs: add trace for read and release of regular file +- fs: add helper fs_file_read_do_trace() +- vfs: add bare tracepoints for vfs read and release +- readahead: introduce FMODE_CTL_WILLNEED to read first 2MB of file +- !3964 drivers: hooks: add bonding driver vendor hooks +- drivers: hooks: add bonding driver vendor hooks +- !3996 hfs: fix null-ptr-deref in hfs_find_init() +- hfs: fix null-ptr-deref in hfs_find_init() +- !3976 Introduce dynamic pool feature +- mm/dynamic_pool: enable CONFIG_DYNAMIC_POOL on x86_64 and arm64 by default +- mm/dynamic_pool: add Document for dynamic hugetlb feature +- mm/dynamic_pool: compatible with memory hwpoison +- mm/dynamic_pool: compatible with HugeTLB Vmemmap +- mm/dynamic_pool: compatible with HugeTLB dissolve +- mm/dynamic_pool: disable THP for task attached with dpool +- mm/dynamic_pool: fill dpool with pagelist +- mm/dynamic_pool: add tracepoints for dpool +- mm/dynamic_pool: support HugeTLB page allocation from dpool +- mm/dynamic_pool: check resv for HugeTLB allocation from dpool +- mm/dynamic_pool: speed up allocation by percpu pages pool +- mm/dynamic_pool: support page allocation from dpool +- mm/dynamic_pool: prevent task attach to another dpool +- mm/dynamic_pool: call mem_cgroup_force_empty before restore pool +- mm/dynamic_pool: migrate used pages before promote to huge page +- mm/dynamic_pool: support to flow pages between 2M and 4K pages pool +- mm/dynamic_pool: support to flow pages between 1G and 2M pages pool +- mm/dynamic_pool: add restore_pool ops to reclaim memory and restore hugepages +- mm/dynamic_pool: add interface to configure the count of hugepages +- mm/dynamic_pool: fill dpool with HugeTLB 1G pages +- mm/dynamic_pool: create dpool by dhugetlb.nr_pages interface +- mm/dynamic_pool: introduce PG_pool to mark pages allocated from dpool +- mm/dynamic_pool: introduce PG_dpool to mark free pages in dpool +- mm/dynamic_pool: introduce per-memcg memory pool +- mm/memcg: introduce memcg_has_children to check memcg +- mm/memcg: introduce mem_cgroup_scan_cgroups to scan all memcgs +- !3833 xfs: fix block space problems +- xfs: longest free extent no need consider postalloc +- xfs: fix xfs shutdown since we reserve more blocks in agfl fixup +- xfs: set minleft correctly for randomly sparse inode allocations +- xfs: account extra freespace btree splits for multiple allocations +- !3902 xfs: update the last_sync_lsn with ctx start lsn +- xfs: update the last_sync_lsn with ctx start lsn +- !3977 Terrace Service Acceleration +- bpf, sockmap: Add sk_rmem_alloc check for sockmap +- bpf: Add new bpf helper to get SO_ORIGINAL_DST/REPLY_SRC +- bpf: Add bpf_get_sockops_uid_gid helper function +- net: core: Add a GID field to struct sock. +- !3974 Add support for mbigen to generate SPIs +- dt-bindings/irqchip/mbigen: add example of MBIGEN generate SPIs +- irqchip/mbigen: add support for a MBIGEN generating SPIs +- irqchip/mbigen: rename register marcros +- !3963 block: Add config to show info about opening a mounted device for write +- add config about writing mounted devices in openeuler_defconfig +- block: Show info about opening a lower device for write while upper-layers mounted +- block: Add config option to show info about opening a mounted device for write +- block: Add config option to detect writing to part0 while partitions mounted +- block: Expand the meaning of bdev_allow_write_mounted +- block: Record writing and mounting regardless of whether bdev_allow_write_mounted is set +- !3921 mm: mem_reliable: Introduce memory reliable +- config: enable MEMORY_RELIABLE by default +- mm: mem_reliable: Show debug info about memory reliable if oom occurs +- mm: mem_reliable: Introduce proc interface to disable memory reliable features +- proc: mem_reliable: Count reliable memory usage of reliable tasks +- mm: mem_reliable: Introduce fallback mechanism for memory reliable +- mm: mem_reliable: Add limiting the usage of reliable memory +- mm: mem_reliable: Show reliable meminfo +- mm: mem_reliable: Count reliable shmem usage +- mm: mem_reliable: Count reliable page cache usage +- mm: mem_reliable: Add cmdline reliable_debug to enable separate feature +- mm/hugetlb: Allocate non-mirrored memory by default +- mm/memblock: Introduce ability to alloc memory from specify memory region +- mm: mem_reliable: Add memory reliable support during hugepaged collapse +- mm: mem_reliable: Alloc pagecache from reliable region +- shmem: mem_reliable: Alloc shmem from reliable region +- mm: mem_reliable: Alloc task memory from reliable region +- mm: mem_reliable: Introduce memory reliable +- efi: Disable mirror feature during crashkernel +- proc: introduce proc_hide_ents to hide proc files +- !3935 pid_ns: Make pid_max per namespace +- pid_ns: Make pid_max per namespace +- !3913 arm64: Add non nmi ipi backtrace support +- arm64: Add non nmi ipi backtrace support +- !3785 【OLK-6.6】PSI cgroupv1 and PSI fine grained +- sched/psi: enable PSI_CGROUP_V1 and PSI_FINE_GRAINED in openeuler_defconfig +- sched/psi: add cpu fine grained stall tracking in pressure.stat +- sched/psi: add more memory fine grained stall tracking in pressure.stat +- sched/psi: Introduce pressure.stat in psi +- sched/psi: Introduce avgs and total calculation for cgroup reclaim +- sched/psi: Introduce fine grained stall time collect for cgroup reclaim +- sched/psi: introduce tracepoints for psi_memstall_{enter, leave} +- sched/psi: update psi irqtime when the irq delta is nozero +- sched/psi: Export cgroup psi from cgroupv2 to cgroupv1 +- sched/psi: Bail out early from irq time accounting +- !3907 cgroup: Support iocost for cgroup v1 +- openeuler_defconfig: enable iocost in openeuler_defconfig for x86 and arm64 +- cgroup: Support iocost for cgroup v1 +- !3897 Some simple extensions of the kfence feature +- arm64: kfence: scale sample_interval to support early init for kfence. +- kfence: Add a module parameter to adjust kfence objects +- !3888 fs/dcache.c: avoid panic while lockref of dentry overflow +- fs/dcache.c: avoid panic while lockref of dentry overflow +- !3894 Add swap control for memcg +- config: enable memcg swap qos for x86_64 and arm64 by default +- memcg/swap: add ability to disable memcg swap +- mm: swap_slots: add per-type slot cache +- mm/swapfile: introduce per-memcg swapfile control +- memcg: add restrict to swap to cgroup1 +- memcg: introduce per-memcg swapin interface +- memcg: introduce memcg swap qos feature +- memcg: make sysctl registration more extensible +- memcg: add page type to memory.reclaim interface +- !3827 backport mainline md patch +- dm-raid: delay flushing event_work() after reconfig_mutex is released +- md/raid1: support read error check +- md: factor out a helper exceed_read_errors() to check read_errors +- md: Whenassemble the array, consult the superblock of the freshest device +- md/raid1: remove unnecessary null checking +- md: split MD_RECOVERY_NEEDED out of mddev_resume +- md: fix stopping sync thread +- md: fix missing flush of sync_work +- md: synchronize flush io with array reconfiguration +- md/md-multipath: remove rcu protection to access rdev from conf +- md/raid5: remove rcu protection to access rdev from conf +- md/raid1: remove rcu protection to access rdev from conf +- md/raid10: remove rcu protection to access rdev from conf +- md: remove flag RemoveSynchronized +- Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d" +- md: bypass block throttle for superblock update +- md: cleanup pers->prepare_suspend() +- md-cluster: check for timeout while a new disk adding +- md: rename __mddev_suspend/resume() back to mddev_suspend/resume() +- md: remove old apis to suspend the array +- md: suspend array in md_start_sync() if array need reconfiguration +- md/raid5: replace suspend with quiesce() callback +- md/md-linear: cleanup linear_add() +- md: cleanup mddev_create/destroy_serial_pool() +- md: use new apis to suspend array before mddev_create/destroy_serial_pool +- md: use new apis to suspend array for ioctls involed array reconfiguration +- md: use new apis to suspend array for adding/removing rdev from state_store() +- md: use new apis to suspend array for sysfs apis +- md/raid5: use new apis to suspend array +- md/raid5-cache: use new apis to suspend array +- md/md-bitmap: use new apis to suspend array for location_store() +- md/dm-raid: use new apis to suspend array +- md: add new helpers to suspend/resume and lock/unlock array +- md: add new helpers to suspend/resume array +- md: replace is_md_suspended() with 'mddev->suspended' in md_check_recovery() +- md/raid5-cache: use READ_ONCE/WRITE_ONCE for 'conf->log' +- md: use READ_ONCE/WRITE_ONCE for 'suspend_lo' and 'suspend_hi' +- md/raid1: don't split discard io for write behind +- md: do not require mddev_lock() for all options in array_state_store() +- md: simplify md_seq_ops +- md: factor out a helper from mddev_put() +- md: replace deprecated strncpy with memcpy +- md: don't check 'mddev->pers' and 'pers->quiesce' from suspend_lo_store() +- md: don't check 'mddev->pers' from suspend_hi_store() +- md-bitmap: suspend array earlier in location_store() +- md-bitmap: remove the checking of 'pers->quiesce' from location_store() +- md: initialize 'writes_pending' while allocating mddev +- md: initialize 'active_io' while allocating mddev +- md: delay remove_and_add_spares() for read only array to md_start_sync() +- md: factor out a helper rdev_addable() from remove_and_add_spares() +- md: factor out a helper rdev_is_spare() from remove_and_add_spares() +- md: factor out a helper rdev_removeable() from remove_and_add_spares() +- md: delay choosing sync action to md_start_sync() +- md: factor out a helper to choose sync action from md_check_recovery() +- md: use separate work_struct for md_start_sync() +- !3857 scsi: fix use-after-free problem in scsi_remove_target +- scsi: fix use-after-free problem in scsi_remove_target +- !3906 sched/core: Change depends of SCHED_CORE +- sched/core: Change depends of SCHED_CORE +- !3747 Introduce multiple qos level +- config: Enable CONFIG_QOS_SCHED_MULTILEVEL +- sched/fair: Introduce multiple qos level +- !3899 fs/dirty_pages: dump the number of dirty pages for each inode +- fs/dirty_pages: dump the number of dirty pages for each inode +- !3815 JFFS2: Fix the race issues caused by the GC of jffs2 +- jffs2: reset pino_nlink to 0 when inode creation failed +- jffs2: make the overwritten xattr invisible after remount +- jffs2: handle INO_STATE_CLEARING in jffs2_do_read_inode() +- jffs2: protect no-raw-node-ref check of inocache by erase_completion_lock +- !3891 block: support to account io_ticks precisely +- block: support to account io_ticks precisely +- !3881 iommu: set CONFIG_SMMU_BYPASS_DEV=y +- iommu: set CONFIG_SMMU_BYPASS_DEV=y +- !3819 support ext3/ext4 netlink error report. +- Add new config 'CONFIG_EXT4_ERROR_REPORT' to control ext3/4 error reporting +- ext4: report error to userspace by netlink +- !3720 blk-mq: make fair tag sharing configurable +- scsi_lib: disable fair tag sharing by default if total tags is less than 128 +- scsi: core: make fair tag sharing configurable via sysfs +- blk-mq: add apis to disable fair tag sharing +- !3090 fs/dcache.c: avoid softlock since too many negative dentry +- fs/dcache.c: avoid softlock since too many negative dentry +- !3656 iommu: Enable smmu-v3 when 3408iMR/3416iMRraid card exist +- iommu: Enable smmu-v3 when 3408iMR/3416iMRraid card exist +- !3843 [OLK-6.6] export cgroup.stat from cgroupv2 to cgroupv1 +- cgroup: Export cgroup.stat from cgroupv2 to cgroupv1 +- !3828 openeuler_defconfig: enable erofs ondemand for x86 and arm64 +- openeuler_defconfig: enable erofs ondemand for x86 and arm64 +- !3851 ext4: fix slab-out-of-bounds in ext4_find_extent() +- ext4: check magic even the extent block bh is verified +- ext4: avoid recheck extent for EXT4_EX_FORCE_CACHE +- !3850 aio: add timeout validity check for io_[p +- aio: add timeout validity check for io_[p]getevents +- !3849 pipe: Fix endless sleep problem due to the out-of-order +- pipe: Fix endless sleep problem due to the out-of-order +- !3787 scsi: sd: unregister device if device_add_disk() failed in sd_probe() +- scsi: sd: unregister device if device_add_disk() failed in sd_probe() +- !3450 Backport nbd bugfix patch +- nbd: pass nbd_sock to nbd_read_reply() instead of index +- nbd: fix null-ptr-dereference while accessing 'nbd->config' +- nbd: factor out a helper to get nbd_config without holding 'config_lock' +- nbd: fold nbd config initialization into nbd_alloc_config() +- !3675 block mainline bugfix backport +- block: Set memalloc_noio to false on device_add_disk() error path +- block: add check of 'minors' and 'first_minor' in device_add_disk() +- block: add check that partition length needs to be aligned with block size +- !3786 ubi: block: fix memleak in ubiblock_create() +- ubi: block: fix memleak in ubiblock_create() +- !3448 ubi: block: Fix use-after-free in ubiblock_cleanup +- ubi: block: Fix use-after-free in ubiblock_cleanup +- !3760 Add huge page allocation limit +- openeuler_defconfig: enable HUGETLB_ALLOC_LIMIT +- hugetlb: Add huge page allocation limit +- !3818 [sync] PR-1989: support Android vendor hooks +- openeuler_defconfig: enable CONFIG_VENDOR_HOOKS for x86 and arm64 +- vendor_hooks: make android vendor hooks feature generic. +- ANDROID: fixup restricted hooks after tracepont refactoring +- ANDROID: simplify vendor hooks for non-GKI builds +- ANDROID: vendor_hooks: fix __section macro +- ANDROID: use static_call() for restricted hooks +- ANDROID: fix redefinition error for restricted vendor hooks +- ANDROID: add support for vendor hooks +- !3502 ARM: LPAE: Use phys_addr_t instead of unsigned long in outercache hooks +- ARM: LPAE: Use phys_addr_t instead of unsigned long in outercache hooks +- !3755 livepatch/core: Fix miss disable ro for MOD_RO_AFTER_INIT memory +- livepatch/core: Fix miss disable ro for MOD_RO_AFTER_INIT memory +- !3813 kernel: add OPENEULER_VERSION_CODE to version.h +- kernel: add OPENEULER_VERSION_CODE to version.h +- !3744 Add NUMA-awareness to qspinlock +- config: Enable CONFIG_NUMA_AWARE_SPINLOCKS on x86 +- locking/qspinlock: Disable CNA by default +- locking/qspinlock: Introduce the shuffle reduction optimization into CNA +- locking/qspinlock: Avoid moving certain threads between waiting queues in CNA +- locking/qspinlock: Introduce starvation avoidance into CNA +- locking/qspinlock: Introduce CNA into the slow path of qspinlock +- locking/qspinlock: Refactor the qspinlock slow path +- locking/qspinlock: Rename mcs lock/unlock macros and make them more generic +- !3517 support CLOCKSOURCE_VALIDATE_LAST_CYCLE on +- config: make CLOCKSOURCE_VALIDATE_LAST_CYCLE not set by default +- timekeeping: Make CLOCKSOURCE_VALIDATE_LAST_CYCLE configurable +- !3710 Backport 6.6.7 LTS Patches +- drm/amdgpu: Restrict extended wait to PSP v13.0.6 +- drm/amdgpu: update retry times for psp BL wait +- drm/amdgpu: Fix refclk reporting for SMU v13.0.6 +- riscv: Kconfig: Add select ARM_AMBA to SOC_STARFIVE +- gcc-plugins: randstruct: Update code comment in relayout_struct() +- ASoC: qcom: sc8280xp: Limit speaker digital volumes +- netfilter: nft_set_pipapo: skip inactive elements during set walk +- MIPS: Loongson64: Enable DMA noncoherent support +- MIPS: Loongson64: Handle more memory types passed from firmware +- MIPS: Loongson64: Reserve vgabios memory on boot +- perf metrics: Avoid segv if default metricgroup isn't set +- perf list: Fix JSON segfault by setting the used skip_duplicate_pmus callback +- KVM: SVM: Update EFER software model on CR0 trap for SEV-ES +- KVM: s390/mm: Properly reset no-dat +- MIPS: kernel: Clear FPU states when setting up kernel threads +- cifs: Fix flushing, invalidation and file size with FICLONE +- cifs: Fix flushing, invalidation and file size with copy_file_range() +- USB: gadget: core: adjust uevent timing on gadget unbind +- powerpc/ftrace: Fix stack teardown in ftrace_no_trace +- x86/CPU/AMD: Check vendor in the AMD microcode callback +- devcoredump: Send uevent once devcd is ready +- serial: 8250_omap: Add earlycon support for the AM654 UART controller +- serial: 8250: 8250_omap: Do not start RX DMA on THRI interrupt +- serial: 8250: 8250_omap: Clear UART_HAS_RHR_IT_DIS bit +- serial: sc16is7xx: address RX timeout interrupt errata +- ARM: PL011: Fix DMA support +- usb: typec: class: fix typec_altmode_put_partner to put plugs +- smb: client: fix potential NULL deref in parse_dfs_referrals() +- Revert "xhci: Loosen RPM as default policy to cover for AMD xHC 1.1" +- cifs: Fix non-availability of dedup breaking generic/304 +- parport: Add support for Brainboxes IX/UC/PX parallel cards +- serial: ma35d1: Validate console index before assignment +- serial: 8250_dw: Add ACPI ID for Granite Rapids-D UART +- nvmem: Do not expect fixed layouts to grab a layout driver +- usb: gadget: f_hid: fix report descriptor allocation +- kprobes: consistent rcu api usage for kretprobe holder +- ASoC: ops: add correct range check for limiting volume +- gpiolib: sysfs: Fix error handling on failed export +- x86/sev: Fix kernel crash due to late update to read-only ghcb_version +- perf: Fix perf_event_validate_size() +- drm/amdgpu: disable MCBP by default +- arm64: dts: mt8183: kukui: Fix underscores in node names +- arm64: dts: mediatek: add missing space before { +- parisc: Fix asm operand number out of range build error in bug table +- parisc: Reduce size of the bug_table on 64-bit kernel by half +- LoongArch: BPF: Don't sign extend function return value +- LoongArch: BPF: Don't sign extend memory load operand +- perf vendor events arm64: AmpereOne: Add missing DefaultMetricgroupName fields +- misc: mei: client.c: fix problem of return '-EOVERFLOW' in mei_cl_write +- misc: mei: client.c: return negative error code in mei_cl_write +- coresight: ultrasoc-smb: Fix uninitialized before use buf_hw_base +- coresight: ultrasoc-smb: Config SMB buffer before register sink +- coresight: ultrasoc-smb: Fix sleep while close preempt in enable_smb +- hwtracing: hisi_ptt: Add dummy callback pmu::read() +- coresight: Fix crash when Perf and sysfs modes are used concurrently +- coresight: etm4x: Remove bogous __exit annotation for some functions +- arm64: dts: mediatek: mt8186: Change gpu speedbin nvmem cell name +- arm64: dts: mediatek: mt8186: fix clock names for power domains +- arm64: dts: mediatek: mt8183-evb: Fix unit_address_vs_reg warning on ntc +- arm64: dts: mediatek: mt8183: Move thermal-zones to the root node +- arm64: dts: mediatek: mt8183: Fix unit address for scp reserved memory +- arm64: dts: mediatek: mt8195: Fix PM suspend/resume with venc clocks +- arm64: dts: mediatek: mt8173-evb: Fix regulator-fixed node names +- arm64: dts: mediatek: cherry: Fix interrupt cells for MT6360 on I2C7 +- arm64: dts: mediatek: mt8183-kukui-jacuzzi: fix dsi unnecessary cells properties +- arm64: dts: mediatek: mt7622: fix memory node warning check +- arm64: dts: mt7986: fix emmc hs400 mode without uboot initialization +- arm64: dts: mt7986: define 3W max power to both SFP on BPI-R3 +- arm64: dts: mt7986: change cooling trips +- drm/i915: Skip some timing checks on BXT/GLK DSI transcoders +- drm/i915/mst: Reject modes that require the bigjoiner +- drm/i915/mst: Fix .mode_valid_ctx() return values +- drm/atomic-helpers: Invoke end_fb_access while owning plane state +- md/raid6: use valid sector values to determine if an I/O should wait on the reshape +- powercap: DTPM: Fix missing cpufreq_cpu_put() calls +- mm/memory_hotplug: fix error handling in add_memory_resource() +- mm: fix oops when filemap_map_pmd() without prealloc_pte +- mm/memory_hotplug: add missing mem_hotplug_lock +- drivers/base/cpu: crash data showing should depends on KEXEC_CORE +- hugetlb: fix null-ptr-deref in hugetlb_vma_lock_write +- workqueue: Make sure that wq_unbound_cpumask is never empty +- platform/surface: aggregator: fix recv_buf() return value +- regmap: fix bogus error on regcache_sync success +- r8169: fix rtl8125b PAUSE frames blasting when suspended +- packet: Move reference count in packet_sock to atomic_long_t +- nfp: flower: fix for take a mutex lock in soft irq context and rcu lock +- leds: trigger: netdev: fix RTNL handling to prevent potential deadlock +- tracing: Fix a possible race when disabling buffered events +- tracing: Fix incomplete locking when disabling buffered events +- tracing: Disable snapshot buffer when stopping instance tracers +- tracing: Stop current tracer when resizing buffer +- tracing: Always update snapshot buffer size +- checkstack: fix printed address +- cgroup_freezer: cgroup_freezing: Check if not frozen +- lib/group_cpus.c: avoid acquiring cpu hotplug lock in group_cpus_evenly +- nilfs2: prevent WARNING in nilfs_sufile_set_segment_usage() +- nilfs2: fix missing error check for sb_set_blocksize call +- highmem: fix a memory copy problem in memcpy_from_folio +- ring-buffer: Force absolute timestamp on discard of event +- ring-buffer: Test last update in 32bit version of __rb_time_read() +- ALSA: hda/realtek: Add quirk for Lenovo Yoga Pro 7 +- ALSA: hda/realtek: Add Framework laptop 16 to quirks +- ALSA: hda/realtek: add new Framework laptop to quirks +- ALSA: hda/realtek: Enable headset on Lenovo M90 Gen5 +- ALSA: hda/realtek: fix speakers on XPS 9530 (2023) +- ALSA: hda/realtek: Apply quirk for ASUS UM3504DA +- ALSA: pcm: fix out-of-bounds in snd_pcm_state_names +- ALSA: usb-audio: Add Pioneer DJM-450 mixer controls +- io_uring: fix mutex_unlock with unreferenced ctx +- nvme-pci: Add sleep quirk for Kingston drives +- io_uring/af_unix: disable sending io_uring over sockets +- ASoC: amd: yc: Fix non-functional mic on ASUS E1504FA +- rethook: Use __rcu pointer for rethook::handler +- scripts/gdb: fix lx-device-list-bus and lx-device-list-class +- kernel/Kconfig.kexec: drop select of KEXEC for CRASH_DUMP +- md: don't leave 'MD_RECOVERY_FROZEN' in error path of md_set_readonly() +- riscv: errata: andes: Probe for IOCP only once in boot stage +- riscv: fix misaligned access handling of C.SWSP and C.SDSP +- arm64: dts: rockchip: Fix eMMC Data Strobe PD on rk3588 +- ARM: dts: imx28-xea: Pass the 'model' property +- ARM: dts: imx7: Declare timers compatible with fsl,imx6dl-gpt +- arm64: dts: imx8-apalis: set wifi regulator to always-on +- ARM: imx: Check return value of devm_kasprintf in imx_mmdc_perf_init +- arm64: dts: imx93: correct mediamix power +- arm64: dts: freescale: imx8-ss-lsio: Fix #pwm-cells +- arm64: dts: imx8-ss-lsio: Add PWM interrupts +- scsi: be2iscsi: Fix a memleak in beiscsi_init_wrb_handle() +- tracing: Fix a warning when allocating buffered events fails +- io_uring/kbuf: check for buffer list readiness after NULL check +- io_uring/kbuf: Fix an NULL vs IS_ERR() bug in io_alloc_pbuf_ring() +- ARM: dts: imx6ul-pico: Describe the Ethernet PHY clock +- arm64: dts: imx8mp: imx8mq: Add parkmode-disable-ss-quirk on DWC3 +- drm/bridge: tc358768: select CONFIG_VIDEOMODE_HELPERS +- RDMA/irdma: Avoid free the non-cqp_request scratch +- RDMA/irdma: Fix support for 64k pages +- RDMA/irdma: Ensure iWarp QP queue memory is OS paged aligned +- RDMA/core: Fix umem iterator when PAGE_SIZE is greater then HCA pgsz +- ASoC: wm_adsp: fix memleak in wm_adsp_buffer_populate +- firmware: arm_scmi: Fix possible frequency truncation when using level indexing mode +- firmware: arm_scmi: Simplify error path in scmi_dvfs_device_opps_add() +- firmware: arm_scmi: Fix frequency truncation by promoting multiplier type +- firmware: arm_scmi: Extend perf protocol ops to get information of a domain +- firmware: arm_scmi: Extend perf protocol ops to get number of domains +- hwmon: (nzxt-kraken2) Fix error handling path in kraken2_probe() +- ASoC: codecs: lpass-tx-macro: set active_decimator correct default value +- hwmon: (acpi_power_meter) Fix 4.29 MW bug +- ARM: dts: bcm2711-rpi-400: Fix delete-node of led_act +- ARM: dts: rockchip: Fix sdmmc_pwren's pinmux setting for RK3128 +- ARM: dts: imx6q: skov: fix ethernet clock regression +- arm64: dt: imx93: tqma9352-mba93xxla: Fix LPUART2 pad config +- RDMA/irdma: Fix UAF in irdma_sc_ccq_get_cqe_info() +- RDMA/bnxt_re: Correct module description string +- RDMA/rtrs-clt: Remove the warnings for req in_use check +- RDMA/rtrs-clt: Fix the max_send_wr setting +- RDMA/rtrs-srv: Destroy path files after making sure no IOs in-flight +- RDMA/rtrs-srv: Free srv_mr iu only when always_invalidate is true +- RDMA/rtrs-srv: Check return values while processing info request +- RDMA/rtrs-clt: Start hb after path_up +- RDMA/rtrs-srv: Do not unconditionally enable irq +- ASoC: fsl_sai: Fix no frame sync clock issue on i.MX8MP +- arm64: dts: rockchip: Expand reg size of vdec node for RK3399 +- arm64: dts: rockchip: Expand reg size of vdec node for RK3328 +- RDMA/irdma: Add wait for suspend on SQD +- RDMA/irdma: Do not modify to SQD on error +- RDMA/hns: Fix unnecessary err return when using invalid congest control algorithm +- RDMA/core: Fix uninit-value access in ib_get_eth_speed() +- tee: optee: Fix supplicant based device enumeration +- mm/damon/sysfs: eliminate potential uninitialized variable warning +- drm/amdkfd: get doorbell's absolute offset based on the db_size +- drm/amd/amdgpu/amdgpu_doorbell_mgr: Correct misdocumented param 'doorbell_index' +- net/smc: fix missing byte order conversion in CLC handshake +- net: dsa: microchip: provide a list of valid protocols for xmit handler +- drop_monitor: Require 'CAP_SYS_ADMIN' when joining "events" group +- psample: Require 'CAP_NET_ADMIN' when joining "packets" group +- bpf: sockmap, updating the sg structure should also update curr +- net: tls, update curr on splice as well +- net: dsa: mv88e6xxx: Restore USXGMII support for 6393X +- tcp: do not accept ACK of bytes we never sent +- netfilter: xt_owner: Fix for unsafe access of sk->sk_socket +- netfilter: nf_tables: validate family when identifying table via handle +- netfilter: nf_tables: bail out on mismatching dynset and set expressions +- netfilter: nf_tables: fix 'exist' matching on bigendian arches +- netfilter: bpf: fix bad registration on nf_defrag +- dt-bindings: interrupt-controller: Allow #power-domain-cells +- octeontx2-af: Update Tx link register range +- octeontx2-af: Add missing mcs flr handler call +- octeontx2-af: Fix mcs stats register address +- octeontx2-af: Fix mcs sa cam entries size +- octeontx2-af: Adjust Tx credits when MCS external bypass is disabled +- net: hns: fix fake link up on xge port +- net: hns: fix wrong head when modify the tx feature when sending packets +- net: atlantic: Fix NULL dereference of skb pointer in +- ipv4: ip_gre: Avoid skb_pull() failure in ipgre_xmit() +- ionic: Fix dim work handling in split interrupt mode +- ionic: fix snprintf format length warning +- tcp: fix mid stream window clamp. +- net: bnxt: fix a potential use-after-free in bnxt_init_tc +- iavf: validate tx_coalesce_usecs even if rx_coalesce_usecs is zero +- i40e: Fix unexpected MFS warning message +- ice: Restore fix disabling RX VLAN filtering +- octeontx2-af: fix a use-after-free in rvu_npa_register_reporters +- xsk: Skip polling event check for unbound socket +- net: stmmac: fix FPE events losing +- octeontx2-pf: consider both Rx and Tx packet stats for adaptive interrupt coalescing +- arcnet: restoring support for multiple Sohard Arcnet cards +- platform/mellanox: Check devm_hwmon_device_register_with_groups() return value +- platform/mellanox: Add null pointer checks for devm_kasprintf() +- mlxbf-bootctl: correctly identify secure boot with development keys +- r8152: Add RTL8152_INACCESSIBLE to r8153_aldps_en() +- r8152: Add RTL8152_INACCESSIBLE to r8153_pre_firmware_1() +- r8152: Add RTL8152_INACCESSIBLE to r8156b_wait_loading_flash() +- r8152: Add RTL8152_INACCESSIBLE checks to more loops +- r8152: Hold the rtnl_lock for all of reset +- hv_netvsc: rndis_filter needs to select NLS +- bpf: Fix a verifier bug due to incorrect branch offset comparison with cpu=v4 +- octeontx2-af: Check return value of nix_get_nixlf before using nixlf +- octeontx2-pf: Add missing mutex lock in otx2_get_pauseparam +- ipv6: fix potential NULL deref in fib6_add() +- platform/x86: wmi: Skip blocks with zero instances +- of: dynamic: Fix of_reconfig_get_state_change() return value documentation +- platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi code +- dt: dt-extract-compatibles: Don't follow symlinks when walking tree +- dt: dt-extract-compatibles: Handle cfile arguments in generator function +- x86/tdx: Allow 32-bit emulation by default +- x86/entry: Do not allow external 0x80 interrupts +- x86/entry: Convert INT 0x80 emulation to IDTENTRY +- x86/coco: Disable 32-bit emulation by default on TDX and SEV +- x86: Introduce ia32_enabled() +- dm-crypt: start allocating with MAX_ORDER +- drm/amdgpu: correct chunk_ptr to a pointer to chunk. +- drm/amdgpu: finalizing mem_partitions at the end of GMC v9 sw_fini +- drm/amdgpu: Do not program VF copy regs in mmhub v1.8 under SRIOV (v2) +- kconfig: fix memory leak from range properties +- modpost: fix section mismatch message for RELA +- tg3: Increment tx_dropped in tg3_tso_bug() +- tg3: Move the [rt]x_dropped counters to tg3_napi +- zstd: Fix array-index-out-of-bounds UBSAN warning +- nouveau: use an rwlock for the event lock. +- netfilter: ipset: fix race condition between swap/destroy and kernel side add/del/test +- i2c: ocores: Move system PM hooks to the NOIRQ phase +- i2c: designware: Fix corrupted memory seen in the ISR +- hrtimers: Push pending hrtimers away from outgoing CPU earlier +- scsi: sd: Fix sshdr use in sd_suspend_common() +- vdpa/mlx5: preserve CVQ vringh index +- !3749 support nokaslr and memmap parameter for kaslr collision detection +- kaslr: enable CONFIG_SKIP_KASLR_MEM_RANGE in openeuler defconfig +- x86/boot: add x86 nokaslr memory regions +- efi/libstub: add arm64 nokaslr memory regions +- efi/libstub: arm64: Fix KASLR and memmap= collision +- efi/libstub: arm64: support strchr function for EFI stub +- efi/libstub: add arm64 kaslr memory region avoid support +- !3737 arm64: Fix compilation error with ILP32 +- config: Disable CONFIG_COMPAT_BINFMT_ELF as default +- arm64: Fix compilation error with ILP32 support +- Revert "Kconfig: regularize selection of CONFIG_BINFMT_ELF" +- !3743 Fix ppc32 build error +- powerpc: Fix ppc32 build +- !3713 Introduce CPU inspect feature +- openeuler_defconfig: enable CPU inspect for arm64 by default +- cpuinspect: add ATF inspector +- cpuinspect: add CPU-inspect infrastructure +- !3730 ARM: spectre-v2: turn off the mitigation via boot cmdline param +- ARM: spectre-v2: turn off the mitigation via boot cmdline param +- !3732 tcp_comp: implement tcp compression +- tcp_comp: implement tcp compression +- !3748 jffs2: move jffs2_init_inode_info() just after allocating inode +- jffs2: move jffs2_init_inode_info() just after allocating inode +- !3542 Support kernel livepatching +- livepatch/powerpc: Add arch_klp_module_check_calltrace +- livepatch/powerpc: Support breakpoint exception optimization +- livepatch/ppc64: Sample testcase fix ppc64 +- livepatch/ppc64: Implement livepatch without ftrace for ppc64be +- livepatch: Bypass dead thread when check calltrace +- livepatch/arm: Add arch_klp_module_check_calltrace +- livepatch/arm64: Add arch_klp_module_check_calltrace +- livepatch/x86: Add arch_klp_module_check_calltrace +- livepatch: Add klp_module_delete_safety_check +- livepatch/arm: Support breakpoint exception optimization +- livepatch/arm64: Support breakpoint exception optimization +- livepatch: Add arch_klp_init +- livepatch/x86: Support breakpoint exception optimization +- livepatch: Use breakpoint exception to optimize enabling livepatch +- livepatch/ppc32: Support livepatch without ftrace +- livepatch/arm: Support livepatch without ftrace +- livepatch/core: Add support for arm for klp relocation +- arm/module: Use plt section indices for relocations +- livepatch: Enable livepatch configs in openeuler_defconfig +- livepatch/core: Revert module_enable_ro and module_disable_ro +- livepatch/arm64: Support livepatch without ftrace +- livepatch/core: Avoid conflict with static {call,key} +- livepatch: Fix patching functions which have static_call +- livepatch: Fix crash when access the global variable in hook +- livepatch/core: Support jump_label +- livepatch: samples: Adapt livepatch-sample for solution without ftrace +- livepatch/core: Support load and unload hooks +- livepatch/core: Restrict livepatch patched/unpatched when plant kprobe +- livepatch/core: Disable support for replacing +- livepatch/x86: Support livepatch without ftrace +- Revert "x86/insn: Make insn_complete() static" +- livepatch/core: Reuse common codes in the solution without ftrace +- livepatch/core: Allow implementation without ftrace +- !3678 timer_list: avoid other cpu soft lockup when printing timer list +- timer_list: avoid other cpu soft lockup when printing timer list +- !3733 drm/radeon: check the alloc_workqueue return value in radeon_crtc_init() +- drm/radeon: check the alloc_workqueue return value in radeon_crtc_init() +- !3734 Introduce qos smt expeller for co-location +- sched/fair: Add cmdline nosmtexpell +- sched/fair: Introduce QOS_SMT_EXPELL priority reversion mechanism +- sched/fair: Start tracking qos_offline tasks count in cfs_rq +- config: Enable CONFIG_QOS_SCHED_SMT_EXPELLER +- sched: Add tracepoint for qos smt expeller +- sched: Add statistics for qos smt expeller +- sched: Implement the function of qos smt expeller +- sched: Introduce qos smt expeller for co-location +- !3629 x86/kdump: make crash kernel boot faster +- x86/kdump: make crash kernel boot faster +- !3722 add memmap interface to reserved memory +- arm64: Request resources for reserved memory via memmap +- arm64: Add support for memmap kernel parameters +- !3724 lib/clear_user: ensure loop in __arch_clear_user cache-aligned v2 +- config: enable CONFIG_CLEAR_USER_WORKAROUND by default +- lib/clear_user: ensure loop in __arch_clear_user cache-aligned v2 +- !3688 Support priority load balance for qos scheduler +- sched: Introduce priority load balance for qos scheduler +- !3712 sched: steal tasks to improve CPU utilization +- config: enable CONFIG_SCHED_STEAL by default +- sched/fair: introduce SCHED_STEAL +- disable stealing by default +- sched/fair: Provide idle search schedstats +- sched/fair: disable stealing if too many NUMA nodes +- sched/fair: Steal work from an overloaded CPU when CPU goes idle +- sched/fair: Provide can_migrate_task_llc +- sched/fair: Generalize the detach_task interface +- sched/fair: Hoist idle_stamp up from idle_balance +- sched/fair: Dynamically update cfs_overload_cpus +- sched/topology: Provide cfs_overload_cpus bitmap +- sched/topology: Provide hooks to allocate data shared per LLC +- sched: Provide sparsemask, a reduced contention bitmap +- !3701 mm: Add sysctl to clear free list pages +- mm: Add sysctl to clear free list pages +- !3598 arm64: add config switch and kernel parameter for cpu0 hotplug +- config: disable config ARM64_BOOTPARAM_HOTPLUG_CPU0 by default +- arm64: Add config switch and kernel parameter for CPU0 hotplug +- !3649 x86/kdump: add log before booting crash kernel +- x86/kdump: add log before booting crash kernel +- !3700 Backport 6.6.6 LTS Patches +- Revert "wifi: cfg80211: fix CQM for non-range use" +- !3565 blk-throttle: enable hierarchical throttle in cgroup v1 +- blk-throttle: enable hierarchical throttle in cgroup v1 +- !3608 xfs: fix two corruption problems +- xfs: shutdown xfs once inode double free +- xfs: shutdown to ensure submits buffers on LSN boundaries +- !3674 mm/hugetlb: Introduce alloc_hugetlb_folio_size() +- mm/hugetlb: Introduce alloc_hugetlb_folio_size() +- !3651 nbd: get config_lock before sock_shutdown +- nbd: get config_lock before sock_shutdown +- !3573 Support dynamic affinity scheduler +- sched/fair: Modify idle cpu judgment in dynamic affinity +- sched/fair: Remove invalid cpu selection logic in dynamic affinity +- config: enable CONFIG_QOS_SCHED_DYNAMIC_AFFINITY by default +- sched: Add cmdline for dynamic affinity +- sched: Add statistics for scheduler dynamic affinity +- sched: Adjust cpu allowed in load balance dynamicly +- sched: Adjust wakeup cpu range according CPU util dynamicly +- cpuset: Introduce new interface for scheduler dynamic affinity +- sched: Introduce dynamic affinity for cfs scheduler +- !3599 arm64: Add framework to turn IPI as NMI +- arm64: kgdb: Roundup cpus using IPI as NMI +- kgdb: Expose default CPUs roundup fallback mechanism +- arm64: ipi_nmi: Add support for NMI backtrace +- nmi: backtrace: Allow runtime arch specific override +- arm64: smp: Assign and setup an IPI as NMI +- irqchip/gic-v3: Enable support for SGIs to act as NMIs +- arm64: Add framework to turn IPI as NMI +- !3638 memcg: support OOM priority for memcg +- memcg: enable CONFIG_MEMCG_OOM_PRIORITY by default +- memcg: Add sysctl memcg_qos_enable +- memcg: support priority for oom +- !3602 xfs: fix attr inactive problems +- xfs: atomic drop extent entries when inactiving attr +- xfs: factor out __xfs_da3_node_read() +- xfs: force shutdown xfs when xfs_attr_inactive fails +- !3601 xfs: fix perag leak when growfs fails +- xfs: fix perag leak when growfs fails +- xfs: add lock protection when remove perag from radix tree +- !3575 ubi: Enhance fault injection capability for the UBI driver +- mtd: Add several functions to the fail_function list +- ubi: Reserve sufficient buffer length for the input mask +- ubi: Add six fault injection type for testing +- ubi: Split io_failures into write_failure and erase_failure +- ubi: Use the fault injection framework to enhance the fault injection capability +- !3588 files cgroups +- enable CONFIG_CGROUP_FILES in openeuler_defconfig for x86 and arm64 +- cgroup/files: support boot parameter to control if disable files cgroup +- fs/filescontrol: add a switch to enable / disable accounting of open fds +- cgroups: Resource controller for open files +- !3605 openeuler_defconfig: enable CONFIG_UNICODE for x86 and arm64 +- openeuler_defconfig: enable CONFIG_UNICODE for x86 and arm64 +- !3600 iommu/arm-smmu-v3: Add a SYNC command to avoid broken page table prefetch +- iommu/arm-smmu-v3: Add a SYNC command to avoid broken page table prefetch +- !3397 xfs: fix some growfs problems +- xfs: fix dir3 block read verify fail during log recover +- xfs: keep growfs sb log item active until ail flush success +- xfs: fix mounting failed caused by sequencing problem in the log records +- xfs: fix the problem of mount failure caused by not refreshing mp->m_sb +- !3582 Add support for memory limit +- mm: support pagecache limit +- mm: support periodical memory reclaim +- !3323 LoongArch: add cpufreq and ls2k500 bmc support +- LoongArch: fix ls2k500 bmc not work when installing iso +- LoongArch: defconfig: enable CONFIG_FB_LS2K500=m. +- ipmi: add ls2k500 bmc ipmi support. +- fbdev: add ls2k500sfb driver for ls2k500 bmc. +- cpufreq: Add cpufreq driver for LoongArch +- !3363 xfs: fix some misc issue +- xfs: xfs_trans_cancel() path must check for log shutdown +- xfs: don't verify agf length when log recovery +- xfs: fix a UAF in xfs_iflush_abort_clean +- xfs: fix a UAF when inode item push +- !3495 xfs: fix hung and warning +- xfs: fix warning in xfs_vm_writepages() +- xfs: fix hung when transaction commit fail in xfs_inactive_ifree +- xfs: fix dead loop when do mount with IO fault injection +- !3525 ARM: support kaslr feature in arm32 platform +- arm32: kaslr: Fix clock_gettime and gettimeofday performance degradation when configure CONFIG_RANDOMIZE_BASE +- arm32: kaslr: Fix the bug of symbols relocation +- arm32: kaslr: print kaslr offset when kernel panic +- arm32: kaslr: pop visibility when compile decompress boot code as we need relocate BSS by GOT. +- arm32: kaslr: When boot with vxboot, we must adjust dtb address before kaslr_early_init, and store dtb address after init. +- No idea why this broke ... +- ARM: decompressor: add KASLR support +- ARM: decompressor: explicitly map decompressor binary cacheable +- ARM: kernel: implement randomization of the kernel load address +- arm: vectors: use local symbol names for vector entry points +- ARM: kernel: refer to swapper_pg_dir via its symbol +- ARM: mm: export default vmalloc base address +- ARM: kernel: use PC relative symbol references in suspend/resume code +- ARM: kernel: use PC-relative symbol references in MMU switch code +- ARM: kernel: make vmlinux buildable as a PIE executable +- ARM: kernel: switch to relative exception tables +- arm-soc: various: replace open coded VA->PA calculation of pen_release +- arm-soc: mvebu: replace open coded VA->PA conversion +- arm-soc: exynos: replace open coded VA->PA conversions +- asm-generic: add .data.rel.ro sections to __ro_after_init +- !3563 memcg: support ksm merge any mode per cgroup +- memcg: support ksm merge any mode per cgroup +- !3528 Print rootfs and tmpfs files charged by memcg +- config: enable CONFIG_MEMCG_MEMFS_INFO by default +- mm/memcg_memfs_info: show files that having pages charged in mem_cgroup +- fs: move {lock, unlock}_mount_hash to fs/mount.h +- !3489 ascend: export interfaces required by ascend drivers +- ascend: export interfaces required by ascend drivers +- !3381 cgroupv1 cgroup writeback enable +- openeuler_defconfig: enable CONFIG_CGROUP_V1_WRITEBACK in openeuler_defconfig for x86 and arm64 +- cgroup: support cgroup writeback on cgroupv1 +- cgroup: factor out __cgroup_get_from_id() for cgroup v1 +- !3537 backport cgroup bugs from olk5.10 +- cgroup: disable kernel memory accounting for all memory cgroups by default +- cgroup: Return ERSCH when add Z process into task +- cgroup: wait for cgroup destruction to complete when umount +- cgroup: check if cgroup root is alive in cgroupstats_show() +- !3439 security: restrict init parameters by configuration +- security: restrict init parameters by configuration +- !3475 kaslr: ppc64: Introduce KASLR for PPC64 +- powerpc/fsl_booke/kaslr: Fix preserved memory size for int-vectors issue +- powerpc/fsl_booke/kaslr: Provide correct r5 value for relocated kernel +- powerpc/fsl_booke/kaslr: rename kaslr-booke32.rst to kaslr-booke.rst and add 64bit part +- powerpc/fsl_booke/64: clear the original kernel if randomized +- powerpc/fsl_booke/64: do not clear the BSS for the second pass +- powerpc/fsl_booke/64: implement KASLR for fsl_booke64 +- powerpc/fsl_booke/64: introduce reloc_kernel_entry() helper +- powerpc/fsl_booke/kaslr: refactor kaslr_legal_offset() and kaslr_early_init() +- !3486 sync smmu patches for olk-6.6 +- iommu/arm-smmu-v3: disable stall for quiet_cd +- iommu/iova: Manage the depot list size +- iommu/iova: Make the rcache depot scale better +- !3434 arm64/ascend: Add new enable_oom_killer interface for oom contrl +- arm64/ascend: Add new enable_oom_killer interface for oom contrl +- !3479 cache: Workaround HiSilicon Linxicore DC CVAU +- cache: Workaround HiSilicon Linxicore DC CVAU +- !3367 ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet +- ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet +- !3471 add redis sockmap sample code +- tools: add sample sockmap code for redis +- net: add local_skb parameter to identify local tcp connection +- net: let sockops can use bpf_get_current_comm() +- !3432 ACPI / APEI: Notify all ras err to driver +- ACPI / APEI: Notify all ras err to driver + +* Tue Dec 26 2023 Zheng Zengkai - 6.6.0-2.0.0.2 +- !3435 iommu/arm-smmu-v3: Add suspend and resume support +- !3315 Backport 6.6.5 LTS Patches +- !3314 Backport 6.6.4 LTS Patches +- !3286 block: Add config option to not allow writing to mounted devices +- !3430 Add support for hisi HBM devices +- !3431 memcg reclaim and cgroup kill +- iommu/arm-smmu-v3: Add suspend and resume support +- config: enable CONFIG_MEMCG_V1_RECLAIM and CONFIG_CGROUP_V1_KILL +- memcg: introduce per-memcg reclaim interface +- memcg: export high_async_ratio to userland +- memcg: enable memcg async reclaim +- memcg: Export memory.events{local} from cgroupv2 to cgroupv1 +- memcg: Export memcg.{min/low/high} from cgroupv2 to cgroupv1 +- cgroup: Export cgroup.kill from cgroupv2 to cgroupv1 +- soc: hisilicon: hisi_hbmdev: Add hbm acls repair and query methods +- soc: hbmcache: Add support for online and offline the hbm cache +- soc: hisilicon: hisi_hbmdev: Provide extra memory topology information +- ACPI: memhotplug: export the state of each hotplug device +- soc: hisilicon: hisi_hbmdev: Add power domain control methods +- ACPI: OSL: Export the symbol of acpi_hotplug_schedule +- !3391 nbd_genl_status: null check for nla_nest_start +- !3352 support userswap feature +- !3383 Support Qos Scheduler +- nbd_genl_status: null check for nla_nest_start +- sched: Enable qos scheduler config +- sched: Introduce handle priority reversion mechanism +- sched: Support kill boost for offline task +- sched: Throttle qos cfs_rq when current cpu is running online task +- sched: Introduce qos scheduler for co-location +- !3306 improve gettimeofday() performance in user space +- !3331 kabi: add kabi helper macros and tools +- mm/userswap: openeuler_defconfig: enable userswap +- mm/userswap: provide cpu info in userfault msg +- mm/userswap: introduce UFFDIO_COPY_MODE_DIRECT_MAP +- mm/userswap: support userswap via userfaultfd +- mm/userswap: introduce MREMAP_USWAP_SET_PTE +- mm/userswap: add enable_userswap boot option +- mm/userswap: add VM_USWAP and SWP_USERSWAP_ENTRY +- !3326 config: Open CONFIG_AARCH32_EL0 and keep CONFIG_ARM64_ILP32 closed +- kabi: add kABI reference checking tool +- kabi: add a tool to generate the kabi reference relationship +- kabi: add script tools to check kabi symbol +- kabi: deduplication friendly structs +- kabi: Generalize naming of kabi helper macros +- openeuler_defconfig: Enable CONFIG_KABI_RESERVE for x86 and arm64 +- KABI: Add CONFIG_KABI_RESERVE to control KABI padding reserve +- kabi: enables more stringent kabi checks +- kabi: add KABI_SIZE_ALIGN_CHECKS for more stringent kabi checks +- kabi: add kabi helper macros +- !3298 ARM: Add unwinding annotations to __loop.*delay functions +- config: Open CONFIG_AARCH32_EL0 and keep CONFIG_ARM64_ILP32 closed +- !3300 Add sharepool support v3 +- vfio: Drop vfio_file_iommu_group() stub to fudge around a KVM wart +- x86/xen: fix percpu vcpu_info allocation +- vfio/pds: Fix possible sleep while in atomic context +- vfio/pds: Fix mutex lock->magic != lock warning +- drm/amd/display: Fix MPCC 1DLUT programming +- drm/amd/display: Simplify brightness initialization +- drm/amd/display: Reduce default backlight min from 5 nits to 1 nits +- drm/amd/display: refactor ILR to make it work +- iommu: Fix printk arg in of_iommu_get_resv_regions() +- drm/amd/pm: fix a memleak in aldebaran_tables_init +- cpufreq/amd-pstate: Only print supported EPP values for performance governor +- cpufreq/amd-pstate: Fix scaling_min_freq and scaling_max_freq update +- drm/panel: nt36523: fix return value check in nt36523_probe() +- drm/panel: starry-2081101qfh032011-53g: Fine tune the panel power sequence +- drm/i915/gsc: Mark internal GSC engine with reserved uabi class +- iommu/vt-d: Make context clearing consistent with context mapping +- iommu/vt-d: Disable PCI ATS in legacy passthrough mode +- iommu/vt-d: Omit devTLB invalidation requests when TES=0 +- cpufreq: imx6q: Don't disable 792 Mhz OPP unnecessarily +- drm/amd/display: Remove power sequencing check +- drm/amd/display: Refactor edp power control +- s390/cmma: fix handling of swapper_pg_dir and invalid_pg_dir +- powerpc/pseries/iommu: enable_ddw incorrectly returns direct mapping for SR-IOV device +- net: ravb: Keep reverse order of operations in ravb_remove() +- net: ravb: Stop DMA in case of failures on ravb_open() +- net: ravb: Start TX queues after HW initialization succeeded +- net: ravb: Make write access to CXR35 first before accessing other EMAC registers +- net: ravb: Use pm_runtime_resume_and_get() +- net: ravb: Check return value of reset_control_deassert() +- ice: Fix VF Reset paths when interface in a failed over aggregate +- bpf, sockmap: af_unix stream sockets need to hold ref for pair sock +- ethtool: don't propagate EOPNOTSUPP from dumps +- ravb: Fix races between ravb_tx_timeout_work() and net related ops +- r8169: prevent potential deadlock in rtl8169_close +- efi/unaccepted: Fix off-by-one when checking for overlapping ranges +- neighbour: Fix __randomize_layout crash in struct neighbour +- octeontx2-pf: Restore TC ingress police rules when interface is up +- octeontx2-pf: Fix adding mbox work queue entry when num_vfs > 64 +- net: stmmac: xgmac: Disable FPE MMC interrupts +- octeontx2-af: Fix possible buffer overflow +- selftests/net: mptcp: fix uninitialized variable warnings +- selftests/net: unix: fix unused variable compiler warning +- selftests/net: fix a char signedness issue +- selftests/net: ipsec: fix constant out of range +- uapi: propagate __struct_group() attributes to the container union +- bpf: Add missed allocation hint for bpf_mem_cache_alloc_flags() +- dpaa2-eth: recycle the RX buffer only after all processing done +- dpaa2-eth: increase the needed headroom to account for alignment +- net: dsa: mv88e6xxx: fix marvell 6350 probe crash +- net: dsa: mv88e6xxx: fix marvell 6350 switch probing +- wifi: mac80211: do not pass AP_VLAN vif pointer to drivers during flush +- wifi: iwlwifi: mvm: fix an error code in iwl_mvm_mld_add_sta() +- ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet +- net: rswitch: Fix missing dev_kfree_skb_any() in error path +- net: rswitch: Fix return value in rswitch_start_xmit() +- net: rswitch: Fix type of ret in rswitch_start_xmit() +- netdevsim: Don't accept device bound programs +- media: v4l2-subdev: Fix a 64bit bug +- pinctrl: stm32: fix array read out of bound +- pinctrl: stm32: Add check for devm_kcalloc +- wifi: cfg80211: fix CQM for non-range use +- io_uring/kbuf: recycle freed mapped buffer ring entries +- io_uring/kbuf: defer release of mapped buffer rings +- io_uring: enable io_mem_alloc/free to be used in other parts +- btrfs: fix 64bit compat send ioctl arguments not initializing version member +- btrfs: free the allocated memory if btrfs_alloc_page_array() fails +- btrfs: make error messages more clear when getting a chunk map +- btrfs: send: ensure send_fd is writable +- btrfs: fix off-by-one when checking chunk map includes logical address +- btrfs: ref-verify: fix memory leaks in btrfs_ref_tree_mod() +- btrfs: add dmesg output for first mount and last unmount of a filesystem +- parisc: Mark altinstructions read-only and 32-bit aligned +- parisc: Ensure 32-bit alignment on parisc unwind section +- parisc: Mark jump_table naturally aligned +- parisc: Drop the HP-UX ENOSYM and EREMOTERELEASE error codes +- parisc: Mark lock_aligned variables 16-byte aligned on SMP +- parisc: Use natural CPU alignment for bug_table +- parisc: Mark ex_table entries 32-bit aligned in uaccess.h +- parisc: Mark ex_table entries 32-bit aligned in assembly.h +- powerpc: Don't clobber f0/vs0 during fp|altivec register save +- KVM: PPC: Book3S HV: Fix KVM_RUN clobbering FP/VEC user registers +- iommu/vt-d: Add MTL to quirk list to skip TE disabling +- ext2: Fix ki_pos update for DIO buffered-io fallback case +- bcache: revert replacing IS_ERR_OR_NULL with IS_ERR +- iommu: Avoid more races around device probe +- io_uring: don't guard IORING_OFF_PBUF_RING with SETUP_NO_MMAP +- dma-buf: fix check in dma_resv_add_fence +- cpufreq/amd-pstate: Fix the return value of amd_pstate_fast_switch() +- powercap: DTPM: Fix unneeded conversions to micro-Watts +- nouveau: find the smallest page allocation to cover a buffer alloc. +- io_uring: free io_buffer_list entries via RCU +- iommu/vt-d: Fix incorrect cache invalidation for mm notification +- io_uring: don't allow discontig pages for IORING_SETUP_NO_MMAP +- ACPI: video: Use acpi_video_device for cooling-dev driver data +- r8169: fix deadlock on RTL8125 in jumbo mtu mode +- nvme: check for valid nvme_identify_ns() before using it +- dm verity: don't perform FEC for failed readahead IO +- dm verity: initialize fec io before freeing it +- drm/amd/display: force toggle rate wa for first link training for a retimer +- drm/amd/display: fix ABM disablement +- drm/amd/display: Update min Z8 residency time to 2100 for DCN314 +- drm/amd/display: Use DRAM speed from validation for dummy p-state +- drm/amd/display: Remove min_dst_y_next_start check for Z8 +- drm/amd/display: Include udelay when waiting for INBOX0 ACK +- drm/amdgpu: Update EEPROM I2C address for smu v13_0_0 +- drm/amdgpu: fix memory overflow in the IB test +- drm/amdgpu: Force order between a read and write to the same address +- drm/amdgpu: correct the amdgpu runtime dereference usage count +- drm/amd: Enable PCIe PME from D3 +- scsi: ufs: core: Clear cmd if abort succeeds in MCQ mode +- scsi: sd: Fix system start for ATA devices +- scsi: Change SCSI device boolean fields to single bit flags +- dm-verity: align struct dm_verity_fec_io properly +- net: libwx: fix memory leak on msix entry +- ALSA: hda/realtek: Add supported ALC257 for ChromeOS +- ALSA: hda/realtek: Headset Mic VREF to 100% +- ALSA: hda: Disable power-save on KONTRON SinglePC +- drm/i915: Also check for VGA converter in eDP probe +- mmc: block: Be sure to wait while busy in CQE error recovery +- mmc: block: Do not lose cache flush during CQE error recovery +- mmc: block: Retry commands in CQE error recovery +- mmc: cqhci: Fix task clearing in CQE error recovery +- mmc: cqhci: Warn of halt or task clear failure +- mmc: cqhci: Increase recovery halt timeout +- mmc: sdhci-sprd: Fix vqmmc not shutting down after the card was pulled +- mmc: sdhci-pci-gli: Disable LPM during initialization +- firewire: core: fix possible memory leak in create_units() +- pinctrl: avoid reload of p state in list iteration +- ksmbd: fix possible deadlock in smb2_open +- smb: client: report correct st_size for SMB and NFS symlinks +- smb: client: fix missing mode bits for SMB symlinks +- cifs: Fix FALLOC_FL_INSERT_RANGE by setting i_size after EOF moved +- cifs: Fix FALLOC_FL_ZERO_RANGE by setting i_size if EOF moved +- leds: class: Don't expose color sysfs entry +- USB: dwc3: qcom: fix wakeup after probe deferral +- USB: dwc3: qcom: fix software node leak on probe errors +- usb: dwc3: set the dma max_seg_size +- usb: dwc3: Fix default mode initialization +- USB: dwc2: write HCINT with INTMASK applied +- usb: typec: tcpm: Skip hard reset when in error recovery +- usb: typec: tcpm: Fix sink caps op current check +- USB: serial: option: don't claim interface 4 for ZTE MF290 +- USB: serial: option: fix FM101R-GL defines +- USB: serial: option: add Fibocom L7xx modules +- usb: cdnsp: Fix deadlock issue during using NCM gadget +- usb: config: fix iteration issue in 'usb_get_bos_descriptor()' +- USB: xhci-plat: fix legacy PHY double init +- bcache: fixup lock c->root error +- bcache: fixup init dirty data errors +- bcache: prevent potential division by zero error +- bcache: check return value from btree_node_alloc_replacement() +- veth: Use tstats per-CPU traffic counters +- dm-delay: fix a race between delay_presuspend and delay_bio +- ALSA: hda/realtek: Add quirks for ASUS 2024 Zenbooks +- ALSA: hda: ASUS UM5302LA: Added quirks for cs35L41/10431A83 on i2c bus +- cifs: fix leak of iface for primary channel +- cifs: account for primary channel in the interface list +- cifs: distribute channels across interfaces based on speed +- Revert "phy: realtek: usb: Add driver for the Realtek SoC USB 2.0 PHY" +- Revert "phy: realtek: usb: Add driver for the Realtek SoC USB 3.0 PHY" +- Revert "usb: phy: add usb phy notify port status API" +- hv_netvsc: Mark VF as slave before exposing it to user-mode +- hv_netvsc: Fix race of register_netdevice_notifier and VF register +- hv_netvsc: fix race of netvsc and VF register_netdevice +- platform/x86: ideapad-laptop: Set max_brightness before using it +- platform/x86/amd/pmc: adjust getting DRAM size behavior +- USB: serial: option: add Luat Air72*U series products +- usb: misc: onboard-hub: add support for Microchip USB5744 +- dt-bindings: usb: microchip,usb5744: Add second supply +- platform/x86: hp-bioscfg: Fix error handling in hp_add_other_attributes() +- platform/x86: hp-bioscfg: move mutex_lock() down in hp_add_other_attributes() +- platform/x86: hp-bioscfg: Simplify return check in hp_add_other_attributes() +- s390/dasd: protect device queue against concurrent access +- io_uring/fs: consider link->flags when getting path for LINKAT +- bcache: fixup multi-threaded bch_sectors_dirty_init() wake-up race +- md: fix bi_status reporting in md_end_clone_io +- bcache: replace a mistaken IS_ERR() by IS_ERR_OR_NULL() in btree_gc_coalesce() +- io_uring: fix off-by one bvec index +- tls: fix NULL deref on tls_sw_splice_eof() with empty record +- swiotlb-xen: provide the "max_mapping_size" method +- ACPI: PM: Add acpi_device_fix_up_power_children() function +- ACPI: resource: Skip IRQ override on ASUS ExpertBook B1402CVA +- ACPI: processor_idle: use raw_safe_halt() in acpi_idle_play_dead() +- ACPI: video: Use acpi_device_fix_up_power_children() +- thunderbolt: Set lane bonding bit only for downstream port +- drm/ast: Disconnect BMC if physical connector is connected +- drm/msm/dpu: Add missing safe_lut_tbl in sc8280xp catalog +- kselftest/arm64: Fix output formatting for za-fork +- prctl: Disable prctl(PR_SET_MDWE) on parisc +- mm: add a NO_INHERIT flag to the PR_SET_MDWE prctl +- lockdep: Fix block chain corruption +- USB: dwc3: qcom: fix ACPI platform device leak +- USB: dwc3: qcom: fix resource leaks on probe deferral +- nvmet: nul-terminate the NQNs passed in the connect command +- nvme: blank out authentication fabrics options if not configured +- afs: Fix file locking on R/O volumes to operate in local mode +- afs: Return ENOENT if no cell DNS record can be found +- net: ipa: fix one GSI register field width +- net: axienet: Fix check for partial TX checksum +- vsock/test: fix SEQPACKET message bounds test +- i40e: Fix adding unsupported cloud filters +- amd-xgbe: propagate the correct speed and duplex status +- amd-xgbe: handle the corner-case during tx completion +- amd-xgbe: handle corner-case during sfp hotplug +- net: veth: fix ethtool stats reporting +- octeontx2-pf: Fix ntuple rule creation to direct packet to VF with higher Rx queue than its PF +- arm/xen: fix xen_vcpu_info allocation alignment +- arm64: mm: Fix "rodata=on" when CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +- s390/ipl: add missing IPL_TYPE_ECKD_DUMP case to ipl_init() +- net/smc: avoid data corruption caused by decline +- net: usb: ax88179_178a: fix failed operations during ax88179_reset +- drm/panel: boe-tv101wum-nl6: Fine tune Himax83102-j02 panel HFP and HBP +- ipv4: Correct/silence an endian warning in __ip_do_redirect +- HID: fix HID device resource race between HID core and debugging support +- accel/ivpu/37xx: Fix hangs related to MMIO reset +- accel/ivpu: Do not initialize parameters on power up +- bpf: Fix dev's rx stats for bpf_redirect_peer traffic +- net: Move {l,t,d}stats allocation to core and convert veth & vrf +- net, vrf: Move dstats structure to core +- PM: tools: Fix sleepgraph syntax error +- drm/rockchip: vop: Fix color for RGB888/BGR888 format on VOP full +- libfs: getdents() should return 0 after reaching EOD +- block: update the stable_writes flag in bdev_add +- filemap: add a per-mapping stable writes flag +- drm/i915: do not clean GT table on error path +- ata: pata_isapnp: Add missing error check for devm_ioport_map() +- octeontx2-pf: Fix memory leak during interface down +- wireguard: use DEV_STATS_INC() +- net: wangxun: fix kernel panic due to null pointer +- drm/panel: simple: Fix Innolux G101ICE-L01 timings +- drm/panel: simple: Fix Innolux G101ICE-L01 bus flags +- fs: Pass AT_GETATTR_NOSEC flag to getattr interface function +- drm/panel: auo,b101uan08.3: Fine tune the panel power sequence +- blk-cgroup: avoid to warn !rcu_read_lock_held() in blkg_lookup() +- afs: Make error on cell lookup failure consistent with OpenAFS +- afs: Fix afs_server_list to be cleaned up with RCU +- rxrpc: Defer the response to a PING ACK until we've parsed it +- rxrpc: Fix RTT determination to use any ACK as a source +- s390/ism: ism driver implies smc protocol +- drm/msm/dsi: use the correct VREG_CTRL_1 value for 4nm cphy +- sched/fair: Fix the decision for load balance +- sched/eevdf: Fix vruntime adjustment on reweight +- hv/hv_kvp_daemon: Some small fixes for handling NM keyfiles +- irqchip/gic-v3-its: Flush ITS tables correctly in non-coherent GIC designs +- NFSD: Fix checksum mismatches in the duplicate reply cache +- NFSD: Fix "start of NFS reply" pointer passed to nfsd_cache_update() +- !3310 kasan: fix the compilation error for memcpy_mcs() +- kasan: fix the compilation error for memcpy_mcs() +- arm64: arch_timer: disable CONFIG_ARM_ARCH_TIMER_WORKAROUND_IN_USERSPACE +- vdso: do cntvct workaround in the VDSO +- arm64: arch_timer: Disable CNTVCT_EL0 trap if workaround is enabled +- mm/sharepool: Protect the va reserved for sharepool +- mm/sharepool: support fork() and exit() to handle the mm +- mm/sharepool: Add proc interfaces to show sp info +- mm/sharepool: Implement mg_sp_config_dvpp_range() +- mm/sharepool: Implement mg_sp_id_of_current() +- mm/sharepool: Implement mg_sp_group_id_by_pid() +- mm/sharepool: Implement mg_sp_group_add_task() +- mm/sharepool: Implement mg_sp_make_share_k2u() +- mm/sharepool: Implement mg_sp_alloc() +- mm/sharepool: Implement mg_sp_free() +- mm/sharepool: Implement mg_sp_walk_page_range() +- mm/sharepool: Implement mg_sp_unshare_kva +- mm/sharepool: Implement mg_sp_make_share_u2k() +- mm/sharepool: Reserve the va space for share_pool +- mm/sharepool: Add sp_area management code +- mm/sharepool: Add base framework for share_pool +- mm: Extend mmap assocated functions to accept mm_struct +- mm/vmalloc: Extend vmalloc usage about hugepage +- mm/hugetlb: Introduce hugetlb_insert_hugepage_pte[_by_pa] +- ARM: Add unwinding annotations to __loop.*delay functions +- !3285 arm64: errata: add option to disable cache readunique prefetch on HIP08 +- !3280 arm64: add machine check safe support +- !3036 Added SM3 as module signing algorithm +- ext4: Block writes to journal device +- xfs: Block writes to log device +- fs: Block writes to mounted block devices +- btrfs: Do not restrict writes to btrfs devices +- block: Add config option to not allow writing to mounted devices +- arm64: errata: enable HISILICON_ERRATUM_HIP08_RU_PREFETCH +- arm64: errata: add option to disable cache readunique prefetch on HIP08 +- arm64: add machine check safe sysctl interface +- arm64: introduce copy_mc_to_kernel() implementation +- arm64: support copy_mc_[user]_highpage() +- mm/hwpoison: return -EFAULT when copy fail in copy_mc_[user]_highpage() +- arm64: add uaccess to machine check safe +- arm64: add support for machine check error safe +- uaccess: add generic fallback version of copy_mc_to_user() +- !3275 arm64: kernel: disable CNP on LINXICORE9100 +- !3099 block: Make blkdev_get_by_*() return +- arm64: kernel: disable CNP on LINXICORE9100 +- !3111 openeuler_defconfig: enable some mm new +- !3211 Add SDEI Watchdog Support +- !3041 Random boot-time optimization +- !3026 Backport ARM64-ILP32 patches +- !3156 xfs: fix intent item leak during reovery +- !3137 LoongArch: add old BPI compatibility +- !3218 ipvlan: Introduce l2e mode +- !3209 exec: Remove redundant check in do_open_execat/uselib +- ipvlan: Introduce local xmit queue for l2e mode +- ipvlan: Introduce l2e mode +- arm64: kexec: only clear EOI for SDEI in NMI context +- stop_machine: mask sdei before running the callback +- openeuler_defconfig: Enable SDEI Watchdog +- kprobes/arm64: Blacklist sdei watchdog callback functions +- init: only move down lockup_detector_init() when sdei_watchdog is enabled +- sdei_watchdog: avoid possible false hardlockup +- sdei_watchdog: set secure timer period base on 'watchdog_thresh' +- sdei_watchdog: clear EOI of the secure timer before kdump +- watchdog: add nmi_watchdog support for arm64 based on SDEI +- lockup_detector: init lockup detector after all the init_calls +- firmware: arm_sdei: make 'sdei_api_event_disable/enable' public +- firmware: arm_sdei: add interrupt binding api +- exec: Remove redundant check in do_open_execat/uselib +- xfs: abort intent items when recovery intents fail +- xfs: factor out xfs_defer_pending_abort +- !3141 Backport 6.6.3 LTS Patches +- drm/amd/display: Change the DMCUB mailbox memory location from FB to inbox +- drm/amd/display: Clear dpcd_sink_ext_caps if not set +- drm/amd/display: Enable fast plane updates on DCN3.2 and above +- drm/amd/display: fix a NULL pointer dereference in amdgpu_dm_i2c_xfer() +- drm/amd/display: Fix DSC not Enabled on Direct MST Sink +- drm/amd/display: Guard against invalid RPTR/WPTR being set +- drm/amdgpu: Fix possible null pointer dereference +- drm/amdgpu: lower CS errors to debug severity +- drm/amdgpu: fix error handling in amdgpu_bo_list_get() +- drm/amdgpu: fix error handling in amdgpu_vm_init +- drm/amdgpu: don't use ATRM for external devices +- drm/amdgpu: add a retry for IP discovery init +- drm/amdgpu: fix GRBM read timeout when do mes_self_test +- drm/amdgpu: don't use pci_is_thunderbolt_attached() +- drm/amdgpu/smu13: drop compute workload workaround +- drm/amd/pm: Fix error of MACO flag setting code +- drm/i915: Flush WC GGTT only on required platforms +- drm/i915: Fix potential spectre vulnerability +- drm/i915: Bump GLK CDCLK frequency when driving multiple pipes +- drm/i915/mtl: Support HBR3 rate with C10 phy and eDP in MTL +- drm/amd/display: Add Null check for DPP resource +- x86/srso: Move retbleed IBPB check into existing 'has_microcode' code block +- drm: bridge: it66121: ->get_edid callback must not return err pointers +- drm/amd/pm: Handle non-terminated overdrive commands. +- ext4: fix racy may inline data check in dio write +- ext4: properly sync file size update after O_SYNC direct IO +- ext4: add missed brelse in update_backups +- ext4: remove gdb backup copy for meta bg in setup_new_flex_group_blocks +- ext4: correct the start block of counting reserved clusters +- ext4: correct return value of ext4_convert_meta_bg +- ext4: mark buffer new if it is unwritten to avoid stale data exposure +- ext4: correct offset of gdb backup in non meta_bg group to update_backups +- ext4: apply umask if ACL support is disabled +- ext4: make sure allocate pending entry not fail +- ext4: no need to generate from free list in mballoc +- ext4: fix race between writepages and remount +- Revert "net: r8169: Disable multicast filter for RTL8168H and RTL8107E" +- Revert "HID: logitech-dj: Add support for a new lightspeed receiver iteration" +- media: qcom: camss: Fix csid-gen2 for test pattern generator +- media: qcom: camss: Fix invalid clock enable bit disjunction +- media: qcom: camss: Fix set CSI2_RX_CFG1_VC_MODE when VC is greater than 3 +- media: qcom: camss: Fix missing vfe_lite clocks check +- media: qcom: camss: Fix VFE-480 vfe_disable_output() +- media: qcom: camss: Fix VFE-17x vfe_disable_output() +- media: qcom: camss: Fix vfe_get() error jump +- media: qcom: camss: Fix pm_domain_on sequence in probe +- mmc: sdhci-pci-gli: GL9750: Mask the replay timer timeout of AER +- r8169: add handling DASH when DASH is disabled +- r8169: fix network lost after resume on DASH systems +- selftests: mptcp: fix fastclose with csum failure +- mptcp: fix setsockopt(IP_TOS) subflow locking +- mptcp: add validity check for sending RM_ADDR +- mptcp: deal with large GSO size +- mm: kmem: drop __GFP_NOFAIL when allocating objcg vectors +- mm: fix for negative counter: nr_file_hugepages +- mmc: sdhci-pci-gli: A workaround to allow GL9750 to enter ASPM L1.2 +- riscv: kprobes: allow writing to x0 +- riscv: correct pt_level name via pgtable_l5/4_enabled +- riscv: mm: Update the comment of CONFIG_PAGE_OFFSET +- riscv: put interrupt entries into .irqentry.text +- riscv: Using TOOLCHAIN_HAS_ZIHINTPAUSE marco replace zihintpause +- swiotlb: fix out-of-bounds TLB allocations with CONFIG_SWIOTLB_DYNAMIC +- swiotlb: do not free decrypted pages if dynamic +- tracing: fprobe-event: Fix to check tracepoint event and return +- LoongArch: Mark __percpu functions as always inline +- NFSD: Update nfsd_cache_append() to use xdr_stream +- nfsd: fix file memleak on client_opens_release +- dm-verity: don't use blocking calls from tasklets +- dm-bufio: fix no-sleep mode +- drm/mediatek/dp: fix memory leak on ->get_edid callback error path +- drm/mediatek/dp: fix memory leak on ->get_edid callback audio detection +- media: ccs: Correctly initialise try compose rectangle +- media: venus: hfi: add checks to handle capabilities from firmware +- media: venus: hfi: fix the check to handle session buffer requirement +- media: venus: hfi_parser: Add check to keep the number of codecs within range +- media: sharp: fix sharp encoding +- media: lirc: drop trailing space from scancode transmit +- f2fs: split initial and dynamic conditions for extent_cache +- f2fs: avoid format-overflow warning +- f2fs: set the default compress_level on ioctl +- f2fs: do not return EFSCORRUPTED, but try to run online repair +- i2c: i801: fix potential race in i801_block_transaction_byte_by_byte +- gfs2: don't withdraw if init_threads() got interrupted +- net: phylink: initialize carrier state at creation +- net: dsa: lan9303: consequently nested-lock physical MDIO +- net: ethtool: Fix documentation of ethtool_sprintf() +- s390/ap: fix AP bus crash on early config change callback invocation +- i2c: designware: Disable TX_EMPTY irq while waiting for block length byte +- sbsa_gwdt: Calculate timeout with 64-bit math +- lsm: fix default return value for inode_getsecctx +- lsm: fix default return value for vm_enough_memory +- Revert "i2c: pxa: move to generic GPIO recovery" +- Revert ncsi: Propagate carrier gain/loss events to the NCSI controller +- ALSA: hda/realtek: Add quirks for HP Laptops +- ALSA: hda/realtek: Enable Mute LED on HP 255 G10 +- ALSA: hda/realtek - Enable internal speaker of ASUS K6500ZC +- ALSA: hda/realtek - Add Dell ALC295 to pin fall back table +- ALSA: hda/realtek: Enable Mute LED on HP 255 G8 +- ALSA: info: Fix potential deadlock at disconnection +- btrfs: zoned: wait for data BG to be finished on direct IO allocation +- xfs: recovery should not clear di_flushiter unconditionally +- cifs: Fix encryption of cleared, but unset rq_iter data buffers +- cifs: do not pass cifs_sb when trying to add channels +- cifs: do not reset chan_max if multichannel is not supported at mount +- cifs: force interface update before a fresh session setup +- cifs: reconnect helper should set reconnect for the right channel +- smb: client: fix mount when dns_resolver key is not available +- smb: client: fix potential deadlock when releasing mids +- smb: client: fix use-after-free in smb2_query_info_compound() +- smb: client: fix use-after-free bug in cifs_debug_data_proc_show() +- smb3: fix caching of ctime on setxattr +- smb3: allow dumping session and tcon id to improve stats analysis and debugging +- smb3: fix touch -h of symlink +- smb3: fix creating FIFOs when mounting with "sfu" mount option +- xhci: Enable RPM on controllers that support low-power states +- parisc: fix mmap_base calculation when stack grows upwards +- parisc/power: Fix power soft-off when running on qemu +- parisc/pgtable: Do not drop upper 5 address bits of physical address +- parisc: Prevent booting 64-bit kernels on PA1.x machines +- selftests/resctrl: Extend signal handler coverage to unmount on receiving signal +- selftests/resctrl: Make benchmark command const and build it with pointers +- selftests/resctrl: Simplify span lifetime +- selftests/resctrl: Remove bw_report and bm_type from main() +- rcutorture: Fix stuttering races and other issues +- torture: Make torture_hrtimeout_ns() take an hrtimer mode parameter +- drm/amd/display: enable dsc_clk even if dsc_pg disabled +- Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE +- Bluetooth: btusb: Add RTW8852BE device 13d3:3570 to device tables +- apparmor: Fix regression in mount mediation +- apparmor: pass cred through to audit info. +- apparmor: rename audit_data->label to audit_data->subj_label +- apparmor: combine common_audit_data and apparmor_audit_data +- apparmor: Fix kernel-doc warnings in apparmor/policy.c +- apparmor: Fix kernel-doc warnings in apparmor/resource.c +- apparmor: Fix kernel-doc warnings in apparmor/lib.c +- apparmor: Fix kernel-doc warnings in apparmor/audit.c +- cxl/port: Fix delete_endpoint() vs parent unregistration race +- cxl/region: Fix x1 root-decoder granularity calculations +- i3c: master: svc: fix random hot join failure since timeout error +- i3c: master: svc: fix SDA keep low when polling IBIWON timeout happen +- i3c: master: svc: fix check wrong status register in irq handler +- i3c: master: svc: fix ibi may not return mandatory data byte +- i3c: master: svc: fix wrong data return when IBI happen during start frame +- i3c: master: svc: fix race condition in ibi work thread +- i3c: master: cdns: Fix reading status register +- cxl/region: Do not try to cleanup after cxl_region_setup_targets() fails +- mtd: cfi_cmdset_0001: Byte swap OTP info +- mm: make PR_MDWE_REFUSE_EXEC_GAIN an unsigned long +- mm/memory_hotplug: use pfn math in place of direct struct page manipulation +- mm/hugetlb: use nth_page() in place of direct struct page manipulation +- mm/cma: use nth_page() in place of direct struct page manipulation +- s390/cmma: fix detection of DAT pages +- s390/mm: add missing arch_set_page_dat() call to gmap allocations +- s390/mm: add missing arch_set_page_dat() call to vmem_crst_alloc() +- dmaengine: stm32-mdma: correct desc prep when channel running +- mcb: fix error handling for different scenarios when parsing +- driver core: Release all resources during unbind before updating device links +- tracing: Have the user copy of synthetic event address use correct context +- selftests/clone3: Fix broken test under !CONFIG_TIME_NS +- i2c: core: Run atomic i2c xfer when !preemptible +- mips: use nth_page() in place of direct struct page manipulation +- fs: use nth_page() in place of direct struct page manipulation +- scripts/gdb/vmalloc: disable on no-MMU +- kernel/reboot: emergency_restart: Set correct system_state +- quota: explicitly forbid quota files from being encrypted +- jbd2: fix potential data lost in recovering journal raced with synchronizing fs bdev +- ASoC: codecs: wsa-macro: fix uninitialized stack variables with name prefix +- hid: lenovo: Resend all settings on reset_resume for compact keyboards +- selftests/resctrl: Reduce failures due to outliers in MBA/MBM tests +- selftests/resctrl: Fix feature checks +- selftests/resctrl: Refactor feature check to use resource and feature name +- selftests/resctrl: Move _GNU_SOURCE define into Makefile +- selftests/resctrl: Remove duplicate feature check from CMT test +- selftests/resctrl: Fix uninitialized .sa_flags +- ASoC: codecs: wsa883x: make use of new mute_unmute_on_trigger flag +- ASoC: soc-dai: add flag to mute and unmute stream during trigger +- netfilter: nf_tables: split async and sync catchall in two functions +- netfilter: nf_tables: remove catchall element in GC sync path +- ima: detect changes to the backing overlay file +- ima: annotate iint mutex to avoid lockdep false positive warnings +- mfd: qcom-spmi-pmic: Fix revid implementation +- mfd: qcom-spmi-pmic: Fix reference leaks in revid helper +- leds: trigger: netdev: Move size check in set_device_name +- arm64: dts: qcom: ipq6018: Fix tcsr_mutex register size +- arm64: dts: qcom: ipq9574: Fix hwlock index for SMEM +- ACPI: FPDT: properly handle invalid FPDT subtables +- firmware: qcom_scm: use 64-bit calling convention only when client is 64-bit +- arm64: dts: qcom: ipq8074: Fix hwlock index for SMEM +- arm64: dts: qcom: ipq5332: Fix hwlock index for SMEM +- thermal: intel: powerclamp: fix mismatch in get function for max_idle +- btrfs: don't arbitrarily slow down delalloc if we're committing +- rcu: kmemleak: Ignore kmemleak false positives when RCU-freeing objects +- PM: hibernate: Clean up sync_read handling in snapshot_write_next() +- PM: hibernate: Use __get_safe_page() rather than touching the list +- dt-bindings: timer: renesas,rz-mtu3: Fix overflow/underflow interrupt names +- arm64: dts: qcom: ipq6018: Fix hwlock index for SMEM +- rcu/tree: Defer setting of jiffies during stall reset +- svcrdma: Drop connection after an RDMA Read error +- wifi: wilc1000: use vmm_table as array in wilc struct +- PCI: Lengthen reset delay for VideoPropulsion Torrent QN16e card +- PCI: exynos: Don't discard .remove() callback +- PCI: kirin: Don't discard .remove() callback +- PCI/ASPM: Fix L1 substate handling in aspm_attr_store_common() +- PCI: qcom-ep: Add dedicated callback for writing to DBI2 registers +- mmc: Add quirk MMC_QUIRK_BROKEN_CACHE_FLUSH for Micron eMMC Q2J54A +- mmc: sdhci_am654: fix start loop index for TAP value parsing +- mmc: vub300: fix an error code +- ksmbd: fix slab out of bounds write in smb_inherit_dacl() +- ksmbd: handle malformed smb1 message +- ksmbd: fix recursive locking in vfs helpers +- clk: qcom: ipq6018: drop the CLK_SET_RATE_PARENT flag from PLL clocks +- clk: qcom: ipq8074: drop the CLK_SET_RATE_PARENT flag from PLL clocks +- integrity: powerpc: Do not select CA_MACHINE_KEYRING +- clk: visconti: Fix undefined behavior bug in struct visconti_pll_provider +- clk: socfpga: Fix undefined behavior bug in struct stratix10_clock_data +- powercap: intel_rapl: Downgrade BIOS locked limits pr_warn() to pr_debug() +- cpufreq: stats: Fix buffer overflow detection in trans_stats() +- parisc/power: Add power soft-off when running on qemu +- parisc/pdc: Add width field to struct pdc_model +- parisc/agp: Use 64-bit LE values in SBA IOMMU PDIR table +- pmdomain: imx: Make imx pgc power domain also set the fwnode +- arm64: module: Fix PLT counting when CONFIG_RANDOMIZE_BASE=n +- arm64: Restrict CPU_BIG_ENDIAN to GNU as or LLVM IAS 15.x or newer +- pmdomain: amlogic: Fix mask for the second NNA mem PD domain +- PCI: keystone: Don't discard .probe() callback +- PCI: keystone: Don't discard .remove() callback +- KEYS: trusted: Rollback init_trusted() consistently +- KEYS: trusted: tee: Refactor register SHM usage +- pmdomain: bcm: bcm2835-power: check if the ASB register is equal to enable +- sched/core: Fix RQCF_ACT_SKIP leak +- genirq/generic_chip: Make irq_remove_generic_chip() irqdomain aware +- mmc: meson-gx: Remove setting of CMD_CFG_ERROR +- wifi: ath12k: fix dfs-radar and temperature event locking +- wifi: ath12k: fix htt mlo-offset event locking +- wifi: ath11k: fix gtk offload status event locking +- wifi: ath11k: fix htt pktlog locking +- wifi: ath11k: fix dfs radar event locking +- wifi: ath11k: fix temperature event locking +- regmap: Ensure range selector registers are updated after cache sync +- ACPI: resource: Do IRQ override on TongFang GMxXGxx +- parisc: Add nop instructions after TLB inserts +- mm/damon/sysfs: check error from damon_sysfs_update_target() +- mm/damon/core.c: avoid unintentional filtering out of schemes +- mm/damon/sysfs-schemes: handle tried regions sysfs directory allocation failure +- mm/damon/sysfs-schemes: handle tried region directory allocation failure +- mm/damon/core: avoid divide-by-zero during monitoring results update +- mm/damon: implement a function for max nr_accesses safe calculation +- mm/damon/ops-common: avoid divide-by-zero during region hotness calculation +- mm/damon/lru_sort: avoid divide-by-zero in hot threshold calculation +- dm crypt: account large pages in cc->n_allocated_pages +- fbdev: stifb: Make the STI next font pointer a 32-bit signed offset +- iommufd: Fix missing update of domains_itree after splitting iopt_area +- watchdog: move softlockup_panic back to early_param +- mm/damon/sysfs: update monitoring target regions for online input commit +- mm/damon/sysfs: remove requested targets when online-commit inputs +- PCI/sysfs: Protect driver's D3cold preference from user space +- hvc/xen: fix event channel handling for secondary consoles +- hvc/xen: fix error path in xen_hvc_init() to always register frontend driver +- hvc/xen: fix console unplug +- acpi/processor: sanitize _OSC/_PDC capabilities for Xen dom0 +- tty: serial: meson: fix hard LOCKUP on crtscts mode +- tty/sysrq: replace smp_processor_id() with get_cpu() +- proc: sysctl: prevent aliased sysctls from getting passed to init +- audit: don't WARN_ON_ONCE(!current->mm) in audit_exe_compare() +- audit: don't take task_lock() in audit_exe_compare() code path +- sched: psi: fix unprivileged polling against cgroups +- mmc: sdhci-pci-gli: GL9755: Mask the replay timer timeout of AER +- KVM: x86: Fix lapic timer interrupt lost after loading a snapshot. +- KVM: x86: Clear bit12 of ICR after APIC-write VM-exit +- KVM: x86: Ignore MSR_AMD64_TW_CFG access +- KVM: x86: hyper-v: Don't auto-enable stimer on write from user-space +- x86/cpu/hygon: Fix the CPU topology evaluation for real +- x86/apic/msi: Fix misconfigured non-maskable MSI quirk +- x86/PCI: Avoid PME from D3hot/D3cold for AMD Rembrandt and Phoenix USB4 +- crypto: x86/sha - load modules based on CPU features +- x86/shstk: Delay signal entry SSP write until after user accesses +- scsi: ufs: core: Fix racing issue between ufshcd_mcq_abort() and ISR +- scsi: qla2xxx: Fix system crash due to bad pointer access +- scsi: ufs: qcom: Update PHY settings only when scaling to higher gears +- scsi: megaraid_sas: Increase register read retry rount from 3 to 30 for selected registers +- scsi: mpt3sas: Fix loop logic +- bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END +- bpf: Fix check_stack_write_fixed_off() to correctly spill imm +- spi: Fix null dereference on suspend +- randstruct: Fix gcc-plugin performance mode to stay in group +- powerpc/perf: Fix disabling BHRB and instruction sampling +- perf intel-pt: Fix async branch flags +- media: venus: hfi: add checks to perform sanity on queue pointers +- drivers: perf: Check find_first_bit() return value +- perf: arm_cspmu: Reject events meant for other PMUs +- i915/perf: Fix NULL deref bugs with drm_dbg() calls +- perf/core: Fix cpuctx refcounting +- cifs: fix check of rc in function generate_smb3signingkey +- cifs: spnego: add ';' in HOST_KEY_LEN +- scsi: ufs: core: Expand MCQ queue slot to DeviceQueueDepth + 1 +- tools/power/turbostat: Enable the C-state Pre-wake printing +- tools/power/turbostat: Fix a knl bug +- macvlan: Don't propagate promisc change to lower dev in passthru +- net: sched: do not offload flows with a helper in act_ct +- net/mlx5e: Check return value of snprintf writing to fw_version buffer for representors +- net/mlx5e: Check return value of snprintf writing to fw_version buffer +- net/mlx5e: Reduce the size of icosq_str +- net/mlx5: Increase size of irq name buffer +- net/mlx5e: Update doorbell for port timestamping CQ before the software counter +- net/mlx5e: Track xmit submission to PTP WQ after populating metadata map +- net/mlx5e: Avoid referencing skb after free-ing in drop path of mlx5e_sq_xmit_wqe +- net/mlx5e: Don't modify the peer sent-to-vport rules for IPSec offload +- net/mlx5e: Fix pedit endianness +- net/mlx5e: fix double free of encap_header in update funcs +- net/mlx5e: fix double free of encap_header +- net/mlx5: Decouple PHC .adjtime and .adjphase implementations +- net/mlx5: Free used cpus mask when an IRQ is released +- Revert "net/mlx5: DR, Supporting inline WQE when possible" +- io_uring/fdinfo: remove need for sqpoll lock for thread/pid retrieval +- gve: Fixes for napi_poll when budget is 0 +- pds_core: fix up some format-truncation complaints +- pds_core: use correct index to mask irq +- net: stmmac: avoid rx queue overrun +- net: stmmac: fix rx budget limit check +- netfilter: nf_tables: bogus ENOENT when destroying element which does not exist +- netfilter: nf_tables: fix pointer math issue in nft_byteorder_eval() +- netfilter: nf_conntrack_bridge: initialize err to 0 +- af_unix: fix use-after-free in unix_stream_read_actor() +- net: ethernet: cortina: Fix MTU max setting +- net: ethernet: cortina: Handle large frames +- net: ethernet: cortina: Fix max RX frame define +- bonding: stop the device in bond_setup_by_slave() +- ptp: annotate data-race around q->head and q->tail +- blk-mq: make sure active queue usage is held for bio_integrity_prep() +- xen/events: fix delayed eoi list handling +- ppp: limit MRU to 64K +- net: mvneta: fix calls to page_pool_get_stats +- tipc: Fix kernel-infoleak due to uninitialized TLV value +- net: hns3: fix VF wrong speed and duplex issue +- net: hns3: fix VF reset fail issue +- net: hns3: fix variable may not initialized problem in hns3_init_mac_addr() +- net: hns3: fix out-of-bounds access may occur when coalesce info is read via debugfs +- net: hns3: fix incorrect capability bit display for copper port +- net: hns3: add barrier in vf mailbox reply process +- net: hns3: fix add VLAN fail issue +- xen/events: avoid using info_for_irq() in xen_send_IPI_one() +- net: ti: icssg-prueth: Fix error cleanup on failing pruss_request_mem_region +- net: ti: icssg-prueth: Add missing icss_iep_put to error path +- tty: Fix uninit-value access in ppp_sync_receive() +- ipvlan: add ipvlan_route_v6_outbound() helper +- net: set SOCK_RCU_FREE before inserting socket into hashtable +- bpf: fix control-flow graph checking in privileged mode +- bpf: fix precision backtracking instruction iteration +- bpf: handle ldimm64 properly in check_cfg() +- gcc-plugins: randstruct: Only warn about true flexible arrays +- vhost-vdpa: fix use after free in vhost_vdpa_probe() +- vdpa_sim_blk: allocate the buffer zeroed +- riscv: split cache ops out of dma-noncoherent.c +- drm/i915/tc: Fix -Wformat-truncation in intel_tc_port_init +- gfs2: Silence "suspicious RCU usage in gfs2_permission" warning +- riscv: provide riscv-specific is_trap_insn() +- RISC-V: hwprobe: Fix vDSO SIGSEGV +- SUNRPC: Fix RPC client cleaned up the freed pipefs dentries +- NFSv4.1: fix SP4_MACH_CRED protection for pnfs IO +- SUNRPC: Add an IS_ERR() check back to where it was +- NFSv4.1: fix handling NFS4ERR_DELAY when testing for session trunking +- drm/i915/mtl: avoid stringop-overflow warning +- mtd: rawnand: meson: check return value of devm_kasprintf() +- mtd: rawnand: intel: check return value of devm_kasprintf() +- SUNRPC: ECONNRESET might require a rebind +- dt-bindings: serial: fix regex pattern for matching serial node children +- samples/bpf: syscall_tp_user: Fix array out-of-bound access +- samples/bpf: syscall_tp_user: Rename num_progs into nr_tests +- sched/core: Optimize in_task() and in_interrupt() a bit +- wifi: iwlwifi: Use FW rate for non-data frames +- mtd: rawnand: tegra: add missing check for platform_get_irq() +- pwm: Fix double shift bug +- drm/amdgpu: fix software pci_unplug on some chips +- ALSA: hda/realtek: Add quirk for ASUS UX7602ZM +- drm/qxl: prevent memory leak +- ASoC: ti: omap-mcbsp: Fix runtime PM underflow warnings +- i2c: dev: copy userspace array safely +- riscv: VMAP_STACK overflow detection thread-safe +- kgdb: Flush console before entering kgdb on panic +- gfs2: Fix slab-use-after-free in gfs2_qd_dealloc +- drm/amd/display: Avoid NULL dereference of timing generator +- media: imon: fix access to invalid resource for the second interface +- media: ccs: Fix driver quirk struct documentation +- media: cobalt: Use FIELD_GET() to extract Link Width +- gfs2: fix an oops in gfs2_permission +- gfs2: ignore negated quota changes +- media: ipu-bridge: increase sensor_name size +- media: vivid: avoid integer overflow +- media: gspca: cpia1: shift-out-of-bounds in set_flicker +- i3c: master: mipi-i3c-hci: Fix a kernel panic for accessing DAT_data. +- virtio-blk: fix implicit overflow on virtio_max_dma_size +- i2c: sun6i-p2wi: Prevent potential division by zero +- i2c: fix memleak in i2c_new_client_device() +- i2c: i801: Add support for Intel Birch Stream SoC +- i3c: mipi-i3c-hci: Fix out of bounds access in hci_dma_irq_handler +- 9p: v9fs_listxattr: fix %s null argument warning +- 9p/trans_fd: Annotate data-racy writes to file::f_flags +- usb: gadget: f_ncm: Always set current gadget in ncm_bind() +- usb: host: xhci: Avoid XHCI resume delay if SSUSB device is not present +- f2fs: fix error handling of __get_node_page +- f2fs: fix error path of __f2fs_build_free_nids +- soundwire: dmi-quirks: update HP Omen match +- usb: ucsi: glink: use the connector orientation GPIO to provide switch events +- usb: dwc3: core: configure TX/RX threshold for DWC3_IP +- phy: qualcomm: phy-qcom-eusb2-repeater: Zero out untouched tuning regs +- phy: qualcomm: phy-qcom-eusb2-repeater: Use regmap_fields +- dt-bindings: phy: qcom,snps-eusb2-repeater: Add magic tuning overrides +- tty: vcc: Add check for kstrdup() in vcc_probe() +- thunderbolt: Apply USB 3.x bandwidth quirk only in software connection manager +- iio: adc: stm32-adc: harden against NULL pointer deref in stm32_adc_probe() +- mfd: intel-lpss: Add Intel Lunar Lake-M PCI IDs +- exfat: support handle zero-size directory +- HID: Add quirk for Dell Pro Wireless Keyboard and Mouse KM5221W +- crypto: hisilicon/qm - prevent soft lockup in receive loop +- ASoC: Intel: soc-acpi-cht: Add Lenovo Yoga Tab 3 Pro YT3-X90 quirk +- PCI: Use FIELD_GET() in Sapphire RX 5600 XT Pulse quirk +- misc: pci_endpoint_test: Add Device ID for R-Car S4-8 PCIe controller +- PCI: dwc: Add missing PCI_EXP_LNKCAP_MLW handling +- PCI: dwc: Add dw_pcie_link_set_max_link_width() +- PCI: Disable ATS for specific Intel IPU E2000 devices +- PCI: Extract ATS disabling to a helper function +- PCI: Use FIELD_GET() to extract Link Width +- scsi: libfc: Fix potential NULL pointer dereference in fc_lport_ptp_setup() +- PCI: Do error check on own line to split long "if" conditions +- atm: iphase: Do PCI error checks on own line +- PCI: mvebu: Use FIELD_PREP() with Link Width +- PCI: tegra194: Use FIELD_GET()/FIELD_PREP() with Link Width fields +- gpiolib: of: Add quirk for mt2701-cs42448 ASoC sound +- ALSA: hda: Fix possible null-ptr-deref when assigning a stream +- ARM: 9320/1: fix stack depot IRQ stack filter +- HID: lenovo: Detect quirk-free fw on cptkbd and stop applying workaround +- jfs: fix array-index-out-of-bounds in diAlloc +- jfs: fix array-index-out-of-bounds in dbFindLeaf +- fs/jfs: Add validity check for db_maxag and db_agpref +- fs/jfs: Add check for negative db_l2nbperpage +- scsi: ibmvfc: Remove BUG_ON in the case of an empty event pool +- scsi: hisi_sas: Set debugfs_dir pointer to NULL after removing debugfs +- RDMA/hfi1: Use FIELD_GET() to extract Link Width +- ASoC: SOF: ipc4: handle EXCEPTION_CAUGHT notification from firmware +- crypto: pcrypt - Fix hungtask for PADATA_RESET +- ASoC: cs35l56: Use PCI SSID as the firmware UID +- ASoC: Intel: sof_sdw: Copy PCI SSID to struct snd_soc_card +- ASoC: SOF: Pass PCI SSID to machine driver +- ASoC: soc-card: Add storage for PCI SSID +- ASoC: mediatek: mt8188-mt6359: support dynamic pinctrl +- selftests/efivarfs: create-read: fix a resource leak +- arm64: dts: ls208xa: use a pseudo-bus to constrain usb dma size +- arm64: dts: rockchip: Add NanoPC T6 PCIe e-key support +- soc: qcom: pmic: Fix resource leaks in a device_for_each_child_node() loop +- drm/amd: check num of link levels when update pcie param +- drm/amd/display: fix num_ways overflow error +- drm/amd: Disable PP_PCIE_DPM_MASK when dynamic speed switching not supported +- drm/amdgpu: Fix a null pointer access when the smc_rreg pointer is NULL +- drm/amdkfd: Fix shift out-of-bounds issue +- drm/panel: st7703: Pick different reset sequence +- drm/amdgpu/vkms: fix a possible null pointer dereference +- drm/radeon: fix a possible null pointer dereference +- drm/panel/panel-tpo-tpg110: fix a possible null pointer dereference +- drm/panel: fix a possible null pointer dereference +- drm/amdgpu: Fix potential null pointer derefernce +- drm/amd: Fix UBSAN array-index-out-of-bounds for Polaris and Tonga +- drm/amd: Fix UBSAN array-index-out-of-bounds for SMU7 +- drm/msm/dp: skip validity check for DP CTS EDID checksum +- drm: vmwgfx_surface.c: copy user-array safely +- drm_lease.c: copy user-array safely +- kernel: watch_queue: copy user-array safely +- kernel: kexec: copy user-array safely +- string.h: add array-wrappers for (v)memdup_user() +- drm/amd/display: use full update for clip size increase of large plane source +- drm/amd: Update `update_pcie_parameters` functions to use uint8_t arguments +- drm/amdgpu: update retry times for psp vmbx wait +- drm/amdkfd: Fix a race condition of vram buffer unref in svm code +- drm/amdgpu: not to save bo in the case of RAS err_event_athub +- md: don't rely on 'mddev->pers' to be set in mddev_suspend() +- drm/edid: Fixup h/vsync_end instead of h/vtotal +- drm/amd/display: add seamless pipe topology transition check +- drm/amd/display: Don't lock phantom pipe on disabling +- drm/amd/display: Blank phantom OTG before enabling +- drm/komeda: drop all currently held locks if deadlock happens +- drm/amdkfd: ratelimited SQ interrupt messages +- drm/gma500: Fix call trace when psb_gem_mm_init() fails +- platform/x86: thinkpad_acpi: Add battery quirk for Thinkpad X120e +- of: address: Fix address translation when address-size is greater than 2 +- platform/chrome: kunit: initialize lock for fake ec_dev +- gpiolib: acpi: Add a ignore interrupt quirk for Peaq C1010 +- tsnep: Fix tsnep_request_irq() format-overflow warning +- ACPI: EC: Add quirk for HP 250 G7 Notebook PC +- Bluetooth: Fix double free in hci_conn_cleanup +- Bluetooth: btusb: Add date->evt_skb is NULL check +- wifi: iwlwifi: mvm: fix size check for fw_link_id +- bpf: Ensure proper register state printing for cond jumps +- vsock: read from socket's error queue +- net: sfp: add quirk for FS's 2.5G copper SFP +- wifi: ath10k: Don't touch the CE interrupt registers after power up +- wifi: ath12k: mhi: fix potential memory leak in ath12k_mhi_register() +- net: annotate data-races around sk->sk_dst_pending_confirm +- net: annotate data-races around sk->sk_tx_queue_mapping +- wifi: mt76: fix clang-specific fortify warnings +- wifi: mt76: mt7921e: Support MT7992 IP in Xiaomi Redmibook 15 Pro (2023) +- net: sfp: add quirk for Fiberstone GPON-ONU-34-20BI +- ACPI: APEI: Fix AER info corruption when error status data has multiple sections +- wifi: ath12k: fix possible out-of-bound write in ath12k_wmi_ext_hal_reg_caps() +- wifi: ath10k: fix clang-specific fortify warning +- wifi: ath12k: fix possible out-of-bound read in ath12k_htt_pull_ppdu_stats() +- wifi: ath9k: fix clang-specific fortify warnings +- bpf: Detect IP == ksym.end as part of BPF program +- atl1c: Work around the DMA RX overflow issue +- wifi: mac80211: don't return unset power in ieee80211_get_tx_power() +- wifi: mac80211_hwsim: fix clang-specific fortify warning +- wifi: ath12k: Ignore fragments from uninitialized peer in dp +- wifi: plfxlc: fix clang-specific fortify warning +- x86/mm: Drop the 4 MB restriction on minimal NUMA node memory size +- workqueue: Provide one lock class key per work_on_cpu() callsite +- cpu/hotplug: Don't offline the last non-isolated CPU +- smp,csd: Throw an error if a CSD lock is stuck for too long +- srcu: Only accelerate on enqueue time +- clocksource/drivers/timer-atmel-tcb: Fix initialization on SAM9 hardware +- clocksource/drivers/timer-imx-gpt: Fix potential memory leak +- selftests/lkdtm: Disable CONFIG_UBSAN_TRAP in test config +- srcu: Fix srcu_struct node grpmask overflow on 64-bit systems +- perf/core: Bail out early if the request AUX area is out of bound +- x86/retpoline: Make sure there are no unconverted return thunks due to KCSAN +- lib/generic-radix-tree.c: Don't overflow in peek() +- btrfs: abort transaction on generation mismatch when marking eb as dirty +- locking/ww_mutex/test: Fix potential workqueue corruption +- LoongArch: use arch specific phys_to_dma +- LoongArch: Fixed EIOINTC structure members +- LoongArch: Fix virtual machine startup error +- LoongArch: Old BPI compatibility +- LoongArch: add kernel setvirtmap for runtime +- arm64: openeuler_defconfig: update for new feature +- x86: openeuler_defconfig: update from new feature +- erofs: fix NULL dereference of dif->bdev_handle in fscache mode +- block: Remove blkdev_get_by_*() functions +- bcache: Fixup error handling in register_cache() +- xfs: Convert to bdev_open_by_path() +- reiserfs: Convert to bdev_open_by_dev/path() +- ocfs2: Convert to use bdev_open_by_dev() +- nfs/blocklayout: Convert to use bdev_open_by_dev/path() +- jfs: Convert to bdev_open_by_dev() +- f2fs: Convert to bdev_open_by_dev/path() +- ext4: Convert to bdev_open_by_dev() +- erofs: Convert to use bdev_open_by_path() +- btrfs: Convert to bdev_open_by_path() +- fs: Convert to bdev_open_by_dev() +- mm/swap: Convert to use bdev_open_by_dev() +- PM: hibernate: Drop unused snapshot_test argument +- PM: hibernate: Convert to bdev_open_by_dev() +- scsi: target: Convert to bdev_open_by_path() +- s390/dasd: Convert to bdev_open_by_path() +- nvmet: Convert to bdev_open_by_path() +- mtd: block2mtd: Convert to bdev_open_by_dev/path() +- md: Convert to bdev_open_by_dev() +- dm: Convert to bdev_open_by_dev() +- bcache: Convert to bdev_open_by_path() +- zram: Convert to use bdev_open_by_dev() +- xen/blkback: Convert to bdev_open_by_dev() +- rnbd-srv: Convert to use bdev_open_by_path() +- pktcdvd: Convert to bdev_open_by_dev() +- drdb: Convert to use bdev_open_by_path() +- block: Use bdev_open_by_dev() in disk_scan_partitions() and blkdev_bszset() +- block: Use bdev_open_by_dev() in blkdev_open() +- block: Provide bdev_open_* functions +- alinux: random: speed up the initialization of module +- keys: Allow automatic module signature with SM3 +- arm64: fix image size inflation with CONFIG_COMPAT_TASK_SIZE +- arm64: set 32-bit compatible TASK_SIZE_MAX to fix U32 libc_write_01 error +- arm64: replace is_compat_task() with is_ilp32_compat_task() in TASK_SIZE_MAX +- arm64: fix address limit problem with TASK_SIZE_MAX +- ilp32: fix compile problem when ARM64_ILP32 and UBSAN are both enabled +- arm64: fix abi change caused by ILP32 +- arm64: fix AUDIT_ARCH_AARCH64ILP32 bug on audit subsystem +- ilp32: skip ARM erratum 1418040 for ilp32 application +- ilp32: avoid clearing upper 32 bits of syscall return value for ilp32 +- arm64: secomp: fix the secure computing mode 1 syscall check for ilp32 +- arm64:ilp32: add ARM64_ILP32 to Kconfig +- arm64:ilp32: add vdso-ilp32 and use for signal return +- arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32 +- arm64: ilp32: introduce ilp32-specific sigframe and ucontext +- arm64: signal32: move ilp32 and aarch32 common code to separated file +- arm64: signal: share lp64 signal structures and routines to ilp32 +- arm64: ilp32: introduce syscall table for ILP32 +- arm64: ilp32: share aarch32 syscall handlers +- arm64: ilp32: introduce binfmt_ilp32.c +- arm64: change compat_elf_hwcap and compat_elf_hwcap2 prefix to a32 +- arm64: introduce binfmt_elf32.c +- arm64: introduce AUDIT_ARCH_AARCH64ILP32 for ilp32 +- arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64 +- arm64: introduce is_a32_compat_{task,thread} for AArch32 compat +- arm64: uapi: set __BITS_PER_LONG correctly for ILP32 and LP64 +- arm64: rename functions that reference compat term +- arm64: rename COMPAT to AARCH32_EL0 +- arm64: ilp32: add documentation on the ILP32 ABI for ARM64 +- thread: move thread bits accessors to separated file +- ptrace: Add compat PTRACE_{G,S}ETSIGMASK handlers +- arm64: signal: Make parse_user_sigframe() independent of rt_sigframe layout + +* Tue Dec 5 2023 Zheng Zengkai - 6.6.0-1.0.0.1 +- !3058 tcp/dccp: Add another way to allocate local ports in connect() +- !3064 mm: PCP high auto-tuning +- !2985 hugetlbfs: avoid overflow in hugetlbfs_fallocate +- !3059 Handle more faults under the VMA lock +- mm, pcp: reduce detecting time of consecutive high order page freeing +- mm, pcp: decrease PCP high if free pages < high watermark +- mm: tune PCP high automatically +- mm: add framework for PCP high auto-tuning +- mm, page_alloc: scale the number of pages that are batch allocated +- mm: restrict the pcp batch scale factor to avoid too long latency +- mm, pcp: reduce lock contention for draining high-order pages +- cacheinfo: calculate size of per-CPU data cache slice +- mm, pcp: avoid to drain PCP when process exit +- mm: handle write faults to RO pages under the VMA lock +- mm: handle read faults under the VMA lock +- mm: handle COW faults under the VMA lock +- mm: handle shared faults under the VMA lock +- mm: call wp_page_copy() under the VMA lock +- mm: make lock_folio_maybe_drop_mmap() VMA lock aware +- tcp/dccp: Add another way to allocate local ports in connect() +- !3044 mm: hugetlb: Skip initialization of gigantic tail struct pages if freed by HVO +- !2980 io_uring: fix soft lockup in io_submit_sqes() +- !3014 anolis: bond: broadcast ARP or ND messages to all slaves +- !3018 folio conversions for numa balance +- mm: hugetlb: skip initialization of gigantic tail struct pages if freed by HVO +- memblock: introduce MEMBLOCK_RSRV_NOINIT flag +- memblock: pass memblock_type to memblock_setclr_flag +- mm: hugetlb_vmemmap: use nid of the head page to reallocate it +- mm: remove page_cpupid_xchg_last() +- mm: use folio_xchg_last_cpupid() in wp_page_reuse() +- mm: convert wp_page_reuse() and finish_mkwrite_fault() to take a folio +- mm: make finish_mkwrite_fault() static +- mm: huge_memory: use folio_xchg_last_cpupid() in __split_huge_page_tail() +- mm: migrate: use folio_xchg_last_cpupid() in folio_migrate_flags() +- sched/fair: use folio_xchg_last_cpupid() in should_numa_migrate_memory() +- mm: add folio_xchg_last_cpupid() +- mm: remove xchg_page_access_time() +- mm: huge_memory: use a folio in change_huge_pmd() +- mm: mprotect: use a folio in change_pte_range() +- sched/fair: use folio_xchg_access_time() in numa_hint_fault_latency() +- mm: add folio_xchg_access_time() +- mm: remove page_cpupid_last() +- mm: huge_memory: use folio_last_cpupid() in __split_huge_page_tail() +- mm: huge_memory: use folio_last_cpupid() in do_huge_pmd_numa_page() +- mm: memory: use folio_last_cpupid() in do_numa_page() +- mm: add folio_last_cpupid() +- mm_types: add virtual and _last_cpupid into struct folio +- sched/numa, mm: make numa migrate functions to take a folio +- mm: mempolicy: make mpol_misplaced() to take a folio +- mm: memory: make numa_migrate_prep() to take a folio +- mm: memory: use a folio in do_numa_page() +- mm: huge_memory: use a folio in do_huge_pmd_numa_page() +- mm: memory: add vm_normal_folio_pmd() +- mm: migrate: remove isolated variable in add_page_for_migration() +- mm: migrate: remove PageHead() check for HugeTLB in add_page_for_migration() +- mm: migrate: use a folio in add_page_for_migration() +- mm: migrate: use __folio_test_movable() +- mm: migrate: convert migrate_misplaced_page() to migrate_misplaced_folio() +- mm: migrate: convert numamigrate_isolate_page() to numamigrate_isolate_folio() +- mm: migrate: remove THP mapcount check in numamigrate_isolate_page() +- mm: migrate: remove PageTransHuge check in numamigrate_isolate_page() +- anolis: bond: broadcast ARP or ND messages to all slaves +- hugetlbfs: avoid overflow in hugetlbfs_fallocate +- io_uring: fix soft lockup in io_submit_sqes() +- !2971 net: sched: sch_qfq: Use non-work-conserving warning handler +- !2968 checkpatch: Update link tags to fix ci warning +- net: sched: sch_qfq: Use non-work-conserving warning handler +- checkpatch: Update check of link tags +- !2945 Backport linux 6.6.2 LTS patches +- btrfs: make found_logical_ret parameter mandatory for function queue_scrub_stripe() +- btrfs: use u64 for buffer sizes in the tree search ioctls +- Revert "mmc: core: Capture correct oemid-bits for eMMC cards" +- Revert "PCI/ASPM: Disable only ASPM_STATE_L1 when driver, disables L1" +- x86/amd_nb: Use Family 19h Models 60h-7Fh Function 4 IDs +- io_uring/net: ensure socket is marked connected on connect retry +- selftests: mptcp: fix wait_rm_addr/sf parameters +- selftests: mptcp: run userspace pm tests slower +- eventfs: Check for NULL ef in eventfs_set_attr() +- tracing/kprobes: Fix the order of argument descriptions +- fbdev: fsl-diu-fb: mark wr_reg_wa() static +- ALSA: hda/realtek: Add support dual speaker for Dell +- fbdev: imsttfb: fix a resource leak in probe +- fbdev: imsttfb: fix double free in probe() +- arm64/arm: arm_pmuv3: perf: Don't truncate 64-bit registers +- spi: spi-zynq-qspi: add spi-mem to driver kconfig dependencies +- ASoC: dapm: fix clock get name +- ASoC: hdmi-codec: register hpd callback on component probe +- ASoC: mediatek: mt8186_mt6366_rt1019_rt5682s: trivial: fix error messages +- ASoC: rt712-sdca: fix speaker route missing issue +- drm/syncobj: fix DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE +- drm/vc4: tests: Fix UAF in the mock helpers +- fs: dlm: Simplify buffer size computation in dlm_create_debug_file() +- module/decompress: use kvmalloc() consistently +- drivers: perf: Do not broadcast to other cpus when starting a counter +- net: ti: icss-iep: fix setting counter value +- RISC-V: Don't fail in riscv_of_parent_hartid() for disabled HARTs +- net/sched: act_ct: Always fill offloading tuple iifidx +- netfilter: nat: fix ipv6 nat redirect with mapped and scoped addresses +- netfilter: xt_recent: fix (increase) ipv6 literal buffer length +- i2c: iproc: handle invalid slave state +- net: enetc: shorten enetc_setup_xdp_prog() error message to fit NETLINK_MAX_FMTMSG_LEN +- virtio/vsock: Fix uninit-value in virtio_transport_recv_pkt() +- r8169: respect userspace disabling IFF_MULTICAST +- vsock/virtio: remove socket from connected/bound list on shutdown +- blk-core: use pr_warn_ratelimited() in bio_check_ro() +- nbd: fix uaf in nbd_open +- tg3: power down device only on SYSTEM_POWER_OFF +- ice: Fix VF-VF direction matching in drop rule in switchdev +- ice: Fix VF-VF filter rules in switchdev mode +- ice: lag: in RCU, use atomic allocation +- ice: Fix SRIOV LAG disable on non-compliant aggregate +- riscv: boot: Fix creation of loader.bin +- nvme: fix error-handling for io_uring nvme-passthrough +- net/smc: put sk reference if close work was canceled +- net/smc: allow cdc msg send rather than drop it with NULL sndbuf_desc +- net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT +- octeontx2-pf: Free pending and dropped SQEs +- selftests: pmtu.sh: fix result checking +- net: stmmac: xgmac: Enable support for multiple Flexible PPS outputs +- Fix termination state for idr_for_each_entry_ul() +- net: r8169: Disable multicast filter for RTL8168H and RTL8107E +- dccp/tcp: Call security_inet_conn_request() after setting IPv6 addresses. +- dccp: Call security_inet_conn_request() after setting IPv4 addresses. +- net: page_pool: add missing free_percpu when page_pool_init fail +- octeontx2-pf: Fix holes in error code +- octeontx2-pf: Fix error codes +- inet: shrink struct flowi_common +- bpf: Check map->usercnt after timer->timer is assigned +- rxrpc: Fix two connection reaping bugs +- tipc: Change nla_policy for bearer-related names to NLA_NUL_STRING +- hsr: Prevent use after free in prp_create_tagged_frame() +- llc: verify mac len before reading mac header +- watchdog: ixp4xx: Make sure restart always works +- watchdog: marvell_gti_wdt: Fix error code in probe() +- Input: synaptics-rmi4 - fix use after free in rmi_unregister_function() +- pwm: brcmstb: Utilize appropriate clock APIs in suspend/resume +- pwm: sti: Reduce number of allocations and drop usage of chip_data +- drm/amdgpu: don't put MQDs in VRAM on ARM | ARM64 +- drm/amdgpu/gfx10,11: use memcpy_to/fromio for MQDs +- regmap: prevent noinc writes from clobbering cache +- cpupower: fix reference to nonexistent document +- media: cec: meson: always include meson sub-directory in Makefile +- media: platform: mtk-mdp3: fix uninitialized variable in mdp_path_config() +- media: mediatek: vcodec: using encoder device to alloc/free encoder memory +- media: imx-jpeg: notify source chagne event when the first picture parsed +- media: mediatek: vcodec: Handle invalid encoder vsi +- media: verisilicon: Fixes clock list for rk3588 av1 decoder +- media: dvb-usb-v2: af9035: fix missing unlock +- media: cadence: csi2rx: Unregister v4l2 async notifier +- media: i2c: imx219: Drop IMX219_REG_CSI_LANE_MODE from common regs array +- media: i2c: imx219: Replace register addresses with macros +- media: i2c: imx219: Convert to CCI register access helpers +- media: cedrus: Fix clock/reset sequence +- media: vidtv: mux: Add check and kfree for kstrdup +- media: vidtv: psi: Add check for kstrdup +- media: s3c-camif: Avoid inappropriate kfree() +- media: mtk-jpegenc: Fix bug in JPEG encode quality selection +- media: amphion: handle firmware debug message +- media: bttv: fix use after free error due to btv->timeout timer +- media: ov5640: Fix a memory leak when ov5640_probe fails +- media: i2c: max9286: Fix some redundant of_node_put() calls +- media: ov5640: fix vblank unchange issue when work at dvp mode +- media: ov13b10: Fix some error checking in probe +- media: verisilicon: Do not enable G2 postproc downscale if source is narrower than destination +- media: hantro: Check whether reset op is defined before use +- media: imx-jpeg: initiate a drain of the capture queue in dynamic resolution change +- pcmcia: ds: fix possible name leak in error path in pcmcia_device_add() +- pcmcia: ds: fix refcount leak in pcmcia_device_add() +- pcmcia: cs: fix possible hung task and memory leak pccardd() +- cxl/hdm: Remove broken error path +- cxl/port: Fix @host confusion in cxl_dport_setup_regs() +- cxl/core/regs: Rename @dev to @host in struct cxl_register_map +- cxl/region: Fix cxl_region_rwsem lock held when returning to user space +- cxl/region: Use cxl_calc_interleave_pos() for auto-discovery +- cxl/region: Calculate a target position in a region interleave +- cxl/region: Prepare the decoder match range helper for reuse +- rtc: pcf85363: fix wrong mask/val parameters in regmap_update_bits call +- virt: sevguest: Fix passing a stack buffer as a scatterlist target +- cxl/mem: Fix shutdown order +- cxl/memdev: Fix sanitize vs decoder setup locking +- cxl/pci: Fix sanitize notifier setup +- cxl/pci: Clarify devm host for memdev relative setup +- cxl/pci: Remove inconsistent usage of dev_err_probe() +- cxl/pci: Cleanup 'sanitize' to always poll +- cxl/pci: Remove unnecessary device reference management in sanitize work +- rtc: brcmstb-waketimer: support level alarm_irq +- i3c: Fix potential refcount leak in i3c_master_register_new_i3c_devs +- rtla: Fix uninitialized variable found +- 9p/net: fix possible memory leak in p9_check_errors() +- perf vendor events intel: Add broadwellde two metrics +- perf vendor events intel: Fix broadwellde tma_info_system_dram_bw_use metric +- perf hist: Add missing puts to hist__account_cycles +- libperf rc_check: Make implicit enabling work for GCC +- perf machine: Avoid out of bounds LBR memory read +- powerpc/vmcore: Add MMU information to vmcoreinfo +- usb: host: xhci-plat: fix possible kernel oops while resuming +- xhci: Loosen RPM as default policy to cover for AMD xHC 1.1 +- perf vendor events: Update PMC used in PM_RUN_INST_CMPL event for power10 platform +- powerpc/pseries: fix potential memory leak in init_cpu_associativity() +- powerpc/imc-pmu: Use the correct spinlock initializer. +- powerpc/vas: Limit open window failure messages in log bufffer +- perf trace: Use the right bpf_probe_read(_str) variant for reading user data +- powerpc: Hide empty pt_regs at base of the stack +- powerpc/xive: Fix endian conversion size +- powerpc/40x: Remove stale PTE_ATOMIC_UPDATES macro +- perf tools: Do not ignore the default vmlinux.h +- modpost: fix ishtp MODULE_DEVICE_TABLE built on big-endian host +- modpost: fix tee MODULE_DEVICE_TABLE built on big-endian host +- s390/ap: re-init AP queues on config on +- perf mem-events: Avoid uninitialized read +- perf parse-events: Fix for term values that are raw events +- perf build: Add missing comment about NO_LIBTRACEEVENT=1 +- interconnect: fix error handling in qnoc_probe() +- powerpc: Only define __parse_fpscr() when required +- interconnect: qcom: osm-l3: Replace custom implementation of COUNT_ARGS() +- interconnect: qcom: sm8350: Set ACV enable_mask +- interconnect: qcom: sm8250: Set ACV enable_mask +- interconnect: qcom: sm8150: Set ACV enable_mask +- interconnect: qcom: sm6350: Set ACV enable_mask +- interconnect: qcom: sdm845: Set ACV enable_mask +- interconnect: qcom: sdm670: Set ACV enable_mask +- interconnect: qcom: sc8280xp: Set ACV enable_mask +- interconnect: qcom: sc8180x: Set ACV enable_mask +- interconnect: qcom: sc7280: Set ACV enable_mask +- interconnect: qcom: sc7180: Set ACV enable_mask +- interconnect: qcom: qdu1000: Set ACV enable_mask +- f2fs: fix to initialize map.m_pblk in f2fs_precache_extents() +- dmaengine: pxa_dma: Remove an erroneous BUG_ON() in pxad_free_desc() +- USB: usbip: fix stub_dev hub disconnect +- tools: iio: iio_generic_buffer ensure alignment +- debugfs: Fix __rcu type comparison warning +- misc: st_core: Do not call kfree_skb() under spin_lock_irqsave() +- tools/perf: Update call stack check in builtin-lock.c +- dmaengine: ti: edma: handle irq_of_parse_and_map() errors +- usb: chipidea: Simplify Tegra DMA alignment code +- usb: chipidea: Fix DMA overwrite for Tegra +- usb: dwc2: fix possible NULL pointer dereference caused by driver concurrency +- dmaengine: idxd: Register dsa_bus_type before registering idxd sub-drivers +- perf record: Fix BTF type checks in the off-cpu profiling +- perf vendor events arm64: Fix for AmpereOne metrics +- pinctrl: renesas: rzg2l: Make reverse order of enable() for disable() +- livepatch: Fix missing newline character in klp_resolve_symbols() +- perf parse-events: Fix tracepoint name memory leak +- tty: tty_jobctrl: fix pid memleak in disassociate_ctty() +- f2fs: fix to drop meta_inode's page cache in f2fs_put_super() +- f2fs: compress: fix to avoid redundant compress extension +- f2fs: compress: fix to avoid use-after-free on dic +- f2fs: compress: fix deadloop in f2fs_write_cache_pages() +- perf kwork: Set ordered_events to true in 'struct perf_tool' +- perf kwork: Add the supported subcommands to the document +- perf kwork: Fix incorrect and missing free atom in work_push_atom() +- pinctrl: baytrail: fix debounce disable case +- iio: frequency: adf4350: Use device managed functions and fix power down issue. +- perf stat: Fix aggr mode initialization +- apparmor: fix invalid reference on profile->disconnected +- scripts/gdb: fix usage of MOD_TEXT not defined when CONFIG_MODULES=n +- leds: trigger: ledtrig-cpu:: Fix 'output may be truncated' issue for 'cpu' +- leds: pwm: Don't disable the PWM when the LED should be off +- leds: turris-omnia: Do not use SMBUS calls +- mfd: arizona-spi: Set pdata.hpdet_channel for ACPI enumerated devs +- dt-bindings: mfd: mt6397: Split out compatible for MediaTek MT6366 PMIC +- mfd: dln2: Fix double put in dln2_probe +- mfd: core: Ensure disabled devices are skipped without aborting +- mfd: core: Un-constify mfd_cell.of_reg +- IB/mlx5: Fix init stage error handling to avoid double free of same QP and UAF +- erofs: fix erofs_insert_workgroup() lockref usage +- ASoC: ams-delta.c: use component after check +- crypto: qat - fix deadlock in backlog processing +- crypto: qat - fix ring to service map for QAT GEN4 +- crypto: qat - use masks for AE groups +- crypto: qat - refactor fw config related functions +- crypto: qat - enable dc chaining service +- crypto: qat - consolidate services structure +- certs: Break circular dependency when selftest is modular +- padata: Fix refcnt handling in padata_free_shell() +- PCI: endpoint: Fix double free in __pci_epc_create() +- ASoC: Intel: Skylake: Fix mem leak when parsing UUIDs fails +- HID: logitech-hidpp: Move get_wireless_feature_index() check to hidpp_connect_event() +- HID: logitech-hidpp: Revert "Don't restart communication if not necessary" +- HID: logitech-hidpp: Don't restart IO, instead defer hid_connect() only +- sh: bios: Revive earlyprintk support +- HID: uclogic: Fix a work->entry not empty bug in __queue_work() +- HID: uclogic: Fix user-memory-access bug in uclogic_params_ugee_v2_init_event_hooks() +- hid: cp2112: Fix IRQ shutdown stopping polling for all IRQs on chip +- RDMA/hfi1: Workaround truncation compilation error +- scsi: ufs: core: Leave space for '\0' in utf8 desc string +- ASoC: fsl: Fix PM disable depth imbalance in fsl_easrc_probe +- ASoC: intel: sof_sdw: Stop processing CODECs when enough are found +- ASoC: SOF: core: Ensure sof_ops_free() is still called when probe never ran. +- RDMA/hns: Fix init failure of RoCE VF and HIP08 +- RDMA/hns: Fix unnecessary port_num transition in HW stats allocation +- RDMA/hns: The UD mode can only be configured with DCQCN +- RDMA/hns: Add check for SL +- RDMA/hns: Fix signed-unsigned mixed comparisons +- RDMA/hns: Fix uninitialized ucmd in hns_roce_create_qp_common() +- RDMA/hns: Fix printing level of asynchronous events +- IB/mlx5: Fix rdma counter binding for RAW QP +- dlm: fix no ack after final message +- dlm: be sure we reset all nodes at forced shutdown +- dlm: fix remove member after close call +- dlm: fix creating multiple node structures +- fs: dlm: Fix the size of a buffer in dlm_create_debug_file() +- ASoC: fsl-asoc-card: Add comment for mclk in the codec_priv +- ASoC: Intel: sof_sdw_rt_sdca_jack_common: add rt713 support +- backlight: pwm_bl: Disable PWM on shutdown, suspend and remove +- ASoC: fsl: mpc5200_dma.c: Fix warning of Function parameter or member not described +- kselftest: vm: fix mdwe's mmap_FIXED test case +- ext4: move 'ix' sanity check to corrent position +- ext4: add missing initialization of call_notify_error in update_super_work() +- ARM: 9323/1: mm: Fix ARCH_LOW_ADDRESS_LIMIT when CONFIG_ZONE_DMA +- ARM: 9321/1: memset: cast the constant byte to unsigned char +- crypto: hisilicon/qm - fix PF queue parameter issue +- hid: cp2112: Fix duplicate workqueue initialization +- PCI: vmd: Correct PCI Header Type Register's multi-function check +- ASoC: SOF: ipc4-topology: Use size_add() in call to struct_size() +- crypto: qat - increase size of buffers +- crypto: caam/jr - fix Chacha20 + Poly1305 self test failure +- crypto: caam/qi2 - fix Chacha20 + Poly1305 self test failure +- nd_btt: Make BTT lanes preemptible +- libnvdimm/of_pmem: Use devm_kstrdup instead of kstrdup and check its return value +- ASoC: soc-pcm.c: Make sure DAI parameters cleared if the DAI becomes inactive +- scsi: ibmvfc: Fix erroneous use of rtas_busy_delay with hcall return code +- crypto: qat - fix unregistration of compression algorithms +- crypto: qat - fix unregistration of crypto algorithms +- crypto: qat - ignore subsequent state up commands +- crypto: qat - fix state machines cleanup paths +- RDMA/core: Use size_{add,sub,mul}() in calls to struct_size() +- hwrng: geode - fix accessing registers +- hwrng: bcm2835 - Fix hwrng throughput regression +- crypto: hisilicon/hpre - Fix a erroneous check after snprintf() +- crypto: ccp - Fix some unfused tests +- crypto: ccp - Fix sample application signature passing +- crypto: ccp - Fix DBC sample application error handling +- crypto: ccp - Fix ioctl unit tests +- crypto: ccp - Get a free page to use while fetching initial nonce +- KEYS: Include linux/errno.h in linux/verification.h +- ALSA: hda: cs35l41: Undo runtime PM changes at driver exit time +- ALSA: hda: cs35l41: Fix unbalanced pm_runtime_get() +- ASoC: cs35l41: Undo runtime PM changes at driver exit time +- ASoC: cs35l41: Verify PM runtime resume errors in IRQ handler +- ASoC: cs35l41: Fix broken shared boost activation +- ASoC: cs35l41: Initialize completion object before requesting IRQ +- ASoC: cs35l41: Handle mdsync_up reg write errors +- ASoC: cs35l41: Handle mdsync_down reg write errors +- module/decompress: use vmalloc() for gzip decompression workspace +- iommufd: Add iopt_area_alloc() +- ARM: dts: BCM5301X: Explicitly disable unused switch CPU ports +- soc: qcom: pmic_glink: fix connector type to be DisplayPort +- selftests/resctrl: Ensure the benchmark commands fits to its array +- selftests/pidfd: Fix ksft print formats +- arm64: tegra: Use correct interrupts for Tegra234 TKE +- memory: tegra: Set BPMP msg flags to reset IPC channels +- firmware: tegra: Add suspend hook and reset BPMP IPC early on resume +- arm64: tegra: Fix P3767 QSPI speed +- arm64: tegra: Fix P3767 card detect polarity +- arm64: dts: imx8mn: Add sound-dai-cells to micfil node +- arm64: dts: imx8mm: Add sound-dai-cells to micfil node +- arm64: dts: imx8mp-debix-model-a: Remove USB hub reset-gpios +- arm64: dts: imx8qm-ss-img: Fix jpegenc compatible entry +- clk: scmi: Free scmi_clk allocated when the clocks with invalid info are skipped +- ARM: dts: am3517-evm: Fix LED3/4 pinmux +- firmware: arm_ffa: Allow the FF-A drivers to use 32bit mode of messaging +- firmware: arm_ffa: Assign the missing IDR allocation ID to the FFA device +- arm64: dts: ti: Fix HDMI Audio overlay in Makefile +- arm64: dts: ti: k3-am62a7-sk: Drop i2c-1 to 100Khz +- arm64: dts: ti: k3-am625-beagleplay: Fix typo in ramoops reg +- arm64: dts: ti: verdin-am62: disable MIPI DSI bridge +- arm64: dts: ti: k3-j721s2-evm-gesi: Specify base dtb for overlay file +- firmware: ti_sci: Mark driver as non removable +- ARM: dts: stm32: stm32f7-pinctrl: don't use multiple blank lines +- kunit: test: Fix the possible memory leak in executor_test +- kunit: Fix possible memory leak in kunit_filter_suites() +- kunit: Fix the wrong kfree of copy for kunit_filter_suites() +- kunit: Fix missed memory release in kunit_free_suite_set() +- soc: qcom: llcc: Handle a second device without data corruption +- ARM: dts: qcom: mdm9615: populate vsdcc fixed regulator +- ARM: dts: qcom: apq8026-samsung-matisse-wifi: Fix inverted hall sensor +- arm64: dts: qcom: apq8016-sbc: Add missing ADV7533 regulators +- riscv: dts: allwinner: remove address-cells from intc node +- arm64: dts: qcom: msm8939: Fix iommu local address range +- arm64: dts: qcom: msm8976: Fix ipc bit shifts +- ARM64: dts: marvell: cn9310: Use appropriate label for spi1 pins +- arm64: dts: qcom: sdx75-idp: align RPMh regulator nodes with bindings +- arm64: dts: qcom: sdm845-mtp: fix WiFi configuration +- arm64: dts: qcom: sm8350: fix pinctrl for UART18 +- arm64: dts: qcom: sm8150: add ref clock to PCIe PHYs +- arm64: dts: qcom: sc7280: drop incorrect EUD port on SoC side +- arm64: dts: qcom: sdm670: Fix pdc mapping +- arm64: dts: qcom: qrb2210-rb1: Fix regulators +- arm64: dts: qcom: qrb2210-rb1: Swap UART index +- arm64: dts: qcom: sc7280: Add missing LMH interrupts +- arm64: dts: qcom: sm6125: Pad APPS IOMMU address to 8 characters +- arm64: dts: qcom: msm8992-libra: drop duplicated reserved memory +- arm64: dts: qcom: msm8916: Fix iommu local address range +- arm64: dts: qcom: sc7280: link usb3_phy_wrapper_gcc_usb30_pipe_clk +- arm64: dts: qcom: sdm845: cheza doesn't support LMh node +- arm64: dts: qcom: sdm845: Fix PSCI power domain names +- ARM: dts: renesas: blanche: Fix typo in GP_11_2 pin name +- perf: hisi: Fix use-after-free when register pmu fails +- drivers/perf: hisi_pcie: Check the type first in pmu::event_init() +- perf/arm-cmn: Fix DTC domain detection +- drm/amd/pm: Fix a memory leak on an error path +- drivers/perf: hisi: use cpuhp_state_remove_instance_nocalls() for hisi_hns3_pmu uninit process +- drm: mediatek: mtk_dsi: Fix NO_EOT_PACKET settings/handling +- clocksource/drivers/arm_arch_timer: limit XGene-1 workaround +- drm/msm/dsi: free TX buffer in unbind +- drm/msm/dsi: use msm_gem_kernel_put to free TX buffer +- xen-pciback: Consider INTx disabled when MSI/MSI-X is enabled +- xen: irqfd: Use _IOW instead of the internal _IOC() macro +- xen: Make struct privcmd_irqfd's layout architecture independent +- xenbus: fix error exit in xenbus_init() +- drm/rockchip: Fix type promotion bug in rockchip_gem_iommu_map() +- arm64/arm: xen: enlighten: Fix KPTI checks +- drm/bridge: lt9611uxc: fix the race in the error path +- gpu: host1x: Correct allocated size for contexts +- drm/rockchip: cdn-dp: Fix some error handling paths in cdn_dp_probe() +- drm/msm/a6xx: Fix unknown speedbin case +- drm/msm/adreno: Fix SM6375 GPU ID +- accel/habanalabs/gaudi2: Fix incorrect string length computation in gaudi2_psoc_razwi_get_engines() +- drm/mediatek: Fix iommu fault during crtc enabling +- drm/mediatek: Fix iommu fault by swapping FBs after updating plane state +- drm/mediatek: Add mmsys_dev_num to mt8188 vdosys0 driver data +- io_uring/kbuf: Allow the full buffer id space for provided buffers +- io_uring/kbuf: Fix check of BID wrapping in provided buffers +- drm/amd/display: Bail from dm_check_crtc_cursor if no relevant change +- drm/amd/display: Refactor dm_get_plane_scale helper +- drm/amd/display: Check all enabled planes in dm_check_crtc_cursor +- drm/amd/display: Fix null pointer dereference in error message +- drm/amdkfd: Handle errors from svm validate and map +- drm/amdkfd: Remove svm range validated_once flag +- drm/amdkfd: fix some race conditions in vram buffer alloc/free of svm code +- drm/amdgpu: Increase IH soft ring size for GFX v9.4.3 dGPU +- drm: Call drm_atomic_helper_shutdown() at shutdown/remove time for misc drivers +- drm/bridge: tc358768: Fix tc358768_ns_to_cnt() +- drm/bridge: tc358768: Clean up clock period code +- drm/bridge: tc358768: Rename dsibclk to hsbyteclk +- drm/bridge: tc358768: Use dev for dbg prints, not priv->dev +- drm/bridge: tc358768: Print logical values, not raw register values +- drm/bridge: tc358768: Use struct videomode +- drm/bridge: tc358768: Fix bit updates +- drm/bridge: tc358768: Fix use of uninitialized variable +- x86/tdx: Zero out the missing RSI in TDX_HYPERCALL macro +- drm/mediatek: Fix coverity issue with unintentional integer overflow +- drm/ssd130x: Fix screen clearing +- drm/bridge: lt8912b: Add missing drm_bridge_attach call +- drm/bridge: lt8912b: Manually disable HPD only if it was enabled +- drm/bridge: lt8912b: Fix crash on bridge detach +- drm/bridge: lt8912b: Fix bridge_detach +- drm: bridge: it66121: Fix invalid connector dereference +- drm/radeon: Remove the references of radeon_gem_ pread & pwrite ioctls +- drm/radeon: possible buffer overflow +- drm/rockchip: vop2: Add missing call to crtc reset helper +- drm/rockchip: vop2: Don't crash for invalid duplicate_state +- drm/rockchip: vop: Fix call to crtc reset helper +- drm/rockchip: vop: Fix reset of state in duplicate state crtc funcs +- drm/loongson: Fix error handling in lsdc_pixel_pll_setup() +- drm: bridge: samsung-dsim: Fix waiting for empty cmd transfer FIFO on older Exynos +- drm: bridge: for GENERIC_PHY_MIPI_DPHY also select GENERIC_PHY +- drm: bridge: samsung-dsim: Initialize ULPS EXIT for i.MX8M DSIM +- spi: omap2-mcspi: Fix hardcoded reference clock +- spi: omap2-mcspi: switch to use modern name +- platform/chrome: cros_ec_lpc: Separate host command and irq disable +- hte: tegra: Fix missing error code in tegra_hte_test_probe() +- hwmon: (sch5627) Disallow write access if virtual registers are locked +- hwmon: (sch5627) Use bit macros when accessing the control register +- hwmon: (pmbus/mp2975) Move PGOOD fix +- Revert "hwmon: (sch56xx-common) Add automatic module loading on supported devices" +- Revert "hwmon: (sch56xx-common) Add DMI override table" +- hwmon: (coretemp) Fix potentially truncated sysfs attribute name +- hwmon: (axi-fan-control) Fix possible NULL pointer dereference +- regulator: qcom-rpmh: Fix smps4 regulator for pm8550ve +- platform/x86: wmi: Fix opening of char device +- platform/x86: wmi: Fix probe failure when failing to register WMI devices +- clk: mediatek: fix double free in mtk_clk_register_pllfh() +- clk: qcom: ipq5332: drop the CLK_SET_RATE_PARENT flag from GPLL clocks +- clk: qcom: ipq9574: drop the CLK_SET_RATE_PARENT flag from GPLL clocks +- clk: qcom: ipq5018: drop the CLK_SET_RATE_PARENT flag from GPLL clocks +- clk: qcom: apss-ipq-pll: Fix 'l' value for ipq5332_pll_config +- clk: qcom: apss-ipq-pll: Use stromer plus ops for stromer plus pll +- clk: qcom: clk-alpha-pll: introduce stromer plus ops +- clk: qcom: config IPQ_APSS_6018 should depend on QCOM_SMEM +- clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data +- clk: mediatek: clk-mt7629: Add check for mtk_alloc_clk_data +- clk: mediatek: clk-mt7629-eth: Add check for mtk_alloc_clk_data +- clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data +- clk: mediatek: clk-mt6779: Add check for mtk_alloc_clk_data +- clk: mediatek: clk-mt6765: Add check for mtk_alloc_clk_data +- clk: npcm7xx: Fix incorrect kfree +- clk: ti: fix double free in of_ti_divider_clk_setup() +- clk: keystone: pll: fix a couple NULL vs IS_ERR() checks +- clk: ralink: mtmips: quiet unused variable warning +- spi: nxp-fspi: use the correct ioremap function +- clk: linux/clk-provider.h: fix kernel-doc warnings and typos +- clk: renesas: rzg2l: Fix computation formula +- clk: renesas: rzg2l: Use FIELD_GET() for PLL register fields +- clk: renesas: rzg2l: Trust value returned by hardware +- clk: renesas: rzg2l: Lock around writes to mux register +- clk: renesas: rzg2l: Wait for status bit of SD mux before continuing +- clk: renesas: rcar-gen3: Extend SDnH divider table +- clk: imx: imx8qxp: Fix elcdif_pll clock +- clk: imx: imx8mq: correct error handling path +- clk: imx: imx8: Fix an error handling path in imx8_acm_clk_probe() +- clk: imx: imx8: Fix an error handling path if devm_clk_hw_register_mux_parent_data_table() fails +- clk: imx: imx8: Fix an error handling path in clk_imx_acm_attach_pm_domains() +- clk: imx: Select MXC_CLK for CLK_IMX8QXP +- regulator: mt6358: Fail probe on unknown chip ID +- gpio: sim: initialize a managed pointer when declaring it +- clk: qcom: gcc-sm8150: Fix gcc_sdcc2_apps_clk_src +- clk: qcom: mmcc-msm8998: Fix the SMMU GDSC +- clk: qcom: mmcc-msm8998: Don't check halt bit on some branch clks +- clk: qcom: clk-rcg2: Fix clock rate overflow for high parent frequencies +- clk: qcom: gcc-msm8996: Remove RPM bus clocks +- clk: qcom: ipq5332: Drop set rate parent from gpll0 dependent clocks +- spi: tegra: Fix missing IRQ check in tegra_slink_probe() +- regmap: debugfs: Fix a erroneous check after snprintf() +- ipvlan: properly track tx_errors +- net: add DEV_STATS_READ() helper +- virtio_net: use u64_stats_t infra to avoid data-races +- ipv6: avoid atomic fragment on GSO packets +- mptcp: properly account fastopen data +- ACPI: sysfs: Fix create_pnp_modalias() and create_of_modalias() +- bpf: Fix unnecessary -EBUSY from htab_lock_bucket +- Bluetooth: hci_sync: Fix Opcode prints in bt_dev_dbg/err +- Bluetooth: Make handle of hci_conn be unique +- Bluetooth: ISO: Pass BIG encryption info through QoS +- wifi: iwlwifi: empty overflow queue during flush +- wifi: iwlwifi: mvm: update IGTK in mvmvif upon D3 resume +- wifi: iwlwifi: pcie: synchronize IRQs before NAPI +- wifi: iwlwifi: mvm: fix netif csum flags +- wifi: iwlwifi: increase number of RX buffers for EHT devices +- wifi: iwlwifi: mvm: remove TDLS stations from FW +- wifi: iwlwifi: mvm: fix iwl_mvm_mac_flush_sta() +- wifi: iwlwifi: mvm: change iwl_mvm_flush_sta() API +- wifi: iwlwifi: mvm: Don't always bind/link the P2P Device interface +- wifi: iwlwifi: mvm: Fix key flags for IGTK on AP interface +- wifi: iwlwifi: mvm: Correctly set link configuration +- wifi: iwlwifi: yoyo: swap cdb and jacket bits values +- wifi: mac80211: Fix setting vif links +- wifi: mac80211: don't recreate driver link debugfs in reconfig +- wifi: iwlwifi: mvm: use correct sta ID for IGTK/BIGTK +- wifi: iwlwifi: mvm: fix removing pasn station for responder +- wifi: iwlwifi: mvm: update station's MFP flag after association +- tcp: fix cookie_init_timestamp() overflows +- chtls: fix tp->rcv_tstamp initialization +- thermal: core: Don't update trip points inside the hysteresis range +- selftests/bpf: Make linked_list failure test more robust +- net: skb_find_text: Ignore patterns extending past 'to' +- bpf: Fix missed rcu read lock in bpf_task_under_cgroup() +- thermal/drivers/mediatek: Fix probe for THERMAL_V2 +- r8169: fix rare issue with broken rx after link-down on RTL8125 +- thermal: core: prevent potential string overflow +- wifi: rtw88: Remove duplicate NULL check before calling usb_kill/free_urb() +- virtio-net: fix the vq coalescing setting for vq resize +- virtio-net: fix per queue coalescing parameter setting +- virtio-net: consistently save parameters for per-queue +- virtio-net: fix mismatch of getting tx-frames +- netfilter: nf_tables: Drop pointless memset when dumping rules +- wifi: wfx: fix case where rates are out of order +- PM / devfreq: rockchip-dfi: Make pmu regmap mandatory +- can: dev: can_put_echo_skb(): don't crash kernel if can_priv::echo_skb is accessed out of bounds +- can: dev: can_restart(): fix race condition between controller restart and netif_carrier_on() +- can: dev: can_restart(): don't crash kernel if carrier is OK +- wifi: ath11k: fix Tx power value during active CAC +- r8152: break the loop when the budget is exhausted +- selftests/bpf: Define SYS_NANOSLEEP_KPROBE_NAME for riscv +- selftests/bpf: Define SYS_PREFIX for riscv +- libbpf: Fix syscall access arguments on riscv +- can: etas_es58x: add missing a blank line after declaration +- can: etas_es58x: rework the version check logic to silence -Wformat-truncation +- ACPI: video: Add acpi_backlight=vendor quirk for Toshiba Portégé R100 +- ACPI: property: Allow _DSD buffer data only for byte accessors +- wifi: rtlwifi: fix EDCA limit set by BT coexistence +- tcp_metrics: do not create an entry from tcp_init_metrics() +- tcp_metrics: properly set tp->snd_ssthresh in tcp_init_metrics() +- tcp_metrics: add missing barriers on delete +- wifi: ath: dfs_pattern_detector: Fix a memory initialization issue +- wifi: mt76: mt7921: fix the wrong rate selected in fw for the chanctx driver +- wifi: mt76: mt7921: fix the wrong rate pickup for the chanctx driver +- wifi: mt76: move struct ieee80211_chanctx_conf up to struct mt76_vif +- wifi: mt76: mt7915: fix beamforming availability check +- wifi: mt76: fix per-band IEEE80211_CONF_MONITOR flag comparison +- wifi: mt76: get rid of false alamrs of tx emission issues +- wifi: mt76: fix potential memory leak of beacon commands +- wifi: mt76: update beacon size limitation +- wifi: mt76: mt7996: fix TWT command format +- wifi: mt76: mt7996: fix rx rate report for CBW320-2 +- wifi: mt76: mt7996: fix wmm queue mapping +- wifi: mt76: mt7996: fix beamformee ss subfield in EHT PHY cap +- wifi: mt76: mt7996: fix beamform mcu cmd configuration +- wifi: mt76: mt7996: set correct wcid in txp +- wifi: mt76: remove unused error path in mt76_connac_tx_complete_skb +- wifi: mt76: mt7603: improve stuck beacon handling +- wifi: mt76: mt7603: improve watchdog reset reliablity +- wifi: mt76: mt7603: rework/fix rx pse hang check +- cpufreq: tegra194: fix warning due to missing opp_put +- PM: sleep: Fix symbol export for _SIMPLE_ variants of _PM_OPS() +- wifi: mac80211: fix check for unusable RX result +- wifi: ath11k: fix boot failure with one MSI vector +- wifi: ath12k: fix DMA unmap warning on NULL DMA address +- wifi: rtw88: debug: Fix the NULL vs IS_ERR() bug for debugfs_create_file() +- net: ethernet: mtk_wed: fix EXT_INT_STATUS_RX_FBUF definitions for MT7986 SoC +- ice: fix pin assignment for E810-T without SMA control +- net: spider_net: Use size_add() in call to struct_size() +- tipc: Use size_add() in calls to struct_size() +- tls: Use size_add() in call to struct_size() +- mlxsw: Use size_mul() in call to struct_size() +- gve: Use size_add() in call to struct_size() +- bpf: Fix kfunc callback register type handling +- tcp: call tcp_try_undo_recovery when an RTOd TFO SYNACK is ACKed +- selftests/bpf: Skip module_fentry_shadow test when bpf_testmod is not available +- udplite: fix various data-races +- udplite: remove UDPLITE_BIT +- udp: annotate data-races around udp->encap_type +- udp: lockless UDP_ENCAP_L2TPINUDP / UDP_GRO +- udp: move udp->accept_udp_{l4|fraglist} to udp->udp_flags +- udp: add missing WRITE_ONCE() around up->encap_rcv +- udp: move udp->gro_enabled to udp->udp_flags +- udp: move udp->no_check6_rx to udp->udp_flags +- udp: move udp->no_check6_tx to udp->udp_flags +- udp: introduce udp->udp_flags +- wifi: cfg80211: fix kernel-doc for wiphy_delayed_work_flush() +- bpf, x64: Fix tailcall infinite loop +- selftests/bpf: Correct map_fd to data_fd in tailcalls +- iavf: Fix promiscuous mode configuration flow messages +- i40e: fix potential memory leaks in i40e_remove() +- wifi: iwlwifi: don't use an uninitialized variable +- wifi: iwlwifi: honor the enable_ini value +- wifi: mac80211: fix # of MSDU in A-MSDU calculation +- wifi: cfg80211: fix off-by-one in element defrag +- wifi: mac80211: fix RCU usage warning in mesh fast-xmit +- wifi: mac80211: move sched-scan stop work to wiphy work +- wifi: mac80211: move offchannel works to wiphy work +- wifi: mac80211: move scan work to wiphy work +- wifi: mac80211: move radar detect work to wiphy work +- wifi: cfg80211: add flush functions for wiphy work +- wifi: ath12k: fix undefined behavior with __fls in dp +- irqchip/sifive-plic: Fix syscore registration for multi-socket systems +- genirq/matrix: Exclude managed interrupts in irq_matrix_allocated() +- string: Adjust strtomem() logic to allow for smaller sources +- PCI/MSI: Provide stubs for IMS functions +- selftests/x86/lam: Zero out buffer for readlink() +- perf: Optimize perf_cgroup_switch() +- pstore/platform: Add check for kstrdup +- x86/nmi: Fix out-of-order NMI nesting checks & false positive warning +- drivers/clocksource/timer-ti-dm: Don't call clk_get_rate() in stop function +- srcu: Fix callbacks acceleration mishandling +- x86/apic: Fake primary thread mask for XEN/PV +- cpu/SMT: Make SMT control more robust against enumeration failures +- x86/boot: Fix incorrect startup_gdt_descr.size +- x86/sev-es: Allow copy_from_kernel_nofault() in earlier boot +- cgroup/cpuset: Fix load balance state in update_partition_sd_lb() +- ACPI/NUMA: Apply SRAT proximity domain to entire CFMWS window +- x86/numa: Introduce numa_fill_memblks() +- futex: Don't include process MM in futex key on no-MMU +- x86/srso: Fix unret validation dependencies +- x86/srso: Fix vulnerability reporting for missing microcode +- x86/srso: Print mitigation for retbleed IBPB case +- x86/srso: Fix SBPB enablement for (possible) future fixed HW +- writeback, cgroup: switch inodes with dirty timestamps to release dying cgwbs +- vfs: fix readahead(2) on block devices +- nfsd: Handle EOPENSTALE correctly in the filecache +- sched: Fix stop_one_cpu_nowait() vs hotplug +- objtool: Propagate early errors +- sched/uclamp: Ignore (util == 0) optimization in feec() when p_util_max = 0 +- sched/uclamp: Set max_spare_cap_cpu even if max_spare_cap is 0 +- iov_iter, x86: Be consistent about the __user tag on copy_mc_to_user() +- sched/fair: Fix cfs_rq_is_decayed() on !SMP +- sched/topology: Fix sched_numa_find_nth_cpu() in non-NUMA case +- sched/topology: Fix sched_numa_find_nth_cpu() in CPU-less case +- numa: Generalize numa_map_to_online_node() +- hwmon: (nct6775) Fix incorrect variable reuse in fan_div calculation +- !2933 Backport linux 6.6.1 LTS patches +- ASoC: SOF: sof-pci-dev: Fix community key quirk detection +- ALSA: hda: intel-dsp-config: Fix JSL Chromebook quirk detection +- serial: core: Fix runtime PM handling for pending tx +- misc: pci_endpoint_test: Add deviceID for J721S2 PCIe EP device support +- dt-bindings: serial: rs485: Add rs485-rts-active-high +- tty: 8250: Add Brainboxes Oxford Semiconductor-based quirks +- tty: 8250: Add support for Intashield IX cards +- tty: 8250: Add support for additional Brainboxes PX cards +- tty: 8250: Fix up PX-803/PX-857 +- tty: 8250: Fix port count of PX-257 +- tty: 8250: Add support for Intashield IS-100 +- tty: 8250: Add support for Brainboxes UP cards +- tty: 8250: Add support for additional Brainboxes UC cards +- tty: 8250: Remove UC-257 and UC-431 +- tty: n_gsm: fix race condition in status line change on dead connections +- Bluetooth: hci_bcm4377: Mark bcm4378/bcm4387 as BROKEN_LE_CODED +- usb: raw-gadget: properly handle interrupted requests +- usb: typec: tcpm: Fix NULL pointer dereference in tcpm_pd_svdm() +- usb: typec: tcpm: Add additional checks for contaminant +- usb: storage: set 1.50 as the lower bcdDevice for older "Super Top" compatibility +- PCI: Prevent xHCI driver from claiming AMD VanGogh USB3 DRD device +- ALSA: usb-audio: add quirk flag to enable native DSD for McIntosh devices +- eventfs: Use simple_recursive_removal() to clean up dentries +- eventfs: Delete eventfs_inode when the last dentry is freed +- eventfs: Save ownership and mode +- eventfs: Remove "is_freed" union with rcu head +- tracing: Have trace_event_file have ref counters +- perf evlist: Avoid frequency mode for the dummy event +- power: supply: core: Use blocking_notifier_call_chain to avoid RCU complaint +- drm/amd/display: Don't use fsleep for PSR exit waits +- !2927 dm ioctl: add DMINFO() to track dm device create/remove +- dm ioctl: add DMINFO() to track dm device create/remove +- !2900 Add initial openeuler_defconfig for arm64 and x86 +- config: add initial openeuler_defconfig for x86 +- config: add initial openeuler_defconfig for arm64 +- kconfig: Add script to check & update openeuler_defconfig +- init from linux v6.6